https://blog.csdn.net/ce123_zhouwei/article/details/7364294
详解U-Boot中printf函数的实现
一、printf函数调用关系
1.1fputc和srial_putc的关系
/*
* Output a single byte to the serial port.
*/
void serial_putc (const char c)//发送数据
{
S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR);
#ifdef CONFIG_MODEM_SUPPORT
if (be_quiet)
return;
#endif
/* wait for room in the tx FIFO */
while (!(uart->UTRSTAT & 0x2));
#ifdef CONFIG_HWFLOW
/* Wait for CTS up */
while(hwflow && !(uart->UMSTAT & 0x1))
;
#endif
uart->UTXH = c;
/* If \n, also do \r */
if (c == '\n')
serial_putc ('\r');
}
serial_putc函数是直接和控制相关的,通过UTXH寄存器发送数据。
void fputc (int file, const char c)
{
if (file < MAX_FILES)
stdio_devices[file]->putc (c);
}
这是在console_init_r中设置stdio_devices[]后才有的,其他的是类似的。
1.2putc和fputc的关系
void putc (const char c)
{
#ifdef CONFIG_SILENT_CONSOLE
if (gd->flags & GD_FLG_SILENT)
return;
#endif
if (gd->flags & GD_FLG_DEVINIT) {
/* Send to the standard output */
fputc (stdout, c);
} else {
/* Send directly to the handler */
serial_putc (c);
}
}
这是console_init_r中设置gd->flags & GD_FLG_DEVINIT,也就是串口设备完全初始化之后才有这种关系,其他的函数是类似的。
二、serial_printf (const char *fmt, ...)
serial_printf函数是通过一个宏va_start把所有的可变参数放到了由args指向的一块内存中,vsprintf将变参列表args中的变量按照fmt中规定的格式保存到临时缓冲printbuffer中,最后调用serial_puts函数将临时缓冲中的字符串数据打印到终端中去。
void serial_printf (const char *fmt, ...)
{
va_list args;
uint i;
char printbuffer[CFG_PBSIZE];
va_start (args, fmt);
/* For this to work, printbuffer must be larger than
* anything we ever want to print.
*/
i = vsprintf (printbuffer, fmt, args);
va_end (args);
serial_puts (printbuffer);
}
三、fprintf(int file, const char *fmt, ...)
fprintf函数是通过一个宏va_start把所有的可变参数放到了由args指向的一块内存中,vsprintf将变参列表args中的变量按照fmt中规定的格式保存到临时缓冲printbuffer中,最后调用fputs函数将临时缓冲中的字符串数据打印到终端中去。
void fprintf (int file, const char *fmt, ...)
{
va_list args;
uint i;
char printbuffer[CFG_PBSIZE];
va_start (args, fmt);
/* For this to work, printbuffer must be larger than
* anything we ever want to print.
*/
i = vsprintf (printbuffer, fmt, args);
va_end (args);
/* Send to desired file */
fputs (file, printbuffer);
}
四、vprintf(const char *fmt, va_list args)
vprintf函数是通过一个宏va_start把所有的可变参数放到了由args指向的一块内存中,vsprintf将变参列表args中的变量按照fmt中规定的格式保存到临时缓冲printbuffer中,最后调用puts函数将临时缓冲中的字符串数据打印到终端中去。
void vprintf (const char *fmt, va_list args)
{
uint i;
char printbuffer[CFG_PBSIZE];
/* For this to work, printbuffer must be larger than
* anything we ever want to print.
*/
i = vsprintf (printbuffer, fmt, args);
/* Print the string */
puts (printbuffer);
}
五、printf(const char *fmt, ...)
printf函数是通过一个宏va_start把所有的可变参数放到了由args指向的一块内存中,vsprintf将变参列表args中的变量按照fmt中规定的格式保存到临时缓冲printbuffer中,最后调用puts函数将临时缓冲中的字符串数据打印到终端中去。
void printf (const char *fmt, ...)
{
va_list args;
uint i;
char printbuffer[CFG_PBSIZE];
va_start (args, fmt);
/* For this to work, printbuffer must be larger than
* anything we ever want to print.
*/
i = vsprintf (printbuffer, fmt, args);
va_end (args);
/* Print the string */
puts (printbuffer);
}
六、小结
serial_printf、vprintf和pringf函数基本相同,都是通过一个宏va_start把所有的可变参数放到了由args指向的一块内存中,vsprintf将变参列表args中的变量按照fmt中规定的格式保存到临时缓冲printbuffer中,最后调用不同的串口输出函数将临时缓冲中的字符串数据打印到终端中去。下面我们就来分析一下va_start、va_eng和vsprintf。
————————————————
版权声明:本文为CSDN博主「ce123」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ce123_zhouwei/article/details/7364294