RT-Thread 驱动开发
RT-Thread 设备驱动框架
RT-Thread 提供了完整的设备驱动框架,应用层通过统一的 I/O 设备管理接口访问硬件:
应用层
rt_device_find("uart1")
rt_device_open() / rt_device_read() / rt_device_write()
│
▼
I/O 设备管理层(rt_device_t)
│
▼
设备驱动层(rt_device_ops)
│
▼
硬件抽象层(HAL)注册设备驱动
c
/* uart_drv.c */
#include <rtthread.h>
#include <rtdevice.h>
struct my_uart_device {
struct rt_device parent; /* 必须是第一个成员 */
rt_uint32_t base_addr;
rt_uint32_t irq_num;
struct rt_semaphore rx_sem;
struct rt_ringbuffer *rx_rb;
};
/* 实现设备操作接口 */
static rt_err_t my_uart_init(rt_device_t dev)
{
struct my_uart_device *uart = (struct my_uart_device *)dev;
/* 初始化硬件 */
hw_uart_init(uart->base_addr, 115200);
rt_sem_init(&uart->rx_sem, "uart_rx", 0, RT_IPC_FLAG_FIFO);
uart->rx_rb = rt_ringbuffer_create(256);
return RT_EOK;
}
static rt_err_t my_uart_open(rt_device_t dev, rt_uint16_t oflag)
{
struct my_uart_device *uart = (struct my_uart_device *)dev;
/* 使能中断 */
rt_hw_interrupt_install(uart->irq_num, my_uart_isr, uart, "uart");
rt_hw_interrupt_umask(uart->irq_num);
return RT_EOK;
}
static rt_err_t my_uart_close(rt_device_t dev)
{
struct my_uart_device *uart = (struct my_uart_device *)dev;
rt_hw_interrupt_mask(uart->irq_num);
return RT_EOK;
}
static rt_ssize_t my_uart_read(rt_device_t dev, rt_off_t pos,
void *buffer, rt_size_t size)
{
struct my_uart_device *uart = (struct my_uart_device *)dev;
rt_uint8_t *buf = (rt_uint8_t *)buffer;
rt_size_t received = 0;
while (received < size) {
/* 等待数据 */
if (rt_sem_take(&uart->rx_sem, RT_WAITING_FOREVER) != RT_EOK)
break;
rt_size_t n = rt_ringbuffer_get(uart->rx_rb,
buf + received, size - received);
received += n;
}
return received;
}
static rt_ssize_t my_uart_write(rt_device_t dev, rt_off_t pos,
const void *buffer, rt_size_t size)
{
struct my_uart_device *uart = (struct my_uart_device *)dev;
const rt_uint8_t *buf = (const rt_uint8_t *)buffer;
for (rt_size_t i = 0; i < size; i++) {
/* 等待发送缓冲区空 */
while (!hw_uart_tx_ready(uart->base_addr))
;
hw_uart_write_byte(uart->base_addr, buf[i]);
}
return size;
}
static rt_err_t my_uart_control(rt_device_t dev, int cmd, void *args)
{
struct my_uart_device *uart = (struct my_uart_device *)dev;
switch (cmd) {
case RT_DEVICE_CTRL_CONFIG: {
struct serial_configure *cfg = (struct serial_configure *)args;
hw_uart_set_baud(uart->base_addr, cfg->baud_rate);
return RT_EOK;
}
default:
return -RT_EINVAL;
}
}
/* 设备操作接口表 */
#ifdef RT_USING_DEVICE_OPS
static const struct rt_device_ops my_uart_ops = {
.init = my_uart_init,
.open = my_uart_open,
.close = my_uart_close,
.read = my_uart_read,
.write = my_uart_write,
.control = my_uart_control,
};
#endif
/* 中断处理 */
static void my_uart_isr(int irqno, void *param)
{
struct my_uart_device *uart = (struct my_uart_device *)param;
rt_uint8_t byte;
while (hw_uart_rx_ready(uart->base_addr)) {
byte = hw_uart_read_byte(uart->base_addr);
rt_ringbuffer_putchar(uart->rx_rb, byte);
}
/* 通知读取任务 */
rt_sem_release(&uart->rx_sem);
}
/* 注册设备 */
static struct my_uart_device uart1_dev = {
.base_addr = UART1_BASE,
.irq_num = UART1_IRQ,
};
int my_uart_register(void)
{
rt_device_t dev = &uart1_dev.parent;
dev->type = RT_Device_Class_Char;
#ifdef RT_USING_DEVICE_OPS
dev->ops = &my_uart_ops;
#else
dev->init = my_uart_init;
dev->open = my_uart_open;
dev->close = my_uart_close;
dev->read = my_uart_read;
dev->write = my_uart_write;
dev->control = my_uart_control;
#endif
return rt_device_register(dev, "uart1", RT_DEVICE_FLAG_RDWR);
}
INIT_BOARD_EXPORT(my_uart_register); /* 自动初始化 */应用层使用
c
#include <rtthread.h>
#include <rtdevice.h>
void uart_sample(void)
{
rt_device_t uart;
char buf[64];
rt_ssize_t len;
/* 查找设备 */
uart = rt_device_find("uart1");
if (!uart) {
rt_kprintf("uart1 not found\n");
return;
}
/* 打开设备(中断接收模式) */
rt_device_open(uart, RT_DEVICE_FLAG_INT_RX);
/* 配置波特率 */
struct serial_configure cfg = RT_SERIAL_CONFIG_DEFAULT;
cfg.baud_rate = BAUD_RATE_9600;
rt_device_control(uart, RT_DEVICE_CTRL_CONFIG, &cfg);
/* 发送数据 */
const char *msg = "Hello RT-Thread!\r\n";
rt_device_write(uart, 0, msg, rt_strlen(msg));
/* 接收数据 */
len = rt_device_read(uart, 0, buf, sizeof(buf) - 1);
if (len > 0) {
buf[len] = '\0';
rt_kprintf("Received: %s\n", buf);
}
rt_device_close(uart);
}RT-Thread 内核同步原语
c
/* 信号量 */
rt_sem_t sem = rt_sem_create("my_sem", 0, RT_IPC_FLAG_FIFO);
rt_sem_release(sem);
rt_sem_take(sem, RT_WAITING_FOREVER);
rt_sem_take(sem, rt_tick_from_millisecond(1000));
rt_sem_delete(sem);
/* 互斥锁(支持优先级继承) */
rt_mutex_t mutex = rt_mutex_create("my_mutex", RT_IPC_FLAG_PRIO);
rt_mutex_take(mutex, RT_WAITING_FOREVER);
rt_mutex_release(mutex);
/* 消息队列 */
rt_mq_t mq = rt_mq_create("my_mq", sizeof(my_msg_t), 10, RT_IPC_FLAG_FIFO);
rt_mq_send(mq, &msg, sizeof(msg));
rt_mq_recv(mq, &msg, sizeof(msg), RT_WAITING_FOREVER);
/* 邮箱(传递指针,效率高) */
rt_mailbox_t mb = rt_mb_create("my_mb", 10, RT_IPC_FLAG_FIFO);
rt_mb_send(mb, (rt_ubase_t)ptr);
rt_mb_recv(mb, (rt_ubase_t *)&ptr, RT_WAITING_FOREVER);自动初始化机制
RT-Thread 提供分级自动初始化,无需手动调用:
c
/* 按初始化阶段分级 */
INIT_BOARD_EXPORT(fn); /* 板级初始化(最早) */
INIT_PREV_EXPORT(fn); /* 纯软件初始化 */
INIT_DEVICE_EXPORT(fn); /* 外设驱动初始化 */
INIT_COMPONENT_EXPORT(fn); /* 组件初始化 */
INIT_ENV_EXPORT(fn); /* 环境初始化 */
INIT_APP_EXPORT(fn); /* 应用初始化(最晚) */FinSH 命令行调试
c
/* 注册调试命令 */
static int uart_test(int argc, char *argv[])
{
rt_kprintf("UART test\n");
return 0;
}
MSH_CMD_EXPORT(uart_test, test uart driver);
/* 在 FinSH 中执行 */
/* msh > uart_test */