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::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            loop {
102                if let Some(interrupt) = cortexm4f::nvic::next_pending() {
103                    if !self.interrupt_service.service_interrupt(interrupt) {
104                        panic!("unhandled interrupt, {}", interrupt);
105                    }
106
107                    let n = cortexm4f::nvic::Nvic::new(interrupt);
108                    n.clear_pending();
109                    n.enable();
110                } else {
111                    break;
112                }
113            }
114        }
115    }
116
117    fn has_pending_interrupts(&self) -> bool {
118        unsafe { cortexm4f::nvic::has_pending() }
119    }
120
121    fn mpu(&self) -> &cortexm4f::mpu::MPU {
122        &self.mpu
123    }
124
125    fn userspace_kernel_boundary(&self) -> &cortexm4f::syscall::SysCall {
126        &self.userspace_kernel_boundary
127    }
128
129    fn sleep(&self) {
130        unsafe {
131            cortexm4f::scb::set_sleepdeep();
132            cortexm4f::support::wfi();
133        }
134    }
135
136    unsafe fn atomic<F, R>(&self, f: F) -> R
137    where
138        F: FnOnce() -> R,
139    {
140        cortexm4f::support::atomic(f)
141    }
142
143    unsafe fn print_state(&self, write: &mut dyn Write) {
144        CortexM4F::print_cortexm_state(write);
145    }
146}