cy8cproto_62_4243_w/
main.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
5#![no_std]
6#![no_main]
7#![deny(missing_docs)]
8
9//! Tock kernel for the CY8CPROTO-062-4343W.
10
11mod io;
12
13kernel::stack_size! {0x2000}
14
15use core::ptr::addr_of_mut;
16
17use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm;
18use components::led::LedsComponent;
19use kernel::component::Component;
20use kernel::hil::led::LedHigh;
21use kernel::platform::{KernelResources, SyscallDriverLookup};
22use kernel::process::ProcessArray;
23use kernel::scheduler::round_robin::RoundRobinSched;
24use kernel::{capabilities, create_capability, static_init};
25
26#[allow(unused)]
27use psoc62xa::{
28    chip::{PsoC62xaDefaultPeripherals, Psoc62xa},
29    gpio::GpioPin,
30    tcpwm::Tcpwm0,
31    BASE_VECTORS,
32};
33
34// State for loading and holding applications.
35// How should the kernel respond when a process faults.
36const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
37    capsules_system::process_policies::PanicFaultPolicy {};
38
39// Number of concurrent processes this platform supports.
40const NUM_PROCS: usize = 4;
41
42/// Static variables used by io.rs.
43static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
44static mut CHIP: Option<&'static Psoc62xa<PsoC62xaDefaultPeripherals>> = None;
45static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
46    None;
47
48/// Supported drivers by the platform
49pub struct Cy8cproto0624343w {
50    console: &'static capsules_core::console::Console<'static>,
51    alarm: &'static capsules_core::alarm::AlarmDriver<
52        'static,
53        VirtualMuxAlarm<'static, psoc62xa::tcpwm::Tcpwm0<'static>>,
54    >,
55    led: &'static capsules_core::led::LedDriver<'static, LedHigh<'static, GpioPin<'static>>, 1>,
56    button: &'static capsules_core::button::Button<'static, GpioPin<'static>>,
57    gpio: &'static capsules_core::gpio::GPIO<'static, psoc62xa::gpio::GpioPin<'static>>,
58    scheduler: &'static RoundRobinSched<'static>,
59    systick: cortexm0p::systick::SysTick,
60}
61
62impl SyscallDriverLookup for Cy8cproto0624343w {
63    fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
64    where
65        F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
66    {
67        match driver_num {
68            capsules_core::console::DRIVER_NUM => f(Some(self.console)),
69            capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
70            capsules_core::led::DRIVER_NUM => f(Some(self.led)),
71            capsules_core::button::DRIVER_NUM => f(Some(self.button)),
72            capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
73            _ => f(None),
74        }
75    }
76}
77
78impl KernelResources<Psoc62xa<'static, PsoC62xaDefaultPeripherals<'static>>> for Cy8cproto0624343w {
79    type SyscallDriverLookup = Self;
80    type SyscallFilter = ();
81    type ProcessFault = ();
82    type Scheduler = RoundRobinSched<'static>;
83    type SchedulerTimer = cortexm0p::systick::SysTick;
84    type WatchDog = ();
85    type ContextSwitchCallback = ();
86
87    fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
88        self
89    }
90    fn syscall_filter(&self) -> &Self::SyscallFilter {
91        &()
92    }
93    fn process_fault(&self) -> &Self::ProcessFault {
94        &()
95    }
96    fn scheduler(&self) -> &Self::Scheduler {
97        self.scheduler
98    }
99    fn scheduler_timer(&self) -> &Self::SchedulerTimer {
100        &self.systick
101    }
102    fn watchdog(&self) -> &Self::WatchDog {
103        &()
104    }
105    fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
106        &()
107    }
108}
109
110fn init_clocks(peripherals: &PsoC62xaDefaultPeripherals) {
111    peripherals.srss.init_clock();
112    peripherals.cpuss.init_clock();
113    peripherals.peri.init_uart_clock();
114    peripherals.peri.init_alarm_clock();
115}
116
117/// Main function called after RAM initialized.
118#[no_mangle]
119pub unsafe fn main() {
120    // Set the offset of the vector table
121    cortexm0p::scb::set_vector_table_offset(0x10000000 as *const ());
122
123    let peripherals = static_init!(
124        PsoC62xaDefaultPeripherals,
125        PsoC62xaDefaultPeripherals::new()
126    );
127
128    // Initialize clocks
129    init_clocks(peripherals);
130
131    // Enable interrupts
132    peripherals.cpuss.enable_int_for_scb5();
133    peripherals.cpuss.enable_int_for_tcpwm00();
134    peripherals.cpuss.enable_int_for_gpio0();
135    cortexm0p::nvic::enable_all();
136
137    //--------------------------------------------------------------------------
138    // UART & CONSOLE & DEBUG
139    //--------------------------------------------------------------------------
140
141    peripherals.scb.set_standard_uart_mode();
142    peripherals.scb.enable_scb();
143    peripherals.hsiom.enable_uart();
144    let uart_tx_pin = peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P5_1);
145    uart_tx_pin.configure_drive_mode(psoc62xa::gpio::DriveMode::Strong);
146    uart_tx_pin.configure_input(false);
147    let uart_rx_pin = peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P5_0);
148    uart_rx_pin.configure_drive_mode(psoc62xa::gpio::DriveMode::HighZ);
149    uart_rx_pin.configure_input(true);
150    let chip = static_init!(
151        Psoc62xa<PsoC62xaDefaultPeripherals>,
152        Psoc62xa::new(peripherals)
153    );
154
155    // Create an array to hold process references.
156    let processes = components::process_array::ProcessArrayComponent::new()
157        .finalize(components::process_array_component_static!(NUM_PROCS));
158    PROCESSES = Some(processes);
159
160    // Setup space to store the core kernel data structure.
161    let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
162
163    // Create a shared UART channel for kernel debug.
164    let uart_mux = components::console::UartMuxComponent::new(&peripherals.scb, 115200)
165        .finalize(components::uart_mux_component_static!());
166
167    let console = components::console::ConsoleComponent::new(
168        board_kernel,
169        capsules_core::console::DRIVER_NUM,
170        uart_mux,
171    )
172    .finalize(components::console_component_static!());
173    components::debug_writer::DebugWriterComponent::new(
174        uart_mux,
175        create_capability!(capabilities::SetDebugWriterCapability),
176    )
177    .finalize(components::debug_writer_component_static!());
178
179    //--------------------------------------------------------------------------
180    // ALARM & TIMER
181    //--------------------------------------------------------------------------
182    peripherals.tcpwm.init_timer();
183
184    let mux_alarm = components::alarm::AlarmMuxComponent::new(&peripherals.tcpwm)
185        .finalize(components::alarm_mux_component_static!(Tcpwm0));
186
187    let alarm = components::alarm::AlarmDriverComponent::new(
188        board_kernel,
189        capsules_core::alarm::DRIVER_NUM,
190        mux_alarm,
191    )
192    .finalize(components::alarm_component_static!(Tcpwm0));
193
194    //--------------------------------------------------------------------------
195    // PROCESS CONSOLE
196    //--------------------------------------------------------------------------
197    let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
198        .finalize(components::process_printer_text_component_static!());
199    PROCESS_PRINTER = Some(process_printer);
200
201    let process_console = components::process_console::ProcessConsoleComponent::new(
202        board_kernel,
203        uart_mux,
204        mux_alarm,
205        process_printer,
206        Some(cortexm0p::support::reset),
207    )
208    .finalize(components::process_console_component_static!(Tcpwm0));
209    let _ = process_console.start();
210
211    let led_pin = peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P13_7);
212
213    let led = LedsComponent::new().finalize(components::led_component_static!(
214        LedHigh<'static, GpioPin>,
215        LedHigh::new(led_pin)
216    ));
217
218    //--------------------------------------------------------------------------
219    // GPIO
220    //--------------------------------------------------------------------------
221
222    let gpio = components::gpio::GpioComponent::new(
223        board_kernel,
224        capsules_core::gpio::DRIVER_NUM,
225        components::gpio_component_helper!(
226            psoc62xa::gpio::GpioPin,
227            5 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P0_5),
228            44 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P5_4),
229            45 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P5_5),
230            46 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P5_6),
231            47 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P5_7),
232            50 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P6_2),
233            51 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P6_3),
234            52 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P6_4),
235            53 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P6_5),
236            64 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P8_0),
237            72 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P9_0),
238            73 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P9_1),
239            74 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P9_2),
240            76 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P9_4),
241            77 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P9_5),
242            78 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P9_6),
243            79 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P9_7),
244            96 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P12_0),
245            97 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P12_1),
246            99 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P12_3),
247            108 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P13_4),
248            110 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P13_6),
249        ),
250    )
251    .finalize(components::gpio_component_static!(psoc62xa::gpio::GpioPin));
252
253    //--------------------------------------------------------------------------
254    // BUTTON
255    //--------------------------------------------------------------------------
256
257    let button_pin = peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P0_4);
258
259    let button = components::button::ButtonComponent::new(
260        board_kernel,
261        capsules_core::button::DRIVER_NUM,
262        components::button_component_helper!(
263            GpioPin,
264            (
265                button_pin,
266                kernel::hil::gpio::ActivationMode::ActiveLow,
267                kernel::hil::gpio::FloatingState::PullNone
268            ),
269        ),
270    )
271    .finalize(components::button_component_static!(GpioPin));
272
273    //--------------------------------------------------------------------------
274    // FINAL SETUP AND BOARD BOOT
275    //--------------------------------------------------------------------------
276
277    let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
278        .finalize(components::round_robin_component_static!(NUM_PROCS));
279
280    let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
281
282    let cy8cproto0624343w = Cy8cproto0624343w {
283        console,
284        alarm,
285        scheduler,
286        led,
287        button,
288        gpio,
289        // Currently, the CPU runs at 8MHz, that being the frequency of the IMO.
290        systick: cortexm0p::systick::SysTick::new_with_calibration(8_000_000),
291    };
292
293    CHIP = Some(chip);
294    (*addr_of_mut!(io::WRITER)).set_scb(&peripherals.scb);
295
296    kernel::debug!("Initialization complete. Entering main loop.");
297
298    //--------------------------------------------------------------------------
299    // PROCESSES AND MAIN LOOP
300    //--------------------------------------------------------------------------
301
302    // These symbols are defined in the linker script.
303    extern "C" {
304        /// Beginning of the ROM region containing app images.
305        static _sapps: u8;
306        /// End of the ROM region containing app images.
307        static _eapps: u8;
308        /// Beginning of the RAM region for app memory.
309        static mut _sappmem: u8;
310        /// End of the RAM region for app memory.
311        static _eappmem: u8;
312    }
313
314    let process_management_capability =
315        create_capability!(capabilities::ProcessManagementCapability);
316
317    kernel::process::load_processes(
318        board_kernel,
319        chip,
320        core::slice::from_raw_parts(
321            core::ptr::addr_of!(_sapps),
322            core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
323        ),
324        core::slice::from_raw_parts_mut(
325            core::ptr::addr_of_mut!(_sappmem),
326            core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
327        ),
328        &FAULT_RESPONSE,
329        &process_management_capability,
330    )
331    .unwrap_or_else(|err| {
332        kernel::debug!("Error loading processes!");
333        kernel::debug!("{:?}", err);
334    });
335
336    board_kernel.kernel_loop(
337        &cy8cproto0624343w,
338        chip,
339        None::<kernel::ipc::IPC<{ NUM_PROCS as u8 }>>.as_ref(),
340        &main_loop_capability,
341    );
342}