Chinaunix首页 | 论坛 | 博客
  • 博客访问: 444028
  • 博文数量: 72
  • 博客积分: 3186
  • 博客等级: 中校
  • 技术积分: 1039
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-07 16:53
文章分类

全部博文(72)

文章存档

2012年(1)

2011年(5)

2010年(10)

2009年(56)

我的朋友

分类: 嵌入式

2009-09-24 15:41:09

vivi进入main后第一件事情就是打印信息,这个步骤是通过串口向终端打印的,用的UART0.
main.c 中打印用了下面这两句:

        /*
         * Step 1:
         */

        putstr("\r\n");
        putstr(vivi_banner);


那么,这里putstr是如何实现的呢?
分析过前面的 head.S 之后,这里肯定也能猜到个大概:使用UART0,将要打印的字符一一写入它的发送寄存器即可。
当然,道理分析起来是非常简单的,但简单并不代表容易。特别地,我们还要熟悉以及学习别人代码中的风格,比如多层嵌套的宏定义,子函数分类放置不同的文件、目录里,逐层分解一个问题的思想。

putstr的声明在 include/vivi_string.h 中,定义在 lib/string.c 中,其函数定义如下:

/*
 * Simple print string
 */


void putnstr(const char *str, size_t n)
{
    if (str == NULL)
        return;

    while (n && *str != '\0') {
        putc(*str);
        str++;
        n--;
    }
}

void putstr(const char *str)
{
    putnstr(str, strlen(str));
}


可见,过程是 putstr -> putnstr -> putc 这样一级一级调用的。
putc在 include/serial.h 中声明。在 drivers/serial/serial_core.c 中定义如下:

void putc(char c)
{
    PROC_SERIAL_PUTC(c);
}



可以猜到 PROC_SERIAL_PUTC(c) 肯定是一个宏。它在 include/processor.h 中是这样定义的:

#define PROC_SERIAL_PUTC(c)    \
        ({ while (!SERIAL_WRITE_READY()); \
         SERIAL_WRITE_CHAR(c); })



其中的SERIAL_WRITE_READY  SERIAL_WRITE_CHAR 都宏定义在 include/proc/proc_s3c2410.h 中。

#define SERIAL_CHAR_READY() (UTRSTAT0 & UTRSTAT_RX_READY)
#define SERIAL_READ_CHAR() URXH0
#define SERIAL_READ_STATUS() (UERSTAT0 & UART_ERR_MASK)

#define SERIAL_WRITE_STATUS()    (UTRSTAT0)
#define SERIAL_WRITE_READY()    ((UTRSTAT0) & UTRSTAT_TX_EMPTY)
#define SERIAL_WRITE_CHAR(c)    ((UTXH0) = (c))


SERIAL_WRITE_READY 即在检查 UTRSTAT0[2]。若为1,则表示发送端为空,可以发送了,
#define UTRSTAT_TX_EMPTY    (1 << 2)
SERIAL_WRITE_CHAR(c) 即(UTXH0) = (c)发送字符。


一层一层剥离之后,我们可以返回去再看看,就明了多了。
putc 即 发送单个字符
putnstr(const char *str, size_t n) 发送字符串直到到达指定数目或遇到字符串结尾符'\0'(字符串也是分割成一个个的字符来分别putc发送的)。
putstr(const char *str) 发送字符串。这里调用了一个函数strlen。


在vivi中这个strlen函数,这个函数是使用函数库里的函数。因为在编译的时候我们有使用 -Bstatic 来静态编译。


也可以另外写一个简单的(完全没这个必要),不考虑一些算法和时间消耗,strlen函数如下:

size_t
strlen(const char *str)
{
        const char *char_ptr;

        for (char_ptr = str; char_ptr != NULL; ++char_ptr)
                if (*char_ptr == '\0')
                        return char_ptr - str;

}



最后,进入main.c中的第一个任务“打印信息”终于在我的终端出来了。这里由于我是逐个功能的添加,所以main.c里很简单,只有打印:

#include "vivi_string.h"
extern char *vivi_banner; // 在version.c中可以修改自己的启动信息。

int
main(int argc, char **argv)
{
        int ret;
        /*
         * Step 1:
         */

        putstr("\r\n");
        putstr(vivi_banner);
        for (;;);
        return 0;
}



贴下打印信息:

@000000D4
MTST-OK
OK
NAND-OK
STKP
33DEFFFC
33F0011C


// 下面是main.c里打印出来的。
ToT Bootloder DIY from VIVI.
                              --------changyongid
                              ---------- changyongid@163.com


阅读(2280) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~