imxrt10xx/
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 cortexm7::{CortexM7, CortexMVariant};
9use kernel::debug;
10use kernel::platform::chip::{Chip, InterruptService};
11
12use crate::nvic;
13
14pub struct Imxrt10xx<I: InterruptService + 'static> {
15    mpu: cortexm7::mpu::MPU,
16    userspace_kernel_boundary: cortexm7::syscall::SysCall,
17    interrupt_service: &'static I,
18}
19
20impl<I: InterruptService + 'static> Imxrt10xx<I> {
21    pub unsafe fn new(interrupt_service: &'static I) -> Self {
22        Imxrt10xx {
23            mpu: cortexm7::mpu::MPU::new(),
24            userspace_kernel_boundary: cortexm7::syscall::SysCall::new(),
25            interrupt_service,
26        }
27    }
28}
29
30pub struct Imxrt10xxDefaultPeripherals {
31    pub iomuxc: crate::iomuxc::Iomuxc,
32    pub iomuxc_snvs: crate::iomuxc_snvs::IomuxcSnvs,
33    pub ccm: &'static crate::ccm::Ccm,
34    pub dcdc: crate::dcdc::Dcdc<'static>,
35    pub dma: crate::dma::Dma<'static>,
36    pub ccm_analog: crate::ccm_analog::CcmAnalog,
37    pub ports: crate::gpio::Ports<'static>,
38    pub lpi2c1: crate::lpi2c::Lpi2c<'static>,
39    pub lpuart1: crate::lpuart::Lpuart<'static>,
40    pub lpuart2: crate::lpuart::Lpuart<'static>,
41    pub gpt1: crate::gpt::Gpt1<'static>,
42    pub gpt2: crate::gpt::Gpt2<'static>,
43}
44
45impl Imxrt10xxDefaultPeripherals {
46    pub fn new(ccm: &'static crate::ccm::Ccm) -> Self {
47        Self {
48            iomuxc: crate::iomuxc::Iomuxc::new(),
49            iomuxc_snvs: crate::iomuxc_snvs::IomuxcSnvs::new(),
50            ccm,
51            dcdc: crate::dcdc::Dcdc::new(ccm),
52            dma: crate::dma::Dma::new(ccm),
53            ccm_analog: crate::ccm_analog::CcmAnalog::new(),
54            ports: crate::gpio::Ports::new(ccm),
55            lpi2c1: crate::lpi2c::Lpi2c::new_lpi2c1(ccm),
56            lpuart1: crate::lpuart::Lpuart::new_lpuart1(ccm),
57            lpuart2: crate::lpuart::Lpuart::new_lpuart2(ccm),
58            gpt1: crate::gpt::Gpt1::new_gpt1(ccm),
59            gpt2: crate::gpt::Gpt2::new_gpt2(ccm),
60        }
61    }
62}
63
64impl InterruptService for Imxrt10xxDefaultPeripherals {
65    unsafe fn service_interrupt(&self, interrupt: u32) -> bool {
66        match interrupt {
67            nvic::LPUART1 => self.lpuart1.handle_interrupt(),
68            nvic::LPUART2 => self.lpuart2.handle_interrupt(),
69            nvic::LPI2C1 => self.lpi2c1.handle_event(),
70            nvic::GPT1 => self.gpt1.handle_interrupt(),
71            nvic::GPT2 => self.gpt2.handle_interrupt(),
72            nvic::GPIO1_1 => self.ports.gpio1.handle_interrupt(),
73            nvic::GPIO1_2 => self.ports.gpio1.handle_interrupt(),
74            nvic::GPIO2_1 => self.ports.gpio2.handle_interrupt(),
75            nvic::GPIO2_2 => self.ports.gpio2.handle_interrupt(),
76            nvic::GPIO3_1 => self.ports.gpio3.handle_interrupt(),
77            nvic::GPIO3_2 => self.ports.gpio3.handle_interrupt(),
78            nvic::GPIO4_1 => self.ports.gpio4.handle_interrupt(),
79            nvic::GPIO4_2 => self.ports.gpio4.handle_interrupt(),
80            nvic::GPIO5_1 => self.ports.gpio5.handle_interrupt(),
81            nvic::GPIO5_2 => self.ports.gpio5.handle_interrupt(),
82            nvic::SNVS_LP_WRAPPER => debug!("Interrupt: SNVS_LP_WRAPPER"),
83            nvic::DMA0_16..=nvic::DMA15_31 => {
84                let low = (interrupt - nvic::DMA0_16) as usize;
85                let high = low + 16;
86                for channel in [&self.dma.channels[low], &self.dma.channels[high]] {
87                    if channel.is_interrupt() | channel.is_error() {
88                        channel.handle_interrupt();
89                    }
90                }
91            }
92            nvic::DMA_ERROR => {
93                while let Some(channel) = self.dma.error_channel() {
94                    channel.handle_interrupt();
95                }
96            }
97            _ => {
98                return false;
99            }
100        }
101        true
102    }
103}
104
105impl<I: InterruptService + 'static> Chip for Imxrt10xx<I> {
106    type MPU = cortexm7::mpu::MPU;
107    type UserspaceKernelBoundary = cortexm7::syscall::SysCall;
108
109    fn service_pending_interrupts(&self) {
110        unsafe {
111            loop {
112                if let Some(interrupt) = cortexm7::nvic::next_pending() {
113                    let handled = self.interrupt_service.service_interrupt(interrupt);
114                    assert!(handled, "Unhandled interrupt number {}", interrupt);
115                    let n = cortexm7::nvic::Nvic::new(interrupt);
116                    n.clear_pending();
117                    n.enable();
118                } else {
119                    break;
120                }
121            }
122        }
123    }
124
125    fn has_pending_interrupts(&self) -> bool {
126        unsafe { cortexm7::nvic::has_pending() }
127    }
128
129    fn mpu(&self) -> &cortexm7::mpu::MPU {
130        &self.mpu
131    }
132
133    fn userspace_kernel_boundary(&self) -> &cortexm7::syscall::SysCall {
134        &self.userspace_kernel_boundary
135    }
136
137    fn sleep(&self) {
138        unsafe {
139            cortexm7::scb::unset_sleepdeep();
140            cortexm7::support::wfi();
141        }
142    }
143
144    unsafe fn atomic<F, R>(&self, f: F) -> R
145    where
146        F: FnOnce() -> R,
147    {
148        cortexm7::support::atomic(f)
149    }
150
151    unsafe fn print_state(&self, write: &mut dyn Write) {
152        CortexM7::print_cortexm_state(write);
153    }
154}