diff --git a/.clang-format b/.clang-format index a4603b2..8ee6161 100644 --- a/.clang-format +++ b/.clang-format @@ -26,7 +26,7 @@ SpaceAfterCStyleCast: false SpaceBeforeAssignmentOperators: true SpacesBeforeTrailingComments: 1 -# Never fold short blocks — clarity over compactness. +# Never fold short blocks: clarity over compactness. AllowShortBlocksOnASingleLine: Never AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: None @@ -36,10 +36,10 @@ AllowShortLoopsOnASingleLine: false # Case labels align with the `switch` (existing code convention). IndentCaseLabels: false -# Don't reorder includes — a few headers depend on order today. +# Don't reorder includes: a few headers depend on order today. SortIncludes: Never -# Macros aligned in blocks — helpful for the RM `USEROBJMAN_DECLARE` family. +# Macros aligned in blocks: helpful for the RM `USEROBJMAN_DECLARE` family. AlignConsecutiveMacros: Consecutive AlignConsecutiveAssignments: None AlignConsecutiveDeclarations: None diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2bcb659..c449117 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -165,7 +165,7 @@ jobs: run: cmake --build build --target dmosal -j "$(nproc)" - name: Run clang-tidy over library sources run: | - files=$(git ls-files 'source/*.c' ':!source/zephyr') + files=$(git ls-files 'source/*.c' ':!source/zephyr' ':!source/freertos') clang-tidy -p build $files zephyr: @@ -194,6 +194,32 @@ jobs: - name: Build and run cmocka tests run: zephyr/docker.sh test + freertos: + name: freertos posix simulator (examples + tests) + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - name: Cache the FreeRTOS build image + id: image-cache + uses: actions/cache@v4 + with: + path: /tmp/dmosal-freertos.tar + key: freertos-image-${{ hashFiles('freertos/Dockerfile') }} + - name: Load cached image + if: steps.image-cache.outputs.cache-hit == 'true' + run: docker load -i /tmp/dmosal-freertos.tar + - name: Build the FreeRTOS image + if: steps.image-cache.outputs.cache-hit != 'true' + run: | + docker build -t dmosal-freertos:local -f freertos/Dockerfile freertos + docker save -o /tmp/dmosal-freertos.tar dmosal-freertos:local + - name: Build examples and tests + run: freertos/docker.sh build + - name: Run examples + run: freertos/docker.sh run + - name: Run cmocka tests + run: freertos/docker.sh test + docs: name: docs (build) runs-on: ubuntu-22.04 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d311444..aef826a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -23,6 +23,16 @@ repos: - id: clang-format types_or: [c, c++] + # Every C source and header must carry an SPDX license identifier. + - repo: local + hooks: + - id: spdx-license-header + name: SPDX license header + language: pygrep + entry: 'SPDX-License-Identifier: \S+' + args: [--negate] + files: \.(c|h)$|\.h\.in$ + # Manual stage: needs build/compile_commands.json. Run with `just tidy`. - repo: local hooks: @@ -30,5 +40,5 @@ repos: name: clang-tidy entry: clang-tidy -p build language: system - files: ^source/(?!zephyr/).*\.c$ + files: ^source/(?!zephyr/|freertos/).*\.c$ stages: [manual] diff --git a/CMakeLists.txt b/CMakeLists.txt index 542db1b..b625c2a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,7 +51,7 @@ set(DMOSAL_EXTRA_WARNING_FLAGS -Wmissing-prototypes ) -# Sanitizers / coverage — one flag string shared between compile and link. +# Sanitizers / coverage: one flag string shared between compile and link. set(_dm_extra "") if(DMOSAL_ENABLE_ASAN) set(_dm_extra "${_dm_extra} -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer -O1") @@ -70,7 +70,7 @@ endif() find_package(Threads REQUIRED) -# Explicit source list — new files require a cmake refresh (on purpose). +# Explicit source list: new files require a cmake refresh (on purpose). set(osal_SRC source/osal.c source/osal_error.c @@ -86,7 +86,7 @@ set(osal_SRC source/linux/osal_timer.c ) -# Generated headers live under the build tree — never in the source tree. +# Generated headers live under the build tree: never in the source tree. set(DMOSAL_GEN_DIR "${CMAKE_CURRENT_BINARY_DIR}/gen/dmosal") file(MAKE_DIRECTORY "${DMOSAL_GEN_DIR}") diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 369913d..93711bd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing -Contributions are welcome — bug reports, patches, or ideas. +Contributions are welcome: bug reports, patches, or ideas. ## Build and test @@ -10,10 +10,15 @@ cmake -S . -B build cmake --build build --target check ``` +Or use [`just`](https://github.com/casey/just): `just check`. Zephyr and FreeRTOS +backends are tested in Docker with `just zephyr-test` and `just freertos-test`. +CI runs all three, so please keep the portable tests in `test/osal/` free of +backend-specific code (put those in `test//`). + ## Style There's a `.clang-format` at the repo root. If you have clang-format handy, running -it over your changes keeps diffs tidy; if not, don't worry about it — CI will point +it over your changes keeps diffs tidy; if not, don't worry about it, CI will point out any drift. ## PRs diff --git a/README.md b/README.md index d03ad04..bdb737a 100644 --- a/README.md +++ b/README.md @@ -1,107 +1,92 @@ -# dmosal — OS Abstraction Layer +# dmosal: OS Abstraction Layer [![CI](https://github.com/drymon/osal/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/drymon/osal/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/drymon/osal/branch/main/graph/badge.svg)](https://codecov.io/gh/drymon/osal) [![License: BSD-2-Clause](https://img.shields.io/badge/License-BSD--2--Clause-blue.svg)](LICENSE) [![Language: C](https://img.shields.io/badge/language-C-brightgreen.svg)](#) -A small, portable embedded C abstraction layer providing deterministic/bounded -resource management and consistent concurrency, timing, and communication -semantics across POSIX and RTOS platforms. +A small, portable C abstraction layer for tasks, mutexes, semaphores, queues, +timers and time, with the same semantics on every supported OS. -Everything (tasks, mutexes, semaphores, queues, timers, ...) is allocated -statically up front through a central resource manager, so there's no malloc -on the hot path and the worst-case memory usage is known ahead of time. A -Linux backend and a Zephyr backend are included; other targets can be -added behind the same API without breaking existing callers. +All resources are statically allocated up front, so there is no `malloc` on +any hot path and worst-case memory use is known in advance. New backends can +be added behind the same API without breaking existing callers. -``` - +-------------------------------+ - | Application | - +-------------------------------+ - +--------------+----------------+ - | OSAL | libc | - +--------------+----------------+ - +-------------------------------+ - | OS User Space APIs | - +-------------------------------+ - +-------------------------------+ - | OS Kernel Space | - +-------------------------------+ - +-------------------------------+ - | HW | - +-------------------------------+ -``` +## Supported backends -## Getting started +| Backend | Source | Tested on | Details | +|----------|---------------------------------|------------------------------------|----------------------------------------| +| Linux | [source/linux/](source/linux/) | Native Linux (pthreads, POSIX IPC) | Quick start | +| Zephyr | [source/zephyr/](source/zephyr/) | `native_sim` virtual board (Docker) | [zephyr/README.md](zephyr/README.md) | +| FreeRTOS | [source/freertos/](source/freertos/) | POSIX/Linux simulator (Docker) | [freertos/README.md](freertos/README.md) | +| ... | your own, see [docs/porting.md](docs/porting.md) | | | -You'll need `cmake`, `libcmocka-dev`, and `doxygen`: +The same [examples](examples/) and [cmocka tests](test/) run unchanged on every +backend. The Zephyr and FreeRTOS targets need no hardware. More backends can be +added behind the same API. ``` -sudo apt install cmake libcmocka-dev doxygen ++-------------------------------+ +| Application | ++---------------+---------------+ +| dmosal | libc | ++---------------+---------------+ +| Linux | Zephyr | FreeRTOS | ...| ++-------------------------------+ ``` -Then build the library, run the tests, and check out the examples: +## Quick start + +Install the dependencies, then build and test on Linux: ``` -just check # configure + build + run tests -just build # build the examples target +sudo apt install cmake libcmocka-dev doxygen +just check # configure, build, run tests +just build # build the examples ``` -If you'd rather not install a toolchain locally, there's a pinned -[`Dockerfile`](Dockerfile): +No toolchain locally? Use the pinned [`Dockerfile`](Dockerfile): ``` docker build -t dmosal-dev . docker run --rm -v "$PWD":/workspace -w /workspace dmosal-dev just check ``` -Don't have [`just`](https://github.com/casey/just) installed? Check the -[`justfile`](justfile) — every recipe there is just a couple of plain -`cmake`/`ctest` commands you can run directly. - -There are a few more recipes worth knowing about: `just check-valgrind`, -`just check-asan`, `just check-tsan`, `just check-coverage`, `just doc`, -`just format`, `just tidy`. Run `just --list` to see everything. +Without [`just`](https://github.com/casey/just), the [`justfile`](justfile) +recipes are plain `cmake`/`ctest` commands you can run directly. -Resource limits (how many tasks, queues, etc. you get) are set at CMake -configure time — see [osal_config.cmake](osal_config.cmake). +Resource limits (number of tasks, queues, ...) are set at configure time in +[osal_config.cmake](osal_config.cmake). -## Zephyr +## Zephyr and FreeRTOS -dmosal also runs on [Zephyr RTOS](https://zephyrproject.org/) through a native -backend (`k_mutex`, `k_sem`, `k_thread`, `k_timer`, `k_msgq`) in -[source/zephyr/](source/zephyr/). The repo is a Zephyr module, and the same -programs from [examples/](examples/) build unchanged for Zephyr. It is tested -on the virtual `native_sim` board, so no hardware is needed, and everything -(including the Zephyr source) runs inside Docker: +Both run inside Docker, so no local SDK is needed: ``` -just zephyr-build # build the examples for Zephyr native_sim (Docker) -just zephyr-run # run the Zephyr examples -``` +just zephyr-build # build examples and tests for native_sim +just zephyr-run # run the examples +just zephyr-test # run the cmocka tests -See [zephyr/README.md](zephyr/README.md) for setup, configuration and how the -backend maps to Zephyr primitives. +just freertos-build # build examples and tests for the POSIX simulator +just freertos-run # run the examples +just freertos-test # run the cmocka tests +``` -## Examples +## Other recipes -Sample programs live in [examples/](examples/). Build them with `just build` -(CMake target `examples`) for Linux, or with `zephyr/docker.sh build` for -Zephyr. +`just check-valgrind`, `check-asan`, `check-tsan`, `check-coverage`, `doc`, +`format`, `tidy`. Run `just --list` for everything. ## Documentation -- API reference (Doxygen): run `just doc`, output ends up in - `build/doc/html/`. -- Design docs: [docs/](docs/README.md) — architecture, API spec, resource - lifetime, thread-safety, porting guide. +- API reference (Doxygen): `just doc` → `build/doc/html/`. +- Design docs: [docs/](docs/README.md) (architecture, API spec, lifetime, + thread safety, porting guide). ## Contributing -Bug reports, patches, ideas — all welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) -for how to build, test, and keep the style consistent. +See [CONTRIBUTING.md](CONTRIBUTING.md) for building, testing and style. ## License -BSD-2-Clause — see [LICENSE](LICENSE). +BSD-2-Clause. See [LICENSE](LICENSE). diff --git a/docs/README.md b/docs/README.md index 2479012..9fa2dae 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,15 +6,15 @@ Doxygen-generated API reference (built via `make doc`). | Document | What it covers | |---|---| | [architecture.md](architecture.md) | Layered design, subsystem overview, resource-manager pattern, callback threading model, backend model. | -| [api-spec.md](api-spec.md) | Behavioral specification per subsystem — functions, states, error codes, invariants. | +| [api-spec.md](api-spec.md) | Behavioral specification per subsystem: functions, states, error codes, invariants. | | [lifetime.md](lifetime.md) | Init/deinit ordering, resource ownership, when it is safe to use / release a resource. | | [porting.md](porting.md) | How to add a new backend (e.g. an RTOS or bare-metal target). Reference: the Linux backend. | | [thread-safety.md](thread-safety.md) | Per-API table classifying every public call as thread-safe, single-owner, or init-thread-only. | If you're just getting started, read them in this order: -1. `architecture.md` — the mental model -2. `thread-safety.md` — what you can and cannot call concurrently -3. `lifetime.md` — how resources come into existence and go away -4. `api-spec.md` — deeper look at each subsystem -5. `porting.md` — only if you're adding a new backend +1. `architecture.md`: the mental model +2. `thread-safety.md`: what you can and cannot call concurrently +3. `lifetime.md`: how resources come into existence and go away +4. `api-spec.md`: deeper look at each subsystem +5. `porting.md`: only if you're adding a new backend diff --git a/docs/api-spec.md b/docs/api-spec.md index f6093f7..f2b50c3 100644 --- a/docs/api-spec.md +++ b/docs/api-spec.md @@ -30,17 +30,17 @@ input. ## Top-level -`osal_init(osal_config_t *config)` — set up every subsystem. Pass `NULL` +`osal_init(osal_config_t *config)`, set up every subsystem. Pass `NULL` for defaults (stdout logger, INFO level for the internal `osal` module). Idempotent: a second call while already initialized returns `OSAL_E_OK` without touching state. -`osal_deinit(void)` — tear down every subsystem in reverse order. Idempotent +`osal_deinit(void)`, tear down every subsystem in reverse order. Idempotent in the "not initialized" case. -`osal_version(void)` — returns a static string. +`osal_version(void)`, returns a static string. -`osal_print_resource(void)` — dumps used/total counts for every pool to +`osal_print_resource(void)`, dumps used/total counts for every pool to the log module. ## Mutex @@ -48,42 +48,43 @@ the log module. State: `{ uninitialized, initialized-empty, initialized-with-mutexes-alive, uninitialized }`. -- `osal_mutex_init(void)` — sets up the mutex pool. Safe to call more than +- `osal_mutex_init(void)`: sets up the mutex pool. Safe to call more than once; subsequent calls are no-ops. -- `osal_mutex_deinit(void)` — releases the mutex pool. All mutexes must +- `osal_mutex_deinit(void)`: releases the mutex pool. All mutexes must have been deleted first. -- `osal_mutex_create(void)` — allocates a mutex; returns NULL if not +- `osal_mutex_create(void)`: allocates a mutex; returns NULL if not initialized or pool exhausted. -- `osal_mutex_delete(mutex)` — releases a mutex back to the pool. Behavior +- `osal_mutex_delete(mutex)`: releases a mutex back to the pool. Behavior undefined if any thread holds or is waiting on the mutex. -- `osal_mutex_lock(mutex)` / `osal_mutex_unlock(mutex)` — non-recursive. +- `osal_mutex_lock(mutex)` / `osal_mutex_unlock(mutex)`: non-recursive. Returns `OSAL_E_PARAM` on NULL, `OSAL_E_OSCALL` on backend failure (a real failure aborts via assert). -- `osal_mutex_use()` / `osal_mutex_avail()` — pool statistics. +- `osal_mutex_use()` / `osal_mutex_avail()`: pool statistics. ## Semaphore State machine: counter ≥ 0. `post` increments, `wait` decrements-or-blocks. -- `osal_sem_init(mutex)` — takes the shared mutex for pool protection. -- `osal_sem_deinit(void)` — tear down. -- `osal_sem_create(void)` — allocates a semaphore initialized with count 0. -- `osal_sem_delete(sem)` — releases. No thread may be blocked in wait. -- `osal_sem_post(sem)` — increments the counter (unblocks one waiter). -- `osal_sem_wait(sem)` — blocks until counter > 0, then decrements. No +- `osal_sem_init(mutex)`: takes the shared mutex for pool protection. +- `osal_sem_deinit(void)`: tear down. +- `osal_sem_create(void)`: allocates a semaphore initialized with count 0. +- `osal_sem_delete(sem)`: releases. No thread may be blocked in wait. +- `osal_sem_post(sem)`: increments the counter (unblocks one waiter). +- `osal_sem_wait(sem)`: blocks until counter > 0, then decrements. No timeout. -- `osal_sem_waittime(sem, usec)` — like `wait` but returns `OSAL_E_TIMEOUT` +- `osal_sem_waittime(sem, usec)`: like `wait` but returns `OSAL_E_TIMEOUT` after `usec` microseconds. ## Task -- `osal_task_init(mutex)` — pool init. -- `osal_task_deinit(void)` — pool tear-down. Does NOT stop running tasks. -- `osal_task_create(cfg)` — allocates a task slot and starts the handler - immediately on a new thread. `cfg->task_handler` must be non-NULL. Hints - in `cfg` (`stack_addr`, `stack_size`, `priority`, `name`) are - backend-dependent and may be ignored. -- `osal_task_delete(task)` — stops the task if still running, joins the +- `osal_task_init(mutex)`: pool init. +- `osal_task_deinit(void)`: pool tear-down. Does NOT stop running tasks. +- `osal_task_create(cfg)`: allocates a task slot and starts the handler + immediately on a new thread. `cfg->task_handler` must be non-NULL. Optional + fields in `cfg` (`stack_addr`, `stack_size`, `priority`, `name`) select the + backend default when 0 / empty. The Linux backend ignores them, Zephyr and + FreeRTOS use them (see `osal_task_cfg_t`). +- `osal_task_delete(task)`: stops the task if still running, joins the thread, releases the slot. Safe on a task whose handler has already returned. - `osal_task_use()` / `osal_task_avail()`. @@ -94,40 +95,40 @@ underlying thread exits and the slot remains "in use" until ## Timer -- `osal_timer_init(mutex)` — pool init. -- `osal_timer_deinit(void)` — tear-down. Callers must have deleted all +- `osal_timer_init(mutex)`: pool init. +- `osal_timer_deinit(void)`: tear-down. Callers must have deleted all active timers. -- `osal_timer_create(expire, arg)` — allocates a timer. The `expire` +- `osal_timer_create(expire, arg)`: allocates a timer. The `expire` callback is invoked from a backend-managed context (not the caller's thread). `expire` must be non-NULL. -- `osal_timer_start(timer, usec, repeat)` — arm the timer. First +- `osal_timer_start(timer, usec, repeat)`: arm the timer. First expiration in `usec` microseconds. If `repeat`, re-arms with the same interval after each expiration. `usec == 0` returns `OSAL_E_PARAM`. -- `osal_timer_stop(timer)` — disarm. Idempotent. -- `osal_timer_delete(timer)` — release. Asserts if called while the - callback is currently executing (from any thread). +- `osal_timer_stop(timer)`: disarm. Idempotent. +- `osal_timer_delete(timer)`: release. Logs an error and does nothing if + called while the callback is currently executing (from any thread). ## Queue -- `osal_queue_init(mutex)` — pool init. -- `osal_queue_deinit(void)` — tear-down. -- `osal_queue_create(cfg)` — allocates and opens or attaches a named +- `osal_queue_init(mutex)`: pool init. +- `osal_queue_deinit(void)`: tear-down. +- `osal_queue_create(cfg)`: allocates and opens or attaches a named queue. `cfg->name`, `cfg->msglen`, `cfg->qsize` must all be non-empty / non-zero. Attaching to an existing kernel queue with mismatched size fails. -- `osal_queue_delete(queue)` — close. If this handle originally created +- `osal_queue_delete(queue)`: close. If this handle originally created the underlying kernel queue, also unlinks it. -- `osal_queue_send(queue, msg, msglen)` — non-blocking. Returns +- `osal_queue_send(queue, msg, msglen)`: non-blocking. Returns `OSAL_E_QFULL` if the queue is full. -- `osal_queue_recv(queue, buf, bufsize, timeout_usec)` — blocks up to +- `osal_queue_recv(queue, buf, bufsize, timeout_usec)`: blocks up to `timeout_usec`. Returns `OSAL_E_TIMEOUT` on deadline elapse, `OSAL_E_QEMPTY` on empty wake (rare). ## Time -- `osal_sleep(sec)` / `osal_usleep(microsec)` — thread sleep. Ignore signal +- `osal_sleep(sec)` / `osal_usleep(microsec)`: thread sleep. Ignore signal interruption. -- `osal_clock_time(&nsec)` — monotonic clock in nanoseconds. Suitable for +- `osal_clock_time(&nsec)`: monotonic clock in nanoseconds. Suitable for measuring intervals; not a wall-clock timestamp. ## Log @@ -136,15 +137,15 @@ The log subsystem indexes log modules by integer, letting the application route different modules to different levels at runtime. Module index 0 is reserved for the library itself (`OSAL_LOG_MODULE_INDEX`). -- `osal_log_init(log_output)` — set the output function. `NULL` returns +- `osal_log_init(log_output)`: set the output function. `NULL` returns `OSAL_E_PARAM`. Subsequent calls (while already initialized) are no-ops. -- `osal_log_deinit(void)` — clears output + module table. -- `osal_log_module_init(idx, name, level, ts)` — reserve a module slot. +- `osal_log_deinit(void)`: clears output + module table. +- `osal_log_module_init(idx, name, level, ts)`: reserve a module slot. `ts=true` prepends a timestamp to every message from this module. Returns `OSAL_E_INUSE` if the slot is already registered. -- `osal_log_module_change(idx, level)` — cheap live level change (or +- `osal_log_module_change(idx, level)`: cheap live level change (or `OSALOG_LEVEL_NONE` to silence). -- `osal_log_print(idx, ts, level, format, ...)` — usually called via the +- `osal_log_print(idx, ts, level, format, ...)`: usually called via the `OSALOG_*` macros, which resolve to a per-source-file `OSALOG_MODULE` index. @@ -157,11 +158,11 @@ Public but rarely called directly by application code (subsystems use it internally). The `OSAL_RM_USEROBJMAN_DECLARE` / `_INIT` macros bundle the common pattern. -- `osal_rm_init(rm, cfg)` — with `cfg->mutex == NULL`, the RM is not +- `osal_rm_init(rm, cfg)`: with `cfg->mutex == NULL`, the RM is not thread-safe. -- `osal_rm_deinit(rm)` — resets the LIFO. Locks its mutex if it has one, +- `osal_rm_deinit(rm)`: resets the LIFO. Locks its mutex if it has one, so the mutex must still be valid at this call. -- `osal_rm_alloc(rm)` / `osal_rm_free(rm, resrc)` — pool ops. +- `osal_rm_alloc(rm)` / `osal_rm_free(rm, resrc)`: pool ops. - `osal_rm_use(rm)` / `osal_rm_avail(rm)`. ## LIFO @@ -174,17 +175,17 @@ LIFO is shared. Used by `osal_rm` as the free-list backing. Time-checkpoint utility for micro-benchmarking hot paths. See the `osal_tmcheck.h` header for details. `osal_tmcheck_capture_ts` records -"first-hit only" — subsequent captures on the same slot are no-ops until +"first-hit only": subsequent captures on the same slot are no-ops until `osal_tmcheck_reset` is called. Useful for capturing "first time this line ran" rather than "every time this line ran". ## Assert -`OSAL_RUNTIME_ASSERT(cond)` — if `cond` is false, print +`OSAL_RUNTIME_ASSERT(cond)`, if `cond` is false, print `assert::!!!` and abort. Can be overridden by defining `OSAL_RUNTIME_ASSERT` before including `osal_assert.h` (e.g. to redirect into a custom fault handler). -`OSAL_STATIC_ASSERT(cond)` — compile-time; usable at file scope. Not +`OSAL_STATIC_ASSERT(cond)`, compile-time; usable at file scope. Not usable more than once per translation unit with different `cond` values that would yield different array sizes. diff --git a/docs/architecture.md b/docs/architecture.md index 0edd6cf..36638a4 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -18,7 +18,7 @@ behaviour matters more than dynamic flexibility. | dmosal (public API) | +---------------+---------------+ | portable | backend | - | layer | (Linux...) | + | layer | (Linux, Zephyr, FreeRTOS, ...) | +---------------+---------------+ | OS user-space API | +-------------------------------+ @@ -28,14 +28,15 @@ behaviour matters more than dynamic flexibility. +-------------------------------+ ``` -- **Public API** — all `osal_*` symbols exposed via `include/dmosal/*.h`. +- **Public API**: all `osal_*` symbols exposed via `include/dmosal/*.h`. Backend-agnostic; no POSIX / RTOS-specific names leak into headers. -- **Portable layer** — `source/*.c`. Data structures and logic shared +- **Portable layer**: `source/*.c`. Data structures and logic shared across every backend (resource manager, LIFO free-list, error strings, logging, time-checkpoint utility, top-level init). -- **Backend** — `source//*.c`. Only these files touch OS-specific +- **Backend**: `source//*.c`. Only these files touch OS-specific APIs. The Linux backend under `source/linux/` is the reference - implementation. + implementation; `source/zephyr/` and `source/freertos/` are the RTOS + backends. ## Subsystems @@ -45,7 +46,7 @@ static resource pool. | Subsystem | Public header | What it provides | |---|---|---| | Top-level | `osal.h` | `osal_init`, `osal_deinit`, config, version, resource print. | -| Mutex | `osal_mutex.h` | Recursive-free lock. Also used to serialize other subsystems' resource pools. | +| Mutex | `osal_mutex.h` | Mutual-exclusion lock. Recursion is backend-specific (recursive on Zephyr, not on Linux or FreeRTOS). Also used to serialize other subsystems' resource pools. | | Semaphore | `osal_sem.h` | Counting semaphore with timed wait. | | Task | `osal_task.h` | Thread/task with a handler function. | | Timer | `osal_timer.h` | One-shot or periodic timer. Callback runs on a backend-managed context. | @@ -90,11 +91,12 @@ deletes are rare (init/shutdown) and avoids per-subsystem locking overhead. Two subsystems invoke user code from a thread other than the caller's: -- **Task** — `osal_task_create(cfg)` spawns a new thread that runs +- **Task**: `osal_task_create(cfg)` spawns a new thread that runs `cfg->task_handler`. The handler runs to completion on that thread. -- **Timer** — the timer callback fires on a backend-managed context, not +- **Timer**: the timer callback fires on a backend-managed context, not the caller's thread. On the Linux backend that means a fresh helper - thread per expiration (via `SIGEV_THREAD`). User code must not assume + thread per expiration (via `SIGEV_THREAD`), on Zephyr the system work + queue, on FreeRTOS the timer service task. User code must not assume any particular thread identity inside the callback. Everything else (mutex lock/unlock, semaphore post/wait, queue send/recv, diff --git a/docs/lifetime.md b/docs/lifetime.md index 18d87bf..0b44d97 100644 --- a/docs/lifetime.md +++ b/docs/lifetime.md @@ -1,6 +1,6 @@ # Resource lifetime -`dmosal` is a static-allocation library — every resource comes from a +`dmosal` is a static-allocation library, every resource comes from a compile-time-sized pool. Understanding when resources come into existence, when they can be used, and when they must be released is critical, because the layer intentionally does very little runtime bookkeeping to catch @@ -15,7 +15,7 @@ misuse. osal_init(cfg) (1) library goes live | v - < resources created — mutex/sem/task/timer/queue/tmcheck > + < resources created, mutex/sem/task/timer/queue/tmcheck > | v < runtime: locks, sends, timer callbacks, task handlers, ... > @@ -34,13 +34,13 @@ misuse. - After (2), no `osal_*` call is safe (except a subsequent `osal_init` that reinitializes the whole layer). -## `osal_init` — what happens +## `osal_init`: what happens `osal_init(config)` initializes subsystems in this order: -1. `osal_mutex_init` — the mutex pool must come first because every other +1. `osal_mutex_init`: the mutex pool must come first because every other subsystem uses a shared mutex from that pool. -2. `osal_log_init(log_output)` — the log sink is set. Default writes to +2. `osal_log_init(log_output)`: the log sink is set. Default writes to stdout. **After this point** the `OSALOG_*` macros produce output. 3. `osal_log_module_init(OSAL_LOG_MODULE_INDEX, "osal", level, false)` registers the library's internal logging module. @@ -48,26 +48,26 @@ misuse. The library holds a private reference in `s_shared_mutex`. 5. `osal_sem_init(s_shared_mutex)`, then `osal_task_init(...)`, `osal_timer_init(...)`, `osal_queue_init(...)`, `osal_tmcheck_init(...)` - — every pool gets the shared mutex so pool operations are serialized. + every pool gets the shared mutex so pool operations are serialized. If any step fails, the library aborts via `OSAL_RUNTIME_ASSERT`. In practice the underlying subsystems only fail when the corresponding pool is misconfigured (size 0), so this rarely fires. -## `osal_deinit` — order matters +## `osal_deinit`: order matters Tear-down is the reverse of init, and the **order is significant** because the subsystem pools reference the shared mutex: 1. `osal_sem_deinit`, `osal_task_deinit`, `osal_timer_deinit`, - `osal_queue_deinit`, `osal_tmcheck_deinit` — each of these calls + `osal_queue_deinit`, `osal_tmcheck_deinit`, each of these calls `osal_rm_deinit(...)` which locks the shared mutex. -2. `osal_log_deinit` — independent of the shared mutex. -3. `osal_mutex_delete(s_shared_mutex)` — return the shared mutex to its - pool. **This must come after step 1** — deleting the shared mutex +2. `osal_log_deinit`: independent of the shared mutex. +3. `osal_mutex_delete(s_shared_mutex)`: return the shared mutex to its + pool. **This must come after step 1**, deleting the shared mutex first would leave the subsystems' `osal_rm_deinit` locking a destroyed mutex. (An early version of the library had this bug.) -4. `osal_mutex_deinit` — tear down the mutex pool itself. +4. `osal_mutex_deinit`: tear down the mutex pool itself. **Rule of thumb**: only call `osal_deinit` once the application has quiesced. In particular: @@ -78,7 +78,7 @@ quiesced. In particular: - No thread may be inside `osal_queue_send/recv`, `osal_sem_wait`, `osal_mutex_lock`, etc. -`dmosal` does not attempt to force this — callers are responsible for +`dmosal` does not attempt to force this, callers are responsible for serializing shutdown against runtime activity. ## Per-resource lifecycle @@ -91,7 +91,7 @@ create -> [locked/unlocked N times] -> delete `osal_mutex_create()` returns a pointer valid until the matching `osal_mutex_delete()`. No thread may hold or attempt to lock the mutex -during delete — the library does not check this. +during delete, the library does not check this. ### Semaphore @@ -112,7 +112,7 @@ create --spawns--> [task_handler running on its own thread] --returns--> - `osal_task_create` starts the handler immediately. - `osal_task_delete` cancels the thread (if still running) and joins it. -- Deleting a task whose handler has already returned normally is safe — +- Deleting a task whose handler has already returned normally is safe: cancel is a no-op, join reaps the exit status. ### Timer @@ -122,8 +122,8 @@ create -> [started/stopped, callback fires 0+ times] -> stop -> delete ``` - `osal_timer_delete` **must not** be called while the callback is - running. The library detects and aborts on this — see - [thread-safety.md](thread-safety.md). + running. The library detects this, logs an error and ignores the + call, see [thread-safety.md](thread-safety.md). - Recommended pattern: `osal_timer_stop(t)`; ensure any in-flight callback has returned; `osal_timer_delete(t)`. @@ -147,7 +147,7 @@ create -> [capture_ts / reset / print] -> delete Diagnostic-only. Concurrent create/delete are internally serialized; concurrent capture/print/get with a delete may see inconsistent state -(deliberate design choice — see [thread-safety.md](thread-safety.md)). +(deliberate design choice, see [thread-safety.md](thread-safety.md)). ## Static-vs-dynamic ownership @@ -158,8 +158,8 @@ without further pool ops. - This makes lifetime analysis local: each resource is created once, used until shutdown, and (optionally) deleted at the very end. -Dynamic create/delete during operation is legal — the pools are -thread-safe — but it makes lifetime reasoning harder and is not the +Dynamic create/delete during operation is legal, the pools are +thread-safe, but it makes lifetime reasoning harder and is not the intended primary use case. There is currently no API to lock a resource manager into a "no more creates/deletes" runtime-only mode; that is purely a usage convention, not something the library enforces. @@ -168,7 +168,7 @@ purely a usage convention, not something the library enforces. - Detect use-after-delete on a resource handle. - Detect double-delete on the same handle (in most subsystems). Tmcheck - is the one exception — it guards `osal_tmcheck_delete` against + is the one exception, it guards `osal_tmcheck_delete` against double-decrement. - Cancel outstanding timer callbacks on `osal_deinit`. - Reap task threads on `osal_deinit` if you skipped `osal_task_delete`. diff --git a/docs/porting.md b/docs/porting.md index 5d3c1e3..be9467f 100644 --- a/docs/porting.md +++ b/docs/porting.md @@ -1,12 +1,14 @@ # Porting guide `dmosal`'s design isolates OS-specific code into a **backend** directory -under `source/`. The rest of the library — the resource manager, LIFO, -logging, error strings, tmcheck, and top-level init — is portable C and +under `source/`. The rest of the library, the resource manager, LIFO, +logging, error strings, tmcheck, and top-level init, is portable C and unchanged across backends. The reference implementation lives at `source/linux/` and targets Linux / -glibc. This document walks through what a new backend must provide. +glibc. `source/zephyr/` and `source/freertos/` are two RTOS backends +(see `zephyr/README.md` and `freertos/README.md`). This document walks +through what a new backend must provide. ## Files a backend must implement @@ -21,7 +23,7 @@ All six live in `source//`: | `osal_queue.c` | `osal_queue_init`, `osal_queue_deinit`, `osal_queue_create`, `osal_queue_delete`, `osal_queue_send`, `osal_queue_recv`, `osal_queue_use`, `osal_queue_avail`. | | `osal_time.c` | `osal_sleep`, `osal_usleep`, `osal_clock_time`. | -The public headers (`include/dmosal/osal_*.h`) are fixed — they define the +The public headers (`include/dmosal/osal_*.h`) are fixed, they define the API the backend must satisfy. ## Contracts to preserve @@ -30,21 +32,21 @@ For each function, honour the behavior documented in [api-spec.md](api-spec.md), [thread-safety.md](thread-safety.md), and [lifetime.md](lifetime.md). Concretely: -- **Pool ops must be thread-safe** — `_create` and `_delete` need to +- **Pool ops must be thread-safe**: `_create` and `_delete` need to serialize their pool touches. On Linux we do this by threading the shared `osal_mutex_t *mutex` through each `_man_t`'s `osal_rm_t`. Reuse that pattern via `OSAL_RM_USEROBJMAN_DECLARE` / `_INIT` if the target OS has a mutex primitive. - **Callbacks run on library-managed threads**, not the caller's: - Task handlers run to completion on a spawned thread; the exit - (returning from the handler) must not free the pool slot — that only + (returning from the handler) must not free the pool slot, that only happens in `osal_task_delete`. - Timer callbacks may run on any backend-managed context. On systems without a helper-thread mechanism, provide one (e.g. a dedicated timer dispatch task). - **`osal_timer_delete` must reject in-callback invocation.** Use the `in_callback` bool pattern from the Linux backend: set true around the - callback invocation, `OSAL_RUNTIME_ASSERT` in delete if it's true. + callback invocation, log an error and return from delete if it's true. ## Steps @@ -59,13 +61,14 @@ For each function, honour the behavior documented in └── osal_timer.c ``` -2. **Add sources to `CMakeLists.txt`.** Extend the `osal_SRC` list to - include `source/mybackend/*.c` when the target backend is selected. - The simplest scheme: add an option `DMOSAL_BACKEND=linux|mybackend` - and switch the source glob accordingly. Only one backend is compiled - in at a time. +2. **Add a build file.** The root `CMakeLists.txt` builds the Linux + backend only. Other backends have their own build entry point that + compiles `source/*.c` (portable layer) plus `source//*.c` + and generates `osal_config.h` / `osal_version.h`: see + `zephyr/CMakeLists.txt` (Zephyr module) and `freertos/CMakeLists.txt` + for templates. Only one backend is compiled in at a time. -3. **Implement `osal_mutex.c` first.** Everything else depends on it — +3. **Implement `osal_mutex.c` first.** Everything else depends on it: the shared mutex from this pool is passed to every other subsystem's init. See `source/linux/osal_mutex.c` for the reference: - `s_mutex_man` static holding the pool. @@ -79,25 +82,28 @@ For each function, honour the behavior documented in `osal_time.c`.** Each mirrors the same `_man_t` + `osal_rm_t` structure. Copy the Linux file and swap the OS calls. -5. **Wire in the build.** `CMakeLists.txt` is the only place where the - backend directory is referenced. Neither the public headers nor the - portable `source/*.c` files hard-code Linux. +5. **Wire in the build.** The build file from step 2 is the only place + where the backend directory is referenced. Neither the public headers + nor the portable `source/*.c` files hard-code a backend. -6. **Run the existing test suite.** All six cmocka tests exercise only - the public API and should pass unchanged. If they fail, the failure +6. **Run the existing test suite.** The cmocka tests in `test/osal/` + exercise only the public API and should pass unchanged. Tests specific + to one backend live in `test//` (for example `test/linux/`). + See `zephyr/app` and `freertos/app` for how to run them on an RTOS. If they fail, the failure is almost always a lifetime / thread-safety contract violation. ## Non-portable knobs you may need Some behaviors are inherently backend-specific and may need adjustment: -- **Log timestamp format** — `osal_log.c` uses `osal_clock_time` to build +- **Log timestamp format**: `osal_log.c` uses `osal_clock_time` to build timestamps. If your backend's monotonic clock has coarser resolution, - the microsecond field will just always show 0 — no code change needed. -- **`osal_task_cfg_t` hints** — `stack_addr`, `stack_size`, `priority`, - `name` are best-effort. Honour them if your target OS supports them. - The Linux reference implementation ignores them. -- **Timer callback thread** — the Linux backend spawns one helper thread + the microsecond field will just always show 0, no code change needed. +- **`osal_task_cfg_t` hints**: `stack_addr`, `stack_size`, `priority`, + `name` are optional (0 / NULL means the default from `osal_config.h`: + `OSAL_TASK_STACK_SIZE_DEFAULT`, `OSAL_TASK_PRIORITY_DEFAULT`). Honour them if your target + OS supports them. Zephyr and FreeRTOS do, Linux ignores them. +- **Timer callback thread**: the Linux backend spawns one helper thread per expiration (`SIGEV_THREAD`). On memory-constrained targets, use a single dedicated timer-dispatch task that walks a pending list. @@ -105,14 +111,14 @@ Some behaviors are inherently backend-specific and may need adjustment: After the backend compiles and links, before you declare it done: -- [ ] `make check` — all six existing suites pass. -- [ ] `make check-valgrind` (or the target's equivalent) — no leaks. -- [ ] TSan or platform equivalent — no data races. +- [ ] Every test in `test/osal/` passes. +- [ ] `make check-valgrind` (or the target's equivalent): no leaks. +- [ ] TSan or platform equivalent: no data races. - [ ] Manual: create a task, have it lock the shared mutex, then `osal_deinit()` after cleanup. Should not crash or hang. - [ ] Manual: create a timer, `osal_timer_delete` from inside its own - callback. Should assert (not silently corrupt). -- [ ] Manual: create a queue with `qsize=1`, send, send again — second + callback. Should log an error and leave the timer intact. +- [ ] Manual: create a queue with `qsize=1`, send, send again: second send returns `OSAL_E_QFULL`. - [ ] Manual: `osal_sem_waittime` with 1 ms timeout on an unposted semaphore returns `OSAL_E_TIMEOUT` in roughly 1 ms. diff --git a/docs/thread-safety.md b/docs/thread-safety.md index 682bf86..f79a09a 100644 --- a/docs/thread-safety.md +++ b/docs/thread-safety.md @@ -2,14 +2,14 @@ Every public `osal_*` function falls into one of four categories: -- **[any]** — Safe to call concurrently from multiple threads on the same +- **[any]**: Safe to call concurrently from multiple threads on the same or different objects, and against other **[any]** calls in this table. -- **[owner]** — Multiple threads may call this, but only one thread may +- **[owner]**: Multiple threads may call this, but only one thread may interact with a given object at a time. The library does not serialize concurrent calls on the same object; the caller must. -- **[init]** — Called once at program start / shutdown from the init +- **[init]**: Called once at program start / shutdown from the init thread. Not safe to race against any other `osal_*` call. -- **[callback]** — Invoked by the library on a backend-managed thread, not +- **[callback]**: Invoked by the library on a backend-managed thread, not the caller's. Inside the callback, other `osal_*` calls follow their own row's rule, subject to the callback-context restrictions in [lifetime.md](lifetime.md). @@ -27,13 +27,13 @@ Every public `osal_*` function falls into one of four categories: | Function | Class | |---|---| -| `osal_errstr` | **[any]** — returns a static string, never NULL | +| `osal_errstr` | **[any]**: returns a static string, never NULL | ## Time | Function | Class | |---|---| -| `osal_sleep`, `osal_usleep` | **[any]** — blocks the calling thread only | +| `osal_sleep`, `osal_usleep` | **[any]**: blocks the calling thread only | | `osal_clock_time` | **[any]** | ## Mutex @@ -41,9 +41,9 @@ Every public `osal_*` function falls into one of four categories: | Function | Class | |---|---| | `osal_mutex_init`, `osal_mutex_deinit` | **[init]** | -| `osal_mutex_create` | **[any]** — pool ops are internally serialized | -| `osal_mutex_delete` | **[owner]** — no thread may hold or lock the mutex being deleted | -| `osal_mutex_lock`, `osal_mutex_unlock` | **[any]** — the mutex itself provides the serialization | +| `osal_mutex_create` | **[any]**: pool ops are internally serialized | +| `osal_mutex_delete` | **[owner]**: no thread may hold or lock the mutex being deleted | +| `osal_mutex_lock`, `osal_mutex_unlock` | **[any]**: the mutex itself provides the serialization | | `osal_mutex_use`, `osal_mutex_avail` | **[any]** | ## Semaphore @@ -52,8 +52,8 @@ Every public `osal_*` function falls into one of four categories: |---|---| | `osal_sem_init`, `osal_sem_deinit` | **[init]** | | `osal_sem_create` | **[any]** | -| `osal_sem_delete` | **[owner]** — no thread may be waiting on or posting to it | -| `osal_sem_post`, `osal_sem_wait`, `osal_sem_waittime` | **[any]** — the semaphore itself is atomic | +| `osal_sem_delete` | **[owner]**: no thread may be waiting on or posting to it | +| `osal_sem_post`, `osal_sem_wait`, `osal_sem_waittime` | **[any]**: the semaphore itself is atomic | | `osal_sem_use`, `osal_sem_avail` | **[any]** | ## Task @@ -61,10 +61,10 @@ Every public `osal_*` function falls into one of four categories: | Function | Class | |---|---| | `osal_task_init`, `osal_task_deinit` | **[init]** | -| `osal_task_create` | **[any]** — pool ops serialized | -| `osal_task_delete` | **[owner]** — must not race concurrent delete on the same task | +| `osal_task_create` | **[any]**: pool ops serialized | +| `osal_task_delete` | **[owner]**: must not race concurrent delete on the same task | | `osal_task_use`, `osal_task_avail` | **[any]** | -| `task_handler` (user callback) | **[callback]** — runs on its own thread | +| `task_handler` (user callback) | **[callback]**: runs on its own thread | ## Timer @@ -72,10 +72,10 @@ Every public `osal_*` function falls into one of four categories: |---|---| | `osal_timer_init`, `osal_timer_deinit` | **[init]** | | `osal_timer_create` | **[any]** | -| `osal_timer_delete` | **[owner]** — asserts if the timer's callback is currently running (from any thread). Stop the timer first, wait for any in-flight callback to return, then delete. | -| `osal_timer_start`, `osal_timer_stop` | **[owner]** — per-timer serialization required | +| `osal_timer_delete` | **[owner]**: logs an error and is ignored if the timer's callback is currently running (from any thread). Stop the timer first, wait for any in-flight callback to return, then delete. | +| `osal_timer_start`, `osal_timer_stop` | **[owner]**: per-timer serialization required | | `osal_timer_use`, `osal_timer_avail` | **[any]** | -| `expire` (user callback) | **[callback]** — runs on a backend-managed thread | +| `expire` (user callback) | **[callback]**: runs on a backend-managed thread | ## Queue @@ -83,8 +83,8 @@ Every public `osal_*` function falls into one of four categories: |---|---| | `osal_queue_init`, `osal_queue_deinit` | **[init]** | | `osal_queue_create` | **[any]** | -| `osal_queue_delete` | **[owner]** — no thread may be sending or receiving | -| `osal_queue_send`, `osal_queue_recv` | **[any]** — the queue itself provides serialization between multiple senders and receivers | +| `osal_queue_delete` | **[owner]**: no thread may be sending or receiving | +| `osal_queue_send`, `osal_queue_recv` | **[any]**: the queue itself provides serialization between multiple senders and receivers | | `osal_queue_use`, `osal_queue_avail` | **[any]** | ## Log @@ -92,14 +92,14 @@ Every public `osal_*` function falls into one of four categories: | Function | Class | |---|---| | `osal_log_init`, `osal_log_deinit` | **[init]** | -| `osal_log_module_init` | **[init]** — call at startup for each module | -| `osal_log_module_change` | **[any]** — cheap level change at runtime | -| `osal_log_print` / `OSALOG_*` macros | **[any]** — the caller-provided output function must itself be thread-safe | +| `osal_log_module_init` | **[init]**: call at startup for each module | +| `osal_log_module_change` | **[any]**: cheap level change at runtime | +| `osal_log_print` / `OSALOG_*` macros | **[any]**: the caller-provided output function must itself be thread-safe | **Note:** the internal formatted string is built on a per-call stack buffer, so different `osal_log_print` calls don't interfere with each other. Message interleaving in the output stream (e.g. `printf` to stdout) depends on the -output-function contract — the default `printf` sink is line-buffered and +output-function contract, the default `printf` sink is line-buffered and generally safe on most systems. ## Resource manager (public but rarely used by application code) @@ -107,7 +107,7 @@ generally safe on most systems. | Function | Class | |---|---| | `osal_rm_init` | **[init]** | -| `osal_rm_deinit` | **[owner]** — see [lifetime.md](lifetime.md) for ordering vs. the RM's mutex | +| `osal_rm_deinit` | **[owner]**: see [lifetime.md](lifetime.md) for ordering vs. the RM's mutex | | `osal_rm_alloc`, `osal_rm_free` | **[any]** if the RM was init'd with a mutex; **[owner]** otherwise | | `osal_rm_use`, `osal_rm_avail` | same as `alloc`/`free` | @@ -115,15 +115,15 @@ generally safe on most systems. | Function | Class | |---|---| -| All `osal_lifo_*` | **[owner]** — the LIFO performs no internal synchronization (plain linked list, not atomics-based); caller synchronizes | +| All `osal_lifo_*` | **[owner]**: the LIFO performs no internal synchronization (plain linked list, not atomics-based); caller synchronizes | ## Tmcheck | Function | Class | |---|---| | `osal_tmcheck_init`, `osal_tmcheck_deinit` | **[init]** | -| `osal_tmcheck_create`, `osal_tmcheck_delete` | **[any]** — internally locked | -| `osal_tmcheck_capture_ts`, `osal_tmcheck_reset`, `osal_tmcheck_reset_all`, all `osal_tmcheck_*_print*`, `osal_tmcheck_get_diff`, `osal_tmcheck_name_get_diff`, `osal_tmcheck_get_captured_ts`, `osal_tmcheck_name_get_captured_ts` | **[owner]** — diagnostic-only paths intentionally unlocked. Data may be slightly inconsistent if racing against `_delete` | +| `osal_tmcheck_create`, `osal_tmcheck_delete` | **[any]**: internally locked | +| `osal_tmcheck_capture_ts`, `osal_tmcheck_reset`, `osal_tmcheck_reset_all`, all `osal_tmcheck_*_print*`, `osal_tmcheck_get_diff`, `osal_tmcheck_name_get_diff`, `osal_tmcheck_get_captured_ts`, `osal_tmcheck_name_get_captured_ts` | **[owner]**: diagnostic-only paths intentionally unlocked. Data may be slightly inconsistent if racing against `_delete` | | `osal_tmcheck_use`, `osal_tmcheck_avail` | **[any]** | ## Assert diff --git a/examples/queue_sample.c b/examples/queue_sample.c index edb3719..4f247f9 100644 --- a/examples/queue_sample.c +++ b/examples/queue_sample.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include #include diff --git a/examples/task_sample.c b/examples/task_sample.c index c484d4d..ff043de 100644 --- a/examples/task_sample.c +++ b/examples/task_sample.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include #include diff --git a/examples/timer_sample.c b/examples/timer_sample.c index 627537e..bc8d874 100644 --- a/examples/timer_sample.c +++ b/examples/timer_sample.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include #include @@ -49,7 +26,7 @@ static void timer_expire(void *arg) ctx->count++; elapsed_us = (long long)((now_ns - ctx->start_ns) / 1000); expected_us = (long long)ctx->period_us * ctx->count; - OSALOG_INFO("%s #%d expired: elapsed %lld us, expected %lld us, error %+lld us\n", + OSALOG_INFO("%s #%d: %lld/%lld us (%+lld)\n", ctx->name, ctx->count, elapsed_us, diff --git a/freertos/CMakeLists.txt b/freertos/CMakeLists.txt new file mode 100644 index 0000000..9b9b1fc --- /dev/null +++ b/freertos/CMakeLists.txt @@ -0,0 +1,64 @@ +# dmosal on FreeRTOS (static allocation only). +# +# Usage from an application that already provides the FreeRTOS kernel target: +# +# add_subdirectory(/freertos dmosal) +# target_link_libraries(my_app PRIVATE dmosal) +# +# The kernel target must be called `freertos_kernel` and be configured as described at the +# top of source/freertos/osal_freertos_priv.h. Pool sizes come from osal_config.cmake and can +# be overridden on the command line (-DOSAL_CONFIG_TASK_NUM_MAX=8 ...). + +get_filename_component(DMOSAL_ROOT "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE) + +include("${DMOSAL_ROOT}/osal_config.cmake") + +set(DMOSAL_MAJOR_VERSION 1) +set(DMOSAL_MINOR_VERSION 0) +set(DMOSAL_PATCH_VERSION 0) +execute_process(COMMAND git rev-parse --short HEAD + WORKING_DIRECTORY "${DMOSAL_ROOT}" + OUTPUT_VARIABLE DMOSAL_GIT_COMMIT + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET) +if(NOT DMOSAL_GIT_COMMIT) + set(DMOSAL_GIT_COMMIT "freertos") +endif() +string(TIMESTAMP DMOSAL_BUILD_TIME "%Y:%m:%d-%H:%M") + +set(DMOSAL_GEN_DIR "${CMAKE_CURRENT_BINARY_DIR}/gen/dmosal") +file(MAKE_DIRECTORY "${DMOSAL_GEN_DIR}") +configure_file("${DMOSAL_ROOT}/include/dmosal/osal_config.h.in" + "${DMOSAL_GEN_DIR}/osal_config.h" @ONLY) +configure_file("${DMOSAL_ROOT}/include/dmosal/osal_version.h.in" + "${DMOSAL_GEN_DIR}/osal_version.h" @ONLY) + +add_library(dmosal STATIC + "${DMOSAL_ROOT}/source/osal.c" + "${DMOSAL_ROOT}/source/osal_error.c" + "${DMOSAL_ROOT}/source/osal_lifo.c" + "${DMOSAL_ROOT}/source/osal_log.c" + "${DMOSAL_ROOT}/source/osal_rm.c" + "${DMOSAL_ROOT}/source/osal_tmcheck.c" + "${DMOSAL_ROOT}/source/freertos/osal_mutex.c" + "${DMOSAL_ROOT}/source/freertos/osal_queue.c" + "${DMOSAL_ROOT}/source/freertos/osal_sem.c" + "${DMOSAL_ROOT}/source/freertos/osal_task.c" + "${DMOSAL_ROOT}/source/freertos/osal_time.c" + "${DMOSAL_ROOT}/source/freertos/osal_timer.c" +) + +target_include_directories(dmosal PUBLIC + "${DMOSAL_ROOT}/include" + "${DMOSAL_ROOT}/include/dmosal" + "${CMAKE_CURRENT_BINARY_DIR}/gen" + "${DMOSAL_GEN_DIR}" +) +target_include_directories(dmosal PRIVATE "${DMOSAL_ROOT}/source/freertos") + +target_compile_options(dmosal PRIVATE + -Wshadow -Wconversion -Wpedantic -Wcast-align -Wpointer-arith + -Wstrict-prototypes -Wmissing-prototypes +) + +target_link_libraries(dmosal PUBLIC freertos_kernel) diff --git a/freertos/Dockerfile b/freertos/Dockerfile new file mode 100644 index 0000000..316ace9 --- /dev/null +++ b/freertos/Dockerfile @@ -0,0 +1,23 @@ +# Slim build environment for running dmosal on the FreeRTOS POSIX/Linux simulator. +# +# The simulator port compiles FreeRTOS + the app into a Linux executable with the host gcc, so +# no cross toolchain or emulator is needed. +# +# Built and used through freertos/docker.sh; see that script for usage. +FROM ubuntu:22.04 + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y --no-install-recommends \ + build-essential ca-certificates cmake curl libcmocka-dev ninja-build \ + && rm -rf /var/lib/apt/lists/* + +# Pinned FreeRTOS kernel, downloaded once into the image (no host download). +ARG FREERTOS_KERNEL_VERSION=V11.1.0 +ENV FREERTOS_KERNEL_PATH=/opt/FreeRTOS-Kernel +RUN mkdir -p ${FREERTOS_KERNEL_PATH} \ + && curl -fsSL https://github.com/FreeRTOS/FreeRTOS-Kernel/archive/refs/tags/${FREERTOS_KERNEL_VERSION}.tar.gz \ + | tar -xz -C ${FREERTOS_KERNEL_PATH} --strip-components=1 \ + && chmod -R a+rX ${FREERTOS_KERNEL_PATH} + +WORKDIR /dmosal diff --git a/freertos/README.md b/freertos/README.md new file mode 100644 index 0000000..1a98e9c --- /dev/null +++ b/freertos/README.md @@ -0,0 +1,86 @@ +# dmosal on FreeRTOS + +The FreeRTOS backend ([source/freertos/](../source/freertos/)) implements the same API as the +Linux and Zephyr backends using the kernel's **static allocation** API when it is enabled (no heap needed), or the +dynamic API otherwise. It is tested on the FreeRTOS +[POSIX/Linux simulator port](https://www.freertos.org/FreeRTOS-simulator-for-Linux.html), which +compiles FreeRTOS and the application into a normal Linux executable, so CI needs no hardware +or emulator. + +## Run + +Everything runs inside Docker; only this repository is mounted. The first run builds the image +(FreeRTOS-Kernel is pinned in `freertos/Dockerfile`). + +``` +just freertos-build # build every examples/*.c and test/osal/*_test.c into build-freertos/ +just freertos-run # run the examples +just freertos-test # run the cmocka tests (TEST=mutex_test for one) +just freertos-shell # shell in the container +``` + +The examples and the cmocka tests under `test/osal/` are the same sources used for Linux and +Zephyr. Each keeps its own `main()`: the build renames it and [app/main.c](app/main.c) runs it +in a FreeRTOS task, then exits the process with its result. + +## Layout + +| Path | Purpose | +|---|---| +| `source/freertos/` | the backend (`osal_mutex.c`, `osal_sem.c`, `osal_task.c`, `osal_timer.c`, `osal_queue.c`, `osal_time.c`) | +| `freertos/CMakeLists.txt` | the `dmosal` library target for FreeRTOS builds | +| `freertos/app/` | simulator application: `FreeRTOSConfig.h`, `main.c`, CMake project | +| `freertos/Dockerfile`, `freertos/docker.sh` | build environment and runner | + +## Use it in your own FreeRTOS project + +```cmake +add_subdirectory(path/to/dmosal/freertos dmosal) # needs a `freertos_kernel` target +target_link_libraries(my_app PRIVATE dmosal) +``` + +The backend uses only the FreeRTOS user-space API, so it works with the kernel configuration your +SoC vendor ships. It adapts to it (see the top of +[source/freertos/osal_freertos_priv.h](../source/freertos/osal_freertos_priv.h)): + +- `configSUPPORT_STATIC_ALLOCATION 1`: static API, no heap. Your application (or the vendor) + provides `vApplicationGetIdleTaskMemory()` and `vApplicationGetTimerTaskMemory()`. +- otherwise: dynamic API (`configSUPPORT_DYNAMIC_ALLOCATION 1` and a heap implementation). + The pools stay static; only the kernel objects come from the heap. +- always: `configUSE_MUTEXES`, `configUSE_COUNTING_SEMAPHORES`, `configUSE_TIMERS`, + `INCLUDE_vTaskDelete`, `INCLUDE_vTaskSuspend`, `INCLUDE_xTaskGetCurrentTaskHandle` (a missing + option stops the build with an `#error`). +- the timer service task priority must be higher than every task that deletes timers + +`FreeRTOSConfig.h` and the idle/timer memory hooks in `freertos/app/` are only the simulator +harness; use the vendor's instead. `CMAKE_ARGS=-DDYNAMIC_ALLOC=ON BUILD_DIR=build-freertos-dyn +freertos/docker.sh build` builds the harness with the dynamic API (not run in CI). + +All settings come from [osal_config.cmake](../osal_config.cmake) (`-DOSAL_CONFIG_TASK_NUM_MAX=8`, +...), the same file as for every backend. This backend uses `OSAL_CONFIG_TASK_STACK_SIZE_DEFAULT` (bytes), +`OSAL_CONFIG_TASK_PRIORITY_DEFAULT` (a FreeRTOS priority, higher is more urgent), `OSAL_CONFIG_QUEUE_MSG_MAX_SIZE` +and `OSAL_CONFIG_QUEUE_MSG_NUM_MAX`. + +## Mapping and behaviour differences + +| dmosal | FreeRTOS | Note | +|---|---|---| +| mutex | `xSemaphoreCreateMutexStatic` | non-recursive; unlock by a non-owner returns `OSAL_E_OSCALL` | +| sem | `xSemaphoreCreateCountingStatic` | | +| task | `xTaskCreateStatic` | one static stack per pool slot | +| timer | `xTimerCreateStatic` | `expire()` runs in the timer service task | +| queue | `xQueueCreateStatic` | in-process, shared by name like the Zephyr backend | +| time | tick count | resolution is one tick (`configTICK_RATE_HZ`, 1 ms in the simulator) | + +- **Time resolution:** sleeps and timeouts are rounded up to whole ticks. `osal_clock_time()` + has tick resolution, so tmcheck differences are multiples of one tick. +- **Task end:** when a task handler returns, the task is parked (a FreeRTOS task must not + return). `osal_task_delete()` removes it; deleting the calling task itself is ignored, as the + kernel only releases its TCB later. +- **Task priority and stack:** `priority`, `stack_size` and `stack_addr` of `osal_task_cfg_t` are + honoured. 0 selects `OSAL_CONFIG_TASK_PRIORITY_DEFAULT` / `OSAL_CONFIG_TASK_STACK_SIZE_DEFAULT`. Without + `stack_addr` the stack is embedded in the task object, so `stack_size` is limited to + `OSAL_CONFIG_TASK_STACK_SIZE_DEFAULT`. With `-DDMOSAL_TASK_STACK_EMBEDDED=OFF` there is no + embedded stack and `osal_task_create()` fails unless `stack_addr` is given. With dynamic + allocation `stack_addr` is not used. +- **Timers:** deleting a timer from its own callback is ignored. diff --git a/freertos/app/CMakeLists.txt b/freertos/app/CMakeLists.txt new file mode 100644 index 0000000..1f037df --- /dev/null +++ b/freertos/app/CMakeLists.txt @@ -0,0 +1,69 @@ +cmake_minimum_required(VERSION 3.15) +project(dmosal_freertos_app C) + +# Builds every example in examples/ and every cmocka test in test/osal/ as a host executable +# running on the FreeRTOS POSIX simulator, plus dmosal itself (../CMakeLists.txt). +# +# FREERTOS_KERNEL_PATH FreeRTOS-Kernel source tree (env or -D) +# +# Tests need libcmocka (apt install libcmocka-dev). + +set(FREERTOS_KERNEL_PATH "$ENV{FREERTOS_KERNEL_PATH}" CACHE PATH "FreeRTOS-Kernel source tree") +if(NOT FREERTOS_KERNEL_PATH) + message(FATAL_ERROR "Set FREERTOS_KERNEL_PATH to a FreeRTOS-Kernel checkout") +endif() + +get_filename_component(REPO_ROOT "${CMAKE_CURRENT_LIST_DIR}/../.." ABSOLUTE) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra") + +option(DYNAMIC_ALLOC "Use the kernel's dynamic allocation API (heap_4) instead of static allocation" OFF) + +add_library(freertos_config INTERFACE) +target_include_directories(freertos_config SYSTEM INTERFACE ${CMAKE_CURRENT_LIST_DIR}) +if(DYNAMIC_ALLOC) + target_compile_definitions(freertos_config INTERFACE DMOSAL_APP_DYNAMIC_ALLOC) + set(FREERTOS_HEAP 4 CACHE STRING "") +endif() + +set(FREERTOS_PORT GCC_POSIX CACHE STRING "") +add_subdirectory(${FREERTOS_KERNEL_PATH} freertos_kernel) +add_subdirectory(${REPO_ROOT}/freertos dmosal) + +add_library(app_main OBJECT main.c) +target_link_libraries(app_main PRIVATE freertos_kernel) + +# Each program keeps its own main(): it is renamed and run from a FreeRTOS task by main.c. +function(add_dmosal_program name source) + add_executable(${name} ${source} $) + set_source_files_properties(${source} PROPERTIES COMPILE_DEFINITIONS main=dmosal_app_main) + target_link_libraries(${name} PRIVATE dmosal) +endfunction() + +enable_testing() +add_custom_target(examples) +add_custom_target(tests) + +file(GLOB EXAMPLE_SOURCES ${REPO_ROOT}/examples/*.c) +foreach(src ${EXAMPLE_SOURCES}) + get_filename_component(name ${src} NAME_WE) + add_dmosal_program(${name} ${src}) + add_dependencies(examples ${name}) +endforeach() + +find_package(cmocka) +if(NOT cmocka_FOUND AND NOT CMOCKA_LIBRARIES) + find_library(CMOCKA_LIBRARIES cmocka REQUIRED) +endif() + +file(GLOB TEST_SOURCES ${REPO_ROOT}/test/osal/*_test.c) +foreach(src ${TEST_SOURCES}) + get_filename_component(name ${src} NAME_WE) + add_dmosal_program(${name} ${src}) + target_include_directories(${name} PRIVATE ${REPO_ROOT}/test) + target_link_libraries(${name} PRIVATE ${CMOCKA_LIBRARIES}) + add_dependencies(tests ${name}) + add_test(NAME ${name} COMMAND ${name}) + set_tests_properties(${name} PROPERTIES TIMEOUT 120) +endforeach() diff --git a/freertos/app/FreeRTOSConfig.h b/freertos/app/FreeRTOSConfig.h new file mode 100644 index 0000000..715f98d --- /dev/null +++ b/freertos/app/FreeRTOSConfig.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ + +/* FreeRTOS configuration for running dmosal on the FreeRTOS POSIX/Linux simulator port. + * By default everything is statically allocated: the kernel does no heap allocation. + * With DMOSAL_APP_DYNAMIC_ALLOC (cmake -DDYNAMIC_ALLOC=ON) the kernel's dynamic API is used + * instead, to check that dmosal works with either kind of vendor configuration. */ +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configUSE_TIME_SLICING 1 +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configTICK_RATE_HZ 1000 +#define configMAX_PRIORITIES 7 +/* Words (not bytes) of the idle task stack; the port turns it into a pthread stack. */ +#define configMINIMAL_STACK_SIZE 4096 +#define configMAX_TASK_NAME_LEN 32 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 + +#ifdef DMOSAL_APP_DYNAMIC_ALLOC +#define configSUPPORT_STATIC_ALLOCATION 0 +#define configSUPPORT_DYNAMIC_ALLOCATION 1 +#define configTOTAL_HEAP_SIZE (8U * 1024U * 1024U) +#else +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 0 +#define configKERNEL_PROVIDED_STATIC_MEMORY 0 +#endif + +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 0 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 0 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TASK_NOTIFICATIONS 1 + +/* Callbacks of osal timers run in the timer service task: give it a priority above every + * other task (see source/freertos/osal_timer.c) and a stack that fits user callbacks. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1) +#define configTIMER_QUEUE_LENGTH 16 +#define configTIMER_TASK_STACK_DEPTH 8192 + +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_xTimerPendFunctionCall 1 + +extern void vAssertCalled(const char *file, int line); +#define configASSERT(x) \ + do { \ + if (!(x)) \ + vAssertCalled(__FILE__, __LINE__); \ + } while (0) + +#endif /* FREERTOS_CONFIG_H */ diff --git a/freertos/app/main.c b/freertos/app/main.c new file mode 100644 index 0000000..739d6ec --- /dev/null +++ b/freertos/app/main.c @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ + +/* Runs a dmosal example or cmocka test on the FreeRTOS POSIX simulator. + * + * The example/test keeps its own main(): the build renames it to dmosal_app_main, and this file + * runs it in a FreeRTOS task, then ends the process with its result so CI can use the exit + * code. With static allocation (default) the idle and timer tasks get their memory from here; + * with DMOSAL_APP_DYNAMIC_ALLOC the kernel allocates everything from the heap. */ +#include +#include +#include "FreeRTOS.h" +#include "task.h" + +extern int dmosal_app_main(void); + +/* Bytes; the test and example code runs here, so keep room for cmocka and local buffers. */ +#define APP_STACK_SIZE (256U * 1024U) +#define APP_PRIORITY (tskIDLE_PRIORITY + 2) /* above the tasks created by dmosal */ + +#ifndef DMOSAL_APP_DYNAMIC_ALLOC +static StaticTask_t s_app_tcb; +static StackType_t s_app_stack[APP_STACK_SIZE / sizeof(StackType_t)]; +#endif + +static void app_task(void *arg) +{ + int rc; + + (void)arg; + rc = dmosal_app_main(); + fflush(stdout); + exit(rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE); +} + +int main(void) +{ +#ifdef DMOSAL_APP_DYNAMIC_ALLOC + xTaskCreate(app_task, "app", APP_STACK_SIZE / sizeof(StackType_t), NULL, APP_PRIORITY, NULL); +#else + xTaskCreateStatic(app_task, + "app", + sizeof(s_app_stack) / sizeof(s_app_stack[0]), + NULL, + APP_PRIORITY, + s_app_stack, + &s_app_tcb); +#endif + vTaskStartScheduler(); + return EXIT_FAILURE; +} + +void vAssertCalled(const char *file, int line) +{ + fprintf(stderr, "FreeRTOS assert failed: %s:%d\n", file, line); + abort(); +} + +#ifndef DMOSAL_APP_DYNAMIC_ALLOC +void vApplicationGetIdleTaskMemory(StaticTask_t **tcb, + StackType_t **stack, + configSTACK_DEPTH_TYPE *depth) +{ + static StaticTask_t s_tcb; + static StackType_t s_stack[configMINIMAL_STACK_SIZE]; + + *tcb = &s_tcb; + *stack = s_stack; + *depth = configMINIMAL_STACK_SIZE; +} + +void vApplicationGetTimerTaskMemory(StaticTask_t **tcb, + StackType_t **stack, + configSTACK_DEPTH_TYPE *depth) +{ + static StaticTask_t s_tcb; + static StackType_t s_stack[configTIMER_TASK_STACK_DEPTH]; + + *tcb = &s_tcb; + *stack = s_stack; + *depth = configTIMER_TASK_STACK_DEPTH; +} +#endif diff --git a/freertos/docker.sh b/freertos/docker.sh new file mode 100755 index 0000000..43811de --- /dev/null +++ b/freertos/docker.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +# Build and run dmosal's examples and cmocka tests on the FreeRTOS POSIX simulator, entirely +# inside Docker. The image (freertos/Dockerfile) contains the FreeRTOS kernel; only this repo +# is mounted. The first build creates the image. +# +# freertos/docker.sh build # build every examples/*.c and test/osal/*_test.c into build-freertos/ +# freertos/docker.sh run # run the examples +# freertos/docker.sh test # run the cmocka tests (ctest) +# freertos/docker.sh shell # interactive shell in the container +# +# CMAKE_ARGS=-DDYNAMIC_ALLOC=ON builds against the kernel's dynamic allocation API instead +# of static allocation (use BUILD_DIR=build-freertos-dyn to keep both). +# TEST= limits test to one test (for example TEST=mutex_test). +set -euo pipefail + +IMAGE=dmosal-freertos:local +BUILD=${BUILD_DIR:-build-freertos} +REPO="$(cd "$(dirname "$0")/.." && pwd)" + +DOCKER_RUN=(docker run --rm -u "$(id -u):$(id -g)" -e HOME=/tmp -v "$REPO":/dmosal) + +if ! docker image inspect "$IMAGE" >/dev/null 2>&1; then + docker build -t "$IMAGE" -f "$REPO/freertos/Dockerfile" "$REPO/freertos" +fi + +case "${1:-}" in +build) + "${DOCKER_RUN[@]}" "$IMAGE" sh -c \ + "cmake -S freertos/app -B $BUILD -G Ninja -DCMAKE_BUILD_TYPE=Debug ${CMAKE_ARGS:-} && cmake --build $BUILD" + ;; +run) + for f in "$REPO"/examples/*.c; do + ex="$(basename "$f" .c)" + echo "=== $ex ===" + "${DOCKER_RUN[@]}" "$IMAGE" timeout 20 "$BUILD/$ex" + done + ;; +test) + "${DOCKER_RUN[@]}" "$IMAGE" ctest --test-dir "$BUILD" --output-on-failure ${TEST:+-R "^$TEST\$"} + ;; +shell) + "${DOCKER_RUN[@]}" -it "$IMAGE" bash + ;; +*) + sed -n "2,10p" "$0" + exit 1 + ;; +esac diff --git a/include/dmosal/osal.h b/include/dmosal/osal.h index d071f48..5dde2b9 100644 --- a/include/dmosal/osal.h +++ b/include/dmosal/osal.h @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ /** * @addtogroup dmosal diff --git a/include/dmosal/osal_assert.h b/include/dmosal/osal_assert.h index 492cc23..f49fefd 100644 --- a/include/dmosal/osal_assert.h +++ b/include/dmosal/osal_assert.h @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ /** * @addtogroup dmosal diff --git a/include/dmosal/osal_config.h.in b/include/dmosal/osal_config.h.in index 448f463..3d707de 100644 --- a/include/dmosal/osal_config.h.in +++ b/include/dmosal/osal_config.h.in @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ /** * @addtogroup dmosal @@ -46,6 +23,35 @@ extern "C" { */ #define OSAL_TASK_NAME_SIZE @OSAL_CONFIG_TASK_NAME_SIZE@ +/** + * @brief Stack size of each task in bytes. + * + * Used by backends that own the task stack (Zephyr, FreeRTOS). Has no effect + * on backends that do not use it (Linux). + */ +#define OSAL_TASK_STACK_SIZE_DEFAULT @OSAL_CONFIG_TASK_STACK_SIZE_DEFAULT@ + +/** + * @brief Whether each task object embeds its own stack array (1) or not (0). + * + * When 0, the backend has no stack memory of its own and + * osal_task_create() fails unless the caller passes @c stack_addr and + * @c stack_size. Used by backends that own the task stack (Zephyr, + * FreeRTOS static allocation). Has no effect on backends that do not use it + * (Linux). + */ +#define OSAL_TASK_STACK_EMBEDDED @OSAL_CONFIG_TASK_STACK_EMBEDDED@ + +/** + * @brief Native priority of the tasks. + * + * Interpreted by the backend in its own priority scheme (for example a + * higher number is a higher priority on FreeRTOS, a lower number is a + * higher priority on Zephyr). Has no effect on backends that do not use it + * (Linux). + */ +#define OSAL_TASK_PRIORITY_DEFAULT @OSAL_CONFIG_TASK_PRIORITY_DEFAULT@ + /** * @brief Maximum number of tasks. * @@ -88,6 +94,28 @@ extern "C" { */ #define OSAL_QUEUE_NUM_MAX @OSAL_CONFIG_QUEUE_NUM_MAX@ +/** + * @brief Maximum message length of a queue in bytes. + * + * Used by backends that keep the queue storage in the library (Zephyr, + * FreeRTOS). Has no effect on backends that do not use it (Linux). + */ +#define OSAL_QUEUE_MSG_MAX_SIZE @OSAL_CONFIG_QUEUE_MSG_MAX_SIZE@ + +/** + * @brief Maximum number of messages per queue. + * + * Used by backends that keep the queue storage in the library (Zephyr, + * FreeRTOS). Has no effect on backends that do not use it (Linux). + */ +#define OSAL_QUEUE_MSG_NUM_MAX @OSAL_CONFIG_QUEUE_MSG_NUM_MAX@ + +/** + * @brief Message buffer size per queue in bytes, derived as + * @ref OSAL_QUEUE_MSG_MAX_SIZE * @ref OSAL_QUEUE_MSG_NUM_MAX. + */ +#define OSAL_QUEUE_BUF_SIZE (OSAL_QUEUE_MSG_MAX_SIZE * OSAL_QUEUE_MSG_NUM_MAX) + /** * @brief Maximum number of the log modules. * diff --git a/include/dmosal/osal_error.h b/include/dmosal/osal_error.h index 8697eac..9b5c8f9 100644 --- a/include/dmosal/osal_error.h +++ b/include/dmosal/osal_error.h @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ /** * @addtogroup dmosal @@ -62,7 +39,7 @@ typedef enum { * @brief Retrieves the human-readable description for an OSAL error code. * * @param e The error code of type ::osal_error_t. - * @return Pointer to a static, null-terminated string. Never returns NULL — + * @return Pointer to a static, null-terminated string. Never returns NULL: * for out-of-range codes returns the literal `"OSAL_UNKNOWN"`. Owned by the * library; the caller must not free it. */ diff --git a/include/dmosal/osal_lifo.h b/include/dmosal/osal_lifo.h index 95510a5..f480867 100644 --- a/include/dmosal/osal_lifo.h +++ b/include/dmosal/osal_lifo.h @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ /** * @addtogroup dmosal diff --git a/include/dmosal/osal_log.h b/include/dmosal/osal_log.h index aa035be..cf463f7 100644 --- a/include/dmosal/osal_log.h +++ b/include/dmosal/osal_log.h @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2024, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ /** * @addtogroup dmosal diff --git a/include/dmosal/osal_mutex.h b/include/dmosal/osal_mutex.h index f8672dd..27a0c62 100644 --- a/include/dmosal/osal_mutex.h +++ b/include/dmosal/osal_mutex.h @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ /** * @addtogroup dmosal diff --git a/include/dmosal/osal_queue.h b/include/dmosal/osal_queue.h index 83c1658..56d02cf 100644 --- a/include/dmosal/osal_queue.h +++ b/include/dmosal/osal_queue.h @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ /** * @addtogroup dmosal diff --git a/include/dmosal/osal_rm.h b/include/dmosal/osal_rm.h index 470b252..b8105c2 100644 --- a/include/dmosal/osal_rm.h +++ b/include/dmosal/osal_rm.h @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ /** * @addtogroup dmosal diff --git a/include/dmosal/osal_sem.h b/include/dmosal/osal_sem.h index 695f866..300d1e3 100644 --- a/include/dmosal/osal_sem.h +++ b/include/dmosal/osal_sem.h @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ /** * @addtogroup dmosal diff --git a/include/dmosal/osal_task.h b/include/dmosal/osal_task.h index 3529a9f..93b5451 100644 --- a/include/dmosal/osal_task.h +++ b/include/dmosal/osal_task.h @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ /** * @addtogroup dmosal diff --git a/include/dmosal/osal_time.h b/include/dmosal/osal_time.h index e7c6126..9e85988 100644 --- a/include/dmosal/osal_time.h +++ b/include/dmosal/osal_time.h @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ /** * @addtogroup dmosal diff --git a/include/dmosal/osal_timer.h b/include/dmosal/osal_timer.h index 41a54c4..bcc92e8 100644 --- a/include/dmosal/osal_timer.h +++ b/include/dmosal/osal_timer.h @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ /** * @addtogroup dmosal @@ -102,9 +79,8 @@ void osal_timer_stop(osal_timer_t *timer); * * @warning Must not be called while the timer's expire callback is running * (from within the callback itself or concurrently from any other thread). - * Doing so aborts the process via @ref OSAL_RUNTIME_ASSERT — the delete - * would free the timer out from under the callback. To retire a timer - * safely, stop it first with @ref osal_timer_stop and ensure any in-flight + * Doing so logs an error and the call is ignored: the delete would free + * the timer out from under the callback. To retire a timer safely, stop it first with @ref osal_timer_stop and ensure any in-flight * callback has returned before calling this function. */ void osal_timer_delete(osal_timer_t *timer); diff --git a/include/dmosal/osal_tmcheck.h b/include/dmosal/osal_tmcheck.h index 9489fe4..a410425 100644 --- a/include/dmosal/osal_tmcheck.h +++ b/include/dmosal/osal_tmcheck.h @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2025, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ /** * @addtogroup dmosal diff --git a/include/dmosal/osal_version.h.in b/include/dmosal/osal_version.h.in index f9ccdb0..c2328cd 100644 --- a/include/dmosal/osal_version.h.in +++ b/include/dmosal/osal_version.h.in @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2024, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ /** * @addtogroup dmosal diff --git a/justfile b/justfile index 4ccef6a..2f04d55 100644 --- a/justfile +++ b/justfile @@ -20,6 +20,10 @@ # just zephyr-run # run the Zephyr examples # just zephyr-test # run the cmocka tests on Zephyr native_sim (TEST= for one) # just zephyr-shell # shell inside the Zephyr container +# just freertos-build # build examples + tests for the FreeRTOS POSIX simulator (Docker) +# just freertos-run # run the FreeRTOS examples +# just freertos-test # run the cmocka tests on the FreeRTOS simulator (TEST= for one) +# just freertos-shell # shell inside the FreeRTOS container # just clean # remove build directories build_dir := "build" @@ -100,10 +104,26 @@ zephyr-test: zephyr-shell: zephyr/docker.sh shell +# Build the examples and tests for the FreeRTOS POSIX simulator inside Docker +freertos-build: + freertos/docker.sh build + +# Run the FreeRTOS examples on the simulator +freertos-run: + freertos/docker.sh run + +# Run the cmocka tests (test/osal) on the FreeRTOS simulator +freertos-test: + freertos/docker.sh test + +# Open a shell in the FreeRTOS container +freertos-shell: + freertos/docker.sh shell + # Remove the default build directory clean: rm -rf {{build_dir}} # Remove all build directories (default + sanitizer variants) distclean: - rm -rf {{build_dir}} build-asan build-tsan build-zephyr build-zephyr-test + rm -rf {{build_dir}} build-asan build-tsan build-zephyr build-zephyr-test build-freertos diff --git a/osal_config.cmake b/osal_config.cmake index a8276a5..1066ed0 100644 --- a/osal_config.cmake +++ b/osal_config.cmake @@ -5,6 +5,23 @@ set(OSAL_CONFIG_TASK_NAME_SIZE 64 CACHE STRING "The size of the task name" ) +set(OSAL_CONFIG_TASK_STACK_SIZE_DEFAULT 16384 + CACHE STRING "Stack size of each task in bytes (RTOS backends; no effect on Linux)" +) + +set(DMOSAL_TASK_STACK_EMBEDDED ON + CACHE BOOL "Each task object embeds a stack array. OFF: the caller must pass cfg->stack_addr (RTOS backends; no effect on Linux)" +) +if(DMOSAL_TASK_STACK_EMBEDDED) + set(OSAL_CONFIG_TASK_STACK_EMBEDDED 1) +else() + set(OSAL_CONFIG_TASK_STACK_EMBEDDED 0) +endif() + +set(OSAL_CONFIG_TASK_PRIORITY_DEFAULT 1 + CACHE STRING "Native priority of tasks (RTOS backends; no effect on Linux)" +) + set(OSAL_CONFIG_TASK_NUM_MAX 64 CACHE STRING "Maximum of number tasks to support" ) @@ -29,6 +46,14 @@ set(OSAL_CONFIG_QUEUE_NUM_MAX 64 CACHE STRING "Maximum number of queues to support" ) +set(OSAL_CONFIG_QUEUE_MSG_MAX_SIZE 128 + CACHE STRING "Maximum message length of a queue in bytes (RTOS backends; no effect on Linux)" +) + +set(OSAL_CONFIG_QUEUE_MSG_NUM_MAX 16 + CACHE STRING "Maximum number of messages per queue (RTOS backends; no effect on Linux)" +) + set(OSAL_CONFIG_LOG_MODULE_NUM_MAX 32 CACHE STRING "Maximum number of log module to support" ) diff --git a/source/freertos/osal_freertos_priv.h b/source/freertos/osal_freertos_priv.h new file mode 100644 index 0000000..c8d0db8 --- /dev/null +++ b/source/freertos/osal_freertos_priv.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ + +/* Private helpers and tunables of the FreeRTOS backend (not a public header). + * + * The backend uses only the FreeRTOS user-space API and adapts to the kernel + * configuration supplied by the SoC vendor or application: + * - configSUPPORT_STATIC_ALLOCATION = 1: every kernel object lives in the + * static pools, no heap is used. The application then provides the + * kernel's own idle/timer task memory hooks. + * - otherwise the kernel's dynamic API is used (configSUPPORT_DYNAMIC_ALLOCATION + * and a heap implementation are required). The pools stay static, only the + * kernel objects come from the heap. + * Always required: configUSE_MUTEXES, configUSE_COUNTING_SEMAPHORES, configUSE_TIMERS, + * INCLUDE_vTaskDelete, INCLUDE_vTaskSuspend, INCLUDE_xTaskGetCurrentTaskHandle and + * INCLUDE_xTimerPendFunctionCall. + */ + +#ifndef OSAL_FREERTOS_PRIV_H +#define OSAL_FREERTOS_PRIV_H + +#include +#include "FreeRTOS.h" +#include "task.h" + +#if !configUSE_MUTEXES || !configUSE_COUNTING_SEMAPHORES || !configUSE_TIMERS +#error "dmosal needs configUSE_MUTEXES, configUSE_COUNTING_SEMAPHORES and configUSE_TIMERS" +#endif +#if !INCLUDE_vTaskDelete || !INCLUDE_vTaskSuspend || !INCLUDE_xTaskGetCurrentTaskHandle || \ + !INCLUDE_xTimerPendFunctionCall +#error \ + "dmosal needs INCLUDE_vTaskDelete, _vTaskSuspend, _xTaskGetCurrentTaskHandle, _xTimerPendFunctionCall" +#endif + +/* Prefer the static API when the kernel has it, else fall back to the heap. */ +#if configSUPPORT_STATIC_ALLOCATION == 1 +#define DMOSAL_FREERTOS_STATIC 1 +#elif configSUPPORT_DYNAMIC_ALLOCATION == 1 +#define DMOSAL_FREERTOS_STATIC 0 +#else +#error "dmosal needs configSUPPORT_STATIC_ALLOCATION or configSUPPORT_DYNAMIC_ALLOCATION" +#endif + +/* Microseconds to ticks, rounded up so a non-zero timeout never becomes "no wait". */ +static inline TickType_t osal_freertos_usec_to_ticks(uint32_t usec) +{ + uint64_t ticks = ((uint64_t)usec * configTICK_RATE_HZ + 999999U) / 1000000U; + + /* portMAX_DELAY means "forever" and must not be produced by a finite timeout. */ + return ticks >= portMAX_DELAY ? portMAX_DELAY - 1U : (TickType_t)ticks; +} + +#endif /* OSAL_FREERTOS_PRIV_H */ diff --git a/source/freertos/osal_mutex.c b/source/freertos/osal_mutex.c new file mode 100644 index 0000000..d9e318e --- /dev/null +++ b/source/freertos/osal_mutex.c @@ -0,0 +1,135 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ + +/* FreeRTOS backend (static allocation only). */ + +#include +#include +#include "osal_mutex.h" +#include "osal_rm.h" +#include "osal_assert.h" +#include "osal_config.h" +#include "osal_freertos_priv.h" +#include "semphr.h" + +struct osal_mutex { +#if DMOSAL_FREERTOS_STATIC + StaticSemaphore_t storage; +#endif + SemaphoreHandle_t handle; + osal_resrc_t *resrc; +}; + +typedef struct { + OSAL_RM_USEROBJMAN_DECLARE(struct osal_mutex, OSAL_MUTEX_NUM_MAX); + bool init; + /* Guards the pool; it cannot use osal_mutex itself. */ +#if DMOSAL_FREERTOS_STATIC + StaticSemaphore_t resrc_storage; +#endif + SemaphoreHandle_t resrc_mutex; +} mutex_man_t; + +static mutex_man_t s_mutex_man; + +osal_error_t osal_mutex_init(void) +{ + if (s_mutex_man.init) { + return OSAL_E_OK; + } + +#if DMOSAL_FREERTOS_STATIC + s_mutex_man.resrc_mutex = xSemaphoreCreateMutexStatic(&s_mutex_man.resrc_storage); +#else + s_mutex_man.resrc_mutex = xSemaphoreCreateMutex(); +#endif + OSAL_RUNTIME_ASSERT(s_mutex_man.resrc_mutex != NULL); + OSAL_RM_USEROBJMAN_INIT(&s_mutex_man, OSAL_MUTEX_NUM_MAX, NULL); + s_mutex_man.init = true; + return OSAL_E_OK; +} + +void osal_mutex_deinit(void) +{ + if (!s_mutex_man.init) { + return; + } + osal_rm_deinit(&s_mutex_man.rm); + vSemaphoreDelete(s_mutex_man.resrc_mutex); + s_mutex_man.init = false; +} + +osal_mutex_t *osal_mutex_create(void) +{ + osal_resrc_t *resrc; + osal_mutex_t *mutex; + + if (!s_mutex_man.init) { + return NULL; + } + + xSemaphoreTake(s_mutex_man.resrc_mutex, portMAX_DELAY); + resrc = osal_rm_alloc(&s_mutex_man.rm); + xSemaphoreGive(s_mutex_man.resrc_mutex); + if (resrc == NULL) { + return NULL; + } + + mutex = (osal_mutex_t *)resrc->data; + OSAL_RUNTIME_ASSERT(mutex != NULL); + mutex->resrc = resrc; +#if DMOSAL_FREERTOS_STATIC + mutex->handle = xSemaphoreCreateMutexStatic(&mutex->storage); +#else + mutex->handle = xSemaphoreCreateMutex(); +#endif + OSAL_RUNTIME_ASSERT(mutex->handle != NULL); + return mutex; +} + +void osal_mutex_delete(osal_mutex_t *mutex) +{ + if (mutex == NULL) { + return; + } + + vSemaphoreDelete(mutex->handle); + xSemaphoreTake(s_mutex_man.resrc_mutex, portMAX_DELAY); + osal_rm_free(&s_mutex_man.rm, mutex->resrc); + xSemaphoreGive(s_mutex_man.resrc_mutex); +} + +osal_error_t osal_mutex_lock(osal_mutex_t *mutex) +{ + if (mutex == NULL) { + return OSAL_E_PARAM; + } + + if (xSemaphoreTake(mutex->handle, portMAX_DELAY) != pdTRUE) { + return OSAL_E_OSCALL; + } + return OSAL_E_OK; +} + +osal_error_t osal_mutex_unlock(osal_mutex_t *mutex) +{ + if (mutex == NULL) { + return OSAL_E_PARAM; + } + + /* Fails when the caller is not the owner. */ + if (xSemaphoreGive(mutex->handle) != pdTRUE) { + return OSAL_E_OSCALL; + } + return OSAL_E_OK; +} + +uint32_t osal_mutex_use(void) +{ + return s_mutex_man.init ? osal_rm_use(&s_mutex_man.rm) : 0; +} + +uint32_t osal_mutex_avail(void) +{ + return s_mutex_man.init ? osal_rm_avail(&s_mutex_man.rm) : 0; +} diff --git a/source/freertos/osal_queue.c b/source/freertos/osal_queue.c new file mode 100644 index 0000000..259a6c5 --- /dev/null +++ b/source/freertos/osal_queue.c @@ -0,0 +1,214 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ + +/* FreeRTOS backend (static allocation only). */ + +#include +#include +#include +#include "osal_queue.h" +#include "osal_rm.h" +#include "osal_assert.h" +#include "osal_config.h" +#include "osal_freertos_priv.h" +#include "queue.h" + +/* Shared by every handle created with the same name (mirrors Linux mq_open attach). */ +typedef struct { +#if DMOSAL_FREERTOS_STATIC + StaticQueue_t storage; + uint8_t buf[OSAL_QUEUE_BUF_SIZE]; +#endif + QueueHandle_t handle; + char name[OSAL_QUEUE_NAME_SIZE + 1]; + uint32_t msglen; + uint32_t qsize; + uint32_t refs; +} queue_core_t; + +struct osal_queue { + queue_core_t *core; + osal_resrc_t *resrc; +}; + +typedef struct { + OSAL_RM_USEROBJMAN_DECLARE(struct osal_queue, OSAL_QUEUE_NUM_MAX); + queue_core_t cores[OSAL_QUEUE_NUM_MAX]; + osal_mutex_t *mutex; /* shared mutex, protects cores[]; may be NULL */ + bool init; +} queue_man_t; + +static queue_man_t s_queue_man; + +static void cores_lock(void) +{ + if (s_queue_man.mutex != NULL) { + osal_error_t res = osal_mutex_lock(s_queue_man.mutex); + + OSAL_RUNTIME_ASSERT(res == OSAL_E_OK); + (void)res; + } +} + +static void cores_unlock(void) +{ + if (s_queue_man.mutex != NULL) { + osal_error_t res = osal_mutex_unlock(s_queue_man.mutex); + + OSAL_RUNTIME_ASSERT(res == OSAL_E_OK); + (void)res; + } +} + +osal_error_t osal_queue_init(osal_mutex_t *mutex) +{ + if (s_queue_man.init) { + return OSAL_E_OK; + } + + OSAL_RM_USEROBJMAN_INIT(&s_queue_man, OSAL_QUEUE_NUM_MAX, mutex); + memset(s_queue_man.cores, 0, sizeof(s_queue_man.cores)); + s_queue_man.mutex = mutex; + s_queue_man.init = true; + return OSAL_E_OK; +} + +void osal_queue_deinit(void) +{ + if (!s_queue_man.init) { + return; + } + osal_rm_deinit(&s_queue_man.rm); + s_queue_man.init = false; +} + +/* Find the core with this name, or claim a free one. Caller holds the lock. */ +static queue_core_t *core_get(const osal_queue_cfg_t *cfg) +{ + queue_core_t *free_core = NULL; + + for (int i = 0; i < OSAL_QUEUE_NUM_MAX; i++) { + queue_core_t *core = &s_queue_man.cores[i]; + + if (core->refs == 0) { + if (free_core == NULL) { + free_core = core; + } + } else if (strncmp(core->name, (const char *)cfg->name, OSAL_QUEUE_NAME_SIZE) == 0) { + if (core->msglen != cfg->msglen || core->qsize != cfg->qsize) { + return NULL; + } + core->refs++; + return core; + } + } + + if (free_core == NULL) { + return NULL; + } + memset(free_core, 0, sizeof(*free_core)); +#if DMOSAL_FREERTOS_STATIC + free_core->handle = + xQueueCreateStatic(cfg->qsize, cfg->msglen, free_core->buf, &free_core->storage); +#else + free_core->handle = xQueueCreate(cfg->qsize, cfg->msglen); +#endif + if (free_core->handle == NULL) { + return NULL; + } + memcpy(free_core->name, cfg->name, OSAL_QUEUE_NAME_SIZE); + free_core->msglen = cfg->msglen; + free_core->qsize = cfg->qsize; + free_core->refs = 1; + return free_core; +} + +osal_queue_t *osal_queue_create(const osal_queue_cfg_t *cfg) +{ + osal_resrc_t *resrc; + osal_queue_t *queue; + queue_core_t *core; + + if (!s_queue_man.init || cfg == NULL || cfg->name[0] == '\0' || cfg->msglen == 0 || + cfg->qsize == 0 || cfg->msglen > OSAL_QUEUE_MSG_MAX_SIZE || + cfg->qsize > OSAL_QUEUE_MSG_NUM_MAX) { + return NULL; + } + + resrc = osal_rm_alloc(&s_queue_man.rm); + if (resrc == NULL) { + return NULL; + } + + cores_lock(); + core = core_get(cfg); + cores_unlock(); + if (core == NULL) { + osal_rm_free(&s_queue_man.rm, resrc); + return NULL; + } + + queue = (osal_queue_t *)resrc->data; + OSAL_RUNTIME_ASSERT(queue != NULL); + queue->resrc = resrc; + queue->core = core; + return queue; +} + +void osal_queue_delete(osal_queue_t *queue) +{ + if (queue == NULL) { + return; + } + + osal_resrc_t *resrc = queue->resrc; + queue_core_t *core = queue->core; + + /* The queue and its pending messages live until the last handle is deleted. */ + cores_lock(); + if (--core->refs == 0) { + vQueueDelete(core->handle); + memset(core, 0, sizeof(*core)); + } + cores_unlock(); + + memset(queue, 0, sizeof(*queue)); + osal_rm_free(&s_queue_man.rm, resrc); +} + +osal_error_t osal_queue_send(osal_queue_t *queue, uint8_t *msg, uint32_t msglen) +{ + if (queue == NULL || msg == NULL || msglen == 0 || msglen > queue->core->msglen) { + return OSAL_E_PARAM; + } + + /* The queue copies a fixed msglen; zero-pad shorter messages. */ + uint8_t tmp[OSAL_QUEUE_MSG_MAX_SIZE] = {0}; + + memcpy(tmp, msg, msglen); + return xQueueSend(queue->core->handle, tmp, 0) == pdTRUE ? OSAL_E_OK : OSAL_E_QFULL; +} + +osal_error_t +osal_queue_recv(osal_queue_t *queue, uint8_t *buf, uint32_t bufsize, uint32_t timeout_usec) +{ + if (queue == NULL || buf == NULL || bufsize < queue->core->msglen) { + return OSAL_E_PARAM; + } + + if (xQueueReceive(queue->core->handle, buf, osal_freertos_usec_to_ticks(timeout_usec)) == + pdTRUE) { + return OSAL_E_OK; + } + return OSAL_E_TIMEOUT; +} + +uint32_t osal_queue_use(void) +{ + return s_queue_man.init ? osal_rm_use(&s_queue_man.rm) : 0; +} + +uint32_t osal_queue_avail(void) +{ + return s_queue_man.init ? osal_rm_avail(&s_queue_man.rm) : 0; +} diff --git a/source/freertos/osal_sem.c b/source/freertos/osal_sem.c new file mode 100644 index 0000000..6ac7641 --- /dev/null +++ b/source/freertos/osal_sem.c @@ -0,0 +1,130 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ + +/* FreeRTOS backend (static allocation only). */ + +#include +#include +#include "osal_sem.h" +#include "osal_rm.h" +#include "osal_assert.h" +#include "osal_config.h" +#include "osal_freertos_priv.h" +#include "semphr.h" + +#define SEM_MAX_COUNT ((UBaseType_t)0x7FFFFFFF) + +struct osal_sem { +#if DMOSAL_FREERTOS_STATIC + StaticSemaphore_t storage; +#endif + SemaphoreHandle_t handle; + osal_resrc_t *resrc; +}; + +typedef struct { + OSAL_RM_USEROBJMAN_DECLARE(struct osal_sem, OSAL_SEM_NUM_MAX); + bool init; +} sem_man_t; + +static sem_man_t s_sem_man; + +osal_error_t osal_sem_init(osal_mutex_t *mutex) +{ + if (s_sem_man.init) { + return OSAL_E_OK; + } + + OSAL_RM_USEROBJMAN_INIT(&s_sem_man, OSAL_SEM_NUM_MAX, mutex); + s_sem_man.init = true; + return OSAL_E_OK; +} + +void osal_sem_deinit(void) +{ + if (!s_sem_man.init) { + return; + } + osal_rm_deinit(&s_sem_man.rm); + s_sem_man.init = false; +} + +osal_sem_t *osal_sem_create(void) +{ + osal_resrc_t *resrc; + osal_sem_t *sem; + + if (!s_sem_man.init) { + return NULL; + } + + resrc = osal_rm_alloc(&s_sem_man.rm); + if (resrc == NULL) { + return NULL; + } + + sem = (osal_sem_t *)resrc->data; + OSAL_RUNTIME_ASSERT(sem != NULL); + sem->resrc = resrc; + +#if DMOSAL_FREERTOS_STATIC + sem->handle = xSemaphoreCreateCountingStatic(SEM_MAX_COUNT, 0, &sem->storage); +#else + sem->handle = xSemaphoreCreateCounting(SEM_MAX_COUNT, 0); +#endif + if (sem->handle == NULL) { + osal_rm_free(&s_sem_man.rm, resrc); + return NULL; + } + return sem; +} + +void osal_sem_delete(osal_sem_t *sem) +{ + if (sem == NULL) { + return; + } + + vSemaphoreDelete(sem->handle); + osal_rm_free(&s_sem_man.rm, sem->resrc); +} + +osal_error_t osal_sem_post(osal_sem_t *sem) +{ + if (sem == NULL) { + return OSAL_E_PARAM; + } + + return xSemaphoreGive(sem->handle) == pdTRUE ? OSAL_E_OK : OSAL_E_OSCALL; +} + +osal_error_t osal_sem_wait(osal_sem_t *sem) +{ + if (sem == NULL) { + return OSAL_E_PARAM; + } + + return xSemaphoreTake(sem->handle, portMAX_DELAY) == pdTRUE ? OSAL_E_OK : OSAL_E_OSCALL; +} + +osal_error_t osal_sem_waittime(osal_sem_t *sem, uint32_t usec) +{ + if (sem == NULL) { + return OSAL_E_PARAM; + } + + if (xSemaphoreTake(sem->handle, osal_freertos_usec_to_ticks(usec)) == pdTRUE) { + return OSAL_E_OK; + } + return OSAL_E_TIMEOUT; +} + +uint32_t osal_sem_use(void) +{ + return s_sem_man.init ? osal_rm_use(&s_sem_man.rm) : 0; +} + +uint32_t osal_sem_avail(void) +{ + return s_sem_man.init ? osal_rm_avail(&s_sem_man.rm) : 0; +} diff --git a/source/freertos/osal_task.c b/source/freertos/osal_task.c new file mode 100644 index 0000000..ac2ab68 --- /dev/null +++ b/source/freertos/osal_task.c @@ -0,0 +1,181 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ + +/* FreeRTOS backend (static allocation only). */ + +#include +#include +#include +#include "osal_task.h" +#include "osal_rm.h" +#include "osal_assert.h" +#include "osal_config.h" +#include "osal_freertos_priv.h" + +/* All build-mode differences (static/dynamic allocation, embedded stack) live in this block. */ +#if DMOSAL_FREERTOS_STATIC && OSAL_TASK_STACK_EMBEDDED +#define EMBEDDED_STACK_WORDS (OSAL_TASK_STACK_SIZE_DEFAULT / sizeof(StackType_t)) +#define TASK_STACK_MEMBER StackType_t stack[EMBEDDED_STACK_WORDS]; +#define EMBEDDED_STACK(t) ((t)->stack) +#else +#define EMBEDDED_STACK_WORDS 0 +#define TASK_STACK_MEMBER +#define EMBEDDED_STACK(t) ((StackType_t *)NULL) +#endif + +#if DMOSAL_FREERTOS_STATIC +#define TASK_KERNEL_MEMBER StaticTask_t tcb; +#else +#define TASK_KERNEL_MEMBER +#endif + +struct osal_task { + TASK_KERNEL_MEMBER + TASK_STACK_MEMBER + TaskHandle_t handle; + osal_task_cfg_t taskcfg; + osal_resrc_t *resrc; +}; + +static void task_entry(void *arg) +{ + osal_task_t *task = arg; + + /* Set before the handler runs: the creator may not have stored the handle yet. */ + task->handle = xTaskGetCurrentTaskHandle(); + task->taskcfg.task_handler(task->taskcfg.task_arg); + + /* A FreeRTOS task must not return, and a self-deleted task keeps its TCB until the idle + * task cleans it up. Park instead, so osal_task_delete() can always remove it safely. */ + for (;;) { + vTaskSuspend(NULL); + } +} + +#if DMOSAL_FREERTOS_STATIC +/* The stack is the caller's (stack_addr) or, if enabled, the one embedded in the task object. */ +static bool task_kernel_create(osal_task_t *task, const char *name, UBaseType_t priority) +{ + const osal_task_cfg_t *cfg = &task->taskcfg; + StackType_t *stack = cfg->stack_addr; + uint32_t words; + + if (stack != NULL) { + if (cfg->stack_size == 0 || ((uintptr_t)stack % portBYTE_ALIGNMENT) != 0) { + return false; + } + words = cfg->stack_size / (uint32_t)sizeof(StackType_t); + } else { + stack = EMBEDDED_STACK(task); + words = cfg->stack_size != 0 ? cfg->stack_size / (uint32_t)sizeof(StackType_t) + : EMBEDDED_STACK_WORDS; + if (stack == NULL || words > EMBEDDED_STACK_WORDS) { + return false; + } + } + if (words == 0) { + return false; + } + task->handle = xTaskCreateStatic(task_entry, name, words, task, priority, stack, &task->tcb); + return task->handle != NULL; +} +#else +/* The kernel allocates the stack from its heap, so stack_addr is not used. */ +static bool task_kernel_create(osal_task_t *task, const char *name, UBaseType_t priority) +{ + uint32_t size = + task->taskcfg.stack_size != 0 ? task->taskcfg.stack_size : OSAL_TASK_STACK_SIZE_DEFAULT; + uint32_t words = size / (uint32_t)sizeof(StackType_t); + + if (words == 0 || + xTaskCreate(task_entry, name, words, task, priority, &task->handle) != pdPASS) { + task->handle = NULL; + } + return task->handle != NULL; +} +#endif + +typedef struct { + OSAL_RM_USEROBJMAN_DECLARE(struct osal_task, OSAL_TASK_NUM_MAX); + bool init; +} task_man_t; + +static task_man_t s_task_man; + +osal_error_t osal_task_init(osal_mutex_t *mutex) +{ + if (s_task_man.init) { + return OSAL_E_OK; + } + + OSAL_RM_USEROBJMAN_INIT(&s_task_man, OSAL_TASK_NUM_MAX, mutex); + s_task_man.init = true; + return OSAL_E_OK; +} + +void osal_task_deinit(void) +{ + if (!s_task_man.init) { + return; + } + osal_rm_deinit(&s_task_man.rm); + s_task_man.init = false; +} + +osal_task_t *osal_task_create(const osal_task_cfg_t *cfg) +{ + osal_resrc_t *resrc; + osal_task_t *task; + UBaseType_t priority; + + if (!s_task_man.init || cfg == NULL || cfg->task_handler == NULL) { + return NULL; + } + priority = cfg->priority != 0 ? cfg->priority : OSAL_TASK_PRIORITY_DEFAULT; + if (priority >= configMAX_PRIORITIES) { + return NULL; + } + + resrc = osal_rm_alloc(&s_task_man.rm); + if (resrc == NULL) { + return NULL; + } + + task = (osal_task_t *)resrc->data; + OSAL_RUNTIME_ASSERT(task != NULL); + memcpy(&task->taskcfg, cfg, sizeof(*cfg)); + task->resrc = resrc; + + const char *name = task->taskcfg.name[0] != '\0' ? (const char *)task->taskcfg.name : "osal"; + if (!task_kernel_create(task, name, priority)) { + osal_rm_free(&s_task_man.rm, resrc); + return NULL; + } + return task; +} + +void osal_task_delete(osal_task_t *task) +{ + if (task == NULL) { + return; + } + + /* A task cannot delete itself: its TCB is only released by the idle task, so the slot + * must not be reused yet. */ + if (task->handle == xTaskGetCurrentTaskHandle()) { + return; + } + + vTaskDelete(task->handle); + osal_rm_free(&s_task_man.rm, task->resrc); +} + +uint32_t osal_task_use(void) +{ + return s_task_man.init ? osal_rm_use(&s_task_man.rm) : 0; +} + +uint32_t osal_task_avail(void) +{ + return s_task_man.init ? osal_rm_avail(&s_task_man.rm) : 0; +} diff --git a/source/freertos/osal_time.c b/source/freertos/osal_time.c new file mode 100644 index 0000000..6455a93 --- /dev/null +++ b/source/freertos/osal_time.c @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ + +/* FreeRTOS backend. Time has tick resolution (1 / configTICK_RATE_HZ). */ + +#include +#include "osal_time.h" +#include "osal_freertos_priv.h" + +_Static_assert(sizeof(TickType_t) >= 4, "16-bit ticks are not supported"); + +osal_error_t osal_sleep(uint32_t sec) +{ + /* Sleep one second at a time so the tick count cannot overflow. */ + while (sec-- > 0) { + vTaskDelay(osal_freertos_usec_to_ticks(1000000U)); + } + return OSAL_E_OK; +} + +osal_error_t osal_usleep(uint32_t microsec) +{ + TickType_t ticks = osal_freertos_usec_to_ticks(microsec); + + if (ticks == 0) { + taskYIELD(); + } else { + vTaskDelay(ticks); + } + return OSAL_E_OK; +} + +osal_error_t osal_clock_time(uint64_t *nsec) +{ + static TickType_t s_last_ticks; + static uint64_t s_wraps; + uint64_t ticks; + + if (nsec == NULL) { + return OSAL_E_PARAM; + } + + /* The tick count is 32 bits wide: extend it to 64 bits by counting the wrap-arounds. */ + taskENTER_CRITICAL(); + { + TickType_t now = xTaskGetTickCount(); + + if (now < s_last_ticks) { + s_wraps++; + } + s_last_ticks = now; + ticks = sizeof(TickType_t) < sizeof(uint64_t) ? (s_wraps << 32) | now : now; + } + taskEXIT_CRITICAL(); + + /* Callers such as tmcheck use 0 as "not set"; the tick count is 0 right after boot. */ + *nsec = ticks * (1000000000ULL / configTICK_RATE_HZ) + 1U; + return OSAL_E_OK; +} diff --git a/source/freertos/osal_timer.c b/source/freertos/osal_timer.c new file mode 100644 index 0000000..8340235 --- /dev/null +++ b/source/freertos/osal_timer.c @@ -0,0 +1,161 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ + +/* FreeRTOS backend (static allocation only). + * + * expire() runs in the FreeRTOS timer service task, which executes callbacks one at a time. + * osal_timer_delete() queues the kernel delete and then a pended call that releases the slot, so + * the slot is only reused after any running callback has returned. Needs + * INCLUDE_xTimerPendFunctionCall. */ + +#include +#include +#include +#include "osal_timer.h" +#include "osal_rm.h" +#include "osal_assert.h" +#include "osal_config.h" +#include "osal_freertos_priv.h" +#include "timers.h" + +struct osal_timer { +#if DMOSAL_FREERTOS_STATIC + StaticTimer_t storage; +#endif + TimerHandle_t handle; + void (*expire)(void *arg); + void *arg; + volatile bool in_callback; + osal_resrc_t *resrc; +}; + +typedef struct { + OSAL_RM_USEROBJMAN_DECLARE(struct osal_timer, OSAL_TIMER_NUM_MAX); + bool init; +} timer_man_t; + +static timer_man_t s_timer_man; + +static void timer_callback(TimerHandle_t handle) +{ + osal_timer_t *timer = pvTimerGetTimerID(handle); + + timer->in_callback = true; + timer->expire(timer->arg); + timer->in_callback = false; +} + +osal_error_t osal_timer_init(osal_mutex_t *mutex) +{ + if (s_timer_man.init) { + return OSAL_E_OK; + } + + OSAL_RM_USEROBJMAN_INIT(&s_timer_man, OSAL_TIMER_NUM_MAX, mutex); + s_timer_man.init = true; + return OSAL_E_OK; +} + +void osal_timer_deinit(void) +{ + if (!s_timer_man.init) { + return; + } + osal_rm_deinit(&s_timer_man.rm); + s_timer_man.init = false; +} + +osal_timer_t *osal_timer_create(void (*expire)(void *arg), void *arg) +{ + osal_resrc_t *resrc; + osal_timer_t *timer; + + if (!s_timer_man.init || expire == NULL) { + return NULL; + } + + resrc = osal_rm_alloc(&s_timer_man.rm); + if (resrc == NULL) { + return NULL; + } + + timer = (osal_timer_t *)resrc->data; + OSAL_RUNTIME_ASSERT(timer != NULL); + memset(timer, 0, sizeof(*timer)); + timer->resrc = resrc; + timer->expire = expire; + timer->arg = arg; + + /* The period is set by osal_timer_start(). */ +#if DMOSAL_FREERTOS_STATIC + timer->handle = xTimerCreateStatic("osal", 1, pdFALSE, timer, timer_callback, &timer->storage); +#else + timer->handle = xTimerCreate("osal", 1, pdFALSE, timer, timer_callback); +#endif + if (timer->handle == NULL) { + osal_rm_free(&s_timer_man.rm, resrc); + return NULL; + } + return timer; +} + +osal_error_t osal_timer_start(osal_timer_t *timer, uint32_t usec, bool repeat) +{ + if (timer == NULL || usec == 0) { + return OSAL_E_PARAM; + } + + vTimerSetReloadMode(timer->handle, repeat ? pdTRUE : pdFALSE); + /* Changing the period of a timer also (re)starts it. */ + if (xTimerChangePeriod(timer->handle, osal_freertos_usec_to_ticks(usec), portMAX_DELAY) != + pdPASS) { + return OSAL_E_OSCALL; + } + return OSAL_E_OK; +} + +void osal_timer_stop(osal_timer_t *timer) +{ + if (timer == NULL) { + return; + } + + xTimerStop(timer->handle, portMAX_DELAY); +} + +static void timer_release(void *param1, uint32_t param2) +{ + osal_timer_t *timer = param1; + + (void)param2; + osal_rm_free(&s_timer_man.rm, timer->resrc); +} + +void osal_timer_delete(osal_timer_t *timer) +{ + if (timer == NULL) { + return; + } + + /* Deleting from inside the expire callback is not supported */ + if (timer->in_callback) { + return; + } + + xTimerDelete(timer->handle, portMAX_DELAY); + /* The timer service task runs this after the delete command above. */ + BaseType_t queued = xTimerPendFunctionCall(timer_release, timer, 0, portMAX_DELAY); + + OSAL_RUNTIME_ASSERT(queued == pdPASS); + (void)queued; +} + +uint32_t osal_timer_use(void) +{ + return s_timer_man.init ? osal_rm_use(&s_timer_man.rm) : 0; +} + +uint32_t osal_timer_avail(void) +{ + return s_timer_man.init ? osal_rm_avail(&s_timer_man.rm) : 0; +} diff --git a/source/linux/osal_mutex.c b/source/linux/osal_mutex.c index 1c14641..24053a5 100644 --- a/source/linux/osal_mutex.c +++ b/source/linux/osal_mutex.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include #include "osal_rm.h" diff --git a/source/linux/osal_queue.c b/source/linux/osal_queue.c index edbe9e9..84a18c4 100644 --- a/source/linux/osal_queue.c +++ b/source/linux/osal_queue.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2024, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include #include diff --git a/source/linux/osal_sem.c b/source/linux/osal_sem.c index e6a4b90..a672972 100644 --- a/source/linux/osal_sem.c +++ b/source/linux/osal_sem.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include #include diff --git a/source/linux/osal_task.c b/source/linux/osal_task.c index 40d5a9f..40f24f1 100644 --- a/source/linux/osal_task.c +++ b/source/linux/osal_task.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include #include diff --git a/source/linux/osal_time.c b/source/linux/osal_time.c index ba42f25..eaed7ac 100644 --- a/source/linux/osal_time.c +++ b/source/linux/osal_time.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include #include diff --git a/source/linux/osal_timer.c b/source/linux/osal_timer.c index 28610dc..ec03497 100644 --- a/source/linux/osal_timer.c +++ b/source/linux/osal_timer.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include #include diff --git a/source/osal.c b/source/osal.c index b268bbb..172e96b 100644 --- a/source/osal.c +++ b/source/osal.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include #include #include "osal.h" @@ -36,6 +13,39 @@ static void log_output_default(char *logstr) printf("%s", logstr); } +static void teardown(void) +{ + /* Tear down subsystems that use the shared mutex FIRST, their + * osal_rm_deinit locks the shared mutex. Deleting the shared mutex + * before this point would leave those locks operating on a destroyed + * mutex. + */ + osal_sem_deinit(); + osal_task_deinit(); + osal_timer_deinit(); + osal_queue_deinit(); + osal_tmcheck_deinit(); + + /* Log is independent of the shared mutex. */ + osal_log_deinit(); + + /* Now safe to destroy the shared mutex and tear down the mutex pool. */ + if (s_shared_mutex != NULL) { + osal_mutex_delete(s_shared_mutex); + s_shared_mutex = NULL; + } + osal_mutex_deinit(); +} + +/* Runs one init step and unwinds everything on failure. */ +#define INIT_STEP(call) \ + do { \ + res = (call); \ + if (res != OSAL_E_OK) { \ + goto fail; \ + } \ + } while (0) + osal_error_t osal_init(const osal_config_t *config) { osal_error_t res; @@ -54,45 +64,45 @@ osal_error_t osal_init(const osal_config_t *config) } /* mutex must be init first since it is used in other osal modules */ - res = osal_mutex_init(); - OSAL_RUNTIME_ASSERT(res == OSAL_E_OK); + INIT_STEP(osal_mutex_init()); /* log initialization */ - res = osal_log_init(log_output); - OSAL_RUNTIME_ASSERT(res == OSAL_E_OK); + INIT_STEP(osal_log_init(log_output)); /* log module initialization */ - res = osal_log_module_init(OSAL_LOG_MODULE_INDEX, "osal", log_level, false); - OSAL_RUNTIME_ASSERT(res == OSAL_E_OK); + INIT_STEP(osal_log_module_init(OSAL_LOG_MODULE_INDEX, "osal", log_level, false)); /* create a shared local mutex */ OSAL_RUNTIME_ASSERT(s_shared_mutex == NULL); s_shared_mutex = osal_mutex_create(); - OSAL_RUNTIME_ASSERT(s_shared_mutex != NULL); + if (s_shared_mutex == NULL) { + res = OSAL_E_RESRC; + goto fail; + } /* semaphore initialization */ - res = osal_sem_init(s_shared_mutex); - OSAL_RUNTIME_ASSERT(res == OSAL_E_OK); + INIT_STEP(osal_sem_init(s_shared_mutex)); /* task initialization */ - res = osal_task_init(s_shared_mutex); - OSAL_RUNTIME_ASSERT(res == OSAL_E_OK); + INIT_STEP(osal_task_init(s_shared_mutex)); /* timer initialization */ - res = osal_timer_init(s_shared_mutex); - OSAL_RUNTIME_ASSERT(res == OSAL_E_OK); + INIT_STEP(osal_timer_init(s_shared_mutex)); /* queue initialization */ - res = osal_queue_init(s_shared_mutex); - OSAL_RUNTIME_ASSERT(res == OSAL_E_OK); + INIT_STEP(osal_queue_init(s_shared_mutex)); - res = osal_tmcheck_init(s_shared_mutex); - OSAL_RUNTIME_ASSERT(res == OSAL_E_OK); + INIT_STEP(osal_tmcheck_init(s_shared_mutex)); /* initialization done */ s_initialized = true; return OSAL_E_OK; + +fail: + /* Every deinit ignores a subsystem that was not initialized. */ + teardown(); + return res; } char *osal_version(void) @@ -138,26 +148,6 @@ void osal_deinit(void) if (s_initialized == false) { return; } - OSAL_RUNTIME_ASSERT(s_shared_mutex != NULL); - - /* Tear down subsystems that use the shared mutex FIRST — their - * osal_rm_deinit locks the shared mutex. Deleting the shared mutex - * before this point would leave those locks operating on a destroyed - * mutex. - */ - osal_sem_deinit(); - osal_task_deinit(); - osal_timer_deinit(); - osal_queue_deinit(); - osal_tmcheck_deinit(); - - /* Log is independent of the shared mutex. */ - osal_log_deinit(); - - /* Now safe to destroy the shared mutex and tear down the mutex pool. */ - osal_mutex_delete(s_shared_mutex); - s_shared_mutex = NULL; - osal_mutex_deinit(); - + teardown(); s_initialized = false; } diff --git a/source/osal_error.c b/source/osal_error.c index 31a39b5..4185fc8 100644 --- a/source/osal_error.c +++ b/source/osal_error.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include #include "osal_error.h" diff --git a/source/osal_lifo.c b/source/osal_lifo.c index cb17309..c5e793c 100644 --- a/source/osal_lifo.c +++ b/source/osal_lifo.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include #include "osal_lifo.h" diff --git a/source/osal_log.c b/source/osal_log.c index 83102b1..758e2c3 100644 --- a/source/osal_log.c +++ b/source/osal_log.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2024, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include #include diff --git a/source/osal_rm.c b/source/osal_rm.c index cb7e595..75965a0 100644 --- a/source/osal_rm.c +++ b/source/osal_rm.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include #include "osal_assert.h" diff --git a/source/osal_tmcheck.c b/source/osal_tmcheck.c index 82cc653..963483c 100644 --- a/source/osal_tmcheck.c +++ b/source/osal_tmcheck.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2025, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include #include "osal.h" #define OSALOG_MODULE OSAL_LOG_MODULE_INDEX diff --git a/source/zephyr/osal_mutex.c b/source/zephyr/osal_mutex.c index a2894f0..6190dd5 100644 --- a/source/zephyr/osal_mutex.c +++ b/source/zephyr/osal_mutex.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ /* Zephyr backend (native kernel API). */ diff --git a/source/zephyr/osal_queue.c b/source/zephyr/osal_queue.c index e4e4a4d..4fc4850 100644 --- a/source/zephyr/osal_queue.c +++ b/source/zephyr/osal_queue.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ /* Zephyr backend (native kernel API). */ @@ -39,7 +16,7 @@ /* Shared by every handle created with the same name (mirrors Linux mq_open attach). */ typedef struct { struct k_msgq msgq; - char buf[CONFIG_DMOSAL_QUEUE_BUF_SIZE] __aligned(sizeof(void *)); + char buf[OSAL_QUEUE_BUF_SIZE] __aligned(sizeof(void *)); char name[OSAL_QUEUE_NAME_SIZE + 1]; uint32_t msglen; uint32_t qsize; @@ -63,14 +40,20 @@ static queue_man_t s_queue_man; static void cores_lock(void) { if (s_queue_man.mutex != NULL) { - OSAL_RUNTIME_ASSERT(osal_mutex_lock(s_queue_man.mutex) == OSAL_E_OK); + osal_error_t res = osal_mutex_lock(s_queue_man.mutex); + + OSAL_RUNTIME_ASSERT(res == OSAL_E_OK); + (void)res; } } static void cores_unlock(void) { if (s_queue_man.mutex != NULL) { - OSAL_RUNTIME_ASSERT(osal_mutex_unlock(s_queue_man.mutex) == OSAL_E_OK); + osal_error_t res = osal_mutex_unlock(s_queue_man.mutex); + + OSAL_RUNTIME_ASSERT(res == OSAL_E_OK); + (void)res; } } @@ -136,8 +119,8 @@ osal_queue_t *osal_queue_create(const osal_queue_cfg_t *cfg) queue_core_t *core; if (!s_queue_man.init || cfg == NULL || cfg->name[0] == '\0' || cfg->msglen == 0 || - cfg->qsize == 0 || cfg->msglen > CONFIG_DMOSAL_QUEUE_MSG_MAX_SIZE || - cfg->msglen * cfg->qsize > CONFIG_DMOSAL_QUEUE_BUF_SIZE) { + cfg->qsize == 0 || cfg->msglen > OSAL_QUEUE_MSG_MAX_SIZE || + cfg->qsize > OSAL_QUEUE_MSG_NUM_MAX) { return NULL; } @@ -189,7 +172,7 @@ osal_error_t osal_queue_send(osal_queue_t *queue, uint8_t *msg, uint32_t msglen) } /* k_msgq copies a fixed msglen; zero-pad shorter messages. */ - uint8_t tmp[CONFIG_DMOSAL_QUEUE_MSG_MAX_SIZE] = {0}; + uint8_t tmp[OSAL_QUEUE_MSG_MAX_SIZE] = {0}; int res; memcpy(tmp, msg, msglen); diff --git a/source/zephyr/osal_sem.c b/source/zephyr/osal_sem.c index b9ab7ae..fe2b3f1 100644 --- a/source/zephyr/osal_sem.c +++ b/source/zephyr/osal_sem.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ /* Zephyr backend (native kernel API). */ diff --git a/source/zephyr/osal_task.c b/source/zephyr/osal_task.c index e7cac5e..e1317b2 100644 --- a/source/zephyr/osal_task.c +++ b/source/zephyr/osal_task.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ /* Zephyr backend (native kernel API). */ @@ -35,12 +12,42 @@ #include "osal_assert.h" #include "osal_config.h" +/* Tasks are kernel threads (no user mode), so they use kernel stacks. */ +#if OSAL_TASK_STACK_EMBEDDED +#define TASK_STACK_MEMBER K_KERNEL_STACK_MEMBER(stack, OSAL_TASK_STACK_SIZE_DEFAULT); +#define EMBEDDED_STACK(t) ((t)->stack) +#define EMBEDDED_STACK_SIZE(t) K_KERNEL_STACK_SIZEOF((t)->stack) +#else +#define TASK_STACK_MEMBER +#define EMBEDDED_STACK(t) ((k_thread_stack_t *)NULL) +#define EMBEDDED_STACK_SIZE(t) 0 +#endif + struct osal_task { struct k_thread thread; + TASK_STACK_MEMBER osal_task_cfg_t taskcfg; osal_resrc_t *resrc; }; +/* The stack is the caller's (stack_addr) or, if enabled, the one embedded in the task object. */ +static bool task_stack_get(osal_task_t *task, k_thread_stack_t **stack, size_t *size) +{ + const osal_task_cfg_t *cfg = &task->taskcfg; + + if (cfg->stack_addr != NULL) { + *stack = cfg->stack_addr; + *size = cfg->stack_size; + } else { + *stack = EMBEDDED_STACK(task); + *size = cfg->stack_size != 0 ? cfg->stack_size : EMBEDDED_STACK_SIZE(task); + if (cfg->stack_size > EMBEDDED_STACK_SIZE(task)) { + return false; + } + } + return *stack != NULL && *size != 0; +} + typedef struct { OSAL_RM_USEROBJMAN_DECLARE(struct osal_task, OSAL_TASK_NUM_MAX); bool init; @@ -48,9 +55,6 @@ typedef struct { static task_man_t s_task_man; -/* One static stack per pool slot; the slot index selects the stack. */ -static K_THREAD_STACK_ARRAY_DEFINE(s_stacks, OSAL_TASK_NUM_MAX, CONFIG_DMOSAL_TASK_STACK_SIZE); - static void task_entry(void *p1, void *p2, void *p3) { osal_task_t *task = p1; @@ -84,10 +88,17 @@ osal_task_t *osal_task_create(const osal_task_cfg_t *cfg) { osal_resrc_t *resrc; osal_task_t *task; + k_thread_stack_t *stack; + size_t stack_size; + uint16_t priority; if (!s_task_man.init || cfg == NULL || cfg->task_handler == NULL) { return NULL; } + priority = cfg->priority != 0 ? cfg->priority : OSAL_TASK_PRIORITY_DEFAULT; + if (priority >= CONFIG_NUM_PREEMPT_PRIORITIES) { + return NULL; + } resrc = osal_rm_alloc(&s_task_man.rm); if (resrc == NULL) { @@ -99,15 +110,19 @@ osal_task_t *osal_task_create(const osal_task_cfg_t *cfg) memcpy(&task->taskcfg, cfg, sizeof(*cfg)); task->resrc = resrc; - size_t idx = (size_t)(task - s_task_man.userobj); + if (!task_stack_get(task, &stack, &stack_size)) { + osal_rm_free(&s_task_man.rm, resrc); + return NULL; + } + k_tid_t tid = k_thread_create(&task->thread, - s_stacks[idx], - K_THREAD_STACK_SIZEOF(s_stacks[idx]), + stack, + stack_size, task_entry, task, NULL, NULL, - K_PRIO_PREEMPT(CONFIG_DMOSAL_TASK_PRIORITY), + K_PRIO_PREEMPT(priority), 0, K_NO_WAIT); if (tid == NULL) { diff --git a/source/zephyr/osal_time.c b/source/zephyr/osal_time.c index d66c04a..e0c8583 100644 --- a/source/zephyr/osal_time.c +++ b/source/zephyr/osal_time.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ /* Zephyr backend (native kernel API). */ diff --git a/source/zephyr/osal_timer.c b/source/zephyr/osal_timer.c index 753b00b..cbc5899 100644 --- a/source/zephyr/osal_timer.c +++ b/source/zephyr/osal_timer.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ /* Zephyr backend (native kernel API). */ diff --git a/test/cmocka_include.h b/test/cmocka_include.h index 53bc512..d6cca88 100644 --- a/test/cmocka_include.h +++ b/test/cmocka_include.h @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #ifndef CMOCKA_INCLUDE_H #define CMOCKA_INCLUDE_H diff --git a/test/linux/queue_unlink_test.c b/test/linux/queue_unlink_test.c index a2268e9..0528140 100644 --- a/test/linux/queue_unlink_test.c +++ b/test/linux/queue_unlink_test.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ /* Linux-only: the Linux queue backend is backed by a POSIX message queue, visible in * /dev/mqueue. Other backends have no such kernel object. */ diff --git a/test/osal/error_test.c b/test/osal/error_test.c index aa5a488..72c1e33 100644 --- a/test/osal/error_test.c +++ b/test/osal/error_test.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include "cmocka_include.h" #include "osal.h" diff --git a/test/osal/lifo_test.c b/test/osal/lifo_test.c index 520eeab..4b7111a 100644 --- a/test/osal/lifo_test.c +++ b/test/osal/lifo_test.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include "cmocka_include.h" #include "osal.h" diff --git a/test/osal/log_test.c b/test/osal/log_test.c index ef27654..64c386f 100644 --- a/test/osal/log_test.c +++ b/test/osal/log_test.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2024, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include "cmocka_include.h" #include "osal.h" diff --git a/test/osal/mutex_test.c b/test/osal/mutex_test.c index 8522ab7..99203d8 100644 --- a/test/osal/mutex_test.c +++ b/test/osal/mutex_test.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include "cmocka_include.h" #include "osal.h" diff --git a/test/osal/osal_test.c b/test/osal/osal_test.c index ec24611..098dfdf 100644 --- a/test/osal/osal_test.c +++ b/test/osal/osal_test.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2026, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include "cmocka_include.h" #include "osal.h" @@ -107,6 +84,26 @@ static void test_osal_init_config_null_log_output(void **state) osal_deinit(); } +static void test_osal_init_unwinds_on_failure(void **state) +{ + osal_mutex_t *m; + + (void)state; + osal_deinit(); + + /* With the mutex pool exhausted osal_init() cannot create its shared mutex. */ + assert_int_equal(osal_mutex_init(), OSAL_E_OK); + do { + m = osal_mutex_create(); + } while (m != NULL); + + assert_int_equal(osal_init(NULL), OSAL_E_RESRC); + + /* The failed init left nothing behind, a new one works. */ + assert_int_equal(osal_init(NULL), OSAL_E_OK); + osal_deinit(); +} + static void test_osal_print_resource(void **state) { (void)state; @@ -138,6 +135,7 @@ int main(void) cmocka_unit_test(test_osal_init_default_config), cmocka_unit_test(test_osal_init_custom_config), cmocka_unit_test(test_osal_init_config_null_log_output), + cmocka_unit_test(test_osal_init_unwinds_on_failure), cmocka_unit_test(test_osal_print_resource), }; return cmocka_run_group_tests(tests, NULL, NULL); diff --git a/test/osal/queue_test.c b/test/osal/queue_test.c index bf0420c..8fb79fd 100644 --- a/test/osal/queue_test.c +++ b/test/osal/queue_test.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include "cmocka_include.h" #include "osal.h" diff --git a/test/osal/rm_test.c b/test/osal/rm_test.c index 4dcf90b..fd24d26 100644 --- a/test/osal/rm_test.c +++ b/test/osal/rm_test.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include "cmocka_include.h" #include "osal.h" @@ -99,7 +76,7 @@ static void test_rm(bool use_mutex) use = osal_rm_use(&rm); assert_int_equal(use, MAX_RES); - /* Tear down the rm before deleting the mutex it references — + /* Tear down the rm before deleting the mutex it references, * osal_rm_deinit locks that mutex to serialize the pool reset. */ osal_rm_deinit(&rm); if (use_mutex) { diff --git a/test/osal/sem_test.c b/test/osal/sem_test.c index 6d9245b..0c90352 100644 --- a/test/osal/sem_test.c +++ b/test/osal/sem_test.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include "cmocka_include.h" #include "osal.h" @@ -107,7 +84,7 @@ static void test_sem_loop(void) assert_int_equal(res, OSAL_E_OK); diff = ts2 - ts1; - /* Allow a generous tolerance — general-purpose Linux scheduling + /* Allow a generous tolerance, general-purpose Linux scheduling * jitter (CI runners, contention) can push sem_timedwait wakeup * by several ms past the requested deadline. */ assert_in_range(diff, wait_nsec, wait_nsec + OSAL_MSEC_NSEC * 20); diff --git a/test/osal/task_test.c b/test/osal/task_test.c index 59932d2..3056e12 100644 --- a/test/osal/task_test.c +++ b/test/osal/task_test.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include "cmocka_include.h" #include "osal.h" @@ -101,7 +78,7 @@ static void test_task_create(void **state) /* Join every task so pthreads are reclaimed (avoids TSan thread-leak * warnings and returns pool slots for the next test). Join *before* * reading test_task_count so the read happens-after every handler's - * write — otherwise the main-thread read races the last handler. */ + * write: otherwise the main-thread read races the last handler. */ for (i = 0; i < OSAL_TASK_NUM_MAX; i++) { osal_task_delete(tasks[i]); } diff --git a/test/osal/time_test.c b/test/osal/time_test.c index f825796..6bd6f77 100644 --- a/test/osal/time_test.c +++ b/test/osal/time_test.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include "cmocka_include.h" #include "osal.h" diff --git a/test/osal/timer_test.c b/test/osal/timer_test.c index 8d8db14..4d99c05 100644 --- a/test/osal/timer_test.c +++ b/test/osal/timer_test.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2023, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include "cmocka_include.h" #include "osal.h" diff --git a/test/osal/tmcheck_test.c b/test/osal/tmcheck_test.c index c59f2b5..ca33dc4 100644 --- a/test/osal/tmcheck_test.c +++ b/test/osal/tmcheck_test.c @@ -1,28 +1,5 @@ -/* BSD 2-Clause License -* -* Copyright (c) 2025, nguyenvannam142@gmail.com -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ #include #include "cmocka_include.h" diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index b29afe8..6f353c1 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -5,17 +5,30 @@ get_filename_component(DMOSAL_ROOT "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE) set(DMOSAL_MAJOR_VERSION 1) set(DMOSAL_MINOR_VERSION 0) set(DMOSAL_PATCH_VERSION 0) -set(DMOSAL_GIT_COMMIT "zephyr") -set(DMOSAL_BUILD_TIME "") +execute_process(COMMAND git rev-parse --short HEAD + WORKING_DIRECTORY "${DMOSAL_ROOT}" + OUTPUT_VARIABLE DMOSAL_GIT_COMMIT + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET) +if(NOT DMOSAL_GIT_COMMIT) + set(DMOSAL_GIT_COMMIT "zephyr") +endif() +string(TIMESTAMP DMOSAL_BUILD_TIME "%Y:%m:%d-%H:%M") # Feed the existing osal_config.h.in template from Kconfig so the # portable code sees the same OSAL_*_NUM_MAX macros as on other backends. foreach(_opt TASK_NAME_SIZE TASK_NUM_MAX MUTEX_NUM_MAX SEM_NUM_MAX TIMER_NUM_MAX QUEUE_NAME_SIZE QUEUE_NUM_MAX LOG_MODULE_NUM_MAX LOG_MODULE_NAME_SIZE - LOG_STRING_SIZE TMCHECK_NUM_MAX) + LOG_STRING_SIZE TMCHECK_NUM_MAX + TASK_STACK_SIZE_DEFAULT TASK_PRIORITY_DEFAULT QUEUE_MSG_MAX_SIZE QUEUE_MSG_NUM_MAX) set(OSAL_CONFIG_${_opt} ${CONFIG_DMOSAL_${_opt}}) endforeach() +if(CONFIG_DMOSAL_TASK_STACK_EMBEDDED) + set(OSAL_CONFIG_TASK_STACK_EMBEDDED 1) +else() + set(OSAL_CONFIG_TASK_STACK_EMBEDDED 0) +endif() set(DMOSAL_GEN_DIR "${CMAKE_CURRENT_BINARY_DIR}/gen/dmosal") file(MAKE_DIRECTORY "${DMOSAL_GEN_DIR}") diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 6d0d6c0..5e2db49 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -52,20 +52,26 @@ config DMOSAL_TMCHECK_NUM_MAX int "Maximum number of time check points" default 16 -config DMOSAL_TASK_STACK_SIZE +config DMOSAL_TASK_STACK_SIZE_DEFAULT int "Stack size of each task in bytes" default 4096 -config DMOSAL_TASK_PRIORITY +config DMOSAL_TASK_STACK_EMBEDDED + bool "Embed a stack array in each task object" + default y + help + When disabled, osal_task_create() requires cfg->stack_addr. + +config DMOSAL_TASK_PRIORITY_DEFAULT int "Preemptible priority of tasks" default 7 -config DMOSAL_QUEUE_BUF_SIZE - int "Message buffer size per queue in bytes (msglen * qsize)" - default 2048 - config DMOSAL_QUEUE_MSG_MAX_SIZE int "Maximum message length of a queue in bytes" - default 256 + default 128 + +config DMOSAL_QUEUE_MSG_NUM_MAX + int "Maximum number of messages per queue" + default 16 endif # DMOSAL diff --git a/zephyr/README.md b/zephyr/README.md index daadeee..0be4f09 100644 --- a/zephyr/README.md +++ b/zephyr/README.md @@ -37,9 +37,9 @@ Board is a constant at the top of `docker.sh`; the Zephyr version is `ZEPHYR_VER |--------|------------------| | mutex | `k_mutex` (own pool lock, since the pool cannot use `osal_mutex`) | | sem | `k_sem` (`-EBUSY`/`-EAGAIN` -> `OSAL_E_TIMEOUT`) | -| task | `k_thread` + static stack per slot (`CONFIG_DMOSAL_TASK_STACK_SIZE`, `_PRIORITY`); `cfg->stack_*`/`priority` are ignored | +| task | `k_thread` + kernel stack inside each task object (`CONFIG_DMOSAL_TASK_STACK_SIZE_DEFAULT`, `_PRIORITY_DEFAULT`); `cfg->priority`, `stack_size` and `stack_addr` override the defaults when set (a caller stack must be a valid Zephyr kernel stack). With `CONFIG_DMOSAL_TASK_STACK_EMBEDDED=n` there is no embedded stack and `stack_addr` is required | | timer | `k_timer` + `k_work`; callback runs in the system work queue, not the ISR | -| queue | `k_msgq` + static buffer per queue (`CONFIG_DMOSAL_QUEUE_BUF_SIZE`, `_MSG_MAX_SIZE`); creating the same name again attaches to the same queue (refcounted, freed with the last handle; not persistent across `osal_deinit`); shorter sends are zero-padded to `msglen` | +| queue | `k_msgq` + static buffer per queue (`CONFIG_DMOSAL_QUEUE_MSG_MAX_SIZE`, `_MSG_NUM_MAX`); creating the same name again attaches to the same queue (refcounted, freed with the last handle; not persistent across `osal_deinit`); shorter sends are zero-padded to `msglen` | | time | `k_sleep`, `k_usleep`, `k_uptime_ticks` | Zephyr-specific behaviour to know: `osal_timer_delete` from inside the callback @@ -49,8 +49,10 @@ Add new examples under `examples/` (portable code only) and select them with `EX ## Notes -- Pool sizes: `CONFIG_DMOSAL_*` in `zephyr/app/prj.conf` - (defaults in `zephyr/Kconfig`), mapped to `OSAL_*` macros in `zephyr/CMakeLists.txt`. +- Settings: `CONFIG_DMOSAL_*` in `zephyr/app/prj.conf` (defaults in `zephyr/Kconfig`), mapped + to the `OSAL_CONFIG_*` values of `osal_config.h.in` in `zephyr/CMakeLists.txt`. The backend + reads the resulting `OSAL_*` macros, like every other backend. Task priority is a Zephyr + preemptible priority. - The app finds the module via `ZEPHYR_EXTRA_MODULES` in `zephyr/app/CMakeLists.txt`. Your own app does the same and sets `CONFIG_DMOSAL=y`. - Zephyr source: inside the image at `/opt/zephyrws/zephyr` (browse with `zephyr/docker.sh shell`). diff --git a/zephyr/app/cmocka/config.h b/zephyr/app/cmocka/config.h index 88b868a..1674183 100644 --- a/zephyr/app/cmocka/config.h +++ b/zephyr/app/cmocka/config.h @@ -1,3 +1,6 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ + /* Minimal cmocka build configuration for Zephyr native_sim (host libc). */ #ifndef DMOSAL_CMOCKA_CONFIG_H #define DMOSAL_CMOCKA_CONFIG_H diff --git a/zephyr/app/test_main.c b/zephyr/app/test_main.c index 97e6384..e06dc7e 100644 --- a/zephyr/app/test_main.c +++ b/zephyr/app/test_main.c @@ -1,3 +1,6 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2023, nguyenvannam142@gmail.com */ + /* Runs the cmocka test whose main() was renamed to dmosal_test_main, then ends the * native_sim process with the test result so CI can use the exit code. */ #include