重映射
在初学C语言时,用的最多的怕是printf()
函数了,其作用就是将传入的参数打印到屏幕上,可以实现人机交互或方便用户对程序的调试等等。
在RT-Thread中,也有一个打印函数rt_kprintf()
,其作用和printf()
类似,可以在调试时输出各种信息。但是如果想要使用rt_kprintf()
函数,就必须将控制台重映射到rt_kprintf()
,这个控制台可以是串口、CAN、USB、以太网等输出设备,这里主要介绍一下将串口重定向到rt_kprintf()
。
rt_kprintf()函数定义
rt_kprintf()
函数是在kservice.c
文件中实现的,属于内核服务类函数,源代码如下:
/**
* 简介:这个函数是用来向控制台打印特定格式的字符串
* 参数:fmt指定的格式
*/
void rt_kprintf(const char *fmt, ...)
{
va_list args;
rt_size_t length;
/* 定义一个字符缓冲区,用于储存将要发生的字符串,默认大小为128 */
static char rt_log_buf[RT_CONSOLEBUF_SIZE];
va_start(args, fmt);
/* 调用rt_vsnprintf()函数,将要输出的字符串按照fmt指定的格式传到rt_log_buf[]
缓冲区,然后我们将缓冲区的内容输出到控制台就可以了 */
length = rt_vsnprintf(rt_log_buf, sizeof(rt_log_buf) - 1, fmt, args);
/* 判断字符串是否超过大小范围,超过的话要裁剪 */
if (length > RT_CONSOLEBUF_SIZE - 1)
length = RT_CONSOLEBUF_SIZE - 1;
/* 如果使用设备驱动,通过设备驱动函数将缓冲区的内容输出到控制台 */
#ifdef RT_USING_DEVICE
if (_console_device == RT_NULL)
{
rt_hw_console_output(rt_log_buf);
}
else
{
rt_uint16_t old_flag = _console_device->open_flag;
_console_device->open_flag |= RT_DEVICE_FLAG_STREAM;
rt_device_write(_console_device, 0, rt_log_buf, length);
_console_device->open_flag = old_flag;
}
/* 如果不使用设备驱动函数,使用rt_hw_console_output()函数将缓冲区的内容输出到控制台 */
#else
rt_hw_console_output(rt_log_buf);
#endif
va_end(args);
}
RTM_EXPORT(rt_kprintf);
#endif
总的来说:使用rt_kprintf()
实现重映射就是先将要显示的字符串传入rt_kprintf()
的形参中,字符串会被放在rt_kprintf()
中申请好的一段缓冲区中,然后将缓冲区中的内容输出到指定的控制台(通过rt_hw_console_output()
函数),这样就实现了重映射,这里我们要重映射到串口,所以要对rt_hw_console_output()
函数进行定义!
自定义rt_hw_console_output()
rt_hw_console_output()
函数可以将缓冲区中的字符串输出到指定的控制台,这里我们将字符串输出到串口,也就是将串口控制台重映射到rt_kprintf()
函数,rt_hw_console_output()
的代码如下:
void rt_hw_console_output( const char *str )
{
/* 进入临界段 */
rt_enter_critical();
while(*str != '\0')
{
if( *str=='\n' )
{
/* 选择串口发送字符串 */
USART_SendData( DEBUG_USARTx, '\r' );
while(USART_GetFlagStatus( DEBUG_USARTx, USART_FLAG_TXE )==RESET)
;
}
}
/* 退出临界段 */
rt_exit_critical();
}
注意:重映射串口到rt_kprintf,要对相应的串口进行初始化。