一、
2.2 vsprintf.c 从linux_0.11 copy过来,稍做修改
2.3 main.c 测试一下
2.4 Makefile 需要修改连接部分
2.4.1 将
$(PLATFORM_LIBS)变量加入,连接时需要libgcc.a库,否则会提示
现在串口只能打印字符串,没有实现格式化输出的功能,所以变量的值还不能打印出来。"逐行打印技术"没法实施,这太痛苦了,马上加入printf。
二、代码
root@ubuntu:~/myboot# tree
.
├── main.c
├── Makefile
├── nand.c
├── nand.h
├── sdram.c
├── start.S
├── uart.c
├── uart.h
├── u-boot.lds
└──
vsprintf.c
0 directories, 10 files
2.1 uart.c 加入uart_printf的实现
点击(此处)折叠或打开
- #include
- #define GPHCON (* (volatile unsigned int *) 0x56000070)
- #define GPHUP (* (volatile unsigned int *) 0x56000078)
-
- #define ULCON0 (* (volatile unsigned int *) 0x50000000)
- #define UCON0 (* (volatile unsigned int *) 0x50000004)
- #define UFCON0 (* (volatile unsigned int *) 0x50000008)
- #define UMCON0 (* (volatile unsigned int *) 0x5000000C)
- #define UTRSTAT0 (* (volatile unsigned int *) 0x50000010)
- #define UERSTAT0 (* (volatile unsigned int *) 0x50000014)
- #define UFSTAT0 (* (volatile unsigned int *) 0x50000018)
- #define UMSTAT0 (* (volatile unsigned int *) 0x5000001C)
- #define UTXH0 (* (volatile unsigned char *) 0x50000020) //类型为:char*
- #define URXH0 (* (volatile unsigned char *) 0x50000024)
- #define UBRDIV0 (* (volatile unsigned int *) 0x50000028)
-
- #define BAUD_RATE 115200
-
- void uart_init(void)
- {
- GPHCON = 0x000000A0;
- GPHUP = 0x000007FF;
- ULCON0 = (0x03); //8N1
- UCON0 = (0x01<<2)|(0x01);
- UFCON0 = 0;
- UMCON0 = 0;
- UBRDIV0 = (int)((50*1000*1000)/(BAUD_RATE*16))-1;
- }
-
- unsigned char uart_getc(void)
- {
- while(!(UTRSTAT0 & 0x01))
- ;
- return (URXH0 & 0xff);
- }
-
- void uart_putc(char c)
- {
- while (!(UTRSTAT0&0x02))
- ;
- UTXH0 = c;
- if('\n' == c)
- uart_putc('\r');
- }
-
- void uart_puts(char *s)
- {
- while (*s)
- {
- uart_putc(*s++);
- }
- }
- /*uart_printf*/
- void uart_printf(char *fmt, ...)
- {
- va_list ap;
- char buf[256];
- va_start(ap, fmt);
- vsprintf(buf, fmt, ap);
- uart_puts(buf);
- va_end(ap);
- }
点击(此处)折叠或打开
- #include <stdarg.h>
- /* we use this so that we can do without the ctype library */
- #define is_digit(c) ((c) >= '0' && (c) <= '9')
- int strlen(const char *s)
- {
- const char *sc;
- for(sc=s; *sc!='\0'; ++sc)
- ;
- return (sc-s);
- }
-
- static int skip_atoi(const char **s)
- {
- int i=0;
-
- while (is_digit(**s))
- i = i*10 + *((*s)++) - '0';
- return i;
- }
-
- #define ZEROPAD 1 /* pad with zero */
- #define SIGN 2 /* unsigned/signed long */
- #define PLUS 4 /* show plus */
- #define SPACE 8 /* space if plus */
- #define LEFT 16 /* left justified */
- #define SPECIAL 32 /* 0x */
- #define SMALL 64 /* use 'abcdef' instead of 'ABCDEF' */
-
- #if 0
- #define do_div(n,base) ({ \
- int __res; \
- __asm__("divl %4":"=a" (n),"=d" (__res):"0" (n),"1" (0),"r" (base)); \
- __res; })
- #endif
-
- #define do_div(n,base) ({ \
- int __res; \
- __res = ((unsigned long) n) % (unsigned) base; \
- n = ((unsigned long) n) / (unsigned) base; \
- __res; \
- })
-
- static char * number(char * str, int num, int base, int size, int precision
- ,int type)
- {
- char c,sign,tmp[36];
- const char *digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- int i;
-
- if (type&SMALL) digits="0123456789abcdefghijklmnopqrstuvwxyz";
- if (type&LEFT) type &= ~ZEROPAD;
- if (base<2 || base>36)
- return 0;
- c = (type & ZEROPAD) ? '0' : ' ' ;
- if (type&SIGN && num<0) {
- sign='-';
- num = -num;
- } else
- sign=(type&PLUS) ? '+' : ((type&SPACE) ? ' ' : 0);
- if (sign) size--;
- if (type&SPECIAL) {
- if (base==16) size -= 2;
- else if (base==8) size--;
- }
- i=0;
- if (num==0)
- tmp[i++]='0';
- else while (num!=0)
- tmp[i++]=digits[do_div(num,base)];
- if (i>precision) precision=i;
- size -= precision;
- if (!(type&(ZEROPAD+LEFT)))
- while(size-->0)
- *str++ = ' ';
- if (sign)
- *str++ = sign;
- if (type&SPECIAL) {
- if (base==8)
- *str++ = '0';
- else if (base==16) {
- *str++ = '0';
- *str++ = digits[33];
- }
- }
- if (!(type&LEFT))
- while(size-->0)
- *str++ = c;
- while(i<precision--)
- *str++ = '0';
- while(i-->0)
- *str++ = tmp[i];
- while(size-->0)
- *str++ = ' ';
- return str;
- }
-
- int vsprintf(char *buf, const char *fmt, va_list args)
- {
- int len;
- int i;
- char * str;
- char *s;
- int *ip;
-
- int flags; /* flags to number() */
-
- int field_width; /* width of output field */
- int precision; /* min. # of digits for integers; max
- number of chars for from string */
- int qualifier; /* 'h', 'l', or 'L' for integer fields */
-
- for (str=buf ; *fmt ; ++fmt) {
- if (*fmt != '%') {
- *str++ = *fmt;
- continue;
- }
-
- /* process flags */
- flags = 0;
- repeat:
- ++fmt; /* this also skips first '%' */
- switch (*fmt) {
- case '-': flags |= LEFT; goto repeat;
- case '+': flags |= PLUS; goto repeat;
- case ' ': flags |= SPACE; goto repeat;
- case '#': flags |= SPECIAL; goto repeat;
- case '0': flags |= ZEROPAD; goto repeat;
- }
-
- /* get field width */
- field_width = -1;
- if (is_digit(*fmt))
- field_width = skip_atoi(&fmt);
- else if (*fmt == '*') {
- /* it's the next argument */
- field_width = va_arg(args, int);
- if (field_width < 0) {
- field_width = -field_width;
- flags |= LEFT;
- }
- }
-
- /* get the precision */
- precision = -1;
- if (*fmt == '.') {
- ++fmt;
- if (is_digit(*fmt))
- precision = skip_atoi(&fmt);
- else if (*fmt == '*') {
- /* it's the next argument */
- precision = va_arg(args, int);
- }
- if (precision < 0)
- precision = 0;
- }
-
- /* get the conversion qualifier */
- qualifier = -1;
- if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
- qualifier = *fmt;
- ++fmt;
- }
-
- switch (*fmt) {
- case 'c':
- if (!(flags & LEFT))
- while (--field_width > 0)
- *str++ = ' ';
- *str++ = (unsigned char) va_arg(args, int);
- while (--field_width > 0)
- *str++ = ' ';
- break;
-
- case 's':
- s = va_arg(args, char *);
- len = strlen(s);
- if (precision < 0)
- precision = len;
- else if (len > precision)
- len = precision;
-
- if (!(flags & LEFT))
- while (len < field_width--)
- *str++ = ' ';
- for (i = 0; i < len; ++i)
- *str++ = *s++;
- while (len < field_width--)
- *str++ = ' ';
- break;
-
- case 'o':
- str = number(str, va_arg(args, unsigned long), 8,
- field_width, precision, flags);
- break;
-
- case 'p':
- if (field_width == -1) {
- field_width = 8;
- flags |= ZEROPAD;
- }
- str = number(str,
- (unsigned long) va_arg(args, void *), 16,
- field_width, precision, flags);
- break;
-
- case 'x':
- flags |= SMALL;
- case 'X':
- str = number(str, va_arg(args, unsigned long), 16,
- field_width, precision, flags);
- break;
-
- case 'd':
- case 'i':
- flags |= SIGN;
- case 'u':
- str = number(str, va_arg(args, unsigned long), 10,
- field_width, precision, flags);
- break;
-
- case 'n':
- ip = va_arg(args, int *);
- *ip = (str - buf);
- break;
-
- default:
- if (*fmt != '%')
- *str++ = '%';
- if (*fmt)
- *str++ = *fmt;
- else
- --fmt;
- break;
- }
- }
- *str = '\0';
- return str-buf;
- }
点击(此处)折叠或打开
- #include "uart.h"
-
- void main(void)
- {
- char c;
- uart_init(); //初始化串口
-
- while(1)
- {
- c = uart_getc();
- uart_printf("input char=%c\n",c);
- uart_printf("input char=%d\n",c);
- uart_printf("input char=%x\n",c);
- }
- }
点击(此处)折叠或打开
- u-boot: $(OBJS) $(LDSCRIPT)
- $(LD) $(LDFLAGS) $(OBJS) $(PLATFORM_LIBS) -Map u-boot.map -o u-boot
vsprintf.o(.text+0x2e4): In function `number':
: undefined reference to `__umodsi3'
vsprintf.o(.text+0x300): In function `number':
: undefined reference to `__udivsi3'
make: *** [u-boot] Error 1
2.4.2 注意连接顺序,
$(PLATFORM_LIBS)一定要放在$(OBJS)后面才行。
myboot_printf.rar (使用时,将后缀名rar改为tar.gz)