Contributing a HAL
The Plexus C SDK uses a Hardware Abstraction Layer (HAL) to decouple core logic from platform-specific code. Adding support for a new board or RTOS means implementing a small set of functions — no changes to the SDK core required.
Overview
A HAL is a single .c file (or .cpp for Arduino-like platforms) that implements platform-specific operations:
- HTTP POST (send telemetry)
- Time functions (timestamps, monotonic ticks, delays)
- Optional: logging, persistent storage, mutex
The SDK ships with HALs for ESP32/Arduino, STM32, and POSIX (Linux/macOS). Your contribution adds another.
Getting Started
-
Copy the template:
cp hal/template/plexus_hal_template.c hal/your_platform/plexus_hal_your_platform.c -
Add a platform guard at the top:
#include "plexus.h" #if defined(YOUR_PLATFORM_MACRO) // ... your implementation ... #endif -
Implement the required functions (see below).
-
Add to CMakeLists.txt (see Build Integration).
Required Functions
These four functions must be implemented. Without them, the SDK cannot compile.
plexus_hal_http_post
plexus_err_t plexus_hal_http_post(
const char* url,
const char* api_key,
const char* user_agent,
const char* body,
size_t body_len
);Send an HTTP POST request with JSON body. Must set:
Content-Type: application/jsonx-api-key: {api_key}User-Agent: {user_agent}(if non-NULL)
Return values:
| Return | Meaning |
|---|---|
PLEXUS_OK | 2xx response |
PLEXUS_ERR_NETWORK | Connection failed or non-2xx |
PLEXUS_ERR_AUTH | 401 response |
PLEXUS_ERR_RATE_LIMIT | 429 response |
PLEXUS_ERR_SERVER | 5xx response |
PLEXUS_ERR_NULL_PTR | NULL argument |
TLS: Use HTTPS with certificate verification in production. If your platform lacks TLS, emit a compile-time #warning and document the limitation.
plexus_hal_get_time_ms
uint64_t plexus_hal_get_time_ms(void);Return wall-clock time in milliseconds since Unix epoch (1970-01-01). Used for metric timestamps. Return 0 if no RTC is available — the server will assign timestamps.
plexus_hal_get_tick_ms
uint32_t plexus_hal_get_tick_ms(void);Return a monotonic tick counter in milliseconds. Used for flush intervals and backoff timing. Must not jump backwards. Wraparound at UINT32_MAX is handled by the SDK.
plexus_hal_delay_ms
void plexus_hal_delay_ms(uint32_t ms);Block for at least ms milliseconds. On RTOS platforms, yield the CPU (e.g., osDelay(ms) or vTaskDelay()). On bare-metal, busy-wait is acceptable.
Optional Functions
Implement these for better diagnostics and reliability. If not implemented, the SDK uses no-op stubs.
Logging
void plexus_hal_log(const char* fmt, ...);Printf-style debug logging. Only called when PLEXUS_DEBUG is enabled. Typical implementation: format to buffer, write to UART.
Persistent Storage
plexus_err_t plexus_hal_storage_write(const char* key, const void* data, size_t len);
plexus_err_t plexus_hal_storage_read(const char* key, void* buf, size_t buf_size, size_t* out_len);
plexus_err_t plexus_hal_storage_clear(const char* key);Key-value storage for offline buffering. When the network is down, the SDK persists unsent batches and retries later. Typical backends: NVS (ESP32), flash sectors (STM32), filesystem (Linux).
Mutex (Thread Safety)
void* plexus_hal_mutex_create(void);
void plexus_hal_mutex_lock(void* mutex);
void plexus_hal_mutex_unlock(void* mutex);
void plexus_hal_mutex_destroy(void* mutex);Required only if PLEXUS_ENABLE_THREAD_SAFE is set. Implement using your platform's mutex primitive (FreeRTOS semaphore, pthread mutex, etc.).
Build Integration
Add your HAL to CMakeLists.txt:
# In hal/CMakeLists.txt
if(PLEXUS_HAL STREQUAL "your_platform")
target_sources(plexus PRIVATE
hal/your_platform/plexus_hal_your_platform.c
)
target_compile_definitions(plexus PUBLIC YOUR_PLATFORM_MACRO)
endif()For Arduino, add the file to your sketch folder — the Arduino IDE compiles all .cpp files automatically.
Verification Checklist
Before submitting your HAL:
- All 4 required functions compile without warnings (
-Wall -Wextra) -
http_postsends correct headers and returns appropriate error codes -
get_tick_msis monotonic and doesn't block -
delay_msactually delays (verify with scope or log timestamps) -
get_time_msreturns valid epoch time (or 0 if no RTC) - Platform guard
#if defined(...)prevents compilation on other targets - TLS is used for HTTPS, or a
#warningdocuments the limitation - Memory usage documented (stack, heap, flash)
- Tested on real hardware (not just compilation)
Reference Implementations
Study these existing HALs:
| HAL | File | Notes |
|---|---|---|
| ESP32/Arduino | hal/arduino/plexus_hal_arduino.cpp | WiFiClientSecure + HTTPClient, FreeRTOS mutex, NVS storage |
| STM32 | hal/stm32/plexus_hal_stm32.c | LwIP sockets, raw HTTP, CMSIS-OS mutex, RTC timestamps |
| POSIX | hal/posix/plexus_hal_posix.c | libcurl, pthread mutex, filesystem storage |
The ESP32 HAL is the most complete reference — it implements all optional functions including persistent storage and thread safety.