printf实现

经常有人包括我自己关心printf是如何通过串口打印数据的。
在IAR中:以FRDM_KL26的SC为例或者FRDM_KE02Z的Driver为例
Printf()->printk()->prink_putc()->out_char()->uart_putchar()函数
在printf.c文件中
int
printf (const char *fmt, …)
{
va_list ap;
int rvalue;
PRINTK_INFO info;

info.dest = DEST_CONSOLE;
info.func = &out_char;
/*
 * Initialize the pointer to the variable length argument list.
 */
va_start(ap, fmt);
rvalue = printk(&info, fmt, ap);
/*
 * Cleanup the variable length argument list.
 */
va_end(ap);
return rvalue;

}

接着调用printk()函数,在ptintk()函数里调用printk_putc()函数。

        if (c != '\n')
        {
            printk_putc(c, &count, info);
        }
        else
        {
            printk_putc(0x0D /* CR */, &count, info);
            printk_putc(0x0A /* LF */, &count, info);
        }


        /*
         * By using 'continue', the next iteration of the loop
         * is used, skipping the code that follows.
         */
        continue;
    }

printk_putc()函数定义如下:
static void
printk_putc (int c, int *count, PRINTK_INFO *info)
{
switch (info->dest)
{
case DEST_CONSOLE:
info->func((char)c);
break;
case DEST_STRING:
*(info->loc) = (unsigned char)c;
++(info->loc);
break;
default:
break;
}
*count += 1;
}
这样就会调用out_char()函数。
Out_char()函数调用的就是uart发送函数。

/**********************************************************/
void
out_char (char ch)
{
if (TERM_PORT_NUM == 0)
uart0_putchar(UART0_BASE_PTR, ch);
else if (TERM_PORT_NUM == 1)
uart_putchar(UART1_BASE_PTR, ch);
else
uart_putchar(UART2_BASE_PTR, ch);

}

顺便说一下printf中 info.dest = DEST_CONSOLE;这句话的作用,这条语句从printk_putc()函数可以看出,它决定着是否打印到console中,如果它的值为DEST_STRING那么会将printf打印的值放到loc参数中,实际使用中可以存到一个char型数组中。
typedef struct
{
int dest;
void (*func)(char);
char *loc;
} PRINTK_INFO;

!!!!
在C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.0\arm\src\lib\dlib中有printf.c定义:

int (printf)(const char _Restrict *fmt, …)
{ /* print formatted to stdout */
int ans;
va_list ap;

va_start(ap, fmt);
ans = _Printf(&_Prout, (void *)1, fmt, &ap _SECURE_PARAM(0));
va_end(ap);
return (ans);
}

_STD_END

这时默认会打印到IAR的terminal。在程序中只要将原来的printf函数实现注释掉即可。调用printf函数只需要添加stdio.h头文件即可。
可以参考:
https://community.freescale.com/docs/DOC-98502

在Keil中:

http://www.stmcu.org/module/forum/thread-598294-1-1.html 非常好!!
Printf->fpuc()->out_char()->uart_putchar()

位于io.c 中

/**********************************************************/
int fputc(int ch, FILE *f)
{
out_char((char)ch);
return 1;
}

void
out_char (char ch)
{
UART_PutChar(TERM_PORT, ch);
}

在MQX中:

你可能感兴趣的:(printf实现)