lpc55s6x/
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 2025.
4
5//! Chip trait setup.
6use core::fmt::Write;
7use core::panic;
8
9use cortexm33::{CortexM33, CortexMVariant};
10use kernel::platform::chip::Chip;
11use kernel::platform::chip::InterruptService;
12
13use crate::ctimer0::LPCTimer;
14use crate::gpio::Pins;
15use crate::interrupts;
16use crate::uart::Uart;
17
18#[repr(u8)]
19pub enum Processor {
20    Processor0 = 0,
21    Processor1 = 1,
22}
23
24pub struct Lpc55s69<'a, I: InterruptService + 'a> {
25    mpu: cortexm33::mpu::MPU<8>,
26    userspace_kernel_boundary: cortexm33::syscall::SysCall,
27    interrupt_service: &'a I,
28}
29
30impl<'a, I: InterruptService> Lpc55s69<'a, I> {
31    pub unsafe fn new(interrupt_service: &'a I) -> Self {
32        Self {
33            mpu: cortexm33::mpu::new(),
34            userspace_kernel_boundary: cortexm33::syscall::SysCall::new(),
35            interrupt_service,
36        }
37    }
38}
39
40impl<I: InterruptService> Chip for Lpc55s69<'_, I> {
41    type MPU = cortexm33::mpu::MPU<8>;
42    type UserspaceKernelBoundary = cortexm33::syscall::SysCall;
43    type ThreadIdProvider = cortexm33::thread_id::CortexMThreadIdProvider;
44
45    fn service_pending_interrupts(&self) {
46        unsafe {
47            while let Some(interrupt) = cortexm33::nvic::next_pending() {
48                if !self.interrupt_service.service_interrupt(interrupt) {
49                    panic!("unhandled interrupt {}", interrupt);
50                }
51
52                let n = cortexm33::nvic::Nvic::new(interrupt);
53                n.clear_pending();
54                n.enable();
55            }
56        }
57    }
58
59    fn has_pending_interrupts(&self) -> bool {
60        unsafe { cortexm33::nvic::has_pending() }
61    }
62
63    fn mpu(&self) -> &Self::MPU {
64        &self.mpu
65    }
66
67    fn userspace_kernel_boundary(&self) -> &Self::UserspaceKernelBoundary {
68        &self.userspace_kernel_boundary
69    }
70
71    fn sleep(&self) {
72        unsafe {
73            cortexm33::support::wfi();
74        }
75    }
76
77    unsafe fn with_interrupts_disabled<F, R>(&self, f: F) -> R
78    where
79        F: FnOnce() -> R,
80    {
81        cortexm33::support::with_interrupts_disabled(f)
82    }
83
84    unsafe fn print_state(_this: Option<&Self>, writer: &mut dyn Write) {
85        CortexM33::print_cortexm_state(writer);
86    }
87}
88
89pub struct Lpc55s69DefaultPeripheral<'a> {
90    pub pins: Pins<'a>,
91    pub ctimer0: LPCTimer<'a>,
92    pub uart: Uart<'a>,
93}
94
95impl Lpc55s69DefaultPeripheral<'_> {
96    pub fn new() -> Self {
97        Self {
98            pins: Pins::new(),
99            ctimer0: LPCTimer::new(),
100            uart: Uart::new_uart0(),
101        }
102    }
103}
104
105impl InterruptService for Lpc55s69DefaultPeripheral<'_> {
106    unsafe fn service_interrupt(&self, interrupt: u32) -> bool {
107        match interrupt {
108            interrupts::GPIO_INT0_IRQ0 => {
109                self.pins.handle_interrupt();
110                true
111            }
112            interrupts::GPIO_INT0_IRQ1 => {
113                self.pins.handle_interrupt();
114                true
115            }
116
117            interrupts::GPIO_INT0_IRQ2 => {
118                self.pins.handle_interrupt();
119                true
120            }
121            interrupts::GPIO_INT0_IRQ3 => {
122                self.pins.handle_interrupt();
123                true
124            }
125            interrupts::GPIO_INT0_IRQ4 => {
126                self.pins.handle_interrupt();
127                true
128            }
129            interrupts::GPIO_INT0_IRQ5 => {
130                self.pins.handle_interrupt();
131                true
132            }
133            interrupts::GPIO_INT0_IRQ6 => {
134                self.pins.handle_interrupt();
135                true
136            }
137            interrupts::GPIO_INT0_IRQ7 => {
138                self.pins.handle_interrupt();
139                true
140            }
141
142            interrupts::CTIMER0 => {
143                self.ctimer0.handle_interrupt();
144                true
145            }
146
147            interrupts::FLEXCOMM0 => {
148                self.uart.handle_interrupt();
149                true
150            }
151
152            _ => true,
153        }
154    }
155}