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::debug::PanicResources;
21use kernel::hil::led::LedHigh;
22use kernel::platform::{KernelResources, SyscallDriverLookup};
23use kernel::scheduler::round_robin::RoundRobinSched;
24use kernel::utilities::single_thread_value::SingleThreadValue;
25use kernel::{capabilities, create_capability, static_init};
26
27#[allow(unused)]
28use psoc62xa::{
29    chip::{PsoC62xaDefaultPeripherals, Psoc62xa},
30    gpio::GpioPin,
31    tcpwm::Tcpwm0,
32    BASE_VECTORS,
33};
34
35// State for loading and holding applications.
36// How should the kernel respond when a process faults.
37const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
38    capsules_system::process_policies::PanicFaultPolicy {};
39
40// Number of concurrent processes this platform supports.
41const NUM_PROCS: usize = 4;
42
43type ChipHw = Psoc62xa<'static, PsoC62xaDefaultPeripherals<'static>>;
44type ProcessPrinterInUse = capsules_system::process_printer::ProcessPrinterText;
45
46/// Resources for when a board panics used by io.rs.
47static PANIC_RESOURCES: SingleThreadValue<PanicResources<ChipHw, ProcessPrinterInUse>> =
48    SingleThreadValue::new(PanicResources::new());
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    // Bind global variables to this thread.
131    PANIC_RESOURCES
132        .bind_to_thread_unsafe::<<ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider>();
133
134    let peripherals = static_init!(
135        PsoC62xaDefaultPeripherals,
136        PsoC62xaDefaultPeripherals::new()
137    );
138
139    // Initialize clocks
140    init_clocks(peripherals);
141
142    // Enable interrupts
143    peripherals.cpuss.enable_int_for_scb5();
144    peripherals.cpuss.enable_int_for_tcpwm00();
145    peripherals.cpuss.enable_int_for_gpio0();
146    cortexm0p::nvic::enable_all();
147
148    //--------------------------------------------------------------------------
149    // UART & CONSOLE & DEBUG
150    //--------------------------------------------------------------------------
151
152    peripherals.scb.set_standard_uart_mode();
153    peripherals.scb.enable_scb();
154    peripherals.hsiom.enable_uart();
155    let uart_tx_pin = peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P5_1);
156    uart_tx_pin.configure_drive_mode(psoc62xa::gpio::DriveMode::Strong);
157    uart_tx_pin.configure_input(false);
158    let uart_rx_pin = peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P5_0);
159    uart_rx_pin.configure_drive_mode(psoc62xa::gpio::DriveMode::HighZ);
160    uart_rx_pin.configure_input(true);
161    let chip = static_init!(
162        Psoc62xa<PsoC62xaDefaultPeripherals>,
163        Psoc62xa::new(peripherals)
164    );
165
166    // Create an array to hold process references.
167    let processes = components::process_array::ProcessArrayComponent::new()
168        .finalize(components::process_array_component_static!(NUM_PROCS));
169    PANIC_RESOURCES.get().map(|resources| {
170        resources.processes.put(processes.as_slice());
171    });
172
173    // Setup space to store the core kernel data structure.
174    let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
175
176    // Create a shared UART channel for kernel debug.
177    let uart_mux = components::console::UartMuxComponent::new(&peripherals.scb, 115200)
178        .finalize(components::uart_mux_component_static!());
179
180    let console = components::console::ConsoleComponent::new(
181        board_kernel,
182        capsules_core::console::DRIVER_NUM,
183        uart_mux,
184    )
185    .finalize(components::console_component_static!());
186    components::debug_writer::DebugWriterComponent::new_unsafe(
187        uart_mux,
188        create_capability!(capabilities::SetDebugWriterCapability),
189        || unsafe {
190            kernel::debug::initialize_debug_writer_wrapper_unsafe::<
191                <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
192            >();
193        },
194    )
195    .finalize(components::debug_writer_component_static!());
196
197    //--------------------------------------------------------------------------
198    // ALARM & TIMER
199    //--------------------------------------------------------------------------
200    peripherals.tcpwm.init_timer();
201
202    let mux_alarm = components::alarm::AlarmMuxComponent::new(&peripherals.tcpwm)
203        .finalize(components::alarm_mux_component_static!(Tcpwm0));
204
205    let alarm = components::alarm::AlarmDriverComponent::new(
206        board_kernel,
207        capsules_core::alarm::DRIVER_NUM,
208        mux_alarm,
209    )
210    .finalize(components::alarm_component_static!(Tcpwm0));
211
212    //--------------------------------------------------------------------------
213    // PROCESS CONSOLE
214    //--------------------------------------------------------------------------
215    let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
216        .finalize(components::process_printer_text_component_static!());
217    PANIC_RESOURCES.get().map(|resources| {
218        resources.printer.put(process_printer);
219    });
220
221    let process_console = components::process_console::ProcessConsoleComponent::new(
222        board_kernel,
223        uart_mux,
224        mux_alarm,
225        process_printer,
226        Some(cortexm0p::support::reset),
227    )
228    .finalize(components::process_console_component_static!(Tcpwm0));
229    let _ = process_console.start();
230
231    let led_pin = peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P13_7);
232
233    let led = LedsComponent::new().finalize(components::led_component_static!(
234        LedHigh<'static, GpioPin>,
235        LedHigh::new(led_pin)
236    ));
237
238    //--------------------------------------------------------------------------
239    // GPIO
240    //--------------------------------------------------------------------------
241
242    let gpio = components::gpio::GpioComponent::new(
243        board_kernel,
244        capsules_core::gpio::DRIVER_NUM,
245        components::gpio_component_helper!(
246            psoc62xa::gpio::GpioPin,
247            5 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P0_5),
248            44 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P5_4),
249            45 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P5_5),
250            46 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P5_6),
251            47 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P5_7),
252            50 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P6_2),
253            51 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P6_3),
254            52 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P6_4),
255            53 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P6_5),
256            64 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P8_0),
257            72 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P9_0),
258            73 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P9_1),
259            74 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P9_2),
260            76 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P9_4),
261            77 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P9_5),
262            78 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P9_6),
263            79 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P9_7),
264            96 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P12_0),
265            97 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P12_1),
266            99 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P12_3),
267            108 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P13_4),
268            110 => peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P13_6),
269        ),
270    )
271    .finalize(components::gpio_component_static!(psoc62xa::gpio::GpioPin));
272
273    //--------------------------------------------------------------------------
274    // BUTTON
275    //--------------------------------------------------------------------------
276
277    let button_pin = peripherals.gpio.get_pin(psoc62xa::gpio::PsocPin::P0_4);
278
279    let button = components::button::ButtonComponent::new(
280        board_kernel,
281        capsules_core::button::DRIVER_NUM,
282        components::button_component_helper!(
283            GpioPin,
284            (
285                button_pin,
286                kernel::hil::gpio::ActivationMode::ActiveLow,
287                kernel::hil::gpio::FloatingState::PullNone
288            ),
289        ),
290    )
291    .finalize(components::button_component_static!(GpioPin));
292
293    //--------------------------------------------------------------------------
294    // FINAL SETUP AND BOARD BOOT
295    //--------------------------------------------------------------------------
296
297    let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
298        .finalize(components::round_robin_component_static!(NUM_PROCS));
299
300    let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
301
302    let cy8cproto0624343w = Cy8cproto0624343w {
303        console,
304        alarm,
305        scheduler,
306        led,
307        button,
308        gpio,
309        // Currently, the CPU runs at 8MHz, that being the frequency of the IMO.
310        systick: cortexm0p::systick::SysTick::new_with_calibration(8_000_000),
311    };
312
313    PANIC_RESOURCES.get().map(|resources| {
314        resources.chip.put(chip);
315    });
316    (*addr_of_mut!(io::WRITER)).set_scb(&peripherals.scb);
317
318    kernel::debug!("Initialization complete. Entering main loop.");
319
320    //--------------------------------------------------------------------------
321    // PROCESSES AND MAIN LOOP
322    //--------------------------------------------------------------------------
323
324    // These symbols are defined in the linker script.
325    extern "C" {
326        /// Beginning of the ROM region containing app images.
327        static _sapps: u8;
328        /// End of the ROM region containing app images.
329        static _eapps: u8;
330        /// Beginning of the RAM region for app memory.
331        static mut _sappmem: u8;
332        /// End of the RAM region for app memory.
333        static _eappmem: u8;
334    }
335
336    let process_management_capability =
337        create_capability!(capabilities::ProcessManagementCapability);
338
339    kernel::process::load_processes(
340        board_kernel,
341        chip,
342        core::slice::from_raw_parts(
343            core::ptr::addr_of!(_sapps),
344            core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
345        ),
346        core::slice::from_raw_parts_mut(
347            core::ptr::addr_of_mut!(_sappmem),
348            core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
349        ),
350        &FAULT_RESPONSE,
351        &process_management_capability,
352    )
353    .unwrap_or_else(|err| {
354        kernel::debug!("Error loading processes!");
355        kernel::debug!("{:?}", err);
356    });
357
358    board_kernel.kernel_loop(
359        &cy8cproto0624343w,
360        chip,
361        None::<kernel::ipc::IPC<{ NUM_PROCS as u8 }>>.as_ref(),
362        &main_loop_capability,
363    );
364}