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::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    type ThreadIdProvider = cortexm4f::thread_id::CortexMThreadIdProvider;
111
112    fn mpu(&self) -> &Self::MPU {
113        &self.mpu
114    }
115
116    fn userspace_kernel_boundary(&self) -> &Self::UserspaceKernelBoundary {
117        &self.userspace_kernel_boundary
118    }
119
120    fn service_pending_interrupts(&self) {
121        unsafe {
122            while 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            }
130        }
131    }
132
133    fn has_pending_interrupts(&self) -> bool {
134        unsafe { nvic::has_pending() }
135    }
136
137    fn sleep(&self) {
138        unsafe {
139            cortexm4f::support::wfi();
140        }
141    }
142
143    unsafe fn with_interrupts_disabled<F, R>(&self, f: F) -> R
144    where
145        F: FnOnce() -> R,
146    {
147        cortexm4f::support::with_interrupts_disabled(f)
148    }
149
150    unsafe fn print_state(&self, write: &mut dyn Write) {
151        CortexM4F::print_cortexm_state(write);
152    }
153}