osal_rs/freertos/
ffi.rs

1/***************************************************************************
2 *
3 * osal-rs
4 * Copyright (C) 2023/2026 Antonio Salsi <passy.linux@zresa.it>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 *
18 ***************************************************************************/
19
20#![allow(non_upper_case_globals)]
21#![allow(non_snake_case)]
22
23use core::ffi::{c_char, c_uint, c_void};
24use core::ptr;
25
26use super::types::{BaseType, StackType, UBaseType, TickType, EventBits};
27
28pub type ThreadHandle = *const c_void;
29pub type QueueHandle = *const c_void;
30pub type SemaphoreHandle = *const c_void;
31pub type EventGroupHandle = *const c_void;
32pub type TimerHandle = *const c_void;
33pub type MutexHandle = *const c_void;
34pub type TimerCallback = unsafe extern "C" fn(timer: TimerHandle);
35pub type TaskState = c_uint;
36
37pub const RUNNING: TaskState = 0;
38pub const READY: TaskState = 1;
39pub const BLOCKED: TaskState = 2;
40pub const SUSPENDED: TaskState = 3;
41pub const DELETED: TaskState = 4;
42pub const INVALID: TaskState = 5;
43
44
45pub const pdFALSE: BaseType = 0;
46
47pub const pdTRUE: BaseType = 1;
48
49pub const pdPASS: BaseType = pdTRUE;
50
51pub const pdFAIL: BaseType = pdFALSE;
52
53pub const tskDEFAULT_INDEX_TO_NOTIFY: UBaseType = 0;
54
55pub const semBINARY_SEMAPHORE_QUEUE_LENGTH: u8 = 1;
56
57pub const semSEMAPHORE_QUEUE_ITEM_LENGTH: u8 = 0;
58
59pub const semGIVE_BLOCK_TIME: TickType = 0;
60
61pub const queueSEND_TO_BACK: BaseType = 0;
62
63pub const queueSEND_TO_FRONT: BaseType = 1;
64
65pub const queueOVERWRITE: BaseType = 2;
66
67pub const queueQUEUE_TYPE_BASE: u8 = 0;
68
69pub const queueQUEUE_TYPE_MUTEX: u8 = 1;
70
71pub const queueQUEUE_TYPE_COUNTING_SEMAPHORE: u8 = 2;
72
73pub const queueQUEUE_TYPE_BINARY_SEMAPHORE: u8 = 3;
74
75pub const queueQUEUE_TYPE_RECURSIVE_MUTEX: u8 = 4;
76
77pub const queueQUEUE_TYPE_SET: u8 = 5;
78
79
80
81#[repr(C)]
82#[derive(Debug, Copy, Clone)]
83pub struct TaskStatus {
84    pub xHandle: ThreadHandle,
85    pub pcTaskName: *const c_char,
86    pub xTaskNumber: UBaseType,
87    pub eCurrentState: TaskState,
88    pub uxCurrentPriority: UBaseType,
89    pub uxBasePriority: UBaseType,
90    pub ulRunTimeCounter: u32,
91    pub pxStackBase: *mut StackType,
92    pub usStackHighWaterMark: StackType
93}
94
95impl Default for TaskStatus {
96    fn default() -> Self {
97        TaskStatus {
98            xHandle: ptr::null(),
99            pcTaskName: ptr::null(),
100            xTaskNumber: 0,
101            eCurrentState: INVALID,
102            uxCurrentPriority: 0,
103            uxBasePriority: 0,
104            ulRunTimeCounter: 0,
105            pxStackBase: ptr::null_mut(),
106            usStackHighWaterMark: 0,
107        }
108    }
109}
110
111pub type TaskFunction = Option<unsafe extern "C" fn(arg: *mut c_void)>;
112
113unsafe extern "C" {
114    
115
116    /// Allocate memory from the  heap
117    /// 
118    /// # Arguments
119    /// * `size` - The number of bytes to allocate
120    /// 
121    /// # Returns
122    /// A pointer to the allocated memory, or null if allocation fails
123    pub fn pvPortMalloc(size: usize) -> *mut c_void;
124
125    /// Free memory previously allocated by pvPortMalloc
126    /// 
127    /// # Arguments
128    /// * `pv` - Pointer to the memory to free
129    pub fn vPortFree(pv: *mut c_void);
130
131    pub fn vTaskDelay(xTicksToDelay: TickType);
132
133    pub fn xTaskDelayUntil(
134        pxPreviousWakeTime: *mut TickType,
135        xTimeIncrement: TickType,
136    ) -> BaseType;
137
138
139    pub fn xTaskGetTickCount() -> TickType;
140
141    pub fn vTaskStartScheduler();
142
143    pub fn vTaskEndScheduler();
144
145    pub fn vTaskSuspendAll();
146
147    pub fn xTaskResumeAll() -> BaseType;
148
149    pub fn xTaskGetCurrentTaskHandle() -> ThreadHandle;
150
151    pub fn eTaskGetState(xTask: ThreadHandle) -> TaskState;
152
153    pub fn uxTaskGetNumberOfTasks() -> UBaseType;
154
155    pub fn uxTaskGetSystemState(
156        pxTaskStatusArray: *mut TaskStatus,
157        uxArraySize: UBaseType,
158        pulTotalRunTime: *mut u32,
159    ) -> UBaseType;
160
161    pub fn xTaskCreate(
162        pxTaskCode: TaskFunction,
163        pcName: *const c_char,
164        uxStackDepth: StackType,
165        pvParameters: *mut c_void,
166        uxPriority: UBaseType,
167        pxCreatedTask: *mut ThreadHandle,
168    ) -> BaseType;
169
170    pub fn vTaskDelete(xTaskToDelete: ThreadHandle);
171
172    pub fn vTaskSuspend(xTaskToSuspend: ThreadHandle);
173
174    pub fn vTaskResume(xTaskToResume: ThreadHandle);
175
176    pub fn vTaskGetInfo(
177        xTask: ThreadHandle,
178        pxTaskStatus: *mut TaskStatus,
179        xGetFreeStackSpace: BaseType,
180        eState: TaskState,
181    );
182
183    pub fn ulTaskGenericNotifyTake(uxIndexToWaitOn: UBaseType, xClearCountOnExit: BaseType, xTicksToWait: TickType) -> u32;
184
185
186    pub fn xTaskGenericNotifyWait(
187        uxIndexToWaitOn: UBaseType,
188        ulBitsToClearOnEntry: u32,
189        ulBitsToClearOnExit: u32,
190        pulNotificationValue: *mut u32,
191        xTicksToWait: TickType,
192    ) -> BaseType;
193
194
195    pub fn xTaskGenericNotify(
196        xTaskToNotify: ThreadHandle,
197        uxIndexToNotify: UBaseType,
198        ulValue: u32,
199        eAction: u32,
200        pulPreviousNotificationValue: *mut u32,
201    ) -> BaseType;
202
203
204    pub fn xTaskGenericNotifyFromISR(
205        xTaskToNotify: ThreadHandle,
206        uxIndexToNotify: UBaseType,
207        ulValue: u32,
208        eAction: u32,
209        pulPreviousNotificationValue: *mut u32,
210        pxHigherPriorityTaskWoken: *mut BaseType,
211    ) -> BaseType;
212    
213    pub fn xEventGroupWaitBits(
214        xEventGroup: EventGroupHandle,
215        uxBitsToWaitFor: EventBits,
216        xClearOnExit: BaseType,
217        xWaitForAllBits: BaseType,
218        xTicksToWait: TickType,
219    ) -> EventBits;
220
221    pub fn xEventGroupClearBits(
222        xEventGroup: EventGroupHandle,
223        uxBitsToClear: EventBits,
224    ) -> EventBits;
225
226    pub fn xEventGroupClearBitsFromISR(
227        xEventGroup: EventGroupHandle,
228        uxBitsToClear: EventBits,
229    ) -> BaseType;
230
231        pub fn xEventGroupSetBits(
232        xEventGroup: EventGroupHandle,
233        uxBitsToSet: EventBits,
234    ) -> EventBits;
235
236
237    pub fn xEventGroupSetBitsFromISR(
238        xEventGroup: EventGroupHandle,
239        uxBitsToSet: EventBits,
240        pxHigherPriorityTaskWoken: *mut BaseType,
241    ) -> BaseType;
242
243    pub fn xEventGroupGetBitsFromISR(xEventGroup: EventGroupHandle) -> EventBits;
244
245    pub fn vEventGroupDelete(xEventGroup: EventGroupHandle);
246
247    pub fn xEventGroupCreate() -> EventGroupHandle;
248
249    pub fn osal_rs_critical_section_enter();
250
251    pub fn osal_rs_critical_section_exit();
252
253    pub fn osal_rs_port_yield_from_isr(pxHigherPriorityTaskWoken: BaseType);
254
255    pub fn osal_rs_port_end_switching_isr( xSwitchRequired: BaseType );
256
257    pub fn xQueueCreateMutex(ucQueueType: u8) -> QueueHandle;
258    
259    pub fn xQueueCreateCountingSemaphore(
260        uxMaxCount: UBaseType,
261        uxInitialCount: UBaseType,
262    ) -> QueueHandle;
263
264    pub fn xQueueSemaphoreTake(xQueue: QueueHandle, xTicksToWait: TickType) -> BaseType;
265
266    pub fn xQueueReceiveFromISR(
267        xQueue: QueueHandle,
268        pvBuffer: *mut c_void,
269        pxHigherPriorityTaskWoken: *mut BaseType,
270    ) -> BaseType;
271
272    pub fn xQueueGenericSend(
273        xQueue: QueueHandle,
274        pvItemToQueue: *const c_void,
275        xTicksToWait: TickType,
276        xCopyPosition: BaseType,
277    ) -> BaseType;
278
279    pub fn xQueueGiveFromISR(
280        xQueue: QueueHandle,
281        pxHigherPriorityTaskWoken: *mut BaseType,
282    ) -> BaseType;
283
284     pub fn vQueueDelete(xQueue: QueueHandle);
285
286    pub fn xQueueGenericCreate(
287        uxQueueLength: UBaseType,
288        uxItemSize: UBaseType,
289        ucQueueType: u8,
290    ) -> QueueHandle;
291
292    pub fn xQueueReceive(
293        xQueue: QueueHandle,
294        pvBuffer: *mut c_void,
295        xTicksToWait: TickType,
296    ) -> BaseType;
297
298    pub fn xQueueGenericSendFromISR(
299        xQueue: QueueHandle,
300        pvItemToQueue: *const c_void,
301        pxHigherPriorityTaskWoken: *mut BaseType,
302        xCopyPosition: BaseType,
303    ) -> BaseType;
304
305    pub fn xQueueTakeMutexRecursive(xMutex: QueueHandle, xTicksToWait: TickType) -> BaseType;
306
307    pub fn xQueueGiveMutexRecursive(xMutex: QueueHandle) -> BaseType;
308
309    pub fn xPortGetFreeHeapSize() -> usize;
310
311    pub fn xTimerCreateTimerTask() -> BaseType;
312
313    pub fn xTimerCreate(
314        pcTimerName: *const c_char,
315        xTimerPeriodInTicks: TickType,
316        xAutoReload: BaseType,
317        pvTimerID: *mut c_void,
318        pxCallbackFunction: Option<TimerCallback>,
319    ) -> TimerHandle;
320
321    pub fn osal_rs_timer_start(xTimer: TimerHandle, xTicksToWait: TickType) -> BaseType;
322
323    pub fn osal_rs_timer_stop(xTimer: TimerHandle, xTicksToWait: TickType) -> BaseType;
324
325    pub fn osal_rs_timer_reset(xTimer: TimerHandle, xTicksToWait: TickType) -> BaseType;
326
327    pub fn osal_rs_timer_change_period(
328        xTimer: TimerHandle,
329        xNewPeriodInTicks: TickType,
330        xTicksToWait: TickType,
331    ) -> BaseType;
332
333    pub fn osal_rs_timer_delete(xTimer: TimerHandle, xTicksToWait: TickType) -> BaseType;
334
335    pub fn pvTimerGetTimerID(xTimer: TimerHandle) -> *mut c_void;
336
337    pub fn printf(fmt: *const u8, ...) -> i32; 
338}
339
340#[macro_export]
341macro_rules! ulTaskNotifyTake {
342    ($xClearCountOnExit:expr, $xTicksToWait:expr) => {
343        unsafe {
344            $crate::freertos::ffi::ulTaskGenericNotifyTake(
345                $crate::freertos::ffi::tskDEFAULT_INDEX_TO_NOTIFY,
346                $xClearCountOnExit,
347                $xTicksToWait
348            )
349        }
350    };
351}
352
353#[macro_export]
354macro_rules! xTaskNotifyWait {
355    ($ulBitsToClearOnEntry:expr, $ulBitsToClearOnExit:expr, $pulNotificationValue:expr, $xTicksToWait:expr) => {
356        unsafe {
357            $crate::freertos::ffi::xTaskGenericNotifyWait(
358                $crate::freertos::ffi::tskDEFAULT_INDEX_TO_NOTIFY,
359                $ulBitsToClearOnEntry,
360                $ulBitsToClearOnExit,
361                $pulNotificationValue,
362                $xTicksToWait
363            )
364        }
365    };
366}
367
368#[macro_export]
369macro_rules! xTaskNotify {
370    ($xTaskToNotify:expr, $ulValue:expr, $eAction:expr) => {
371        unsafe {
372            $crate::freertos::ffi::xTaskGenericNotify(
373                $xTaskToNotify,
374                $crate::freertos::ffi::tskDEFAULT_INDEX_TO_NOTIFY,
375                $ulValue,
376                $eAction,
377                core::ptr::null_mut()
378            )
379        }
380    };
381}
382
383#[macro_export]
384macro_rules! xTaskNotifyFromISR {
385    ($xTaskToNotify:expr, $ulValue:expr, $eAction:expr, $pxHigherPriorityTaskWoken:expr) => {
386        unsafe {
387            $crate::freertos::ffi::xTaskGenericNotifyFromISR(
388                $xTaskToNotify,
389                $crate::freertos::ffi::tskDEFAULT_INDEX_TO_NOTIFY,
390                $ulValue,
391                $eAction,
392                core::ptr::null_mut(),
393                $pxHigherPriorityTaskWoken
394            )
395        }
396    };
397}
398
399#[macro_export]
400macro_rules! xTaskNotifyAndQuery {
401    ($xTaskToNotify:expr, $ulValue:expr, $eAction:expr, $pulPreviousNotificationValue:expr) => {
402        unsafe {
403            $crate::freertos::ffi::xTaskGenericNotify(
404                $xTaskToNotify,
405                $crate::freertos::ffi::tskDEFAULT_INDEX_TO_NOTIFY,
406                $ulValue,
407                $eAction,
408                $pulPreviousNotificationValue
409            )
410        }
411    };
412}
413
414#[macro_export]
415macro_rules! vTaskDelayUntil {
416    ($pxPreviousWakeTime:expr, $xTimeIncrement:expr) => {
417        unsafe {
418            $crate::freertos::ffi::xTaskDelayUntil(
419                $pxPreviousWakeTime,
420                $xTimeIncrement
421            );
422        }
423    };
424}
425
426#[macro_export]
427macro_rules! xEventGroupGetBits {
428    ($xEventGroup:expr) => {
429        unsafe {
430            $crate::freertos::ffi::xEventGroupClearBits($xEventGroup, 0)
431        }
432    };
433}
434
435#[macro_export]
436macro_rules! xSemaphoreCreateCounting {
437    ($uxMaxCount:expr, $uxInitialCount:expr) => {
438        unsafe {
439            $crate::freertos::ffi::xQueueCreateCountingSemaphore(
440                $uxMaxCount,
441                $uxInitialCount
442            )
443        }
444    };
445}
446
447#[macro_export]
448macro_rules! xSemaphoreTake {
449    ($xSemaphore:expr, $xBlockTime:expr) => {
450        unsafe {
451            $crate::freertos::ffi::xQueueSemaphoreTake(
452                $xSemaphore,
453                $xBlockTime
454            )
455        }
456    };
457}
458
459#[macro_export]
460macro_rules! xSemaphoreTakeFromISR {
461    ($xSemaphore:expr, $pxHigherPriorityTaskWoken:expr) => {
462        unsafe {
463            $crate::freertos::ffi::xQueueReceiveFromISR(
464                $xSemaphore,
465                core::ptr::null_mut(),
466                $pxHigherPriorityTaskWoken
467            )
468        }
469    };
470}
471
472#[macro_export]
473macro_rules! xSemaphoreGive {
474    ($xSemaphore:expr) => {
475        unsafe {
476            $crate::freertos::ffi::xQueueGenericSend(
477                $xSemaphore,
478                core::ptr::null(),
479                $crate::freertos::ffi::semGIVE_BLOCK_TIME,
480                $crate::freertos::ffi::queueSEND_TO_BACK
481            )
482        }
483    };
484}
485
486#[macro_export]
487macro_rules! xSemaphoreGiveFromISR {
488    ($xSemaphore:expr, $pxHigherPriorityTaskWoken:expr) => {
489        unsafe {
490            $crate::freertos::ffi::xQueueGiveFromISR(
491                $xSemaphore,
492                $pxHigherPriorityTaskWoken
493            )
494        }
495    };
496}
497
498#[macro_export]
499macro_rules! vSemaphoreDelete {
500    ($xSemaphore:expr) => {
501        unsafe {
502            $crate::freertos::ffi::vQueueDelete($xSemaphore)
503        }
504    };
505}
506
507#[macro_export]
508macro_rules! xQueueCreate {
509    ($uxQueueLength:expr, $uxItemSize:expr) => {
510        unsafe {
511            $crate::freertos::ffi::xQueueGenericCreate(
512                $uxQueueLength,
513                $uxItemSize,
514                $crate::freertos::ffi::queueQUEUE_TYPE_BASE
515            )
516        }
517    };
518}
519
520#[macro_export]
521macro_rules! xQueueSendToBackFromISR {
522    ($xQueue:expr, $pvItemToQueue:expr, $pxHigherPriorityTaskWoken:expr) => {
523        unsafe {
524            $crate::freertos::ffi::xQueueGenericSendFromISR(
525                $xQueue,
526                $pvItemToQueue,
527                $pxHigherPriorityTaskWoken,
528                $crate::freertos::ffi::queueSEND_TO_BACK
529            )
530        }
531    };
532}
533
534#[macro_export]
535macro_rules! xQueueSendToBack {
536    ($xQueue:expr, $pvItemToQueue:expr, $xTicksToWait:expr) => {
537        unsafe {
538            $crate::freertos::ffi::xQueueGenericSend(
539                $xQueue,
540                $pvItemToQueue,
541                $xTicksToWait,
542                $crate::freertos::ffi::queueSEND_TO_BACK
543            )
544        }
545    };
546}
547
548#[macro_export]
549macro_rules! xSemaphoreCreateRecursiveMutex {
550    () => {
551        unsafe {
552            $crate::freertos::ffi::xQueueCreateMutex(
553                $crate::freertos::ffi::queueQUEUE_TYPE_RECURSIVE_MUTEX
554            )
555        }
556    };
557}
558
559#[macro_export]
560macro_rules! xSemaphoreTakeRecursive {
561    ($xMutex:expr, $xBlockTime:expr) => {
562        unsafe {
563            $crate::freertos::ffi::xQueueTakeMutexRecursive(
564                $xMutex,
565                $xBlockTime
566            )
567        }
568    };
569}
570
571#[macro_export]
572macro_rules! xSemaphoreGiveRecursive {
573    ($xMutex:expr) => {
574        unsafe {
575            $crate::freertos::ffi::xQueueGiveMutexRecursive($xMutex)
576        }
577    };
578}