硬件抽象层 (HAL)¶
概述¶
Nexus HAL 为不同 MCU 平台的硬件外设提供统一的面向对象接口。它使用工厂模式创建设备实例,并采用基于接口的设计进行操作。
主要特性:
工厂模式用于设备创建和生命周期管理
基于接口的设计,跨外设提供一致的 API
引用计数实现安全的资源管理
支持同步和异步操作
电源管理和诊断接口
参见
操作系统抽象层 (OSAL) - OS Abstraction Layer for RTOS integration
外设 配置 Guide - Peripheral configuration guide
平台 Guides - Platform-specific guides
GPIO Control 教程 - GPIO tutorial
UART Communication 教程 - UART tutorial
HAL API 参考 - Complete HAL API reference
架构¶
HAL 分为以下几层:
graph TB
APP[Application Code] --> FACTORY[nx_factory]
FACTORY --> CREATE[Create Device]
CREATE --> INTERFACE[Device Interface]
INTERFACE --> GPIO[nx_gpio_t]
INTERFACE --> UART[nx_uart_t]
INTERFACE --> SPI[nx_spi_t]
INTERFACE --> I2C[nx_i2c_t]
GPIO --> PLATFORM[Platform Implementation]
UART --> PLATFORM
SPI --> PLATFORM
I2C --> PLATFORM
PLATFORM --> STM32F4[STM32F4 HAL]
PLATFORM --> STM32H7[STM32H7 HAL]
PLATFORM --> NATIVE[Native HAL]
STM32F4 --> HW[Hardware]
STM32H7 --> HW
style APP fill:#e1f5ff
style FACTORY fill:#fff4e1
style INTERFACE fill:#ffe1f5
style PLATFORM fill:#e1ffe1
style HW fill:#cccccc
Device Lifecycle¶
The following diagram shows the complete device lifecycle from creation to release:
sequenceDiagram
participant App as Application
participant Factory as nx_factory
participant Device as Device Instance
participant Platform as Platform HAL
participant HW as Hardware
App->>Factory: nx_factory_gpio(port, pin)
Factory->>Platform: Allocate device
Platform->>HW: Initialize hardware
HW-->>Platform: Hardware ready
Platform-->>Factory: Device created
Factory-->>App: Return device pointer
App->>Device: write(device, value)
Device->>Platform: Platform-specific write
Platform->>HW: Set pin state
HW-->>Platform: State set
Platform-->>Device: Write complete
Device-->>App: Operation complete
App->>Factory: nx_factory_gpio_release(device)
Factory->>Platform: Decrement ref count
Platform->>HW: Deinitialize hardware
HW-->>Platform: Hardware released
Platform-->>Factory: Device released
Factory-->>App: Release complete
支持的外设¶
模块 |
接口 |
描述 |
|---|---|---|
GPIO |
nx_gpio_t |
通用输入输出 |
UART |
nx_uart_t |
串行通信 |
SPI |
nx_spi_t |
SPI 总线 |
I2C |
nx_i2c_t |
I2C 总线 |
定时器 |
nx_timer_t |
硬件定时器 |
ADC |
nx_adc_t |
模拟输入 |
快速开始¶
Include the main header:
#include "hal/nx_hal.h"
Initialize and use:
int main(void)
{
/* Initialize HAL */
nx_status_t status = nx_hal_init();
if (status != NX_OK) {
return -1;
}
/* Get a GPIO device (port is character 'A', 'B', etc.) */
nx_gpio_write_t* led = nx_factory_gpio_write('A', 5);
if (led) {
/* Initialize GPIO device */
nx_lifecycle_t* lc = led->get_lifecycle(led);
status = lc->init(lc);
if (status == NX_OK) {
led->write(led, 1); /* Turn on */
led->toggle(led); /* Toggle */
}
}
/* Get UART device */
nx_uart_t* uart = nx_factory_uart(0);
if (uart) {
/* Initialize UART device */
nx_lifecycle_t* lc = uart->get_lifecycle(uart);
status = lc->init(lc);
if (status == NX_OK) {
nx_tx_sync_t* tx = uart->get_tx_sync(uart);
const char* msg = "Hello!\n";
tx->send(tx, (const uint8_t*)msg, strlen(msg), 1000);
}
}
/* Cleanup */
nx_hal_deinit();
return 0;
}
GPIO 模块¶
Get GPIO device:
/* Get GPIO read-write interface (port is a character 'A', 'B', etc.) */
nx_gpio_t* gpio = nx_factory_gpio('A', 5); /* Port A, Pin 5 */
/* Or get specific interfaces */
nx_gpio_read_t* input = nx_factory_gpio_read('B', 0);
nx_gpio_write_t* output = nx_factory_gpio_write('C', 13);
Write operations:
nx_gpio_write_t* led = nx_factory_gpio_write('A', 5);
if (led) {
/* Initialize device */
nx_lifecycle_t* lc = led->get_lifecycle(led);
nx_status_t status = lc->init(lc);
if (status == NX_OK) {
led->write(led, 1); /* High */
led->write(led, 0); /* Low */
led->toggle(led); /* Toggle state */
}
}
Read operations:
nx_gpio_read_t* button = nx_factory_gpio_read('B', 0);
if (button) {
/* Initialize device */
nx_lifecycle_t* lc = button->get_lifecycle(button);
nx_status_t status = lc->init(lc);
if (status == NX_OK) {
uint8_t state = button->read(button);
}
}
External interrupt:
void button_callback(void* user_data)
{
/* Handle button press */
}
nx_gpio_read_t* btn = nx_factory_gpio_read('B', 0);
if (btn) {
/* Initialize device */
nx_lifecycle_t* lc = btn->get_lifecycle(btn);
nx_status_t status = lc->init(lc);
if (status == NX_OK) {
btn->register_exti(btn, button_callback, NULL, NX_GPIO_TRIGGER_FALLING);
}
}
UART 模块¶
Get UART device:
nx_uart_t* uart = nx_factory_uart(0); /* UART0 */
备注
UART configuration (baudrate, parity, stop bits, etc.) is done through Kconfig at compile-time. The factory function returns a configured device.
Synchronous operations (blocking):
nx_uart_t* uart = nx_factory_uart(0);
if (uart) {
/* Initialize device */
nx_lifecycle_t* lc = uart->get_lifecycle(uart);
nx_status_t status = lc->init(lc);
if (status != NX_OK) {
return;
}
nx_tx_sync_t* tx = uart->get_tx_sync(uart);
nx_rx_sync_t* rx = uart->get_rx_sync(uart);
/* Transmit with timeout */
const char* msg = "Hello, Nexus!";
status = tx->send(tx, (const uint8_t*)msg, strlen(msg), 1000);
/* Receive with timeout */
uint8_t buf[64];
size_t len = sizeof(buf);
status = rx->receive(rx, buf, &len, 1000);
/* Receive exact length */
len = 10;
status = rx->receive_all(rx, buf, &len, 1000);
}
Asynchronous operations (non-blocking):
nx_uart_t* uart = nx_factory_uart(0);
if (uart) {
/* Initialize device */
nx_lifecycle_t* lc = uart->get_lifecycle(uart);
nx_status_t status = lc->init(lc);
if (status != NX_OK) {
return;
}
nx_tx_async_t* tx = uart->get_tx_async(uart);
nx_rx_async_t* rx = uart->get_rx_async(uart);
/* Non-blocking send */
status = tx->send(tx, data, len);
if (status == NX_ERR_BUSY) {
/* Device busy, try later */
}
/* Non-blocking receive */
uint8_t buf[64];
size_t len = sizeof(buf);
status = rx->receive(rx, buf, &len);
if (status == NX_OK) {
/* Data received, len contains actual bytes read */
}
}
SPI 模块¶
Get SPI bus:
nx_spi_t* spi = nx_factory_spi(0); /* SPI0 bus */
备注
Bus-level configuration (clock frequency, pin mapping) is done through Kconfig at compile-time. Device-specific parameters (CS pin, speed, mode) are specified when acquiring communication handles.
Synchronous operations (blocking):
nx_spi_t* spi = nx_factory_spi(0);
if (spi) {
/* Initialize device */
nx_lifecycle_t* lc = spi->get_lifecycle(spi);
nx_status_t status = lc->init(lc);
if (status != NX_OK) {
return;
}
/* Configure device parameters */
nx_spi_device_config_t dev_cfg = NX_SPI_DEVICE_CONFIG_DEFAULT(5, 1000000);
dev_cfg.mode = NX_SPI_MODE_0;
dev_cfg.bit_order = NX_SPI_BIT_ORDER_MSB;
/* Get sync TX/RX handle for this device */
nx_tx_rx_sync_t* txrx = spi->get_tx_rx_sync_handle(spi, dev_cfg);
if (txrx) {
uint8_t tx_data[] = {0x01, 0x02, 0x03};
uint8_t rx_data[3];
size_t rx_len = sizeof(rx_data);
status = txrx->tx_rx(txrx, tx_data, sizeof(tx_data),
rx_data, &rx_len, 1000);
}
}
Asynchronous operations (non-blocking):
nx_spi_t* spi = nx_factory_spi(0);
if (spi) {
/* Initialize device */
nx_lifecycle_t* lc = spi->get_lifecycle(spi);
nx_status_t status = lc->init(lc);
if (status != NX_OK) {
return;
}
nx_spi_device_config_t dev_cfg = NX_SPI_DEVICE_CONFIG_DEFAULT(5, 1000000);
/* Get async TX/RX handle */
nx_tx_rx_async_t* txrx = spi->get_tx_rx_async_handle(spi, dev_cfg,
my_callback, NULL);
if (txrx) {
uint8_t tx_data[] = {0x01, 0x02, 0x03};
status = txrx->tx_rx(txrx, tx_data, sizeof(tx_data), 1000);
/* Received data will be delivered via callback */
}
}
I2C 模块¶
Get I2C bus:
nx_i2c_t* i2c = nx_factory_i2c(0); /* I2C0 bus */
备注
Bus-level configuration (speed, pin mapping) is done through Kconfig at compile-time. Device address is specified when acquiring communication handles.
Synchronous operations (blocking):
nx_i2c_t* i2c = nx_factory_i2c(0);
if (i2c) {
/* Initialize device */
nx_lifecycle_t* lc = i2c->get_lifecycle(i2c);
nx_status_t status = lc->init(lc);
if (status != NX_OK) {
return;
}
uint8_t dev_addr = 0x50; /* Device address (7-bit) */
/* Get sync TX/RX handle for this device */
nx_tx_rx_sync_t* txrx = i2c->get_tx_rx_sync_handle(i2c, dev_addr);
if (txrx) {
uint8_t tx_data[] = {0x00, 0x10}; /* Register address */
uint8_t rx_data[16];
size_t rx_len = sizeof(rx_data);
status = txrx->tx_rx(txrx, tx_data, sizeof(tx_data),
rx_data, &rx_len, 1000);
}
/* Or use TX-only handle */
nx_tx_sync_t* tx = i2c->get_tx_sync_handle(i2c, dev_addr);
if (tx) {
uint8_t data[] = {0x00, 0x10, 0xAA};
status = tx->send(tx, data, sizeof(data), 1000);
}
}
Asynchronous operations (non-blocking):
nx_i2c_t* i2c = nx_factory_i2c(0);
if (i2c) {
/* Initialize device */
nx_lifecycle_t* lc = i2c->get_lifecycle(i2c);
nx_status_t status = lc->init(lc);
if (status != NX_OK) {
return;
}
uint8_t dev_addr = 0x50;
/* Get async TX/RX handle */
nx_tx_rx_async_t* txrx = i2c->get_tx_rx_async_handle(i2c, dev_addr,
my_callback, NULL);
if (txrx) {
uint8_t tx_data[] = {0x00, 0x10};
status = txrx->tx_rx(txrx, tx_data, sizeof(tx_data), 1000);
/* Received data will be delivered via callback */
}
}
错误处理¶
所有工厂函数在失败时返回 NULL。接口方法返回 nx_status_t:
nx_gpio_t* gpio = nx_factory_gpio('A', 5);
if (!gpio) {
/* Handle error: device not available */
return -1;
}
/* Check operation status */
nx_lifecycle_t* lc = gpio->read.get_lifecycle(&gpio->read);
nx_status_t status = lc->init(lc);
if (status != NX_OK) {
/* Handle error */
const char* err_str = nx_status_to_string(status);
}
常见状态码:
NX_OK- SuccessNX_ERR_INVALID_PARAM- Invalid parameterNX_ERR_INVALID_STATE- Invalid stateNX_ERR_TIMEOUT- Operation timeoutNX_ERR_BUSY- Resource busyNX_ERR_NO_MEMORY- Out of memoryNX_ERR_NO_DATA- No data availableNX_ERR_NACK- NACK received (I2C)NX_ERR_BUS- Bus error
生命周期管理¶
设备通过 nx_lifecycle_t 接口支持生命周期操作:
nx_uart_t* uart = nx_factory_uart(0);
if (uart) {
nx_lifecycle_t* lc = uart->get_lifecycle(uart);
/* Initialize device */
nx_status_t status = lc->init(lc);
/* Check device state */
nx_device_state_t state = lc->get_state(lc);
/* Suspend device */
status = lc->suspend(lc);
/* Resume device */
status = lc->resume(lc);
/* Deinitialize device */
status = lc->deinit(lc);
}
电源管理¶
设备通过 nx_power_t 接口支持电源管理:
nx_uart_t* uart = nx_factory_uart(0);
if (uart) {
nx_power_t* pwr = uart->get_power(uart);
/* Disable peripheral clock to save power */
nx_status_t status = pwr->disable(pwr);
/* Enable peripheral clock */
status = pwr->enable(pwr);
/* Check power state */
bool enabled = pwr->is_enabled(pwr);
}
API 参考¶
完整 API 文档请参阅 HAL API 参考。