stm32f4xx/
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
12use crate::dma;
13use crate::nvic;
14
15use crate::chip_specific::chip_specs::ChipSpecs as ChipSpecsTrait;
16
17pub struct Stm32f4xx<'a, I: InterruptService + 'a> {
18    mpu: cortexm4f::mpu::MPU,
19    userspace_kernel_boundary: cortexm4f::syscall::SysCall,
20    interrupt_service: &'a I,
21}
22
23pub struct Stm32f4xxDefaultPeripherals<'a, ChipSpecs> {
24    pub adc1: crate::adc::Adc<'a>,
25    pub dac: crate::dac::Dac<'a>,
26    pub dma1_streams: [crate::dma::Stream<'a, dma::Dma1<'a>>; 8],
27    pub dma2_streams: [crate::dma::Stream<'a, dma::Dma2<'a>>; 8],
28    pub exti: &'a crate::exti::Exti<'a>,
29    pub flash: crate::flash::Flash<ChipSpecs>,
30    pub fsmc: crate::fsmc::Fsmc<'a>,
31    pub gpio_ports: crate::gpio::GpioPorts<'a>,
32    pub i2c1: crate::i2c::I2C<'a>,
33    pub clocks: &'a crate::clocks::Clocks<'a, ChipSpecs>,
34    pub spi3: crate::spi::Spi<'a>,
35    pub tim2: crate::tim2::Tim2<'a>,
36    pub usart1: crate::usart::Usart<'a, dma::Dma2<'a>>,
37    pub usart2: crate::usart::Usart<'a, dma::Dma1<'a>>,
38    pub usart3: crate::usart::Usart<'a, dma::Dma1<'a>>,
39}
40
41impl<'a, ChipSpecs: ChipSpecsTrait> Stm32f4xxDefaultPeripherals<'a, ChipSpecs> {
42    pub fn new(
43        clocks: &'a crate::clocks::Clocks<'a, ChipSpecs>,
44        exti: &'a crate::exti::Exti<'a>,
45        dma1: &'a dma::Dma1<'a>,
46        dma2: &'a dma::Dma2<'a>,
47    ) -> Self {
48        Self {
49            adc1: crate::adc::Adc::new(clocks),
50            clocks,
51            dac: crate::dac::Dac::new(clocks),
52            dma1_streams: dma::new_dma1_stream(dma1),
53            dma2_streams: dma::new_dma2_stream(dma2),
54            exti,
55            flash: crate::flash::Flash::new(),
56            fsmc: crate::fsmc::Fsmc::new(
57                [
58                    Some(crate::fsmc::FSMC_BANK1),
59                    None,
60                    Some(crate::fsmc::FSMC_BANK3),
61                    None,
62                ],
63                clocks,
64            ),
65            gpio_ports: crate::gpio::GpioPorts::new(clocks, exti),
66            i2c1: crate::i2c::I2C::new(clocks),
67            spi3: crate::spi::Spi::new(
68                crate::spi::SPI3_BASE,
69                crate::spi::SpiClock(crate::clocks::phclk::PeripheralClock::new(
70                    crate::clocks::phclk::PeripheralClockType::APB1(
71                        crate::clocks::phclk::PCLK1::SPI3,
72                    ),
73                    clocks,
74                )),
75                dma::Dma1Peripheral::SPI3_TX,
76                dma::Dma1Peripheral::SPI3_RX,
77            ),
78            tim2: crate::tim2::Tim2::new(clocks),
79            usart1: crate::usart::Usart::new_usart1(clocks),
80            usart2: crate::usart::Usart::new_usart2(clocks),
81            usart3: crate::usart::Usart::new_usart3(clocks),
82        }
83    }
84
85    // Setup any circular dependencies and register deferred calls
86    pub fn setup_circular_deps(&'static self) {
87        self.clocks.set_flash(&self.flash);
88        self.gpio_ports.setup_circular_deps();
89
90        // Note: Boards with a CAN bus present also need to register its
91        // deferred call.
92        kernel::deferred_call::DeferredCallClient::register(&self.usart1);
93        kernel::deferred_call::DeferredCallClient::register(&self.usart2);
94        kernel::deferred_call::DeferredCallClient::register(&self.usart3);
95        kernel::deferred_call::DeferredCallClient::register(&self.fsmc);
96    }
97}
98
99impl<ChipSpecs: ChipSpecsTrait> InterruptService for Stm32f4xxDefaultPeripherals<'_, ChipSpecs> {
100    unsafe fn service_interrupt(&self, interrupt: u32) -> bool {
101        match interrupt {
102            nvic::DMA1_Stream1 => self.dma1_streams
103                [dma::Dma1Peripheral::USART3_RX.get_stream_idx()]
104            .handle_interrupt(),
105            nvic::DMA1_Stream2 => {
106                self.dma1_streams[dma::Dma1Peripheral::SPI3_RX.get_stream_idx()].handle_interrupt()
107            }
108            nvic::DMA1_Stream3 => self.dma1_streams
109                [dma::Dma1Peripheral::USART3_TX.get_stream_idx()]
110            .handle_interrupt(),
111            nvic::DMA1_Stream5 => self.dma1_streams
112                [dma::Dma1Peripheral::USART2_RX.get_stream_idx()]
113            .handle_interrupt(),
114            nvic::DMA1_Stream6 => self.dma1_streams
115                [dma::Dma1Peripheral::USART2_TX.get_stream_idx()]
116            .handle_interrupt(),
117            nvic::DMA1_Stream7 => {
118                self.dma1_streams[dma::Dma1Peripheral::SPI3_TX.get_stream_idx()].handle_interrupt()
119            }
120
121            nvic::DMA2_Stream5 => self.dma2_streams
122                [dma::Dma2Peripheral::USART1_RX.get_stream_idx()]
123            .handle_interrupt(),
124            nvic::DMA2_Stream7 => self.dma2_streams
125                [dma::Dma2Peripheral::USART1_TX.get_stream_idx()]
126            .handle_interrupt(),
127
128            nvic::USART1 => self.usart1.handle_interrupt(),
129            nvic::USART2 => self.usart2.handle_interrupt(),
130            nvic::USART3 => self.usart3.handle_interrupt(),
131
132            nvic::ADC => self.adc1.handle_interrupt(),
133
134            nvic::I2C1_EV => self.i2c1.handle_event(),
135            nvic::I2C1_ER => self.i2c1.handle_error(),
136
137            nvic::SPI3 => self.spi3.handle_interrupt(),
138
139            nvic::EXTI0 => self.exti.handle_interrupt(),
140            nvic::EXTI1 => self.exti.handle_interrupt(),
141            nvic::EXTI2 => self.exti.handle_interrupt(),
142            nvic::EXTI3 => self.exti.handle_interrupt(),
143            nvic::EXTI4 => self.exti.handle_interrupt(),
144            nvic::EXTI9_5 => self.exti.handle_interrupt(),
145            nvic::EXTI15_10 => self.exti.handle_interrupt(),
146
147            nvic::TIM2 => self.tim2.handle_interrupt(),
148
149            _ => return false,
150        }
151        true
152    }
153}
154
155impl<'a, I: InterruptService + 'a> Stm32f4xx<'a, I> {
156    pub unsafe fn new(interrupt_service: &'a I) -> Self {
157        Self {
158            mpu: cortexm4f::mpu::MPU::new(),
159            userspace_kernel_boundary: cortexm4f::syscall::SysCall::new(),
160            interrupt_service,
161        }
162    }
163}
164
165impl<'a, I: InterruptService + 'a> Chip for Stm32f4xx<'a, I> {
166    type MPU = cortexm4f::mpu::MPU;
167    type UserspaceKernelBoundary = cortexm4f::syscall::SysCall;
168
169    fn service_pending_interrupts(&self) {
170        unsafe {
171            loop {
172                if let Some(interrupt) = cortexm4f::nvic::next_pending() {
173                    if !self.interrupt_service.service_interrupt(interrupt) {
174                        panic!("unhandled interrupt {}", interrupt);
175                    }
176
177                    let n = cortexm4f::nvic::Nvic::new(interrupt);
178                    n.clear_pending();
179                    n.enable();
180                } else {
181                    break;
182                }
183            }
184        }
185    }
186
187    fn has_pending_interrupts(&self) -> bool {
188        unsafe { cortexm4f::nvic::has_pending() }
189    }
190
191    fn mpu(&self) -> &cortexm4f::mpu::MPU {
192        &self.mpu
193    }
194
195    fn userspace_kernel_boundary(&self) -> &cortexm4f::syscall::SysCall {
196        &self.userspace_kernel_boundary
197    }
198
199    fn sleep(&self) {
200        unsafe {
201            cortexm4f::scb::unset_sleepdeep();
202            cortexm4f::support::wfi();
203        }
204    }
205
206    unsafe fn atomic<F, R>(&self, f: F) -> R
207    where
208        F: FnOnce() -> R,
209    {
210        cortexm4f::support::atomic(f)
211    }
212
213    unsafe fn print_state(&self, write: &mut dyn Write) {
214        CortexM4F::print_cortexm_state(write);
215    }
216}