RTT-UART驱动框架分析


UART

通过设备管理接口调用UART
I/O设备管理接口

libraries\HAL_Drivers\drivers\drv_usart.c下有串口初始化函数将,串口注册到系统中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
int rt_hw_usart_init(void)
{
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
rt_err_t result = 0;

stm32_uart_get_dma_config();

for (rt_size_t i = 0; i < sizeof(uart_obj) / sizeof(struct stm32_uart); i++)
{
/* init UART object */
uart_obj[i].config = &uart_config[i];
uart_obj[i].serial.ops = &stm32_uart_ops;
uart_obj[i].serial.config = config;

/* register UART device */
result = rt_hw_serial_register(&uart_obj[i].serial, uart_obj[i].config->name,
RT_DEVICE_FLAG_RDWR
| RT_DEVICE_FLAG_INT_RX
| RT_DEVICE_FLAG_INT_TX
| uart_obj[i].uart_dma_flag
, NULL);
RT_ASSERT(result == RT_EOK);
}

return result;
}
1
2
3
4
5
6
7
8
9
static struct stm32_uart_config uart_config[] =
{
#ifdef BSP_USING_UART1
UART1_CONFIG,
#endif
#ifdef BSP_USING_UART2
UART2_CONFIG,
#endif
};

其中UART1_CONFIG的定义是

1
2
3
4
5
6
7
#define UART1_CONFIG             \
{ \
.name = "uart1", \
.Instance = USART1, \
.irq_type = USART1_IRQn, \
}
#endif /* UART1_CONFIG */

所以可以通过名字搜索到设备

rt_device_find()

在注册后,可以通过搜索名字找到具体设备
同样是向下调用,在 object 中每一钟类型都有一个链表,如线程、信号量、互斥量、邮箱等等

1
2
3
4
rt_device_t rt_device_find(const char *name)
{
return (rt_device_t)rt_object_find(name, RT_Object_Class_Device);
}

rt_device_open()

设备管理层在rt-thread\components\drivers\core\device.c可搜索到函数rt_device_open()
设备驱动框架层的封装rt-thread\components\drivers\serial\dev_serial.c,如rt_serial_init()
驱动层libraries\HAL_Drivers\drivers\drv_usart.c是具体实现,如stm32_configure()

rt_device_open()
->device_init()->dev->init()
->rt_serial_init()
->result = serial->ops->configure(serial, &serial->config);
->stm32_configure()
->device_open()
->rt_serial_open()
->serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX);
->stm32_control()

rt_device_write()

过程大同小异
都是向下调用,最终会调用到 stm32_putc()/stm32_dma_transmit(),这里就是往寄存器写了

rt_device_read()

stm32_getc()/dma_recv_isr()

应用层是从上往下
中断是从下往上

USART1_IRQHandler
->uart_isr
->rt_hw_serial_isr
->serial->parent.rx_indicate(&serial->parent,rx_length)

其中可以注册回调函数

1
2
3
rt_err_t rt_device_set_rx_indicate(rt_device_t dev,
rt_err_t (*rx_ind)(rt_device_t dev,
rt_size_t size))