diff --git a/cmake/Generic.cmake b/cmake/Generic.cmake new file mode 100644 index 0000000..46b37c9 --- /dev/null +++ b/cmake/Generic.cmake @@ -0,0 +1,18 @@ +#******************************************************************** +# _ _ _ +# _ __ | |_ _ | | __ _ | |__ ___ +# | '__|| __|(_)| | / _` || '_ \ / __| +# | | | |_ _ | || (_| || |_) |\__ \ +# |_| \__|(_)|_| \__,_||_.__/ |___/ +# +# www.rt-labs.com +# Copyright 2026 rt-labs AB, Sweden. +# +# This software is licensed under the terms of the BSD 3-clause +# license. See the file LICENSE distributed with this software for +# full license information. +#*******************************************************************/ + +if(ZEPHYR_BASE) + include(${CMAKE_CURRENT_LIST_DIR}/Zephyr.cmake) +endif() diff --git a/cmake/Zephyr.cmake b/cmake/Zephyr.cmake new file mode 100644 index 0000000..daa73a8 --- /dev/null +++ b/cmake/Zephyr.cmake @@ -0,0 +1,20 @@ +#******************************************************************** +# _ _ _ +# _ __ | |_ _ | | __ _ | |__ ___ +# | '__|| __|(_)| | / _` || '_ \ / __| +# | | | |_ _ | || (_| || |_) |\__ \ +# |_| \__|(_)|_| \__,_||_.__/ |___/ +# +# www.rt-labs.com +# Copyright 2026 rt-labs AB, Sweden. +# +# This software is licensed under the terms of the BSD 3-clause +# license. See the file LICENSE distributed with this software for +# full license information. +#*******************************************************************/ + +add_subdirectory(src/zephyr) + +set (OSAL_DEFAULT_SYSTEM + osal-zephyr + CACHE STRING ${OSAL_DEFAULT_SYSTEM_HELP_STRING}) diff --git a/src/zephyr/CMakeLists.txt b/src/zephyr/CMakeLists.txt new file mode 100644 index 0000000..8257c51 --- /dev/null +++ b/src/zephyr/CMakeLists.txt @@ -0,0 +1,56 @@ +#******************************************************************** +# _ _ _ +# _ __ | |_ _ | | __ _ | |__ ___ +# | '__|| __|(_)| | / _` || '_ \ / __| +# | | | |_ _ | || (_| || |_) |\__ \ +# |_| \__|(_)|_| \__,_||_.__/ |___/ +# +# www.rt-labs.com +# Copyright 2017 rt-labs AB, Sweden. +# +# This software is licensed under the terms of the BSD 3-clause +# license. See the file LICENSE distributed with this software for +# full license information. +#*******************************************************************/ + +set(_osal_sys osal-zephyr) +add_library(${_osal_sys}) + +add_dependencies(${_osal_sys} zephyr_generated_headers) + +target_compile_features(${_osal_sys} + PUBLIC + c_std_99 + ) + +target_sources(${_osal_sys} + PRIVATE + osal.c + osal_log.c + ) + +target_compile_options(${_osal_sys} + PRIVATE + -Wall + -Wextra + -Werror + -Wno-unused-parameter + ) + +target_link_libraries(${_osal_sys} + PUBLIC + osal-interface + PRIVATE + $ + $ + ) + +target_include_directories(${_osal_sys} + PRIVATE + sys + ) + +install( + TARGETS ${_osal_sys} + EXPORT OsalTargets + ) diff --git a/src/zephyr/README.md b/src/zephyr/README.md new file mode 100644 index 0000000..db52ee6 --- /dev/null +++ b/src/zephyr/README.md @@ -0,0 +1,35 @@ +# OSAL Zephyr backend + +## Required Kconfig options + +Applications linking against `osal` on Zephyr need the following in +their `prj.conf`: + +``` +CONFIG_HEAP_MEM_POOL_SIZE= +CONFIG_THREAD_STACK_INFO=y +CONFIG_DYNAMIC_THREAD=y +CONFIG_DYNAMIC_THREAD_ALLOC=y +CONFIG_EVENTS=y +CONFIG_THREAD_NAME=y +CONFIG_LOG=y +``` + +- `HEAP_MEM_POOL_SIZE`: backs `k_malloc`/`k_free`, used throughout `osal.c`. +- `THREAD_STACK_INFO`: required by `DYNAMIC_THREAD`. +- `DYNAMIC_THREAD` + `DYNAMIC_THREAD_ALLOC`: `os_thread_create()` takes a + runtime stack size, so stacks are heap-allocated via + `k_thread_stack_alloc()` rather than declared statically. +- `EVENTS`: backs `os_event_*()` (`k_event`). +- `THREAD_NAME`: `os_thread_create()` sets the Zephyr thread name from + its `name` argument. +- `LOG`: backs `os_log()` (`osal_log.c`). Without it, log calls compile + down to no-ops. + +## Linking + +Link against `osal` normally: + +```cmake +target_link_libraries(app PRIVATE osal) +``` diff --git a/src/zephyr/osal.c b/src/zephyr/osal.c new file mode 100644 index 0000000..be398cd --- /dev/null +++ b/src/zephyr/osal.c @@ -0,0 +1,279 @@ +/********************************************************************* + * _ _ _ + * _ __ | |_ _ | | __ _ | |__ ___ + * | '__|| __|(_)| | / _` || '_ \ / __| + * | | | |_ _ | || (_| || |_) |\__ \ + * |_| \__|(_)|_| \__,_||_.__/ |___/ + * + * www.rt-labs.com + * Copyright 2017 rt-labs AB, Sweden. + * + * This software is licensed under the terms of the BSD 3-clause + * license. See the file LICENSE distributed with this software for + * full license information. + ********************************************************************/ + +#include "osal.h" +#include "osal_sys.h" + +#include + +static k_timeout_t os_to_timeout (uint32_t time) +{ + return (time == OS_WAIT_FOREVER) ? K_FOREVER : K_MSEC (time); +} + +void * os_malloc (size_t size) +{ + return k_malloc (size); +} + +void os_free (void * ptr) +{ + k_free (ptr); +} + +static void os_thread_trampoline (void * p1, void * p2, void * p3) +{ + void (*entry) (void * arg) = p1; + + ARG_UNUSED (p3); + entry (p2); +} + +os_thread_t * os_thread_create ( + const char * name, + uint32_t priority, + size_t stacksize, + void (*entry) (void * arg), + void * arg) +{ + os_thread_t * thread; + k_tid_t tid; + + thread = k_malloc (sizeof (*thread)); + CC_ASSERT (thread != NULL); + + thread->stacksize = stacksize; + thread->stack = k_thread_stack_alloc (stacksize, 0); + CC_ASSERT (thread->stack != NULL); + + tid = k_thread_create ( + &thread->thread, + thread->stack, + stacksize, + os_thread_trampoline, + (void *)entry, + arg, + NULL, + priority, + 0, + K_NO_WAIT); + CC_ASSERT (tid != NULL); + + k_thread_name_set (tid, name); + + return thread; +} + +os_mutex_t * os_mutex_create (void) +{ + os_mutex_t * mutex; + + mutex = k_malloc (sizeof (*mutex)); + CC_ASSERT (mutex != NULL); + + k_mutex_init (&mutex->mutex); + + return mutex; +} + +void os_mutex_lock (os_mutex_t * mutex) +{ + k_mutex_lock (&mutex->mutex, K_FOREVER); +} + +void os_mutex_unlock (os_mutex_t * mutex) +{ + k_mutex_unlock (&mutex->mutex); +} + +void os_mutex_destroy (os_mutex_t * mutex) +{ + k_free (mutex); +} + +void os_usleep (uint32_t us) +{ + k_sleep (K_USEC (us)); +} + +uint32_t os_get_current_time_us (void) +{ + return (uint32_t)k_ticks_to_us_floor64 (k_uptime_ticks()); +} + +os_tick_t os_tick_current (void) +{ + return (os_tick_t)k_uptime_ticks(); +} + +os_tick_t os_tick_from_us (uint32_t us) +{ + return (os_tick_t)k_us_to_ticks_ceil64 (us); +} + +void os_tick_sleep (os_tick_t tick) +{ + k_sleep (K_TICKS ((k_ticks_t)tick)); +} + +os_sem_t * os_sem_create (size_t count) +{ + os_sem_t * sem; + + sem = k_malloc (sizeof (*sem)); + CC_ASSERT (sem != NULL); + + k_sem_init (&sem->sem, count, K_SEM_MAX_LIMIT); + + return sem; +} + +bool os_sem_wait (os_sem_t * sem, uint32_t time) +{ + return k_sem_take (&sem->sem, os_to_timeout (time)) != 0; +} + +void os_sem_signal (os_sem_t * sem) +{ + k_sem_give (&sem->sem); +} + +void os_sem_destroy (os_sem_t * sem) +{ + k_free (sem); +} + +os_event_t * os_event_create (void) +{ + os_event_t * event; + + event = k_malloc (sizeof (*event)); + CC_ASSERT (event != NULL); + + k_event_init (&event->event); + + return event; +} + +bool os_event_wait (os_event_t * event, uint32_t mask, uint32_t * value, uint32_t time) +{ + *value = k_event_wait (&event->event, mask, false, os_to_timeout (time)); + return *value == 0; +} + +void os_event_set (os_event_t * event, uint32_t value) +{ + k_event_post (&event->event, value); +} + +void os_event_clr (os_event_t * event, uint32_t value) +{ + k_event_clear (&event->event, value); +} + +void os_event_destroy (os_event_t * event) +{ + k_free (event); +} + +os_mbox_t * os_mbox_create (size_t size) +{ + os_mbox_t * mbox; + void ** buffer; + + mbox = k_malloc (sizeof (*mbox)); + CC_ASSERT (mbox != NULL); + + buffer = k_malloc (size * sizeof (void *)); + CC_ASSERT (buffer != NULL); + + k_msgq_init (&mbox->msgq, (char *)buffer, sizeof (void *), size); + mbox->buffer = buffer; + + return mbox; +} + +bool os_mbox_fetch (os_mbox_t * mbox, void ** msg, uint32_t time) +{ + return k_msgq_get (&mbox->msgq, msg, os_to_timeout (time)) != 0; +} + +bool os_mbox_post (os_mbox_t * mbox, void * msg, uint32_t time) +{ + return k_msgq_put (&mbox->msgq, &msg, os_to_timeout (time)) != 0; +} + +void os_mbox_destroy (os_mbox_t * mbox) +{ + k_msgq_purge (&mbox->msgq); + k_free (mbox->buffer); + k_free (mbox); +} + +static void os_timer_expiry (struct k_timer * ztimer) +{ + os_timer_t * timer = k_timer_user_data_get (ztimer); + + if (timer->fn) + { + timer->fn (timer, timer->arg); + } +} + +os_timer_t * os_timer_create ( + uint32_t us, + void (*fn) (os_timer_t *, void * arg), + void * arg, + bool oneshot) +{ + os_timer_t * timer; + + timer = k_malloc (sizeof (*timer)); + CC_ASSERT (timer != NULL); + + timer->fn = fn; + timer->arg = arg; + timer->us = us; + timer->oneshot = oneshot; + + k_timer_init (&timer->timer, os_timer_expiry, NULL); + k_timer_user_data_set (&timer->timer, timer); + + return timer; +} + +void os_timer_set (os_timer_t * timer, uint32_t us) +{ + timer->us = us; +} + +void os_timer_start (os_timer_t * timer) +{ + k_timer_start ( + &timer->timer, + K_USEC (timer->us), + timer->oneshot ? K_NO_WAIT : K_USEC (timer->us)); +} + +void os_timer_stop (os_timer_t * timer) +{ + k_timer_stop (&timer->timer); +} + +void os_timer_destroy (os_timer_t * timer) +{ + k_timer_stop (&timer->timer); + k_free (timer); +} diff --git a/src/zephyr/osal_log.c b/src/zephyr/osal_log.c new file mode 100644 index 0000000..e032f75 --- /dev/null +++ b/src/zephyr/osal_log.c @@ -0,0 +1,53 @@ +/********************************************************************* + * _ _ _ + * _ __ | |_ _ | | __ _ | |__ ___ + * | '__|| __|(_)| | / _` || '_ \ / __| + * | | | |_ _ | || (_| || |_) |\__ \ + * |_| \__|(_)|_| \__,_||_.__/ |___/ + * + * www.rt-labs.com + * Copyright 2017 rt-labs AB, Sweden. + * + * This software is licensed under the terms of the BSD 3-clause + * license. See the file LICENSE distributed with this software for + * full license information. + ********************************************************************/ + +#include "osal_log.h" + +#include +#include +#include + +LOG_MODULE_REGISTER (osal, LOG_LEVEL_DBG); + +void os_log_impl (uint8_t type, const char * fmt, ...) +{ + va_list list; + char msg[128]; + + va_start (list, fmt); + vsnprintf (msg, sizeof (msg), fmt, list); + va_end (list); + + switch (LOG_LEVEL_GET (type)) + { + case LOG_LEVEL_DEBUG: + LOG_DBG ("%s", msg); + break; + case LOG_LEVEL_INFO: + LOG_INF ("%s", msg); + break; + case LOG_LEVEL_WARNING: + LOG_WRN ("%s", msg); + break; + case LOG_LEVEL_ERROR: + case LOG_LEVEL_FATAL: + LOG_ERR ("%s", msg); + break; + default: + break; + } +} + +os_log_t os_log = os_log_impl; diff --git a/src/zephyr/sys/osal_sys.h b/src/zephyr/sys/osal_sys.h new file mode 100644 index 0000000..5b86584 --- /dev/null +++ b/src/zephyr/sys/osal_sys.h @@ -0,0 +1,66 @@ +/********************************************************************* + * _ _ _ + * _ __ | |_ _ | | __ _ | |__ ___ + * | '__|| __|(_)| | / _` || '_ \ / __| + * | | | |_ _ | || (_| || |_) |\__ \ + * |_| \__|(_)|_| \__,_||_.__/ |___/ + * + * www.rt-labs.com + * Copyright 2017 rt-labs AB, Sweden. + * + * This software is licensed under the terms of the BSD 3-clause + * license. See the file LICENSE distributed with this software for + * full license information. + ********************************************************************/ + +#ifndef OSAL_SYS_H +#define OSAL_SYS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef struct os_thread +{ + struct k_thread thread; + k_thread_stack_t * stack; + size_t stacksize; +} os_thread_t; + +typedef struct os_mutex +{ + struct k_mutex mutex; +} os_mutex_t; + +typedef struct os_sem +{ + struct k_sem sem; +} os_sem_t; + +typedef struct os_event +{ + struct k_event event; +} os_event_t; + +typedef struct os_mbox +{ + struct k_msgq msgq; + void ** buffer; +} os_mbox_t; + +typedef struct os_timer +{ + struct k_timer timer; + void (*fn) (struct os_timer *, void * arg); + void * arg; + uint32_t us; + bool oneshot; +} os_timer_t; + +#ifdef __cplusplus +} +#endif + +#endif /* OSAL_SYS_H */