Core Concepts¶
This guide explains the fundamental concepts and design principles of the Nexus platform.
Architecture Overview¶
Layered Design¶
Nexus follows a strict layered architecture:
┌─────────────────────────────────────┐
│ Application Layer │ Your code
├─────────────────────────────────────┤
│ Framework Layer │ Log, Shell, Config, Init
├─────────────────────────────────────┤
│ OS Abstraction Layer (OSAL) │ Tasks, Mutex, Queue, Timer
├─────────────────────────────────────┤
│ Hardware Abstraction Layer (HAL) │ GPIO, UART, SPI, I2C, ADC
├─────────────────────────────────────┤
│ Platform Layer │ STM32F4, STM32H7, Native
└─────────────────────────────────────┘
Key Principles:
Separation of Concerns: Each layer has a specific responsibility
Abstraction: Hide implementation details behind clean interfaces
Portability: Minimize platform-specific code in applications
Dependency Rule: Upper layers depend on lower layers, never reverse
Design Patterns¶
Factory Pattern
HAL uses factory functions to create device instances:
/* Create GPIO device */
nx_gpio_write_t* led = nx_factory_gpio_write('A', 5);
/* Use device */
led->toggle(led);
/* Release device */
nx_factory_gpio_release((nx_gpio_t*)led);
Interface Pattern
Devices expose interfaces with function pointers:
typedef struct {
void (*write)(nx_gpio_write_t* self, uint8_t value);
void (*toggle)(nx_gpio_write_t* self);
uint8_t (*read)(nx_gpio_write_t* self);
} nx_gpio_write_t;
Adapter Pattern
OSAL adapts different RTOS backends to a common interface:
/* Same API works with FreeRTOS, bare-metal, etc. */
osal_task_create(task_func, "task", 512, NULL, 1, NULL);
Hardware Abstraction Layer (HAL)¶
Purpose¶
HAL provides unified APIs for hardware peripherals, hiding platform differences.
Benefits:
Write once, run on multiple platforms
Consistent API across different MCUs
Easy to test with native simulation
Simplified driver development
Key Concepts¶
Device Instances
Each peripheral is represented as a device instance:
/* GPIO device */
nx_gpio_write_t* led;
/* UART device */
nx_uart_t* uart;
/* SPI device */
nx_spi_t* spi;
Configuration Structures
Devices are configured using structures:
nx_gpio_config_t gpio_cfg = {
.mode = NX_GPIO_MODE_OUTPUT_PP,
.pull = NX_GPIO_PULL_NONE,
.speed = NX_GPIO_SPEED_LOW,
};
nx_uart_config_t uart_cfg = {
.baudrate = 115200,
.word_length = 8,
.stop_bits = 1,
.parity = 0,
};
Factory Functions
Create devices using factory functions:
/* Simple creation */
nx_gpio_write_t* led = nx_factory_gpio_write('A', 5);
/* Creation with configuration */
nx_gpio_t* gpio = nx_factory_gpio_with_config('A', 5, &gpio_cfg);
/* Release when done */
nx_factory_gpio_release(gpio);
Interface Methods
Access device functionality through interface methods:
/* GPIO operations */
led->write(led, 1);
led->toggle(led);
uint8_t state = led->read(led);
/* UART operations */
nx_tx_sync_t* tx = uart->get_tx_sync(uart);
tx->send(tx, data, len, timeout);
Peripheral Types¶
GPIO - General Purpose I/O
Digital input/output
Interrupt support
Pull-up/pull-down configuration
UART - Serial Communication
Asynchronous serial
Configurable baud rate
TX/RX with timeouts
SPI - Serial Peripheral Interface
Master/slave modes
Full-duplex communication
Configurable clock polarity/phase
I2C - Inter-Integrated Circuit
Master/slave modes
7-bit/10-bit addressing
Clock stretching support
ADC - Analog-to-Digital Converter
Single/continuous conversion
Multiple channels
DMA support
Timer - Hardware Timers
PWM generation
Input capture
Output compare
See 硬件抽象层 (HAL) for detailed HAL documentation.
OS Abstraction Layer (OSAL)¶
Purpose¶
OSAL provides portable RTOS primitives, allowing applications to work with different operating systems.
Supported Backends:
Bare-metal (cooperative scheduling)
FreeRTOS
RT-Thread
Zephyr
Key Concepts¶
Tasks/Threads
Create and manage concurrent execution:
/* Task function */
void my_task(void* arg) {
while (1) {
/* Task work */
osal_task_delay(1000);
}
}
/* Create task */
osal_task_handle_t task;
osal_task_create(my_task, "my_task", 512, NULL, 1, &task);
Mutexes
Mutual exclusion for shared resources:
/* Create mutex */
osal_mutex_handle_t mutex;
osal_mutex_create(&mutex);
/* Lock */
osal_mutex_lock(mutex, OSAL_WAIT_FOREVER);
/* Critical section */
shared_resource++;
/* Unlock */
osal_mutex_unlock(mutex);
Semaphores
Signaling and resource counting:
/* Create binary semaphore */
osal_sem_handle_t sem;
osal_sem_create(&sem, 0, 1);
/* Wait for signal */
osal_sem_wait(sem, OSAL_WAIT_FOREVER);
/* Signal */
osal_sem_give(sem);
Message Queues
Inter-task communication:
/* Create queue */
osal_queue_handle_t queue;
osal_queue_create(&queue, 10, sizeof(message_t));
/* Send message */
message_t msg = {.id = 1, .data = 42};
osal_queue_send(queue, &msg, OSAL_WAIT_FOREVER);
/* Receive message */
message_t received;
osal_queue_receive(queue, &received, OSAL_WAIT_FOREVER);
Software Timers
Periodic or one-shot timers:
/* Timer callback */
void timer_callback(void* arg) {
/* Timer expired */
}
/* Create timer */
osal_timer_handle_t timer;
osal_timer_create(&timer, "timer", 1000, true, NULL, timer_callback);
/* Start timer */
osal_timer_start(timer);
Synchronization Patterns¶
Producer-Consumer
/* Producer task */
void producer_task(void* arg) {
while (1) {
data_t data = produce_data();
osal_queue_send(queue, &data, OSAL_WAIT_FOREVER);
}
}
/* Consumer task */
void consumer_task(void* arg) {
while (1) {
data_t data;
osal_queue_receive(queue, &data, OSAL_WAIT_FOREVER);
consume_data(&data);
}
}
Resource Protection
/* Shared resource with mutex */
static int shared_counter = 0;
static osal_mutex_handle_t counter_mutex;
void increment_counter(void) {
osal_mutex_lock(counter_mutex, OSAL_WAIT_FOREVER);
shared_counter++;
osal_mutex_unlock(counter_mutex);
}
See 操作系统抽象层 (OSAL) for detailed OSAL documentation.
Framework Layer¶
Logging Framework¶
Flexible logging with multiple backends and log levels.
Log Levels:
LOG_ERROR("Critical error: %d", error_code);
LOG_WARN("Warning: %s", warning_msg);
LOG_INFO("Information: %d", value);
LOG_DEBUG("Debug: %s", debug_info);
Module Filtering:
/* Define module */
#define LOG_MODULE "MyModule"
/* Log with module tag */
LOG_INFO("Module-specific log");
Backends:
Console (stdout)
UART
File
Custom backends
See 日志框架 for detailed logging documentation.
Shell Framework¶
Interactive command-line interface for debugging and control.
Command Registration:
static int cmd_handler(int argc, char* argv[]) {
shell_printf("Command executed\n");
return 0;
}
static const shell_command_t cmd_def = {
.name = "mycommand",
.handler = cmd_handler,
.help = "My custom command",
.usage = "mycommand [args]",
.completion = NULL
};
shell_register_command(&cmd_def);
Features:
Command history
Tab completion
Built-in commands (help, clear, reboot)
Custom command registration
See Shell 框架 for detailed shell documentation.
Configuration Framework¶
Key-value configuration storage with persistence.
Basic Usage:
/* Store values */
config_set_i32("app.timeout", 5000);
config_set_str("device.name", "MyDevice");
config_set_bool("feature.enabled", true);
/* Retrieve values */
int32_t timeout;
config_get_i32("app.timeout", &timeout, 0);
Namespaces:
/* Open namespace */
config_ns_handle_t wifi_ns;
config_open_namespace("wifi", &wifi_ns);
/* Store in namespace */
config_ns_set_str(wifi_ns, "ssid", "MyNetwork");
/* Close namespace */
config_close_namespace(wifi_ns);
Import/Export:
/* Export to JSON */
char buffer[1024];
size_t size;
config_export(CONFIG_FORMAT_JSON, 0, buffer, sizeof(buffer), &size);
/* Import from JSON */
config_import(CONFIG_FORMAT_JSON, 0, buffer, size);
See 配置管理器 for detailed configuration documentation.
Configuration System (Kconfig)¶
Purpose¶
Kconfig provides compile-time configuration for:
Platform selection
Peripheral enablement
Feature selection
Resource allocation
Key Concepts¶
Configuration Options
Define what features to include:
config HAL_GPIO
bool "Enable GPIO support"
default y
help
Enable GPIO peripheral support
Dependencies
Express relationships between options:
config HAL_SPI
bool "Enable SPI support"
depends on HAL_GPIO
help
Enable SPI peripheral support
Defaults
Provide sensible defaults:
config HAL_UART_BAUDRATE
int "Default UART baud rate"
default 115200
range 9600 921600
Generated Header
Kconfig generates nexus_config.h:
#define CONFIG_HAL_GPIO 1
#define CONFIG_HAL_UART 1
#define CONFIG_HAL_UART_BAUDRATE 115200
Usage in Code¶
#include "nexus_config.h"
#ifdef CONFIG_HAL_GPIO
/* GPIO code */
#endif
#ifdef CONFIG_HAL_UART
/* UART code */
#endif
See Configuration for detailed Kconfig usage.
Memory Management¶
Static Allocation¶
All memory allocated at compile time:
Advantages:
Deterministic behavior
No fragmentation
Suitable for safety-critical systems
Disadvantages:
Less flexible
May waste memory
Example:
#define MAX_DEVICES 10
static device_t devices[MAX_DEVICES];
Dynamic Allocation¶
Runtime memory allocation:
Advantages:
Flexible
Efficient memory usage
Disadvantages:
Fragmentation risk
Non-deterministic
Example:
device_t* device = malloc(sizeof(device_t));
/* Use device */
free(device);
Pool Allocation¶
Fixed-size memory pools:
Advantages:
Fast allocation
No fragmentation
Predictable behavior
Disadvantages:
Fixed block size
May waste memory
Example:
/* Create pool */
osal_pool_handle_t pool;
osal_pool_create(&pool, 10, sizeof(device_t));
/* Allocate from pool */
device_t* device = osal_pool_alloc(pool);
/* Return to pool */
osal_pool_free(pool, device);
Error Handling¶
Status Codes¶
All APIs return status codes:
typedef enum {
HAL_OK = 0,
HAL_ERR_FAIL,
HAL_ERR_PARAM,
HAL_ERR_STATE,
HAL_ERR_TIMEOUT,
HAL_ERR_NO_MEMORY,
} hal_status_t;
Error Checking¶
Always check return values:
hal_status_t status = hal_gpio_init(port, pin, &config);
if (status != HAL_OK) {
LOG_ERROR("GPIO init failed: %d", status);
return status;
}
Error Recovery¶
Implement appropriate recovery strategies:
/* Retry on timeout */
int retries = 3;
while (retries--) {
status = hal_uart_send(uart, data, len, timeout);
if (status == HAL_OK) {
break;
}
if (status == HAL_ERR_TIMEOUT) {
continue; /* Retry */
}
return status; /* Other errors */
}
Resource Management¶
Initialization¶
Proper initialization order:
int main(void) {
/* 1. Initialize HAL */
nx_hal_init();
/* 2. Initialize OSAL */
osal_init();
/* 3. Initialize frameworks */
log_init(NULL);
shell_init(&shell_config);
/* 4. Initialize application */
app_init();
/* 5. Start scheduler (if using RTOS) */
osal_start_scheduler();
return 0;
}
Cleanup¶
Proper resource cleanup:
void app_cleanup(void) {
/* Release devices */
nx_factory_gpio_release(led);
nx_factory_uart_release(uart);
/* Deinitialize frameworks */
shell_deinit();
log_deinit();
/* Deinitialize HAL */
nx_hal_deinit();
}
Best Practices¶
Code Organization¶
Separate concerns: One file per module
Use headers: Public API in headers, implementation in source
Minimize dependencies: Reduce coupling between modules
Document interfaces: Use Doxygen comments
Error Handling¶
Check all return values: Never ignore errors
Log errors: Use logging framework
Fail gracefully: Implement recovery strategies
Use assertions: For programming errors
Resource Management¶
Initialize before use: Always initialize resources
Clean up: Release resources when done
Avoid leaks: Match allocations with deallocations
Use RAII pattern: Acquire resources in initialization
Concurrency¶
Protect shared data: Use mutexes
Avoid deadlocks: Acquire locks in consistent order
Minimize critical sections: Hold locks briefly
Use queues: For inter-task communication
Testing¶
Write unit tests: Test individual components
Test error paths: Don't just test happy path
Use mocks: Isolate dependencies
Automate tests: Run tests in CI/CD
Next Steps¶
Now that you understand core concepts:
Configuration - Master Kconfig configuration
Examples Tour - Explore complex examples
架构 - Deep dive into architecture
教程 - Follow step-by-step tutorials
See Also¶
硬件抽象层 (HAL) - HAL API reference
操作系统抽象层 (OSAL) - OSAL API reference
日志框架 - Logging framework
编码规范 - Coding standards