【第22期】观点:IT 行业加班,到底有没有价值?

bootloader---16.实现printf

原创 2016年08月29日 13:57:08
一、 
   现在串口只能打印字符串,没有实现格式化输出的功能,所以变量的值还不能打印出来。"逐行打印技术"没法实施,这太痛苦了,马上加入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的实现

点击(此处)折叠或打开

  1. #include 
  2. #define GPHCON (* (volatile unsigned int *) 0x56000070)
  3. #define GPHUP (* (volatile unsigned int *) 0x56000078)

  4. #define ULCON0 (* (volatile unsigned int *) 0x50000000)
  5. #define UCON0 (* (volatile unsigned int *) 0x50000004)
  6. #define UFCON0 (* (volatile unsigned int *) 0x50000008)
  7. #define UMCON0 (* (volatile unsigned int *) 0x5000000C)
  8. #define UTRSTAT0 (* (volatile unsigned int *) 0x50000010)
  9. #define UERSTAT0 (* (volatile unsigned int *) 0x50000014)
  10. #define UFSTAT0 (* (volatile unsigned int *) 0x50000018)
  11. #define UMSTAT0 (* (volatile unsigned int *) 0x5000001C)
  12. #define UTXH0 (* (volatile unsigned char *) 0x50000020) //类型为:char*
  13. #define URXH0 (* (volatile unsigned char *) 0x50000024)
  14. #define UBRDIV0 (* (volatile unsigned int *) 0x50000028)

  15. #define BAUD_RATE 115200

  16. void uart_init(void)
  17. {
  18.     GPHCON = 0x000000A0;
  19.     GPHUP = 0x000007FF;
  20.     ULCON0 = (0x03); //8N1        
  21.     UCON0 = (0x01<<2)|(0x01);
  22.     UFCON0 = 0;
  23.     UMCON0 = 0;
  24.     UBRDIV0 = (int)((50*1000*1000)/(BAUD_RATE*16))-1;
  25. }

  1. unsigned char uart_getc(void)
  2. {
  3.     while(!(UTRSTAT0 & 0x01))
  4.         ;
  5.     return (URXH0 & 0xff);
  6. }

  7. void uart_putc(char c)
  8. {
  9.     while (!(UTRSTAT0&0x02))
  10.         ;
  11.     UTXH0 = c;
  12.     if('\n' == c)
  13.         uart_putc('\r');
  14. }

  15. void uart_puts(char *s)
  16. {
  17.     while (*s)
  18.     {
  19.         uart_putc(*s++);
  20.     }
  21. }
  22. /*uart_printf*/
  23. void uart_printf(char *fmt, ...)
  24. {
  25.     va_list ap;
  26.     char buf[256];
  27.     va_start(ap, fmt);
  28.     vsprintf(buf, fmt, ap);
  29.     uart_puts(buf);
  30.     va_end(ap);
  31. }
2.2 vsprintf.c 从linux_0.11 copy过来,稍做修改

点击(此处)折叠或打开

  1. #include <stdarg.h>
  2. /* we use this so that we can do without the ctype library */
  3. #define is_digit(c)    ((c) >= '0' && (c) <= '9')
  4. int strlen(const char *s)
  5. {
  6.     const char *sc;
  7.     for(sc=s; *sc!='\0'; ++sc)
  8.         ;
  9.     return (sc-s);
  10. }

  11. static int skip_atoi(const char **s)
  12. {
  13.     int i=0;

  14.     while (is_digit(**s))
  15.         i = i*10 + *((*s)++) - '0';
  16.     return i;
  17. }

  18. #define ZEROPAD    1        /* pad with zero */
  19. #define SIGN    2        /* unsigned/signed long */
  20. #define PLUS    4        /* show plus */
  21. #define SPACE    8        /* space if plus */
  22. #define LEFT    16        /* left justified */
  23. #define SPECIAL    32        /* 0x */
  24. #define SMALL    64        /* use 'abcdef' instead of 'ABCDEF' */

  25. #if 0
  26. #define do_div(n,base) ({ \
  27. int __res; \
  28. __asm__("divl %4":"=a" (n),"=d" (__res):"0" (n),"1" (0),"r" (base)); \
  29. __res; })
  30. #endif

  31. #define do_div(n,base) ({ \
  32.     int __res; \
  33.     __res = ((unsigned long) n) % (unsigned) base; \
  34.     n = ((unsigned long) n) / (unsigned) base; \
  35.     __res; \
  36. })

  37. static char * number(char * str, int num, int base, int size, int precision
  38.     ,int type)
  39. {
  40.     char c,sign,tmp[36];
  41.     const char *digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  42.     int i;

  43.     if (type&SMALL) digits="0123456789abcdefghijklmnopqrstuvwxyz";
  44.     if (type&LEFT) type &= ~ZEROPAD;
  45.     if (base<|| base>36)
  46.         return 0;
  47.     c = (type & ZEROPAD) ? '0' : ' ' ;
  48.     if (type&SIGN && num<0) {
  49.         sign='-';
  50.         num = -num;
  51.     } else
  52.         sign=(type&PLUS) ? '+' : ((type&SPACE) ? ' ' : 0);
  53.     if (sign) size--;
  54.     if (type&SPECIAL) {
  55.         if (base==16) size -= 2;
  56.         else if (base==8) size--;
  57.     }
  58.     i=0;
  59.     if (num==0)
  60.         tmp[i++]='0';
  61.     else while (num!=0)
  62.         tmp[i++]=digits[do_div(num,base)];
  63.     if (i>precision) precision=i;
  64.     size -= precision;
  65.     if (!(type&(ZEROPAD+LEFT)))
  66.         while(size-->0)
  67.             *str++ = ' ';
  68.     if (sign)
  69.         *str++ = sign;
  70.     if (type&SPECIAL) {
  71.         if (base==8)
  72.             *str++ = '0';
  73.         else if (base==16) {
  74.             *str++ = '0';
  75.             *str++ = digits[33];
  76.         }
  77.     }
  78.     if (!(type&LEFT))
  79.         while(size-->0)
  80.             *str++ = c;
  81.     while(i<precision--)
  82.         *str++ = '0';
  83.     while(i-->0)
  84.         *str++ = tmp[i];
  85.     while(size-->0)
  86.         *str++ = ' ';
  87.     return str;
  88. }

  89. int vsprintf(char *buf, const char *fmt, va_list args)
  90. {
  91.     int len;
  92.     int i;
  93.     char * str;
  94.     char *s;
  95.     int *ip;

  96.     int flags;        /* flags to number() */

  97.     int field_width;    /* width of output field */
  98.     int precision;        /* min. # of digits for integers; max
  99.                  number of chars for from string */
  100.     int qualifier;        /* 'h', 'l', or 'L' for integer fields */

  101.     for (str=buf ; *fmt ; ++fmt) {
  102.         if (*fmt != '%') {
  103.             *str++ = *fmt;
  104.             continue;
  105.         }
  106.             
  107.         /* process flags */
  108.         flags = 0;
  109.         repeat:
  110.             ++fmt;        /* this also skips first '%' */
  111.             switch (*fmt) {
  112.                 case '-': flags |= LEFT; goto repeat;
  113.                 case '+': flags |= PLUS; goto repeat;
  114.                 case ' ': flags |= SPACE; goto repeat;
  115.                 case '#': flags |= SPECIAL; goto repeat;
  116.                 case '0': flags |= ZEROPAD; goto repeat;
  117.                 }
  118.         
  119.         /* get field width */
  120.         field_width = -1;
  121.         if (is_digit(*fmt))
  122.             field_width = skip_atoi(&fmt);
  123.         else if (*fmt == '*') {
  124.             /* it's the next argument */
  125.             field_width = va_arg(args, int);
  126.             if (field_width < 0) {
  127.                 field_width = -field_width;
  128.                 flags |= LEFT;
  129.             }
  130.         }

  131.         /* get the precision */
  132.         precision = -1;
  133.         if (*fmt == '.') {
  134.             ++fmt;    
  135.             if (is_digit(*fmt))
  136.                 precision = skip_atoi(&fmt);
  137.             else if (*fmt == '*') {
  138.                 /* it's the next argument */
  139.                 precision = va_arg(args, int);
  140.             }
  141.             if (precision < 0)
  142.                 precision = 0;
  143.         }

  144.         /* get the conversion qualifier */
  145.         qualifier = -1;
  146.         if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
  147.             qualifier = *fmt;
  148.             ++fmt;
  149.         }

  150.         switch (*fmt) {
  151.         case 'c':
  152.             if (!(flags & LEFT))
  153.                 while (--field_width > 0)
  154.                     *str++ = ' ';
  155.             *str++ = (unsigned char) va_arg(args, int);
  156.             while (--field_width > 0)
  157.                 *str++ = ' ';
  158.             break;

  159.         case 's':
  160.             s = va_arg(args, char *);
  161.             len = strlen(s);
  162.             if (precision < 0)
  163.                 precision = len;
  164.             else if (len > precision)
  165.                 len = precision;

  166.             if (!(flags & LEFT))
  167.                 while (len < field_width--)
  168.                     *str++ = ' ';
  169.             for (= 0; i < len; ++i)
  170.                 *str++ = *s++;
  171.             while (len < field_width--)
  172.                 *str++ = ' ';
  173.             break;

  174.         case 'o':
  175.             str = number(str, va_arg(args, unsigned long), 8,
  176.                 field_width, precision, flags);
  177.             break;

  178.         case 'p':
  179.             if (field_width == -1) {
  180.                 field_width = 8;
  181.                 flags |= ZEROPAD;
  182.             }
  183.             str = number(str,
  184.                 (unsigned long) va_arg(args, void *), 16,
  185.                 field_width, precision, flags);
  186.             break;

  187.         case 'x':
  188.             flags |= SMALL;
  189.         case 'X':
  190.             str = number(str, va_arg(args, unsigned long), 16,
  191.                 field_width, precision, flags);
  192.             break;

  193.         case 'd':
  194.         case 'i':
  195.             flags |= SIGN;
  196.         case 'u':
  197.             str = number(str, va_arg(args, unsigned long), 10,
  198.                 field_width, precision, flags);
  199.             break;

  200.         case 'n':
  201.             ip = va_arg(args, int *);
  202.             *ip = (str - buf);
  203.             break;

  204.         default:
  205.             if (*fmt != '%')
  206.                 *str++ = '%';
  207.             if (*fmt)
  208.                 *str++ = *fmt;
  209.             else
  210.                 --fmt;
  211.             break;
  212.         }
  213.     }
  214.     *str = '\0';
  215.     return str-buf;
  216. }
2.3 main.c 测试一下

点击(此处)折叠或打开

  1. #include "uart.h"

  2. void main(void)
  3. {
  4.     char c;
  5.     uart_init();        //初始化串口

  6.     while(1)
  7.     {
  8.         c = uart_getc();
  9.         uart_printf("input char=%c\n",c);
  10.         uart_printf("input char=%d\n",c);
  11.         uart_printf("input char=%x\n",c);
  12.     }
  13. }
2.4 Makefile 需要修改连接部分

点击(此处)折叠或打开

  1. u-boot: $(OBJS) $(LDSCRIPT)
  2. $(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)后面才行。

 myboot_printf.rar   (使用时,将后缀名rar改为tar.gz)
版权声明:本文为博主原创文章,转载请注明出处。 举报

相关文章推荐

自己写bootloader(3)——实现printf

void printf (const char *fmt, ...) { va_list args; uint i; char printbuffer[CFG_PBSIZE]; va_sta...

【嵌入式开发】 Bootloader 详解 ( 代码环境 | ARM 启动流程 | uboot 工作流程 | 架构设计)

作者 : 韩曙亮 <span style="color: #000

程序员升职加薪指南!还缺一个“证”!

CSDN出品,立即查看!

STM32通过USB实现Bootloader/IAP功能

原文地址:http://www.embed-net.com/thread-268-1-1.html 前沿: 最近在做STM32的USB Bootlader/IAP功能,也就是通过USB实现固件升级...

自己动手编写嵌入式Bootloader之(3)

自己动手编写嵌入式Bootloader之(3) 2011年04月03日   这一部分将对前文没有提到的几段关键代码进行简单说明,介绍一下源代码组织结构和Makefile系统,展示一下实验运行结果,并提供全部源代码下载。   1. 定时器初始化和延时程序   因为在 CS8900A的驱动...

SAMSUNG S3C2440的简易BootLoader ㈢

SAMSUNG S3C2440的简易BootLoader ㈢ 2010年06月05日   [b]SAMSUNG S3C2440的简易BootLoader ㈢[/b]   [b][/b]   [b]第三部分:源代码,运行结果   [/b]这一部分将对前文没有提到的几段关键代码进行简单说明...
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)