nrf52/
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
5use core::fmt::Write;
6use cortexm4f::{nvic, CortexM4F, CortexMVariant};
7use kernel::platform::chip::InterruptService;
8
9pub struct NRF52<'a, I: InterruptService + 'a> {
10    mpu: cortexm4f::mpu::MPU,
11    userspace_kernel_boundary: cortexm4f::syscall::SysCall,
12    interrupt_service: &'a I,
13}
14
15impl<'a, I: InterruptService + 'a> NRF52<'a, I> {
16    pub unsafe fn new(interrupt_service: &'a I) -> Self {
17        Self {
18            mpu: cortexm4f::mpu::MPU::new(),
19            userspace_kernel_boundary: cortexm4f::syscall::SysCall::new(),
20            interrupt_service,
21        }
22    }
23}
24
25/// This struct, when initialized, instantiates all peripheral drivers for the nrf52.
26///
27/// If a board wishes to use only a subset of these peripherals, this
28/// should not be used or imported, and a modified version should be
29/// constructed manually in main.rs.
30pub struct Nrf52DefaultPeripherals<'a> {
31    pub acomp: crate::acomp::Comparator<'a>,
32    pub ecb: crate::aes::AesECB<'a>,
33    pub pwr_clk: crate::power::Power<'a>,
34    pub ble_radio: crate::ble_radio::Radio<'a>,
35    pub trng: crate::trng::Trng<'a>,
36    pub rtc: crate::rtc::Rtc<'a>,
37    pub temp: crate::temperature::Temp<'a>,
38    pub timer0: crate::timer::TimerAlarm<'a>,
39    pub timer1: crate::timer::TimerAlarm<'a>,
40    pub timer2: crate::timer::Timer,
41    pub uarte0: crate::uart::Uarte<'a>,
42    pub spim0: crate::spi::SPIM<'a>,
43    pub twi1: crate::i2c::TWI<'a>,
44    pub spim2: crate::spi::SPIM<'a>,
45    pub adc: crate::adc::Adc<'a>,
46    pub nvmc: crate::nvmc::Nvmc,
47    pub clock: crate::clock::Clock,
48    pub pwm0: crate::pwm::Pwm,
49}
50
51impl Nrf52DefaultPeripherals<'_> {
52    pub fn new() -> Self {
53        Self {
54            acomp: crate::acomp::Comparator::new(),
55            ecb: crate::aes::AesECB::new(),
56            pwr_clk: crate::power::Power::new(),
57            ble_radio: crate::ble_radio::Radio::new(),
58            trng: crate::trng::Trng::new(),
59            rtc: crate::rtc::Rtc::new(),
60            temp: crate::temperature::Temp::new(),
61            timer0: crate::timer::TimerAlarm::new(0),
62            timer1: crate::timer::TimerAlarm::new(1),
63            timer2: crate::timer::Timer::new(2),
64            uarte0: crate::uart::Uarte::new(crate::uart::UARTE0_BASE),
65            spim0: crate::spi::SPIM::new(0),
66            twi1: crate::i2c::TWI::new_twi1(),
67            spim2: crate::spi::SPIM::new(2),
68            // Default to 3.3 V VDD reference.
69            adc: crate::adc::Adc::new(3300),
70            nvmc: crate::nvmc::Nvmc::new(),
71            clock: crate::clock::Clock::new(),
72            pwm0: crate::pwm::Pwm::new(),
73        }
74    }
75    // Necessary for setting up circular dependencies
76    pub fn init(&'static self) {
77        kernel::deferred_call::DeferredCallClient::register(&self.nvmc);
78    }
79}
80impl kernel::platform::chip::InterruptService for Nrf52DefaultPeripherals<'_> {
81    unsafe fn service_interrupt(&self, interrupt: u32) -> bool {
82        match interrupt {
83            crate::peripheral_interrupts::COMP => self.acomp.handle_interrupt(),
84            crate::peripheral_interrupts::ECB => self.ecb.handle_interrupt(),
85            crate::peripheral_interrupts::POWER_CLOCK => self.pwr_clk.handle_interrupt(),
86            crate::peripheral_interrupts::RADIO => match self.ble_radio.is_enabled() {
87                false => (),
88                true => self.ble_radio.handle_interrupt(),
89            },
90            crate::peripheral_interrupts::RNG => self.trng.handle_interrupt(),
91            crate::peripheral_interrupts::RTC1 => self.rtc.handle_interrupt(),
92            crate::peripheral_interrupts::TEMP => self.temp.handle_interrupt(),
93            crate::peripheral_interrupts::TIMER0 => self.timer0.handle_interrupt(),
94            crate::peripheral_interrupts::TIMER1 => self.timer1.handle_interrupt(),
95            crate::peripheral_interrupts::TIMER2 => self.timer2.handle_interrupt(),
96            crate::peripheral_interrupts::UART0 => self.uarte0.handle_interrupt(),
97            crate::peripheral_interrupts::SPI0_TWI0 => self.spim0.handle_interrupt(),
98            crate::peripheral_interrupts::SPI1_TWI1 => self.twi1.handle_interrupt(),
99            crate::peripheral_interrupts::SPIM2_SPIS2_SPI2 => self.spim2.handle_interrupt(),
100            crate::peripheral_interrupts::ADC => self.adc.handle_interrupt(),
101            _ => return false,
102        }
103        true
104    }
105}
106
107impl<'a, I: InterruptService + 'a> kernel::platform::chip::Chip for NRF52<'a, I> {
108    type MPU = cortexm4f::mpu::MPU;
109    type UserspaceKernelBoundary = cortexm4f::syscall::SysCall;
110
111    fn mpu(&self) -> &Self::MPU {
112        &self.mpu
113    }
114
115    fn userspace_kernel_boundary(&self) -> &Self::UserspaceKernelBoundary {
116        &self.userspace_kernel_boundary
117    }
118
119    fn service_pending_interrupts(&self) {
120        unsafe {
121            loop {
122                if let Some(interrupt) = nvic::next_pending() {
123                    if !self.interrupt_service.service_interrupt(interrupt) {
124                        panic!("unhandled interrupt {}", interrupt);
125                    }
126                    let n = nvic::Nvic::new(interrupt);
127                    n.clear_pending();
128                    n.enable();
129                } else {
130                    break;
131                }
132            }
133        }
134    }
135
136    fn has_pending_interrupts(&self) -> bool {
137        unsafe { nvic::has_pending() }
138    }
139
140    fn sleep(&self) {
141        unsafe {
142            cortexm4f::support::wfi();
143        }
144    }
145
146    unsafe fn atomic<F, R>(&self, f: F) -> R
147    where
148        F: FnOnce() -> R,
149    {
150        cortexm4f::support::atomic(f)
151    }
152
153    unsafe fn print_state(&self, write: &mut dyn Write) {
154        CortexM4F::print_cortexm_state(write);
155    }
156}