今天在研究RT-Thread日志模块ulog的时候发现最终log是通过控制台设备输出,控制台设备本质也是一个串口设备,于是就研究了一下串口设备。
我们先来看一下log输出:
rt_device_t dev = rt_console_get_device();
rt_uint16_t old_flag = dev->open_flag;
dev->open_flag |= RT_DEVICE_FLAG_STREAM;
rt_device_write(dev, 0, log, len);
dev->open_flag = old_flag;
log输出前先获取console设备,然后调用rt_device_write输出。接着看一下console设备初始化流程。
#ifdef RT_USING_CONSOLE
rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif
上面这段代码是在rt_hw_board_init()中进行。其中RT_CONSOLE_DEVICE_NAME定义如下:
#define RT_CONSOLE_DEVICE_NAME “uart1”
可见是一个串口设备,具体的初始化如下:
rt_device_t rt_console_set_device(const char *name)
{
rt_device_t new_device, old_device;
/* save old device */
old_device = _console_device;
/* find new console device */
new_device = rt_device_find(name);
/* check whether it's a same device */
if (new_device == old_device) return RT_NULL;
if (new_device != RT_NULL)
{
if (_console_device != RT_NULL)
{
/* close old console device */
rt_device_close(_console_device);
}
/* set new console device */
rt_device_open(new_device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM);
_console_device = new_device;
}
return old_device;
}
RTM_EXPORT(rt_console_set_device);
从这里可以看到控制台设备就是一个串口设备。
重新看回rt_hw_board_init()函数
/* USART driver initialization is open by default */
#ifdef RT_USING_SERIAL
rt_hw_usart_init();
#endif
/* Set the shell console output device */
#ifdef RT_USING_CONSOLE
rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif
可以看到初始化控制台设备之前对串口驱动进行初始化。具体的代码如下
int rt_hw_usart_init(void)
{
rt_size_t obj_num = sizeof(uart_obj) / sizeof(struct stm32_uart);
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
rt_err_t result = 0;
stm32_uart_get_dma_config();
for (int i = 0; i < obj_num; 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;
}
主要看一下这个地方uart_obj[i].config->name,我们找一下这个name在哪定义。
“uart_obj[i].config = &uart_config[i]”,由这一行代码我们看到串口配置是在uart_config这个数组里边。他的定义如下:
tatic struct stm32_uart_config uart_config[] =
{
#ifdef BSP_USING_UART1
UART1_CONFIG,
#endif
#ifdef BSP_USING_UART2
UART2_CONFIG,
#endif
#ifdef BSP_USING_UART3
UART3_CONFIG,
#endif
#ifdef BSP_USING_UART4
UART4_CONFIG,
#endif
#ifdef BSP_USING_UART5
UART5_CONFIG,
#endif
#ifdef BSP_USING_UART6
UART6_CONFIG,
#endif
#ifdef BSP_USING_UART7
UART7_CONFIG,
#endif
#ifdef BSP_USING_UART8
UART8_CONFIG,
#endif
#ifdef BSP_USING_LPUART1
LPUART1_CONFIG,
#endif
};
我们用的是uart1,接着看一下uart1的定义:
#define UART1_CONFIG \
{ \
.name = "uart1", \
.Instance = USART1, \
.irq_type = USART1_IRQn, \
}
名字就是uart1,回个头看rt_console_set_device(RT_CONSOLE_DEVICE_NAME),初始化控制台设备时就是用的uart1这个串口设备。