u-boot移植随笔(16):u-boot技巧二则

linux内核中版本信息字符串为一宏定义,如下:

1
2
3
4
5
#define version(a) Version_ ## a
#define version_string(a) version(a)

extern int version_string(LINUX_VERSION_CODE);
int version_string(LINUX_VERSION_CODE);

在u-boot中,同样有相似的宏定义:

1
2
#define XMK_STR(x)        #x
#define MK_STR(x) XMK_STR(x)

它是这样使用的(例子还有很多):

1
"baudrate="        MK_STR(CONFIG_BAUDRATE) "\0"

作一测试,语句和运行结果如下:

1
2
3
4
printf("XMK_STR(x):%s \nMK_STR(x): %s\n", XMK_STR(CONFIG_BAUDRATE), MK_STR(CONFIG_BAUDRATE));

XMK_STR(x):CONFIG_BAUDRATE
MK_STR(x): 115200

一开始我不明白为何要定义两个宏(XMK_STR和MK_STR),经过测试才知道原因。因为在实际使用过程中,宏括号里的也是宏定义,如果单单使用XMK_STR,即C语言中的“#”,则会原封不动地输出“#”后的内容(亦即宏括号里的内容),如果这个“参数”也是宏的话,输出的当然是这个宏的名称了,正如上面所示那样。所以为了输出宏的真正内容使用,需要再加上一个宏,不过此刻的内容是一个字符串。

在u-boot中使用nand write.yaffs2命令将根文件系统映像写入nand flash中,会有如下提示:

1
Writing at 0x3680000 --55% is complete

变化的是其中的地址(偏移量)和进度(百分之几)。像这个其实不难实现。在实际代码中是这样的:

1
printf("rWriting at 0x%llx --%d%% is complete",offset,100-(left_to_write/(*length/100)));

关键的便是其中的“r”,ASCII码为0x0d,这个字符我们很常见,在区别和处理Windows和Linux的回车换行时经常遇到。它就是“回车”,回到一行的行首。而C语言的printf函数常用的“n”则是换行,ASCII码为0x0a。这里不能使用“n”,否则会影响显示效果。
上面的语句每执行一次,那一行字符串都重新回到这一行的行首。这样看上去只有地址和进度来变化,其实整个字符串都已经重新打印一遍了,只不过我们没这个感觉而已。 大家可以测试一下下面的语句:

1
2
3
4
5
6
        for (i = 0; i < 100; i++)
        {
                printf("\r%d%% is complete.", i);
                sleep(100);
        }
        printf("\n");

大家可以测试一下“\r”和“\n”这些组合的效果。 木草山人 即日