重映射
在初學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,要對相應的串口進行初始化。