FreeRTOS + lwIP Platform Port¶
Overview¶
OpenSOME/IP supports FreeRTOS + lwIP as a platform backend via the platform abstraction layer. This enables the SOME/IP stack to run on any FreeRTOS-based embedded system with lwIP networking, without coupling to any specific BSW framework.
CMake Flags¶
| Flag | Default | Description |
|---|---|---|
SOMEIP_USE_FREERTOS |
OFF |
Use FreeRTOS for threading primitives (Mutex, Thread, ConditionVariable, sleep_for) |
SOMEIP_USE_LWIP |
OFF |
Use lwIP socket API for networking (TCP/UDP sockets, byte-order) |
Both flags should be enabled together for a complete embedded build:
cmake -B build \
-DSOMEIP_USE_FREERTOS=ON \
-DSOMEIP_USE_LWIP=ON \
-DCMAKE_TOOLCHAIN_FILE=path/to/arm-none-eabi.cmake
Required FreeRTOS Configuration¶
The following FreeRTOSConfig.h settings are required:
| Setting | Value | Why |
|---|---|---|
configUSE_MUTEXES |
1 |
platform::Mutex uses xSemaphoreCreateMutex() |
configUSE_COUNTING_SEMAPHORES |
1 |
platform::ConditionVariable uses xSemaphoreCreateCounting() |
configSUPPORT_DYNAMIC_ALLOCATION |
1 |
Task and semaphore creation use dynamic allocation |
Required lwIP Configuration¶
The following lwipopts.h settings are required:
| Setting | Value | Why |
|---|---|---|
LWIP_SOCKET |
1 |
Socket API is the transport layer's interface to the network stack |
LWIP_COMPAT_SOCKETS |
1 (recommended) |
When enabled, standard POSIX socket names are available without macro mapping. When 0, the backend provides explicit macros. |
LWIP_PROVIDE_ERRNO |
1 |
Required if the C library does not provide errno |
LWIP_TCP |
1 |
Required for SOME/IP TCP transport |
LWIP_UDP |
1 |
Required for SOME/IP UDP transport and Service Discovery |
LWIP_IGMP |
1 |
Required for SOME/IP-SD multicast group management |
lwIP API Compatibility Notes¶
poll/select: Supported vialwip_poll()/lwip_select().fcntl: OnlyO_NONBLOCKis meaningful in lwIP.SO_RCVTIMEO/SO_SNDTIMEO: Supported withstruct timeval.- TCP keep-alive: Not supported on lwIP builds; the keep-alive
block in
tcp_transport.cppis compiled out.
Configurable Defines¶
| Define | Default | Description |
|---|---|---|
SOMEIP_FREERTOS_THREAD_STACK_SIZE |
4096 |
Stack size in bytes for SOME/IP worker threads |
SOMEIP_FREERTOS_THREAD_PRIORITY |
tskIDLE_PRIORITY + 2 |
FreeRTOS task priority for SOME/IP threads |
SOMEIP_FREERTOS_MESSAGE_POOL_SIZE |
16 |
Number of pre-allocated Message objects in the static pool |
Thread Lifecycle¶
- Creation:
xTaskCreate()with a trampoline function. A binary semaphore is created forjoin()synchronization. - join(): Blocks on the binary semaphore until the user function completes. Idempotent (second call is a no-op). Cleans up the task handle, trampoline context, and join semaphore.
- Destructor (task still running): Aborts the task via
vTaskDelete(), then cleans up all resources. Matches the Zephyr backend behavior (k_thread_abort).
ConditionVariable Semantics¶
FreeRTOS has no native condition variable. The backend uses a counting semaphore:
notify_one():xSemaphoreGive()— one waiter (if any) unblocks.wait(Mutex& mtx): Unlocks the mutex, takes the semaphore (blocking), re-locks the mutex.wait(Mutex& mtx, Pred pred): Predicate loop —while (!pred()) { wait(mtx); }.
Callers must use the predicate form to handle stale tokens.
Memory Pool¶
Message objects are allocated from a fixed-size static pool to avoid heap fragmentation:
- Alignment:
alignas(Message)on the pool buffer. - Exhaustion:
allocate_message()returnsnullptr. Callers must check the return value. - Locking: One FreeRTOS mutex per pool; all alloc/release operations are under that mutex.
Integrator Example¶
cmake_minimum_required(VERSION 3.20)
project(my_embedded_app LANGUAGES CXX)
set(CMAKE_TOOLCHAIN_FILE "path/to/arm-none-eabi.cmake")
set(SOMEIP_USE_FREERTOS ON CACHE BOOL "")
set(SOMEIP_USE_LWIP ON CACHE BOOL "")
add_subdirectory(third_party/some-ip someip_build)
# Integrator provides FreeRTOS and lwIP headers + libs
target_include_directories(someip-core PUBLIC ${FREERTOS_INCLUDE_DIRS})
target_include_directories(someip-transport PUBLIC ${LWIP_INCLUDE_DIRS})
add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE someip-transport someip-core freertos_kernel lwip)
CI Runtime Testing (FreeRTOS POSIX Port)¶
FreeRTOS provides an official POSIX/Linux simulator port
(portable/ThirdParty/GCC/Posix) that runs the FreeRTOS kernel as a
native Linux process using pthreads. This enables real FreeRTOS runtime
testing in CI without any emulator or hardware.
This option:
- Fetches FreeRTOS-Kernel V11.1.0 via FetchContent
- Builds FreeRTOS with FREERTOS_PORT=GCC_POSIX, FREERTOS_HEAP=4
- Enables SOMEIP_USE_FREERTOS=ON automatically
- Builds and runs test_freertos_core, which boots the real FreeRTOS
scheduler (vTaskStartScheduler()) and exercises Message, Endpoint,
Serializer, threading primitives (Mutex, ConditionVariable, Thread
join, sleep_for), and the memory pool -- all inside a FreeRTOS task.
The test task calls exit() after completing, since
vTaskStartScheduler() never returns.
Renode Testing (STM32F407 Cortex-M4)¶
For testing on actual ARM Cortex-M4F architecture, the project supports running tests on the Renode hardware simulator using a simulated STM32F407 Discovery board.
Running locally¶
# Requires arm-none-eabi-gcc and Renode installed
./scripts/run_freertos_renode_test.sh --timeout 60
The script handles the full workflow:
1. Cross-compiles with the freertos-cortexm4-renode CMake preset
2. Launches Renode headless with renode/stm32f4_test.resc
3. Captures USART2 output via CreateFileBackend
4. Parses [PASS]/[FAIL] results and generates JUnit XML
CMake preset¶
This preset:
- Uses the arm-none-eabi-gcc toolchain for Cortex-M4F
- Enables SOMEIP_FREERTOS_RENODE_TESTS=ON and SOMEIP_USE_LWIP=ON
- Uses lwIP headers (fetched via FetchContent, not compiled) so the
build matches the real deployment configuration; byteorder macros
resolve to __builtin_bswap intrinsics via cmake/config/lwip/arch/cc.h
- Builds test_freertos_renode.elf linked with a minimal BSP
(bsp/stm32f407_renode/) providing startup code, linker script,
and UART retarget
Renode example¶
The examples/renode/freertos_multitask/ demo shows a producer/consumer
pattern with FreeRTOS tasks exchanging SOME/IP messages via a FreeRTOS
queue, exercising platform::Mutex and platform::allocate_message()
on real ARM code paths.
Supported Platform Combinations¶
| Platform | Threading Backend | Networking Backend | Status |
|---|---|---|---|
| POSIX (Linux/macOS) | std::thread |
POSIX sockets | Supported |
| Windows | std::thread |
Winsock2 | Supported |
| Zephyr | k_thread / k_mutex |
Zephyr zsock | Supported |
| FreeRTOS + lwIP | xTaskCreate / xSemaphore |
lwIP sockets | Supported |
| ThreadX + lwIP | tx_thread_create / TX_MUTEX |
lwIP sockets | Supported |