一、
现在串口只能打印字符串,没有实现格式化输出的功能,所以变量的值还不能打印出来。"逐行打印技术"没法实施,这太痛苦了,马上加入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);
-
}
2.2 vsprintf.c 从linux_0.11 copy过来,稍做修改
-
#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;
-
}
2.3 main.c 测试一下
-
#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);
-
}
-
}
2.4 Makefile 需要修改连接部分
-
u-boot: $(OBJS) $(LDSCRIPT)
-
$(LD) $(LDFLAGS) $(OBJS) $(PLATFORM_LIBS) -Map u-boot.map -o u-boot
2.4.1 将
$(PLATFORM_LIBS)变量加入,连接时需要libgcc.a库,否则会提示
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)后面才行。
阅读(2446) | 评论(0) | 转发(1) |