u-boot-1.3.4 移植到S3C2440 (带有某些解析)

发布时间:2024-07-26  

一.预备知识:

1.       首先,U-Boot1.3.4还没有支持s3c2440,移植仍是用2410的文件稍作修改而成的。

2.       2440和2410的区别:

2440和2410的区别主要是2440的主频更高,增加了摄像头接口和AC‘97音频接口;寄存器方面,除了新增模块的寄存器外,移植所要注意的是NAND FlASH控制器的寄存器有较大的变化、芯片的时钟频率控制寄存器(芯片PLL的寄存器)有一定的变化。其他寄存器基本是兼容的。

3.  你开发板的boot方式是什么,开发板上电以后是怎么执行的。

一般来说三星的开发板有三种启动方式:nand、nor、ram。

具体用那一种方式来启动决定于CPU的0M[0:1]这两个引脚,具体请参考S3C2440的datasheet

 

nand:对于2440来说,CPU是不给nand-flash分配地址空间的,nand-flash只相当于CPU的一个外设,S3C2440做了一个从nand-flash启动的机制。开发板一上电,CPU就自动复制

      nand-flash里面的前4K-Bytes内容到S3C2440内部集成的SDRAM,然后把4K内容所在         的RAM映射到S3C2440的0地址,从0地址开始执行。这4K的内容主要负责下面这些工         作:初始化中断矢量、设定CPU的工作模式为SVC32模式、屏蔽看门狗、屏蔽中断、            初始化时钟、把整个u-boot重定向到外部SDRAM、跳到主要的C函数入口。

nor:  早期的时候利用nor-flash启动的方式比较多,就是把u-boot烧写到nor-flash里面,       直接把nor-flash映射到S3C2440的0地址,上电从0地址开始执行。

ram:  直接把u-boot放到外部SDRAM上跑,这一般debug时候用到。

4.  u-boot程序的入口地址问题

要理解程序的入口地址,自然想到的是连接文件,首先看看开发板相对于某个开发板的连接文件"/board/你的开发板/u-boot.lds",看一个2410的例子:

ENTRY(_start)

SECTIONS

{

       . = 0x00000000;

 

       . = ALIGN(4);

       .text      :

       {

         cpu/arm920t/start.o (.text)

         *(.text)

       }

 

       . = ALIGN(4);

       .rodata : { *(.rodata) }

 

       . = ALIGN(4);

       .data : { *(.data) }

 

       . = ALIGN(4);

       .got : { *(.got) }

 

       __u_boot_cmd_start = .;

       .u_boot_cmd : { *(.u_boot_cmd) }

       __u_boot_cmd_end = .;

 

       . = ALIGN(4);

       __bss_start = .;

       .bss : { *(.bss) }

       _end = .;

}

(1) 从ENTRY(_start)可以看出u-boot的入口函数是_start,这个没错

(2) 从. = 0x00000000也许可以看出_start的地址是0x00000000,事实并不是这样的,这里的0x00000000没效,在连接的时候最终会被TETX_BASE所代替的,具体请参考u-boot根目录下的config.mk.

(3) 网上很多说法是 _start=TEXT_BASE,我想这种说法也是正确的,但没有说具体原因。

本人的理解是这样的,TEXT_BASE表示text段的起始地址,而从

.text      :

{

  cpu/arm920t/start.o (.text)

  *(.text)

}

看,放在text段的第一个文件就是start.c编译后的内容,而start.c中的第一个函数就是

_start,所以 _start应该是放在text段的起始位置,因此说_start=TEXT_BASE也不为过。

5.  一直不明白的U-BOOT是怎样从4Ksteppingstone跳到RAM中执行的,现在终于明白了。关键在于:

              ldr   pc, _start_armboot

_start_armboot:    .word start_armboot

这两条语句,ldr       pc, _start_armboot指令把_start_armboot这个标签的地方存放的内容(也即是start_armboot)移到PC寄存器里面,start_armboot是一个函数地址,在编译的时候给分配了一个绝对地址,所以上面语句实际上是完成了一个绝对地址的跳转。而我一直不明白的为什么在start.S里面有很多BL,B跳转语句都没有跳出4Ksteppingstone,原因是他们都是相对于PC的便宜的跳转,而不是绝对地址的跳转。还有要补充一下LDR,MOV,LDR伪指令的区别。

LDR      R0,0x12345678   //把地址0x12345678存放的内容放到R0里面

MOV    R0,#x                   //把立即数x放到R0里面,x必须是一个8 bits的数移到偶数次得到的数。

LDR      R0,=0x12345678        //把立即数0x12345678放到R0里面

6.  在移植u-boot-1.3.3以上版本的时候要注意:

    在u-boot1.3.3及以上版本Makefile有一定的变化,使得对于24x0处理器从nand启动的遇到问题。也就是网上有人说的:无法运行过lowlevel_init。其实这个问题是由于编译器将我们自己添加的用于nandboot的子函数nand_read_ll放到了4K之后造成的(到这不理解的话,请仔细看看24x0处理器nandboot原理)。我是在运行失败后,利用mini2440的4个LED调试发现u-boot根本没有完成自我拷贝,然后看了uboot根目录下的System.map文件就可知道原因。

解决办法其实很简单:
将__LIBS := $(subst $(obj),,$(LIBS)) $(subst $(obj),,$(LIBBOARD))
改为__LIBS := $(subst $(obj),,$(LIBBOARD)) $(subst $(obj),,$(LIBS))

7.   然后说一下跳转指令。ARM有两种跳转方式。

(1)mov pc <跳转地址〉

 这种向程序计数器PC直接写跳转地址,能在4GB连续空间内任意跳转。

(2)通过B BL BLX BX可以完成在当前指令向前或者向后32MB的地址空间的跳转(为什么是32MB呢?寄存器是32位的,此时的值是24位有符号数,所以32MB)。

B是最简单的跳转指令。要注意的是,跳转指令的实际值不是绝对地址,而是相对地址——是相对当前PC值的一个偏移量,它的值由汇编器计算得出。

BL非常常用。它在跳转之前会在寄存器LR(R14)中保存PC的当前内容。BL的经典用法如下:

       bl NEXT  ; 跳转到NEXT

       ……

    NEXT

       ……

       mov pc, lr   ; 从子程序返回。

二.开始上机移植:(红色字体为添加的内容,蓝色字体为修改的内容,下同)

给自己的开发板取名为qljt2440。

1.       随便找个目录解压u-boot,

$tar –xjvf u-boot-1.3.4.tar.gz2

2.       进入u-boot目录修改Makefile (你要编译u-boot那当然少不了配置啦)

$cd u-boot-1.3.4

[uboot@localhost u-boot-1.3.4]$ vim Makefile  修改内容如下:

__LIBS := $(subst $(obj),,$(LIBS)) $(subst $(obj),,$(LIBBOARD))
改为

__LIBS := $(subst $(obj),,$(LIBBOARD)) $(subst $(obj),,$(LIBS))

 

sbc2410x_config: unconfig @$(MKCONFIG) $(@:_config=) arm arm920t sbc2410x NULL s3c24x0

qljt2440_config : unconfig @$(MKCONFIG) $(@:_config=) arm arm920t qljt2440 qljt s3c24x0

/*

各项的意思如下:

       qljt2440_config : 这个名字是将来你配置板子时候用到的名字,参见make qljt2440_config命令。

arm: CPU的架构(ARCH)

arm920t: CPU的类型(CPU),其对应于cpu/arm920t子目录。

qljt2440: 开发板的型号(BOARD),对应于board/qljt/qljt2440目录。

qljt: 开发者/或经销商(vender)。 s3c24x0: 片上系统(SOC)。

*/

4. 在/board子目录中建立自己的开发板qljt2440目录

由于我在上一步板子的开发者/或经销商(vender)中填了 qljt ,所以开发板qljt2440目录一定要建在/board子目录中的qljt目录下,否则编译会出错。

[uboot@localhost u-boot-1.3.4]$ cd board

[uboot@localhost board]$ mkdir qljt qljt/qljt2440

[uboot@localhost board]$ cp -arf sbc2410x/* qljt/qljt2440/

[uboot@localhost board]$ cd qljt/qljt2440/

[uboot@localhost qljt2440]$ mv sbc2410x.c qljt2440.c

[uboot@localhost qljt2440]$ ls 可以看到下面这些文件:

       config.mk  flash.c  lowlevel_init.s   Makefile   qljt2440.c  u-boot.lds

[uboot@localhost qljt2440]$ vim Makefile

       COBJS := qljt2440.o flash.o

5. 在 include/configs/ 中建立开发板所需要的配置头文件

[uboot@localhost qljt2440]$ cd http://www.cnblogs.com/..

[uboot@localhost u-boot-1.3.4]$ cp include/configs/sbc2410x.h include/configs/qljt2440.h

6. 测试交叉编译能否成功

(1)配置

       [uboot@localhost u-boot-1.3.4]$ make qljt2440_config

       Configure for qljt2440 board…

(2)测试编译

       [uboot@localhost u-boot-1.3.4]$ make

详细信息如下:

编译信息最后两行:

       arm-linux-objcopy --gap-fill=0xff -O srec u-boot u-boot.srec

arm-linux-objcopy --gap-fill=0xff -O binary u-boot u-boot.bin

到此交叉编译成功。

三.开始针对自己的开发板移植

1.  修改/cpu/arm920t/start.S

1.1 修改寄存器地址定义

#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)  
/* turn off the watchdog */
#if defined(CONFIG_S3C2400)
# define pWTCON        0x15300000
# define INTMSK        0x14400008    /* Interupt-Controller base addresses */
# define CLKDIVN    0x14800014    /* clock divisor register */
#else

# define pWTCON        0x53000000     /*该地址用来屏蔽看门狗*/
# define INTMSK        0x4A000008    /* Interupt-Controller base addresses 该地址用来屏蔽中断*/
# define INTSUBMSK    0x4A00001C  /*该地址用来屏蔽子中断*/
# define CLKDIVN    0x4C000014    /* clock divisor register 该地址用来决定FCLK、HCLK、PCLK的比例*/

#define CLK_CTL_BASE        0x4c000000  /* qljt 从S3C2440A.pdf中可以看出该寄存器是存放Mpll和Upll的P254 */
#if defined(CONFIG_S3C2440)      

#define MDIV_405       0x7f << 12   /* qljt  参见P255表,同时要知道本开发板的Fin是12MHz,需要的Fclk(也就

是Mpll)是405MHz*/
#define PSDIV_405       0x21       /* qljt 同上,同时设定PDIV和SDIV的值,PDIV和SDIV参见S3C2440A.pdf*/
#endif
#endif

1.2  修改中断禁止部分
  # if defined(CONFIG_S3C2410)
    ldr    r1, =0x7ff   //根据2410芯片手册,INTSUBMSK有11位可用,
                       //vivi也是0x7ff,不知为什么U-Boot一直没改过来。但是由于芯片复位默认

//所有的终端都是被屏蔽的,所以这个不影响工作
    ldr    r0, =INTSUBMSK
    str    r1, [r0]
# endif
# if  defined(CONFIG_S3C2440)
    ldr    r1, =0x7fff   //根据2440芯片手册,INTSUBMSK有15位可用
    ldr    r0, =INTSUBMSK
    str    r1, [r0]
# endif

1.3 修改时钟设置

/*时钟控制逻辑单元能够产生s3c2440需要的时钟信号,包括CPU使用的主频FCLK,AHB总线使用的HCLK,APB总线设备使用的PCLK,2440里面的两个锁相环(PLL),其中一个对应FCLK、HCLK、PCLK,另外一个对应UCLK(48MHz)*/

/*注意:AHP、APB总线的简介参见“AHB与APB总线.doc” */

/* FCLK:HCLK:PCLK = 1:4:8 */
    ldr    r0, =CLKDIVN
    mov    r1, #5
    str    r1, [r0]
/*这三条协处理器命令确实不知道什么意思,在ATXJGYBC_ql.pdf中搜p15和c1,只知道它们执行以后会把协处理器p15的寄存器c1的最高两位置1,但c1的最高两位是没有意义啊,弄不懂它的真正意思

不过我却知道这三条语句是从哪里出来的,详细请参考s3c2440的datasheet和s3c2440datasheet中的R1_nF和R1_iA.doc */
    mrc    p15, 0, r1, c1, c0, 0        /*read ctrl register   qljt*/
    orr    r1, r1, #0xc0000000       /*Asynchronous  qljt改变总线模式为异步模式网上某位朋友说不知到在哪里看到过

如果FCLK与HCLK不同的话就要选择这种模式的 */
    mcr    p15, 0, r1, c1, c0, 0      /*write ctrl register qljt*/

#if defined(CONFIG_S3C2440)   // (2440的主频可达533MHz,但听说设到533MHz时系统

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>