bootloader开发阶段总结以及可能会碰到的问题

到今天,vivi源代码基本分析完毕。对bootloader有了更深层的认识。在此期间,仔细阅读了毛德操、胡希明先生编著的《嵌入式系统--采用公开源代码和StrongARM/XScale处理器》第七章:嵌入式系统的引导和装入。看了看出版时间,才明白牛人詹荣开或许也受惠于此书。他在IBM Development上发表的那篇《嵌入式bootloader技术内幕》一文,后来在sourceforge上的开源项目jtager,在此书中有详尽的描述。(当然,他们可能是独立研究的。)两者结合起来看,对自己的帮助非常大。

 
    现在看来,bootloader主要的工作量有三个: 一是根据开发板,确定硬件初始化部分二是内存初始化,不过内存检测技术相对比较成熟了;三是 读写存储介质,包括nor/nand flash或者其他。设置内核传递参数相对前面还是比较简单的。如果完成这些基本功能,一个比较简单的实现就是blob;vivi虽然也比较小,但是还是比blob大一些,也复杂一些。有了这个基本的框架,如果公司是为了推销自己的SoC,那么会做Demo板,也就是所谓的“公版”,为之开发bootloader,并不打算支持更多的SoC,比如blob,vivi都是这样。他们的功能并不完善, 如果后来的维护者想要增强功能,一是在下载手段上下功夫,比如增加tftp下载或者usb下载,二是在支持文件系统方面做工作。另外有机构专门开发并维护bootloader,想要支持尽可能多的SoC,比如uboot, 它就可以在软件架构方面更多的考虑可扩展性,可移植性,同时增强上述手段,另外, 可以增加monitor功能,在内核尚未移植完成的阶段增加调试手段
 
    由此形成了对bootloader比较全面的认识。要想继续深入bootloader,那么有下面的工作:
 
    ·提高阅读datasheet,提取有用信息的能力。能够更快的开发出硬件初始化代码。
    ·掌握内存检测算法,能够快速编写。
    ·学习MTD技术,开发存储介质驱动程序。
    ·掌握tag内核参数传递技术。
 
    这些都是具体的细节的工作。在软件架构的学习上,我想还是应该以uboot为主,因为它的可移植性、可扩展性等,都是其他的bootloader不能相比的。要想在基本的简单的bootloader的基础上有所提高,那么就需要深入的去了解学习uboot。在后续的开发中,如果需要自己开发bootloader,那么就以vivi/blob为模型,重新编写;如果仅仅需要移植,而且该SoC并没有自己的bootloader,那么最好还是以uboot最为移植。
 
    bootloader算是比较简单,下点功夫完全掌握并非难事。在bootloader的学习过程中,把相关的基础继续加强巩固。我想,到07年末,这个任务应该可以完成。这次可是充分估计的学习内容的广度和深度了。要想学好,就要学深学透。这部分内容的开发也比较适合自己的知识背景。完成此部分后,再进入内核开发的驱动部分,从外围入手,逐步的深入的学习内核。课题也分配下来了,还需要在应用上做工作。要做的事情很多,但是不要急,慢慢来。还是那句话,这些技术都是非常成熟了,有文档和资料。只要静下心来,就一定能够掌握。所以,学习这些实用技术的同时,还不能忽略专业理论知识的学习。两者结合,才能走得更远。
网友: piaoxiang 时间:2007-07-28 08:14:44 IP地址:122.4.41.★
 
 
 
2007-07-28
    通过后面的vivi学习才发现,为什么会需要LINUX_INCLUDE_DIR这个宏来包含内核的头文件。很简单,vivi就是Linux kernel的小“儿女”,里面有些C文件的使用仍然用了“<>”包含的方式。而mizi公司没有经过仔细的验证分析,认为加上这个宏就不会出现编译问题。于是,为什么网上有的人把该宏定义为编译器的include目录,有些人把它定义为kernel的include目录,编译都没有问题,就不难理解了。如果你把该宏去掉编译,仍然没有问题(也许我测试的不到位)。但是我考虑的是,vivi是bootloader,应该具有引导不同版本内核的能力,所以还是要通过测试把该宏相关的内容去除比较合适。我在后续工作中已经去掉了该宏,暂时还没有发现编译问题。
    另外,增加的蜂鸣器关闭的汇编程序也不太合适。关于它的处理应该是由[init/main.c]------[arch/s3c2410/smdk.c] board_init()-----set_gpios()来完成的。也就是说vGPBCON的值不合适。应该修改[include/platform/smdk2410.h]默认的#define vGPBCON            0x00044555。这需要查看Datasheet,了解一下GPBCON各个位的含义,然后根据自己的开发板进行修改。其他的初始状态不合适,也要考虑修改此头文件中的初始值。
    需要注意的一个小地方是,在vivi的头文件中,如果寄存器前加字母v,表示value,即取值。如果加个o,则表示offset,即偏移值。这样读程序就很容易理解了。
    vivi也就逐步清晰起来了。
 
     

     
网友: spring11 时间:2007-08-31 23:40:06 IP地址:59.78.25.★
 
 
 
写得太好了,这是我看到的最详细的一篇!!
好想转到我的百度博客上,HOHO,不过这么好的文章还是每次都到里来吧:)

Blog作者的回复:
谢谢

 
     

     
网友: 本站网友 时间:2007-11-11 01:28:09 IP地址:210.72.218.★
 
 
 
佩服Super的学习态度和深度,也让我看到自己的很多不足,如果能和你成为同事,真是件辛事:)希望在以后的日子能和你多多交流,重要的是向你学习,我会给你发邮件的:)请多关照哦

Blog作者的回复:
^_^

 
     

     
网友: bob_zhang2004 时间:2007-11-12 23:28:48 IP地址:211.103.74.★
 
 
 
太好了, 我们也正在讨论中,正在拜读你的文章, 

也 欢迎到我们的帖子,大家一起再讨论一下:

http://www.linuxforum.net/forum/showflat.php?Cat=&Board=driver&Number=664503&page=0&view=&sb=&o=&fpart=1&vc=1  

Blog作者的回复:
共同讨论。

 
     

     
网友: bob_zhang2004 时间:2007-11-13 10:52:18 IP地址:58.211.114.★
 
 
 
>> 3、主时钟源来自外部晶振或者外部时钟。复位后,MPLL虽然默认启动,但是如果不向MPLLCON中写入value,那么外部晶振直接作为系统时钟。
>> EDUKIT-III的外部晶振有两个,一是用于系统时钟,为12MHz;一个用于RTC,为32.768KHz。
>> 以前实验没有向MPLLCON写入数值,所以系统时钟都是12MHz。

>> 从这里也可以发现一个问题,如果外部晶振开始没有焊上,那么系统是无法正常启动的。因为按照上述规则,
>> 复位后还没有写入MPLLCON,这时又没有可以使用的时钟源,所以不会启动。也就是硬件完成后,这个12MHz的晶振是一定要焊上的,
>> 才能进行后续的硬件测试工作。

您这里所说的外部时钟 , 是指什么呢? 能否举个现实中的例子。 

1》不是一般情况下, 有外部晶振就够了呢? 
2》  >> 但是如果不向MPLLCON中写入value,那么外部晶振直接作为系统时钟
我的疑问是: 那我要是往 MPLLCON写入value 呢? 那谁会作为系统时钟呢?      这个时候 12MHz还有意义吗?

Blog作者的回复:
我想,你对硬件可能不是很熟悉。
1、首先,硬件系统需要一个时钟信号。我们常用石英晶振作为这个时钟信号源。你可以看看你的板子,应该有个银白色帽子的东西,那就是晶振。再深入了解,你需要看看晶振的物理原理,了解为什么能够产生时钟信号了。
2、为了产生高频,在硬件上一般采用锁相环电路,这也是高频电路的知识。简单的说,12MHz如果作为一级时钟源,只能产生12MHz的主频,要想提到200MHz,那就需要倍频。就是相当于12×n=200.锁相环电路完成这个n的作用,这就是MPLL的作用。等到得到了200MHz的时钟源,那么现在的系统时钟就是1/(200MHz)了。
3、因为硬件设计的特点,具体电路就比较复杂了。简单说,要想使MPLL真正起作用,就需要一个触发事件,而这个事件就是要往MPLLCON中写入value,确定分频比,这样电路才能接通。(主要是硬件设计部分,电路的细节我也不是太清晰,但是这种设计在51单片机等上面是很广泛的。)也就是说,你没有理解硬件上的设计,12MHz是最初的时钟源啊,即使经过了倍频,那200MHz是二级的时钟源,这个时钟体系也是一个树状的体系结构,简称时钟树。如果把12MHz去掉,那么200MHz的源是不可能得到的。
4、刚才说的是12MHz的晶振,另外还有一个32.768KHz的晶振,他们都是晶振,只不过频率不同,用途也不同。32.768KHz用于RTC,仅仅用作这个目的。它的这部分电路和12MHz的主频电路是不同的。
5、这里的术语可能不太严谨,所以产生了问题。外部晶振对应的是频率f,f=12MHz的话,那么对应的时钟就是1/f。二者在说法上是等同的。

简单总结一下,外部晶振和外部时钟实际是一个东西,说法不太严谨就是了,都是提供时钟树的硬件组件。关于高频的时钟设计上,要用分级的观点来考虑。一级时钟源一般是物理的晶振,直接产生,二级时钟源则是通过锁相环电路转换产生。很显然,少了一级物理晶振,也就不可能产生二级高频时钟了。一般是二级设计,如果是多级,就会出现时钟同步等等比较复杂的问题了。

 
     

     
网友: bob_zhang2004 时间:2007-11-14 07:23:34 IP地址:211.103.74.★
 
 
 
非常感谢你的回答, 我对硬件懂得不多, datasheet还能看懂 , 现在就是想再深入了解一下硬件原理, 这样对kernel和driver很有好处。 

听了你的阐述, 我明白了。我最后的理解是这样的: Mpll只是一个倍频输出电路, 通过它 可以 12MHz的一级时钟输入倍频输出 ,产生二级时钟,供其他的外设来使用而已。 
而 MPLLCON 寄存器的作用仅仅是提供倍频参数, 用户必须写入(在我们的环境中是 u-boot初始化的时候,写入 0x5c040) ,这样MPLL 倍频电路才能生效, 产生 200MHz的输出。 

如果用户不写入 MPLLCON 寄存器(即使有默认值),MPLL根本就不生效, 也就没有二级时钟了, 相当于 所有的外设都得 使用 12MHz的频率了。 

所以这样看起来 , 12MHz的外部晶振必须焊接上, 按您所说 ,如果没焊上 , 板子连唯一的一级时钟都没有了, 自然无法启动了。 

++++++++++++++++++++++++++++++++++++++++++++++++

Blog作者的回复:
对,就是这个意思。

 
     

     
网友: bob_zhang2004 时间:2007-11-14 07:31:17 IP地址:211.103.74.★
 
 
 
对于 PLL VALUE SELECTION TABLE 表我还是有点疑惑:望指教:
图请看这里 http://blogimg.chinaunix.net/blog/upfile2/071112215834.jpg

1>  MDIV和 HDIV ,SDIV 默认值分别是 : 0x5c , 0x4 , 0x00 
但是为什么表里没有0x5c 呢? 倒是有0x52 , 
PDIV 和 SDIV , 也没有对应的 0x04 和 0x0 啊? 


Blog作者的回复:
看看公式:Mpll(Fclk)=(m×Fin)/(p×(2^s))【m=MDIV+8, p=PDIV+2,s=SDIV】
这里面有两个需要注意。一个是Fin,就是说这是一级时钟源的频率,F代表Frequency,in代表input。Mpll实际上是Main锁相环电路的本地输出频率,实际上就是系统的Fclk。现在已知Fin为12MHz,要想获得Mpll,取决于三个参数。但是这三个参数可以是任意的,并没有死规定,也就是我前面说的,这是一个多解方程式。
手册上也说过,表中的数据是可靠的,应用没有问题。如果我想要得到200MHz,但是表中并没有这个输出频率,而官方提供的vivi中使用了这个200MHz,说明这个数据也是可靠的。所以在s3c2410中就普遍的使用可以生成200MHz的这三个参数了。可以说,这三个参数是源于vivi的。之所以选择200MHz,也是为了精确定时。比如sdram的刷新频率的选择,等等。
总之,datasheet给定了公式和table。table只是官方经过测试比较稳定的一些参数组合,并非全部。还可以有任意多的组合方式,但是呢,官方不保证你自己选择的参数在硬件上稳定可靠。而vivi也是官方的,它提供了datasheet上没有的200MHz输出的一组参数,所以在200MHz这个时钟频率上就普遍的采用了0x5c 0x4 0x00。因为选择200MHz在很多与时间相关的设置上的方便性,就使得200MHz成为2410上最为普遍的选择了。

 
     

     
网友: bob_zhang2004 时间:2007-11-14 10:29:22 IP地址:58.211.114.★
 
 
 
明白了, 原来是没有写出来啊, 怪不得。 

这回明白了 Fin 是什么意思, 之前只是知道肯定是 12MHz , 但就是不知道什么意思, 呵呵。 

多谢了。 
 
     

     
网友: 时间:2007-11-22 13:07:37 IP地址:202.199.138.★
 
 
 
科研的精神和乐于助人的精神都值得学习,非常感谢!
 
     

     
网友: scanmiss 时间:2007-11-22 16:35:17 IP地址:218.5.3.★
 
 
 
hi, 这两个礼拜几乎每天都来,有关vivi的理解得真的不错,我现在也在写一个s3c2410的bootloader, 但是出现问题了,我用的是nor flash, sdram 64M,地址为0x30000000, 从0x30000000-0x3020000用做显示缓冲及其他功能, kernel (2.6.22)放在0x3020000+0x8000的地方, kernel参数放在0x3020000+0x100的地方,跳转到0x3020000+0x8000后就一点消息都没有,不知道是怎么回事?窜口连一点信息都不给,(提示信息到跳转到内核之前,之后的就没有了),是不是内核只能放在0x30000000,或者在什么地方有设这个值的?

Blog作者的回复:
内核默认是解压到mem_base+0x8000处。而这个mem_base没有通过bootloader的参数导入(参数只会导入mem的大小,默认情况下,mem_base是固定的)。所以,如果一定要在0x30200000,就需要修改内核的代码了。

 
     

     
网友: scanmiss 时间:2007-11-22 17:46:35 IP地址:218.5.3.★
 
 
 
谢谢你的回复,
刚才我把kernel放在0x3000000的地方,但窜口也还是一点信息都没有,
我用make zImage做的内核zImage下载到nor flash, 在启动内核之前,我把mem_base+0x8000(0x30000000+0x8000)的数据打印出来如下:
e1a00000                e1a00000                e1a00000                e1a00000
e1a00000                e1a00000                e1a00000                e1a00000
ea000002                016f2818                00000000                0016b184
e1a07001                e1a08002                e10f2000                e3120003
1a000001                e3a00017                ef123456                e10f2000
e38220c0                e121f002                00000000                00000000
e28f00d0
和zImage的内容相同,窜口我用的参数传入(这用的是tag 的方式"console=ttySAC0,115200n8", 用param_struct时用的是" "noinitrd  console=ttySAC0"") 两者都不行,我用的是ADS 1.2 开发的,由于对汇编不熟,基本上是用vivi的汇编代码.
启动的代码如下:____________________________________________________
int boot_kernel(ulong from, size_t size, int media_type)
{
        int ret;
        int i;
        ulong boot_mem_base;    /* base address of bootable memory */
        ulong to;
        ulong mach_type;
        
        void (*call_linux)(int zero, int arch, unsigned long params_addr) = 
          (void (*)(int, int, unsigned long))(LINUX_KERNEL_BASE + LINUX_KERNEL_OFFSET);

        boot_mem_base = LINUX_KERNEL_BASE;

    /* copy kerne image */
        to = boot_mem_base + LINUX_KERNEL_OFFSET;

        DBGMSG(DEBUG, ("Copy linux kernel from 0x%08lx to 0x%08lx, size = 0x%08lx ... ",
                from, to, size));

        ret = copy_kernel_img(to, (char *)from, size, media_type);

        if (ret) 
        {
                DBGMSG(DEBUG, ("failed/n"));
                return -1;
        } 
    else 
        {
                DBGMSG(DEBUG, ("done/n"));
        }

        if (*(ulong *)(to + 9*4) != LINUX_ZIMAGE_MAGIC) 
        {
                DBGMSG(DEBUG, ("Warning: this binary is not compressed linux kernel image/n"));
                DBGMSG(DEBUG, ("zImage magic = 0x%08lx/n", *(ulong *)(to + 9*4)));
        } 
        else 
        {
                DBGMSG(DEBUG, ("zImage magic = 0x%08lx/n", *(ulong *)(to + 9*4)));
        }

         /* Setup linux parameters and linux command line */
        setup_linux_param(boot_mem_base + LINUX_PARAM_OFFSET);

        /* Get machine type, see arch/arm/tools/mach-types */
        mach_type = MACH_TYPE;

        DBGMSG(DEBUG, ("MACH_TYPE = %d/n", mach_type));

        /* Go Go Go */
        DBGMSG(DEBUG, ("NOW, Booting Linux....../n"));
        clean_before_call_linux();
        
        DBGMSG(DEBUG, ("Maybe we can check some date!addr:0x%08lx /n", to));
        
        for(i = 0; i < 100; )
        {
            DBGMSG(DEBUG, ("%08lx        ", *(ulong *)(to + i)));
            i = i + 4;    
            if(i%16 == 0)
            {
                 DBGMSG(DEBUG, ("/n"));
            }
        }
        
        call_linux(0, mach_type, (unsigned long)(boot_mem_base + LINUX_PARAM_OFFSET));        

        DBGMSG(DEBUG, ("If here, error!/n"));
        
        return 0;   
}
______________________________________________________

Blog作者的回复:
命令行传递参数加上mem=64M。我在使用uboot的时候发现,如果不加入mem,则2.6.22的内核引导后,串口没有任何输出。

 
     

     
网友: scanmiss 时间:2007-11-22 18:03:12 IP地址:218.5.3.★
 
 
 
晕倒,我的机器上有4个窜口,我用的窜口是"console=ttySAC1,115200n8"
刚才才恍然大悟,我没有用mem=64M

Blog作者的回复:
只用115200就可以了。默认就是8n1的模式。

 
     

     
网友: scanmiss 时间:2007-11-22 18:52:35 IP地址:218.5.3.★
 
 
 
我把地址改成0x30200000后,果然内核就起不来了,
但是程序是跳转到0x30200000执行啊,机器码一个一个读进来执行,放在什么地方没什么关系吧?还是内核找不到参数表,所以就起不来了?

Blog作者的回复:
看看vivi开发笔记17,再读读lufuchong的bootm解析。
zImage bin文件分为三个部分,实现自解压。搬移地址是非常重要的,不能发生冲突。
这个地方与内核是相关的,并不是boot loader单方面的事情。

 
     

     
网友: tianhao_1983 时间:2007-12-18 11:19:17 IP地址:221.11.46.★
 
 
 
这里交流的好热闹呀,看到这么多的人有如此互相学习互相帮助的积极性,真是高兴,希望向calmarrow请教学习!!
 
     

     
网友: 不死书生 时间:2008-01-01 21:17:19 IP地址:60.191.189.★
 
 
 
中国人如果多一点像你这样的人,那是中国的幸事,少一点浮华,多一点实在,中国的未来就要靠你们这样的人来支撑着。

Blog作者的回复:
过誉了,只是安心做自己的事情

 
     

     
网友: 低调 时间:2008-04-19 17:16:09 IP地址:60.22.211.★
 
 
 
哥们,问一下。vivi的makefile中的

init/ version.o: init/ version.c include/compile.h
    $(CC) $(CFLAGS) -DUTS_MACHINE='"$(ARCH)"' -c -o init/ version.o init/ version.c

其中的 -DUTS_MACHINE  是什么意思啊?   是给$(CC) 的参数吗?   

是arm体系的意识吧?
可是$(CC) 已经定义成arm-linux-gcc了  还要给它传递体系吗?   
为什么编译hello.c等简单的程序时,不用这个-DUTS_MACHINE  呢?
多谢!

Blog作者的回复:
man gcc ==> -D name=define

 
     

     
网友: 低调 时间:2008-04-20 11:19:33 IP地址:60.22.214.★
 
 
 

ifdef CONFIGURATION
..$(CONFIGURATION):
    @echo
    @echo "You have a bad or nonexistent" .$(CONFIGURATION) ": running 'make" $(CONFIGURATION)"'"
    @echo
    $(MAKE) $(CONFIGURATION)
    @echo
    @echo "Successful. Try re-making (ignore the error that follows)"
    @echo
    exit 1

dummy:

else

dummy:

endif

这是vivi的makefile中的代码
请问..$(CONFIGURATION)中的那个".."是什么意思啊?谢谢

Blog作者的回复:
可以把该定义规则删除,没有用处

 
     

     
网友: 本站网友 时间:2008-04-22 16:14:55 IP地址:218.104.217.★
 
 
 
vivi 请教您一个关于重定位的问题,
例如现在我有三个数据段运行顺序为
.data
.bss
.text
 
其中.text为重定位段,被定位到.data后面。
实际的内存存放位置为
.data
.text
.bss
 
我们在执行链接脚本计算.bss段起始地址大小时需要知道它前面一段的大小就是.text段的大小,但这个时候我们还不能使用SIZEOF(.text)来计算。链接的时候就会报错,请问您有没有什么好办法解决这个问题。就是在执行脚本语言的时刻可不可以在没有定义.text段时就在前面引用它, 谢谢了 。
 
 
     

     
网友: 本站网友 时间:2008-04-22 16:19:08 IP地址:218.104.217.★
 
 
 
CalmArrow其实我问的问题主要就是LD在执行脚本语言时只进行一次链接可不可以先计算出每个数据段的大小,然后在根据这些大小以及我们配置的运行与加载顺序生成一个二进制文件??? 谢谢了 呵呵 

Blog作者的回复:
我认为这个问题的解决方案是按照内存的顺序编写好链接规则,这样可以通过定义的段的起始地址和终止地址得到段的位置和大小,然后增加一个搬移代码,完成搬移就可以了吧。
AT91RM9200提供的boot就是这种思路。
读一下http://blog.chinaunix.net/u/21948/showart_481779.html,会有帮助。
希望能够解决你的问题。

 
     

     
网友: 低调 时间:2008-04-25 23:38:13 IP地址:60.22.202.★
 
 
 
首先,感谢CalmArrow前面两个问题的回复。
这两天被vivi的分区弄得晕头转向,在网上找了些文章还是有点晕。
能帮我们讲讲vivi分区,part show看到的分区,bon分区,mtd分区到底都是 干什么的吗?为什么 还要通过bon命令重新设置分区呢?  不能 在vivi源代码中改写吗?   多谢了:)

Blog作者的回复:
采用bon分区主要是为了把分区表信息传递给内核,这样内核就不需要再次配置分区表。通信是双方的,所以内核必须有对bon分区的支持,具体的传递方式则是约定为最后一个分区的最后16KB区域作为共享区域来实现的。具体比较复杂,自己读下源代码吧。

 
     

     
网友: 低调 时间:2008-04-26 11:34:36 IP地址:60.23.123.★
 
 
 
请问斑竹:
vivi的bon分区是干什么的?
为什么我无论怎么使用bon 命令“胡乱”分区,内核也能照样运行,而且yaffs文件系统也能照样运行呢?
多谢!

Blog作者的回复:
你的内核应该采用了MTD分区,而不是bon分区。

 
     

     
网友: 低调 时间:2008-05-03 09:56:39 IP地址:60.22.213.★
 
 
 
感谢!
 
     

     
网友: 低调 时间:2008-05-03 13:49:40 IP地址:60.22.213.★
 
 
 
vivi都向内核传递了什么?
我先把我理解的都列出来,缺的和错的,请 CalmArrow和诸位兄弟帮补充一下,谢谢。
1,传递了param_struct。
    (1)page_size。为什么要传递这个呢?是因为vivi中设置的那个页表映射吗?这个页表映射kernel也要使用吗?kernel中不也会重新设置页表吗?
    (2)nr_pages。  
     (3)commandline 。内核启动的时候,使用哪个串口打印信息是由commandline中的“console=?”决定的吗?
2,传递了machine type通过设置r1.
3,设置了r1=0.为什么呀?
4,为什么没有传递media_type?内核怎么知道文件系统是在nand中还是在其他地方?
5,内核和vivi都有哪些约定?
    (1)内核和vivi的MTD分区要一致。
    (2)zImage一定要放在mem_base+0x8000处吗?
    (3)param_struct也要放在那个固定位置吗?

哈哈,我扔一块砖头  ,等着CalmArrow和诸位兄弟的玉哦:)

  
   
 
     

     
网友: joshuazzh 时间:2008-06-27 10:18:01 IP地址:222.35.60.★
 
 
 
看到您的博客如此有条理、思路清晰,自己真觉得自惭形秽!
您给我做了好榜样
见贤思齐,见不贤而内自醒!
谢谢你
我研究生入学马上一年了,这学期开始刚接触linux,到现在做过的工作有在恒颐H2410F的开发板上移植vivi、移植2.6.14.1内核、制作cramfs和yaffs文件系统、编写简单的脚本文件、在板子上进行串口网口socket编程,实现UATR1接收到的数据通过网口发送至internet远端主机等一些工作
做完之后没有好好整理思路笔记,现在自己都有很多记不清了
我是伴随您的博客一起学习linux的,
从入门到现在经常光顾您的博客,
第一次给您留言,
以后还有很多问题向您请教!
 
     

     
网友: 本站网友 时间:2008-08-06 16:54:59 IP地址:218.104.217.★
 
 
 
CalmArrow您好
请教您个问题,我们的开发环境原来GCC的版本用的是3.4.4现在换成用2.95.2在编译同一个工程的时候他在链接的时候报错:
错误消息如下:E:/host/acoreos2x/arch/x86/bin/dcore-ld: final link failed: Bad value
make: *** [E/target/workspace/os/i386_le_soft_debug/make/os.elf] Error 1
make: Target `all' not remade because of errors.

请问是不是2.9与3.4所执行的ld脚本有区别?谢谢
 
     

     
网友: clf1985 时间:2008-08-15 12:54:19 IP地址:58.39.1.★
 
 
 
从今天开始,学习你的贴子。写的很好,思路很清晰。
 
     

     
网友: NEWCOMER 时间:2008-08-22 13:47:54 IP地址:219.128.48.★
 
 
 
BON分区是老式的,基本没用;MTD分区是存放系统文件的。
现在分区的时候采用bon, 安装系统时实际是yaffs, bon算是辅助性的。你可以看vivi源代码。vivi.tgz
以上也是网上找来的.但是加进去你的文章可以解释BON 和MTD的问题
 
     

     
网友: agela 时间:2008-09-28 14:10:52 IP地址:123.127.134.★
 
 
 
你的timer那块怎么没什么说明啊,能说说timer吗?
 
     

     
网友: 本站网友 时间:2009-03-24 00:29:12 IP地址:202.122.32.★
 
 
 
步骤一:下载VIVI源码

步骤二: 修改Makefile 里面的3个编译量

编译成功生成vivi

步骤三:sjf2410下载 vivi  

显示结果:

@000000E8
OK  
00000054
00ABEA00
FAIL

经过多天的追踪,发现是VIVI的

copy_myself 程序 复制 128K到 sdram 的0x33f00000 地址之后 跳转到

ok_nand_read程序下 进行4K的二进制代码比较,

比较 中 由于 sdram 与 sram 里面的不一样 跳入 notmatch程序 

得到的问题:

1,是sdram的问题,还是sjf2410写bin文件写的就是错的?

2,如果sjf2410写没有错误,那么可能就是nand_read.c文件里面的nandflash读程序有问题?

3,如果sjf2410写没错,nand_read.c里面的nand_read_ll()也没问题

那我的问题在那里呢?

郁闷呀!!!!!!!!!!!!!

希望得到高手指点
 
     

     
网友: liuyan546 时间:2009-05-14 18:35:33 IP地址:221.0.91.★
 
 
 
看了你学习vivi的这第一章我就有种仰视的感觉,也感受到了作为一个技术员的差距,向你学习,首先是做人做事的态度。谢谢,让我知道了自己的缺陷和目标。。希望在有生之年能让自己有资格拜见一下前辈
 
     

     
网友: 本站网友 时间:2009-08-13 11:20:39 IP地址:219.133.141.★
 
 
 
X
 
     

     
网友: 本站网友 时间:2009-08-13 11:21:47 IP地址:219.133.141.★
 
 
 
你好!关于VA-->MVA的问题我还是不明白,总觉得利用PID生成MVA的方法没什么太大的实际意义。就算在小于32M是成立的,但大于32M呢,也会出现重叠VA的现象啊!搞不懂,请赐教!
 
     

     
网友: 本站网友 时间:2009-10-14 00:26:20 IP地址:121.249.204.★
 
 
 
关于GPIO试验的确是非常简单,但也有要注意的问题,比如:启动代码后缀的s要大写,即init.S,如果是小写会提示找不到_start入口。另外,从这个简单的例子也可以看出编译语言的高效性,实现相同功能的代码,执行的效率简直是天壤之别。
 
     

     
网友: qiudeyezi 时间:2009-10-20 15:33:43 IP地址:58.248.224.★
 
 
 
你好!我最近读了您的文章,我尝试将viv移植到s3c2440的开发板上,编译成功后,串口只打印了一句"Starting application at 0x30000000...“这句话就完全没反应了,我从网上另外找了一个2440的vivi源码编译过后却可以看到启动信息,我发现这两个源码的vivi.lds是不相同的,是否是这个原因?请指教,感谢!
 
     

     
网友: feitian0896 时间:2010-04-08 16:14:39 IP地址:61.191.26.★
 
 
 
仔细看了你的文章。很不错。有个疑问,不知道是笔误还是其他。你有这么一段话。
##虽然bl 30000040 是30000040,但是要注意,此处指令为bl,所以只能相对寻址,而不能够绝对寻址,也就是说,它只能跳转到距离0x30000000为0x40的位置,这点查看bl的汇编指令说明就比较清晰了。##

最后一句话,这个应该是跳转到距离0x00000000为0x40的位置。因为相对寻址是相对于pc的。此时pc应为0x00000000.
memsetup是个绝对地址。bl会把这个地址左移2位当成偏移量来加上pc的。

你可能感兴趣的:(vivi源代码学习)