psoc62xa/
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 OxidOS Automotive 2025 SRL.
4
5use kernel::platform::chip::Chip;
6use kernel::platform::chip::InterruptService;
7
8use crate::{cpuss, gpio, hsiom, peri, scb, srss, tcpwm};
9use cortexm0p::{CortexM0P, CortexMVariant};
10
11pub struct Psoc62xa<'a, I: InterruptService + 'a> {
12    mpu: cortexm0p::mpu::MPU,
13    userspace_kernel_boundary: cortexm0p::syscall::SysCall,
14    interrupt_service: &'a I,
15}
16
17impl<'a, I: InterruptService> Psoc62xa<'a, I> {
18    pub fn new(interrupt_service: &'a I) -> Self {
19        Self {
20            mpu: unsafe { cortexm0p::mpu::new() },
21            userspace_kernel_boundary: unsafe { cortexm0p::syscall::SysCall::new() },
22            interrupt_service,
23        }
24    }
25}
26
27impl<I: InterruptService> Chip for Psoc62xa<'_, I> {
28    type MPU = cortexm0p::mpu::MPU;
29    type UserspaceKernelBoundary = cortexm0p::syscall::SysCall;
30    type ThreadIdProvider = cortexm0p::thread_id::CortexMThreadIdProvider;
31
32    fn mpu(&self) -> &Self::MPU {
33        &self.mpu
34    }
35
36    fn sleep(&self) {
37        unsafe {
38            cortexm0p::support::wfi();
39        }
40    }
41
42    unsafe fn with_interrupts_disabled<F, R>(&self, f: F) -> R
43    where
44        F: FnOnce() -> R,
45    {
46        cortexm0p::support::with_interrupts_disabled(f)
47    }
48
49    unsafe fn print_state(&self, writer: &mut dyn core::fmt::Write) {
50        CortexM0P::print_cortexm_state(writer);
51    }
52
53    fn userspace_kernel_boundary(&self) -> &Self::UserspaceKernelBoundary {
54        &self.userspace_kernel_boundary
55    }
56
57    fn has_pending_interrupts(&self) -> bool {
58        unsafe { cortexm0p::nvic::has_pending() }
59    }
60
61    fn service_pending_interrupts(&self) {
62        unsafe {
63            while let Some(interrupt) = cortexm0p::nvic::next_pending() {
64                if !self.interrupt_service.service_interrupt(interrupt) {
65                    panic!("unhandled interrupt {}", interrupt);
66                }
67                let n = cortexm0p::nvic::Nvic::new(interrupt);
68                n.clear_pending();
69                n.enable();
70            }
71            while let Some(interrupt) = cortexm0p::nvic::next_pending() {
72                let nvic = cortexm0p::nvic::Nvic::new(interrupt);
73                nvic.clear_pending();
74                nvic.enable();
75            }
76        }
77    }
78}
79
80pub struct PsoC62xaDefaultPeripherals<'a> {
81    pub cpuss: cpuss::Cpuss,
82    pub gpio: gpio::PsocPins<'a>,
83    pub hsiom: hsiom::Hsiom,
84    pub peri: peri::Peri,
85    pub scb: scb::Scb<'a>,
86    pub srss: srss::Srss,
87    pub tcpwm: tcpwm::Tcpwm0<'a>,
88}
89
90impl PsoC62xaDefaultPeripherals<'_> {
91    pub fn new() -> Self {
92        Self {
93            cpuss: cpuss::Cpuss::new(),
94            gpio: gpio::PsocPins::new(),
95            hsiom: hsiom::Hsiom::new(),
96            peri: peri::Peri::new(),
97            scb: scb::Scb::new(),
98            srss: srss::Srss::new(),
99            tcpwm: tcpwm::Tcpwm0::new(),
100        }
101    }
102}
103
104impl InterruptService for PsoC62xaDefaultPeripherals<'_> {
105    unsafe fn service_interrupt(&self, interrupt: u32) -> bool {
106        match interrupt {
107            0 => {
108                self.scb.handle_interrupt();
109                self.tcpwm.handle_interrupt();
110            }
111            1 => {
112                // We use interrupt number 1 for GPIO so we don't
113                // check for all of the GPIO ports on every non-GPIO
114                // releated interrupt.
115                self.gpio.handle_interrupt();
116            }
117            _ => return false,
118        }
119        true
120    }
121}