ove/bsp.rs
1// Copyright (C) 2026 Kamil Lulko <kamil.lulko@gmail.com>
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4//
5// This file is part of oveRTOS.
6
7//! Backward-compatible BSP module — delegates to board, gpio, led modules.
8
9use crate::bindings;
10use crate::error::{Error, Result};
11
12// SAFETY (module-wide contract for the `unsafe { bindings::ove_*(...) }` FFI
13// calls below): any handle passed to the C API is non-null and refers to a
14// live RTOS object — wrapper constructors establish validity via
15// `Error::from_code`, and `Drop` (or an explicit `deinit`) is the only place
16// a handle is released. Pointer and slice arguments reference caller-owned
17// memory valid for the duration of the call; the C side copies whatever it
18// retains and does not alias them past return (verified against the
19// signatures in `include/ove/*.h`). Blocks that deviate — `transmute`, raw
20// pointer casts from user data, slice reconstruction via `from_raw_parts`,
21// or storing a callback across the FFI boundary — carry their own
22// `// SAFETY:` comment.
23
24/// Initialize the board support package.
25///
26/// # Errors
27/// Returns an error if any hardware peripheral fails to initialize.
28pub fn board_init() -> Result<()> {
29 let rc = unsafe { bindings::ove_board_init() };
30 Error::from_code(rc)
31}
32
33/// Toggle the state of an LED.
34pub fn led_toggle(led: u32) {
35 unsafe { bindings::ove_led_toggle(led) }
36}
37
38/// Set the state of an LED.
39pub fn led_set(led: u32, on: bool) {
40 unsafe { bindings::ove_led_set(led, on as i32) }
41}
42
43/// Set a GPIO pin's output level (`value`: 0 = low, non-zero = high).
44///
45/// # Errors
46/// Returns [`Error::InvalidParam`] if `port` or `pin` is out of range.
47pub fn gpio_set(port: u32, pin: u32, value: i32) -> Result<()> {
48 let rc = unsafe { bindings::ove_gpio_set(port, pin, value) };
49 Error::from_code(rc)
50}
51
52/// Read a GPIO pin input value. Returns 0 (low) or 1 (high) on success.
53///
54/// # Errors
55/// Returns [`Error::InvalidParam`] if `port` or `pin` is out of range.
56pub fn gpio_get(port: u32, pin: u32) -> Result<i32> {
57 let rc = unsafe { bindings::ove_gpio_get(port, pin) };
58 if rc < 0 {
59 Error::from_code(rc)?;
60 }
61 Ok(rc)
62}
63
64/// GPIO interrupt trigger mode (BSP re-export of [`gpio::GpioIrqMode`](crate::gpio::GpioIrqMode)).
65#[repr(u32)]
66#[derive(Debug, Copy, Clone, PartialEq, Eq)]
67pub enum GpioIrqMode {
68 /// Trigger on rising edge.
69 Rising = 0x01,
70 /// Trigger on falling edge.
71 Falling = 0x02,
72 /// Trigger on both edges.
73 Both = 0x03,
74}
75
76/// Register a GPIO interrupt callback.
77///
78/// # Safety
79/// The callback and user_data must remain valid for the lifetime of the
80/// registration.
81pub unsafe fn gpio_irq_register(
82 port: u32,
83 pin: u32,
84 mode: GpioIrqMode,
85 callback: bindings::ove_gpio_irq_cb,
86 user_data: *mut core::ffi::c_void,
87) -> Result<()> {
88 let rc = unsafe {
89 bindings::ove_gpio_irq_register(
90 port,
91 pin,
92 mode as bindings::ove_gpio_irq_mode_t,
93 callback,
94 user_data,
95 )
96 };
97 Error::from_code(rc)
98}
99
100/// Enable a previously registered GPIO interrupt.
101///
102/// # Errors
103/// Returns an error if the interrupt has not been registered or the pin is invalid.
104pub fn gpio_irq_enable(port: u32, pin: u32) -> Result<()> {
105 let rc = unsafe { bindings::ove_gpio_irq_enable(port, pin) };
106 Error::from_code(rc)
107}
108
109/// Disable a registered GPIO interrupt without removing the registration.
110///
111/// # Errors
112/// Returns an error if the interrupt has not been registered or the pin is invalid.
113pub fn gpio_irq_disable(port: u32, pin: u32) -> Result<()> {
114 let rc = unsafe { bindings::ove_gpio_irq_disable(port, pin) };
115 Error::from_code(rc)
116}