Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ jobs:
run: zephyr/docker.sh run
- name: Build and run cmocka tests
run: zephyr/docker.sh test
- name: clang-tidy (backend sources)
run: zephyr/docker.sh tidy

freertos:
name: freertos posix simulator (examples + tests)
Expand All @@ -219,6 +221,8 @@ jobs:
run: freertos/docker.sh run
- name: Run cmocka tests
run: freertos/docker.sh test
- name: clang-tidy (backend sources)
run: freertos/docker.sh tidy

docs:
name: docs (build)
Expand Down
78 changes: 44 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,59 +8,67 @@
A small, portable C abstraction layer for tasks, mutexes, semaphores, queues,
timers and time, with the same semantics on every supported OS.

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.
All resources are statically allocated up front, so the code in dmosal itself
never calls `malloc` on any hot path and its worst-case memory use is known in
advance. This does not cover the OS calls underneath: pthreads, POSIX message
queues and timers on Linux, or the FreeRTOS kernel in dynamic allocation mode,
may allocate internally. New backends can be added behind the same API without
breaking existing callers.

## Supported backends

| 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) | | |
| Backend | Source | Tested on | Details |
|----------|--------------------------------------------------|-------------------------------------|------------------------------------------|
| Linux | [source/linux/](source/linux/) | Native Linux (pthreads, POSIX IPC) | Quick start below |
| 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) | | |

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.

```
+-------------------------------+
| Application |
+---------------+---------------+
| dmosal | libc |
+---------------+---------------+
| Linux | Zephyr | FreeRTOS | ...|
+-------------------------------+
+-------------------------------------------------+
| Application |
+-------------------------------------------------+
|
+-------------------------------------------------+
| dmosal public API |
+-------------------------------------------------+
|
+----------+ +----------+ +----------+ +----------+
| Linux | | Zephyr | | FreeRTOS | | ... |
+----------+ +----------+ +----------+ +----------+
```

## Quick start

Install the dependencies, then build and test on Linux:
On Linux you only need a compiler, CMake and cmocka:

```
sudo apt install cmake libcmocka-dev doxygen
just check # configure, build, run tests
just build # build the examples
sudo apt install cmake libcmocka-dev
just check # build and run the tests
just run-examples # build and run the examples
```

No toolchain locally? Use the pinned [`Dockerfile`](Dockerfile):
The `just` recipes are thin wrappers around `cmake` and `ctest`. Without
`just`, run the equivalent commands from the [`justfile`](justfile).

The [`Dockerfile`](Dockerfile) provides the full toolchain:

```
docker build -t dmosal-dev .
docker run --rm -v "$PWD":/workspace -w /workspace dmosal-dev just check
```

Without [`just`](https://github.com/casey/just), the [`justfile`](justfile)
recipes are plain `cmake`/`ctest` commands you can run directly.

Resource limits (number of tasks, queues, ...) are set at configure time in
[osal_config.cmake](osal_config.cmake).
Resource pool sizes (tasks, queues, mutexes, etc.) are fixed at build time in
[osal_config.cmake](osal_config.cmake) and can be overridden, e.g.
`cmake -DOSAL_CONFIG_QUEUE_NUM_MAX=8 ..`.

## Zephyr and FreeRTOS

Both run inside Docker, so no local SDK is needed:
Both backends run inside Docker, so no local SDK is required:

```
just zephyr-build # build examples and tests for native_sim
Expand All @@ -72,20 +80,22 @@ just freertos-run # run the examples
just freertos-test # run the cmocka tests
```

## Other recipes
## More checks

`just check-valgrind`, `check-asan`, `check-tsan`, `check-coverage`, `doc`,
`format`, `tidy`. Run `just --list` for everything.
Additional recipes: `just check-valgrind`, `check-asan`, `check-tsan` and
`check-coverage` for dynamic analysis, `just format` and `just tidy` for style
checks (`just zephyr-tidy` and `just freertos-tidy` for the RTOS backends).
`just --list` shows all recipes.

## Documentation

- API reference (Doxygen): `just doc` → `build/doc/html/`.
- Design docs: [docs/](docs/README.md) (architecture, API spec, lifetime,
thread safety, porting guide).
`just doc` builds the API reference into `build/doc/html/` (requires
`doxygen`). Design documents are in [docs/](docs/README.md): architecture, API
spec, object lifetime, thread safety and the porting guide.

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) for building, testing and style.
See [CONTRIBUTING.md](CONTRIBUTING.md) for build, test and code style requirements.

## License

Expand Down
5 changes: 4 additions & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
`dmosal` is a thin OS abstraction layer with a **static-allocation** ethos:
every resource (mutex, semaphore, task, timer, queue, tmcheck) comes from a
fixed-size pool sized at compile time. Applications acquire resources at
initialization, then run without further heap allocation. The layer is
initialization, then run without further heap allocation in dmosal's own code.
The OS or library calls underneath (for example pthreads, POSIX message
queues and timers, or the FreeRTOS kernel in dynamic mode) may still allocate
internally, and dmosal does not control that. The layer is
designed for embedded / real-time contexts where predictable memory
behaviour matters more than dynamic flexibility.

Expand Down
4 changes: 4 additions & 0 deletions freertos/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,8 @@ RUN mkdir -p ${FREERTOS_KERNEL_PATH} \
| tar -xz -C ${FREERTOS_KERNEL_PATH} --strip-components=1 \
&& chmod -R a+rX ${FREERTOS_KERNEL_PATH}

# Static analysis of the backend sources (docker.sh tidy).
RUN apt-get update && apt-get install -y --no-install-recommends clang-tidy \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /dmosal
7 changes: 6 additions & 1 deletion freertos/docker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
# 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 tidy # clang-tidy over source/freertos/*.c
# freertos/docker.sh shell # interactive shell in the container
#
# CMAKE_ARGS=-DDYNAMIC_ALLOC=ON builds against the kernel's dynamic allocation API instead
Expand Down Expand Up @@ -38,11 +39,15 @@ run)
test)
"${DOCKER_RUN[@]}" "$IMAGE" ctest --test-dir "$BUILD" --output-on-failure ${TEST:+-R "^$TEST\$"}
;;
tidy)
"${DOCKER_RUN[@]}" "$IMAGE" sh -c \
"cmake -S freertos/app -B build-freertos-tidy -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON >/dev/null && cmake --build build-freertos-tidy >/dev/null && clang-tidy -p build-freertos-tidy --quiet --warnings-as-errors='*' source/freertos/*.c"
;;
shell)
"${DOCKER_RUN[@]}" -it "$IMAGE" bash
;;
*)
sed -n "2,10p" "$0"
sed -n "2,11p" "$0"
exit 1
;;
esac
10 changes: 10 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@
# just zephyr-build # build the examples for Zephyr native_sim (Docker)
# just zephyr-run # run the Zephyr examples
# just zephyr-test # run the cmocka tests on Zephyr native_sim (TEST=<name> for one)
# just zephyr-tidy # clang-tidy over source/zephyr (Docker)
# 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=<name> for one)
# just freertos-tidy # clang-tidy over source/freertos (Docker)
# just freertos-shell # shell inside the FreeRTOS container
# just clean # remove build directories

Expand Down Expand Up @@ -88,6 +90,14 @@ tidy:
cmake --build {{build_dir}} --target dmosal -j{{jobs}}
pre-commit run clang-tidy --all-files --hook-stage manual

# Run clang-tidy over the Zephyr backend inside Docker
zephyr-tidy:
zephyr/docker.sh tidy

# Run clang-tidy over the FreeRTOS backend inside Docker
freertos-tidy:
freertos/docker.sh tidy

# Build the examples for Zephyr native_sim inside Docker (EXAMPLE=<name> for one)
zephyr-build:
zephyr/docker.sh build
Expand Down
7 changes: 7 additions & 0 deletions zephyr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,11 @@ zephyr_library_sources(
"${DMOSAL_ROOT}/source/zephyr/osal_timer.c"
)

# Same extra warnings as the other backends, except -Wpedantic and -Wconversion: Zephyr builds
# with a strict -std that rejects the variadic log macros, and its own headers trigger both
# (they are not system headers). Conversions are covered by clang-tidy (just zephyr-tidy).
zephyr_library_compile_options(
-Wshadow -Wcast-align -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes
)

endif()
4 changes: 4 additions & 0 deletions zephyr/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,8 @@ RUN mkdir -p /opt/cmocka \
# west and cmake write caches inside the Zephyr tree, and the container runs as the host user.
RUN mkdir -p /opt/zephyrws/zephyr/.cache && chmod -R a+rwX /opt/zephyrws/.west /opt/zephyrws/zephyr/.cache

# Static analysis of the backend sources (docker.sh tidy).
RUN apt-get update && apt-get install -y --no-install-recommends clang-tidy \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /dmosal
4 changes: 4 additions & 0 deletions zephyr/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,8 @@ config DMOSAL_QUEUE_MSG_NUM_MAX
int "Maximum number of messages per queue"
default 16

config DMOSAL_QUEUE_MSG_NUM_MAX
int "Maximum number of messages per queue"
default 16

endif # DMOSAL
12 changes: 11 additions & 1 deletion zephyr/docker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
# zephyr/docker.sh build # build every examples/*.c into build-zephyr/<name>
# zephyr/docker.sh run # run them all
# zephyr/docker.sh test # build + run every test/osal/*_test.c (cmocka) on native_sim
# zephyr/docker.sh tidy # clang-tidy over source/zephyr/*.c
# zephyr/docker.sh shell # interactive shell in the container
#
# EXAMPLE=<name> limits build/run to one file from examples/.
Expand Down Expand Up @@ -62,11 +63,20 @@ test)
exit 1
fi
;;
tidy)
# clang does not know a few gcc-only flags that Zephyr passes, so they are dropped from the
# compilation database.
"${DOCKER_RUN[@]}" "$IMAGE" sh -c \
"west build -b $BOARD -d build-zephyr-tidy zephyr/app -p auto -- -DEXAMPLE=queue_sample -DCMAKE_EXPORT_COMPILE_COMMANDS=ON >/dev/null &&
mkdir -p build-zephyr-tidy/db &&
sed -e 's/ -fno-freestanding//g; s/ -fno-reorder-functions//g' build-zephyr-tidy/compile_commands.json > build-zephyr-tidy/db/compile_commands.json &&
clang-tidy -p build-zephyr-tidy/db --quiet --warnings-as-errors='*' source/zephyr/*.c"
;;
shell)
"${DOCKER_RUN[@]}" -it "$IMAGE" bash
;;
*)
sed -n "2,10p" "$0"
sed -n "2,11p" "$0"
exit 1
;;
esac
Loading