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