Zephyr RTOS作为现代嵌入式系统开发的重要平台,积累了众多经典的开发实践。这些实践不仅体现了Zephyr的技术特色,也为开发者提供了宝贵的经验参考。以下是几个值得深入学习的经典实践案例。
Device Tree是Zephyr用于描述硬件和配置信息的核心机制,它提供了一种动态描述硬件的数据结构语言,而不是将板卡硬件的每个细节硬编码到操作系统中。
// 设备树定义 (board.dts)
/ {
aliases {
led0 = &green_led_0;
sw0 = &button_0;
};
leds {
compatible = "gpio-leds";
green_led_0: led_0 {
gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
label = "Green LED 0";
};
};
buttons {
compatible = "gpio-keys";
button_0: button_0 {
gpios = <&gpio0 11 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
label = "Push button switch 0";
};
};
};
// 应用代码中的Device Tree访问
#include
#include
#define LED0_NODE DT_ALIAS(led0)
#define SW0_NODE DT_ALIAS(sw0)
static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET(SW0_NODE, gpios);
int main(void)
{
if (!device_is_ready(led.port) || !device_is_ready(button.port)) {
return -ENODEV;
}
gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
gpio_pin_configure_dt(&button, GPIO_INPUT);
// 使用硬件抽象进行操作
while (1) {
if (gpio_pin_get_dt(&button)) {
gpio_pin_toggle_dt(&led);
}
k_msleep(100);
}
}
Zephyr提供了强大的线程管理和数据传递机制,包括线程上下文和中断上下文的处理。
#include
#include
#define STACK_SIZE 1024
#define PRIORITY 7
#define QUEUE_SIZE 10
// 定义消息队列
K_MSGQ_DEFINE(sensor_msgq, sizeof(int), QUEUE_SIZE, 4);
// 定义线程栈
K_THREAD_STACK_DEFINE(producer_stack, STACK_SIZE);
K_THREAD_STACK_DEFINE(consumer_stack, STACK_SIZE);
// 线程控制块
struct k_thread producer_thread;
struct k_thread consumer_thread;
// 生产者线程
void producer_thread_entry(void *p1, void *p2, void *p3)
{
int sensor_data = 0;
while (1) {
// 模拟传感器数据采集
sensor_data = sys_rand32_get() % 100;
// 发送数据到队列
if (k_msgq_put(&sensor_msgq, &sensor_data, K_NO_WAIT) != 0) {
printk("Producer: Queue full, data dropped\n");
} else {
printk("Producer: Data %d sent\n", sensor_data);
}
k_msleep(500);
}
}
// 消费者线程
void consumer_thread_entry(void *p1, void *p2, void *p3)
{
int received_data;
while (1) {
// 从队列接收数据
if (k_msgq_get(&sensor_msgq, &received_data, K_FOREVER) == 0) {
printk("Consumer: Processing data %d\n", received_data);
// 模拟数据处理
k_msleep(100);
}
}
}
int main(void)
{
printk("Multi-thread messaging example\n");
// 创建生产者线程
k_thread_create(&producer_thread, producer_stack,
K_THREAD_STACK_SIZEOF(producer_stack),
producer_thread_entry, NULL, NULL, NULL,
PRIORITY, 0, K_NO_WAIT);
// 创建消费者线程
k_thread_create(&consumer_thread, consumer_stack,
K_THREAD_STACK_SIZEOF(consumer_stack),
consumer_thread_entry, NULL, NULL, NULL,
PRIORITY, 0, K_NO_WAIT);
return 0;
}
#include
#include
#include
#define BME280_I2C_ADDR 0x76
#define BME280_CHIP_ID_REG 0xD0
#define BME280_CHIP_ID 0x60
struct bme280_data {
const struct device *i2c_dev;
uint8_t i2c_addr;
};
static int bme280_sample_fetch(const struct device *dev)
{
struct bme280_data *data = dev->data;
uint8_t chip_id;
// 读取芯片ID验证通信
if (i2c_reg_read_byte(data->i2c_dev, data->i2c_addr,
BME280_CHIP_ID_REG, &chip_id) < 0) {
return -EIO;
}
if (chip_id != BME280_CHIP_ID) {
printk("Invalid chip ID: 0x%02x\n", chip_id);
return -EINVAL;
}
// 实际的传感器数据读取逻辑
printk("BME280 sensor communication OK\n");
return 0;
}
static int bme280_init(const struct device *dev)
{
struct bme280_data *data = dev->data;
// 获取I2C设备
data->i2c_dev = DEVICE_DT_GET(DT_NODELABEL(i2c0));
if (!device_is_ready(data->i2c_dev)) {
printk("I2C device not ready\n");
return -ENODEV;
}
data->i2c_addr = BME280_I2C_ADDR;
// 初始化传感器
return bme280_sample_fetch(dev);
}
// 驱动API结构
static const struct sensor_driver_api bme280_api = {
.sample_fetch = bme280_sample_fetch,
};
// 设备数据
static struct bme280_data bme280_data_0;
// 设备定义
DEVICE_DT_DEFINE(DT_NODELABEL(bme280), bme280_init, NULL,
&bme280_data_0, NULL, POST_KERNEL,
CONFIG_SENSOR_INIT_PRIORITY, &bme280_api);
&i2c0 {
status = "okay";
clock-frequency = ;
bme280: bme280@76 {
compatible = "bosch,bme280";
reg = <0x76>;
label = "BME280";
};
};
#include
#include
#include
// 电源管理回调
static void app_pm_policy_handler(const struct pm_state_info *state)
{
printk("Entering power state: %d\n", state->state);
}
// 唤醒源配置
static void configure_wakeup_sources(void)
{
const struct gpio_dt_spec button = GPIO_DT_SPEC_GET(DT_ALIAS(sw0), gpios);
if (device_is_ready(button.port)) {
gpio_pin_configure_dt(&button, GPIO_INPUT);
gpio_pin_interrupt_configure_dt(&button, GPIO_INT_EDGE_TO_ACTIVE);
}
}
int main(void)
{
configure_wakeup_sources();
// 注册电源管理策略
pm_policy_handler_register(app_pm_policy_handler);
while (1) {
printk("Application running...\n");
// 执行必要的工作
k_msleep(1000);
// 允许系统进入低功耗状态
pm_device_action_run(DEVICE_DT_GET(DT_CHOSEN(zephyr_console)),
PM_DEVICE_ACTION_SUSPEND);
// 系统会自动根据策略进入适当的电源状态
k_msleep(5000);
pm_device_action_run(DEVICE_DT_GET(DT_CHOSEN(zephyr_console)),
PM_DEVICE_ACTION_RESUME);
}
}
#include
#include
#include
#include
#define SERVER_ADDR "192.168.1.100"
#define SERVER_PORT 5683
#define COAP_URI_PATH "sensors/temperature"
static struct sockaddr_in server_addr;
static int coap_sock;
static int send_coap_request(float temperature)
{
struct coap_packet request;
uint8_t request_buf[256];
char payload[32];
int ret;
// 构建CoAP请求
ret = coap_packet_init(&request, request_buf, sizeof(request_buf),
COAP_VERSION_1, COAP_TYPE_CON,
sizeof(coap_next_token()), coap_next_token(),
COAP_METHOD_POST, coap_next_id());
if (ret < 0) {
return ret;
}
// 添加URI路径选项
ret = coap_packet_append_option(&request, COAP_OPTION_URI_PATH,
COAP_URI_PATH, strlen(COAP_URI_PATH));
if (ret < 0) {
return ret;
}
// 准备负载数据
snprintf(payload, sizeof(payload), "{\"temp\":%.2f}", temperature);
// 添加负载
ret = coap_packet_append_payload_marker(&request);
if (ret < 0) {
return ret;
}
ret = coap_packet_append_payload(&request, payload, strlen(payload));
if (ret < 0) {
return ret;
}
// 发送请求
ret = send(coap_sock, request.data, request.offset, 0);
if (ret < 0) {
printk("Failed to send CoAP request: %d\n", errno);
return ret;
}
printk("CoAP request sent: %s\n", payload);
return 0;
}
static void wifi_connect_handler(struct net_mgmt_event_callback *cb,
uint32_t mgmt_event, struct net_if *iface)
{
if (mgmt_event == NET_EVENT_WIFI_CONNECT_RESULT) {
printk("WiFi connected, starting CoAP client\n");
// 创建UDP套接字
coap_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (coap_sock < 0) {
printk("Failed to create socket\n");
return;
}
// 配置服务器地址
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
inet_pton(AF_INET, SERVER_ADDR, &server_addr.sin_addr);
// 连接到服务器
connect(coap_sock, (struct sockaddr *)&server_addr, sizeof(server_addr));
}
}
int main(void)
{
static struct net_mgmt_event_callback wifi_cb;
// 注册WiFi事件回调
net_mgmt_init_event_callback(&wifi_cb, wifi_connect_handler,
NET_EVENT_WIFI_CONNECT_RESULT);
net_mgmt_add_event_callback(&wifi_cb);
// 模拟传感器数据发送
float temperature = 25.5f;
while (1) {
if (coap_sock > 0) {
send_coap_request(temperature);
temperature += 0.1f; // 模拟温度变化
}
k_msleep(10000); // 每10秒发送一次
}
return 0;
}
#include
#include
// 证书定义(实际应用中应该从安全存储加载)
static const char ca_certificate[] = {
#include "ca_cert.inc"
};
static int setup_tls_credentials(void)
{
int ret;
// 添加CA证书
ret = tls_credential_add(CA_CERTIFICATE_TAG, TLS_CREDENTIAL_CA_CERTIFICATE,
ca_certificate, sizeof(ca_certificate));
if (ret < 0) {
printk("Failed to add CA certificate: %d\n", ret);
return ret;
}
return 0;
}
static int secure_socket_create(void)
{
int sock;
int protocol = IPPROTO_TLS_1_2;
sec_tag_t sec_tag_list[] = { CA_CERTIFICATE_TAG };
sock = socket(AF_INET, SOCK_STREAM, protocol);
if (sock < 0) {
return -errno;
}
// 配置TLS选项
if (setsockopt(sock, SOL_TLS, TLS_SEC_TAG_LIST,
sec_tag_list, sizeof(sec_tag_list)) < 0) {
close(sock);
return -errno;
}
return sock;
}
#include
// 被测试的函数
int calculator_add(int a, int b)
{
return a + b;
}
int calculator_divide(int a, int b)
{
if (b == 0) {
return -EINVAL;
}
return a / b;
}
// 测试用例
ZTEST(calculator_tests, test_add_positive_numbers)
{
zassert_equal(calculator_add(2, 3), 5, "2 + 3 should equal 5");
}
ZTEST(calculator_tests, test_add_negative_numbers)
{
zassert_equal(calculator_add(-2, -3), -5, "-2 + (-3) should equal -5");
}
ZTEST(calculator_tests, test_divide_by_zero)
{
zassert_equal(calculator_divide(10, 0), -EINVAL,
"Division by zero should return -EINVAL");
}
ZTEST(calculator_tests, test_divide_normal)
{
zassert_equal(calculator_divide(10, 2), 5, "10 / 2 should equal 5");
}
// 测试套件定义
ZTEST_SUITE(calculator_tests, NULL, NULL, NULL, NULL, NULL);
#include
#include
LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG);
int main(void)
{
LOG_INF("Application started");
// 启用系统跟踪
sys_trace_thread_switched_in();
int sensor_value = read_sensor();
LOG_DBG("Sensor value: %d", sensor_value);
if (sensor_value < 0) {
LOG_ERR("Sensor read failed with error: %d", sensor_value);
return sensor_value;
}
LOG_INF("Sensor read successfully: %d", sensor_value);
return 0;
}
这些经典实践展现了Zephyr RTOS的强大能力:
Zephyr OS基于小占用空间的内核设计,适用于资源受限的嵌入式系统,从简单的环境传感器到复杂的IoT无线网关。这些实践不仅体现了技术的先进性,更重要的是提供了解决实际问题的可行方案。
对于开发者而言,掌握这些经典实践将大大提升开发效率,同时确保项目的可维护性和可扩展性。建议根据项目需求选择合适的实践模式,并在实际应用中不断优化和完善。