1use 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}