apollo3/
chip.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Chip trait setup.
6
7use core::fmt::Write;
8use cortexm4f::{CortexM4F, CortexMVariant};
9use kernel::platform::chip::Chip;
10use kernel::platform::chip::InterruptService;
11
12pub struct Apollo3<I: InterruptService + 'static> {
13    mpu: cortexm4f::mpu::MPU,
14    userspace_kernel_boundary: cortexm4f::syscall::SysCall,
15    interrupt_service: &'static I,
16}
17
18impl<I: InterruptService + 'static> Apollo3<I> {
19    pub unsafe fn new(interrupt_service: &'static I) -> Self {
20        Self {
21            mpu: cortexm4f::mpu::new(),
22            userspace_kernel_boundary: cortexm4f::syscall::SysCall::new(),
23            interrupt_service,
24        }
25    }
26}
27
28/// This struct, when initialized, instantiates all peripheral drivers for the apollo3.
29///
30/// If a board wishes to use only a subset of these peripherals, this
31/// should not be used or imported, and a modified version should be
32/// constructed manually in main.rs.
33pub struct Apollo3DefaultPeripherals {
34    pub stimer: crate::stimer::STimer<'static>,
35    pub uart0: crate::uart::Uart<'static>,
36    pub uart1: crate::uart::Uart<'static>,
37    pub gpio_port: crate::gpio::Port<'static>,
38    pub iom0: crate::iom::Iom<'static>,
39    pub iom1: crate::iom::Iom<'static>,
40    pub iom2: crate::iom::Iom<'static>,
41    pub iom3: crate::iom::Iom<'static>,
42    pub iom4: crate::iom::Iom<'static>,
43    pub iom5: crate::iom::Iom<'static>,
44    pub ios: crate::ios::Ios<'static>,
45    pub ble: crate::ble::Ble<'static>,
46    pub flash_ctrl: crate::flashctrl::FlashCtrl<'static>,
47}
48
49impl Apollo3DefaultPeripherals {
50    pub fn new() -> Self {
51        Self {
52            stimer: crate::stimer::STimer::new(),
53            uart0: crate::uart::Uart::new_uart_0(),
54            uart1: crate::uart::Uart::new_uart_1(),
55            gpio_port: crate::gpio::Port::new(),
56            iom0: crate::iom::Iom::new0(),
57            iom1: crate::iom::Iom::new1(),
58            iom2: crate::iom::Iom::new2(),
59            iom3: crate::iom::Iom::new3(),
60            iom4: crate::iom::Iom::new4(),
61            iom5: crate::iom::Iom::new5(),
62            ios: crate::ios::Ios::new(),
63            ble: crate::ble::Ble::new(),
64            flash_ctrl: crate::flashctrl::FlashCtrl::new(),
65        }
66    }
67
68    pub fn init(&'static self) {
69        kernel::deferred_call::DeferredCallClient::register(&self.flash_ctrl);
70    }
71}
72
73impl kernel::platform::chip::InterruptService for Apollo3DefaultPeripherals {
74    unsafe fn service_interrupt(&self, interrupt: u32) -> bool {
75        use crate::nvic;
76        match interrupt {
77            nvic::STIMER..=nvic::STIMER_CMPR7 => self.stimer.handle_interrupt(),
78            nvic::UART0 => self.uart0.handle_interrupt(),
79            nvic::UART1 => self.uart1.handle_interrupt(),
80            nvic::GPIO => self.gpio_port.handle_interrupt(),
81            nvic::IOMSTR0 => self.iom0.handle_interrupt(),
82            nvic::IOMSTR1 => self.iom1.handle_interrupt(),
83            nvic::IOMSTR2 => self.iom2.handle_interrupt(),
84            nvic::IOMSTR3 => self.iom3.handle_interrupt(),
85            nvic::IOMSTR4 => self.iom4.handle_interrupt(),
86            nvic::IOMSTR5 => self.iom5.handle_interrupt(),
87            nvic::IOSLAVE | nvic::IOSLAVEACC => self.ios.handle_interrupt(),
88            nvic::BLE => self.ble.handle_interrupt(),
89            _ => return false,
90        }
91        true
92    }
93}
94
95impl<I: InterruptService + 'static> Chip for Apollo3<I> {
96    type MPU = cortexm4f::mpu::MPU;
97    type UserspaceKernelBoundary = cortexm4f::syscall::SysCall;
98
99    fn service_pending_interrupts(&self) {
100        unsafe {
101            while let Some(interrupt) = cortexm4f::nvic::next_pending() {
102                if !self.interrupt_service.service_interrupt(interrupt) {
103                    panic!("unhandled interrupt, {}", interrupt);
104                }
105
106                let n = cortexm4f::nvic::Nvic::new(interrupt);
107                n.clear_pending();
108                n.enable();
109            }
110        }
111    }
112
113    fn has_pending_interrupts(&self) -> bool {
114        unsafe { cortexm4f::nvic::has_pending() }
115    }
116
117    fn mpu(&self) -> &cortexm4f::mpu::MPU {
118        &self.mpu
119    }
120
121    fn userspace_kernel_boundary(&self) -> &cortexm4f::syscall::SysCall {
122        &self.userspace_kernel_boundary
123    }
124
125    fn sleep(&self) {
126        unsafe {
127            cortexm4f::scb::set_sleepdeep();
128            cortexm4f::support::wfi();
129        }
130    }
131
132    unsafe fn atomic<F, R>(&self, f: F) -> R
133    where
134        F: FnOnce() -> R,
135    {
136        cortexm4f::support::atomic(f)
137    }
138
139    unsafe fn print_state(&self, write: &mut dyn Write) {
140        CortexM4F::print_cortexm_state(write);
141    }
142}