一、怎么使用
例子:
#define RT_DEVICE_UART "uart1"
static rt_device_t uart; // 静态创建一个串口设备
const char *str ="Hello World!\n";
uart = rt_device_find(RT_DEVICE_UART); // 查找串口设备,函数会在设备链表中找出与RT_DEVICE_UART宏指定的设备名一致的设备
rt_device_open(uart, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM); // 打开该串口设备
rt_device_write(uart, 0, str, rt_strlen(str)); // 发送str指向的数据
rt_device_close(uart); // 关闭串口设备
二、从头开始解析
在$Super$$main函数调用rtthread_startup(),
components.c
int $Super$$main(void)
{
rt_hw_interrupt_disable();
rtthread_startup();
return 0;
}
rtthread_startup()->rt_hw_board_init()
components.c
int rtthread_startup(void)
{
……
/* board level initalization
* NOTE: please initialize heap inside board initialization.
*/
rt_hw_board_init();
……
}
rt_hw_board_init()->rt_components_board_init()
board.c
void rt_hw_board_init(void)
{
……
#ifdef RT_USING_COMPONENTS_INIT
rt_components_board_init();
#endif
……
}
在rt_components_board_init()函数里会依次调用INIT_BOARD_EXPORT()这个宏存放在特定位置的函数,自然而然的调用了rt_hw_usart_init()这个函数
drv_usart.c
INIT_BOARD_EXPORT(rt_hw_usart_init);
components.c
void rt_components_board_init(void)
{
……
for (fn_ptr = &__rt_init_rti_board_start; fn_ptr < &__rt_init_rti_board_end; fn_ptr++)
{
(*fn_ptr)();
}
……
}
/***********************************************************************************************************/
drv_usart.c
int rt_hw_usart_init(void)
{
struct stm32_uart *uart;
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
#if defined(RT_USING_UART1)
uart = &uart1;
config.baud_rate = BAUD_RATE_115200;
serial1.ops = &stm32_uart_ops; // 底层操作函数
serial1.config = config;
MX_USART_UART_Init(&uart->huart); // 硬件层的初始化
/* register UART1 device */
rt_hw_serial_register(&serial1, "uart1",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
uart);
#endif /* RT_USING_UART1 */
……
}
说明:rt_hw_usart_init()函数进行了默认的一系列初始化工作,serial1.ops 存放收发和配置函数。
并把serial1以uart1为名放入设备链表中,查找可以用rt_device_find(“uart1”)函数实现。
serial.c
rt_err_t rt_hw_serial_register(struct rt_serial_device *serial,
const char *name,
rt_uint32_t flag,
void *data)
{
rt_err_t ret;
struct rt_device *device;
RT_ASSERT(serial != RT_NULL);
device = &(serial->parent);
device->type = RT_Device_Class_Char;
device->rx_indicate = RT_NULL;
device->tx_complete = RT_NULL;
device->init = rt_serial_init;
device->open = rt_serial_open;
device->close = rt_serial_close;
device->read = rt_serial_read;
device->write = rt_serial_write;
device->control = rt_serial_control;
device->user_data = data;
/* register a character device */
ret = rt_device_register(device, name, flag);
return ret;
}
说明:应用层面的rt_device_open()、rt_device_write()和rt_device_read()函数就是调用对应的
rt_serial_open()、rt_serial_write()、 rt_serial_read()函数,最终调用rt_hw_usart_init()函数里
stm32_uart_ops结构体里存放的的函数。
比如rt_serial_read()函数,调用关系rt_serial_read()->_serial_poll_rx()->serial->ops->getc()
serial.c
static rt_size_t rt_serial_read(struct rt_device *dev,
rt_off_t pos,
void *buffer,
rt_size_t size)
{
struct rt_serial_device *serial;
RT_ASSERT(dev != RT_NULL);
if (size == 0) return 0;
serial = (struct rt_serial_device *)dev;
if (dev->open_flag & RT_DEVICE_FLAG_INT_RX)
{
return _serial_int_rx(serial, buffer, size);
}
return _serial_poll_rx(serial, buffer, size);
}
serial.c
rt_inline int _serial_poll_rx(struct rt_serial_device *serial, rt_uint8_t *data, int length)
{
int ch;
int size;
RT_ASSERT(serial != RT_NULL);
size = length;
while (length)
{
ch = serial->ops->getc(serial);
if (ch == -1) break;
*data = ch;
data ++; length --;
if (ch == '\n') break;
}
return size - length;
}
这样初始化之后应用层函数就可以操作rt_device_write()和rt_device_read()等函数。
总结:
1、首先创建一个struct rt_serial_device serial1;设备;
2、对串口设备serial1进行初始化,挂接底层处理函数,注册等工作;
3、应用层使用相应接口函数使用串口设备;