1. 程式人生 > >12 裸板實現printf函式

12 裸板實現printf函式

裸板實現printf函式


在uboot上,首先uart第0個控制器已經被uboot驅動好了。
uart控制器負責資料的收發,我們只要把資料交給uart控制器發出,和從uart控制器裡把資料取回來即可。
也就是我們只要找到相應的uart控制器的配置暫存器即可。


檢視Allwinner_H3_Datasheet_V1.1.edit.pdf說明文件P468頁:

uart0的基地址0x01C28000

UART_RBR:uart0的資料接收暫存器0x01c28000,通過這個暫存器從uart控制器裡把資料取回 
UART_THR:uart0的資料傳送暫存器0x01c28000,通過這個暫存器把要發出的資料交給uart控制器 
    //注意這兩個暫存器地址一樣,區分是接收或傳送,通過對暫存器的讀操作或寫操作
UART_LSR:uart0的狀態暫存器0x01c28014,通過這個暫存器可以判斷是否可以發出資料或有資料可取回 //第6位為1表示,傳送器為空了,可以接著給資料來發送 //第0位為1表示uart控制器已接收到資料,可以從控制器取回資料

在uboot上測試:

mw.b  0x01c28000  0x41 1    //讓uart0控制器發出字母'A'

實現printf函式(myprintf.c):

typedef volatile unsigned int u32;

#define UART_RBR (*(u32 *)0x01c28000)
#define UART_THR (*(u32 *)0x01c28000)
#define UART_LSR (*(u32 *)0x01c28014) void puts(char *line); void putchar(int val); void printf(char *line, ...); void _start() { int i; puts("myprintf test ...\n"); printf("myprintf_int test %d\n", 112233); for (i = 0; i < 10; i++) { printf("myprintf test : %d, %c, %s, %x, %p\n"
, 1122, 'K', "hello", 0x77889394, 0x33445566); } } void print_int(int val) { //12345678 if (val <= 0) return; print_int(val/10); putchar('0' + val%10); } void print_hex(int val) { if (val <= 0) return; print_hex(val/16); if ((val%16) >= 10) putchar('a' + val%16-10); else putchar('0' + val%16); } void printf(char *line, ...) { unsigned char *l = line; unsigned long *p = (unsigned long *)(&line); p++; while (*l) { while ((*l) && (*l != '%')) putchar(*l++); if (0 == *l) break; l++; switch(*l) { case 'd': print_int(*p++); break; case 'p': puts("0x"); case 'x': print_hex(*p++); break; case 'c': putchar(*p++); break; case 's': puts(*p++); break; } l++; } } void putchar(int val) { while (!(UART_LSR & (1 << 6))) ; UART_THR = val; if ('\n' == val) putchar('\r'); } void puts(char *line) { while (*line) putchar(*line++); }