发布时间:2024-02-04 14:00
上一篇实现了基本移植操作,完成了uart单字节输出,为了便于调试,我们可以将printf函数重映射到uart上进行信息输出。
如果查阅其他足够多的资料,都会提到printf函数最终调用fputc()来实现输出,而关于比较实用的修改案例只有正点原子的STM32的修改,参考不多。
我这里再按照自己的理解来大概苏理一下实现思路,
首先,例如这样的printf(“asd%d”,n)函数执行的是格式化输出字符串,如果是你来写printf函数如何要让几乎所有的支持c的平台都能实现该函数。
实际做法是,① printf的格式化控制部分的功能写成标准的,也即将含有不定数量个变量的格式化输入转换成字符串输出,大致就是检测“%”,然后根据后面的格式控制符进行各种字符处理,最后统一成一个字符串量。② 将转换完成的字符串交给底层打印函数输出,而且为了通用,最好底层实现是单个字符单个字符输出。
可以看到E906例程代码中,printf的一种参考实现:
里面调用了_vsnprintf()
而这个函数的大致实现就是如下,几乎都是字符的格式控制
可以猜测_vsnprintf() 后就调用了所谓的fputc来进行打印输出。
扯了那么多,其实是就是重新实现一下fputc函数来覆盖默认的定义。
最简单的main函数 前加一个fputc的函数
int fputc(int ch, FILE *stream)
{
ck_uart_putc(&uart0, (char)ch);
}
最终整个hello_world:
#include \"datatype.h\"
#include \"stdio.h\"
#include \"uart.h\"
t_ck_uart_device uart0 = {0xFFFF};
//sys 50Mhz
void delay_ms(int time){
int i,j;
for(i=0;i<time;i++){
for(j=0;j<50000;j++){
;
}
}
}
//重写fputc
int fputc(int ch, FILE *stream)
{
ck_uart_putc(&uart0, (char)ch);
}
int main (void)
{
int a;
//--------------------------------------------------------
// setup uart
//--------------------------------------------------------
t_ck_uart_cfig uart_cfig;
uart_cfig.baudrate = BAUD; // any integer value is allowed
uart_cfig.parity = PARITY_NONE; // PARITY_NONE / PARITY_ODD / PARITY_EVEN
uart_cfig.stopbit = STOPBIT_1; // STOPBIT_1 / STOPBIT_2
uart_cfig.wordsize = WORDSIZE_8; // from WORDSIZE_5 to WORDSIZE_8
uart_cfig.txmode = ENABLE; // ENABLE or DISABLE
// open UART device with id = 0 (UART0)
ck_uart_open(&uart0, 0);
// initialize uart using uart_cfig structure
ck_uart_init(&uart0, &uart_cfig);
//Section 1: Function
printf(\"printf test!\\n\");
//Section 2: Uart
while(1){
for(a=0;a<10;a++){
// ck_uart_putc(&uart0, a+48);
// delay_ms(10);
printf(\"\\n %d: Hello World!\\n\",a);
delay_ms(10);
}
}
return 0;
}
最后再把工程中 opene906-main/smart_run/tests/lib/clib/fputc.c文件中的 fputc函数注释掉