U-Boot-1.1.6移植到MINI2440开发板(4) —— 源码分析第二阶段(1)

最新更新时间:2022-11-18来源: zhihu关键字:U-Boot  移植  MINI2440开发板 手机看文章 扫描二维码
随时随地手机看文章

下面开始分析U-Boot第二阶段:


/lib_arm/board.c:


由前述分析可知,在start.S中对CPU进行了基本的设置,准备好了C程序的运行环境(设置好了堆栈并清BSS),并调用C函数start_armboot,进入lib_arm目录下的board.c文件,第236行开始即为start_armboot函数:


------- /lib_arm/board.c -------

236 void start_armboot (void)

237 {

238     init_fnc_t **init_fnc_ptr;

239     char *s;

240 #ifndef CFG_NO_FLASH

241     ulong size;

242 #endif

243 #if defined(CONFIG_VFD) || defined(CONFIG_LCD)

244     unsigned long addr;

245 #endif

一些变量的定义,其中init_fnc_ptr为初始化函数序列的指针。

接下来初始化全局变量gd与gd->bd的内存区域(清0),第55行的宏定义声明了gd:


------- /lib_arm/board.c -------

55 DECLARE_GLOBAL_DATA_PTR;

这个宏定义在/include/asm-arm/global_data.h中,(凡是用到gd的文件中都会引用这个宏定义):


------- /include/asm-arm/global_data.h -------

64 #define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")

register volatile gd_t *gd asm ("r8"):声明一个寄存器变量gd,用R8寄存器来存储其指针,不占用内存,且避免编译器再将R8分配给其他变量。

第248行设置gd指针的具体地址,其中_armboot_start表示0x33F80000地址,CFG_MALLOC_LEN定义的大小为0x30000=192kB,然后调用memset函数将gd指针开始的、大小为sizeof(gd_t)的内存区域初始化为0:


------- /lib_arm/board.c -------

247     /* Pointer is writable since we allocated a register for it */

248     gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));

249     /* compiler optimization barrier needed for GCC >= 3.4 */

250     __asm__ __volatile__("": : :"memory");

251 

252     memset ((void*)gd, 0, sizeof (gd_t));

__asm__:在此插入汇编语句;

__volatile__:禁止优化,即编译器将按照此处的语句处理;

"memory":强制编译器假设所有内存单元均被汇编指令修改,即CPU必须重新读取内存中的数据,而不是利用cache的缓存数据。

举个栗子(来自网络博客):

1 int a = 5, b = 6;

2 __asm__ __volatile__("": : :"memory");

3 a = b;

此时第3行的处理,编译器不会用存放b的寄存器给a赋值,而是让CPU重新读取内存中b的值,并赋给a。


第253行、254行设置bd的指针,并将其内存区域初始化为0:


------- /lib_arm/board.c -------

253     gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));

254     memset (gd->bd, 0, sizeof (bd_t));

255

256     monitor_flash_len = _bss_start - _armboot_start;

接下来按照初始化函数序列的顺序,执行所有的初始化函数:


------- /lib_arm/board.c -------

258     for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {

259         if ((*init_fnc_ptr)() != 0) {

260             hang ();

261         }

262     }

初始化函数正确执行的返回值应该为0,否则将调用hang()函数,输出错误信息并进入死循环暂停。

初始化函数序列包括CPU的初始化、板级初始化、中断初始化、环境变量初始化、波特率初始化、串口初始化、控制台初始化、显示U-Boot信息以及DRAM的初始化等:


------- /lib_arm/board.c -------

212 typedef int (init_fnc_t) (void);

...

216 init_fnc_t *init_sequence[] = {

217     cpu_init,        /* basic cpu dependent setup */

218     board_init,        /* basic board dependent setup */

219     interrupt_init,        /* set up exceptions */

220     env_init,        /* initialize environment */

221     init_baudrate,        /* initialze baudrate settings */

222     serial_init,        /* serial communications setup */

223     console_init_f,        /* stage 1 init of console */

224     display_banner,        /* say that we are here */

225 #if defined(CONFIG_DISPLAY_CPUINFO)

226     print_cpuinfo,        /* display cpu info (and speed) */

227 #endif

228 #if defined(CONFIG_DISPLAY_BOARDINFO)

229     checkboard,        /* display board info */

230 #endif

231     dram_init,        /* configure available RAM banks */

232     display_dram_config,

233     NULL,

234 };

下面对初始化函数序列进行详细说明(可以先初始化波特率和串口,便于输出调试信息,这里按顺序进行分析修改)。




初始化函数序列分析:


cpu_init:


位于/cpu/arm920t/cpu.c文件中,主要用于设置中断的堆栈,在这里并没有定义CONFIG_USE_IRQ,因此实际上无作用,不需进行修改:


------- /cpu/arm920t/cpu.c -------

92 int cpu_init (void)

93 {

94     /*

95      * setup up stacks if necessary

96      */

97 #ifdef CONFIG_USE_IRQ

98     IRQ_STACK_START = _armboot_start - CFG_MALLOC_LEN - CFG_GBL_DATA_SIZE - 4;

99     FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ;

100 #endif

101     return 0;

102 }



board_init:


位于/board/mini2440/mini2440.c文件中,主要用于CPU时钟与引脚设置:


------- /board/mini2440/mini2440.c -------

68 int board_init (void)

69 {

70     S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

71     S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();

S3C24X0_CLOCK_POWER:在/include/s3c24x0.h中定义,而S3C2440多一个CAMDIVN寄存器,因此在添加修改(不修改也没事):


------- /include/s3c24x0.h -------

120 /* CLOCK & POWER MANAGEMENT (see S3C2400 manual chapter 6) */

121 /*                          (see S3C2410 manual chapter 7) */

122 typedef struct {

123     S3C24X0_REG32    LOCKTIME;

124     S3C24X0_REG32    MPLLCON;

125     S3C24X0_REG32    UPLLCON;

126     S3C24X0_REG32    CLKCON;

127     S3C24X0_REG32    CLKSLOW;

128     S3C24X0_REG32    CLKDIVN;

129 #ifdef CONFIG_S3C2440

130     S3C24X0_REG32    CAMDIVN;

131 #endif

132 } /*__attribute__((__packed__))*/ S3C24X0_CLOCK_POWER;

...

845 /* CLOCK & POWER MANAGEMENT */

846 #define rLOCKTIME       (*(volatile unsigned *)0x4C000000)

847 #define rMPLLCON        (*(volatile unsigned *)0x4C000004)

848 #define rUPLLCON        (*(volatile unsigned *)0x4C000008)

849 #define rCLKCON         (*(volatile unsigned *)0x4C00000C)

850 #define rCLKSLOW        (*(volatile unsigned *)0x4C000010)

851 #define rCLKDIVN        (*(volatile unsigned *)0x4C000014)

852 #define rCAMDIVN        (*(volatile unsigned *)0x4C000018)

S3C2440还有一些寄存器与S3C2410不同,在后续遇到时将进行修改。

S3C24X0_GPIO:在/include/s3c24x0.h中定义,在前面已经添加了S3C2440的GPIO寄存器:


------- /include/s3c24x0.h -------

385 /* I/O PORT (see manual chapter 9) */

386 typedef struct {

...

470 #ifdef CONFIG_S3C2440

471     S3C24X0_REG32    GPACON;

472     S3C24X0_REG32    GPADAT;

473     S3C24X0_REG32    res1[2];

474     S3C24X0_REG32    GPBCON;

475     S3C24X0_REG32    GPBDAT;

476     S3C24X0_REG32    GPBUP;

477     S3C24X0_REG32    res2;

478     S3C24X0_REG32    GPCCON;

479     S3C24X0_REG32    GPCDAT;

480     S3C24X0_REG32    GPCUP;

481     S3C24X0_REG32    res3;

482     S3C24X0_REG32    GPDCON;

483     S3C24X0_REG32    GPDDAT;

484     S3C24X0_REG32    GPDUP;

485     S3C24X0_REG32    res4;

486     S3C24X0_REG32    GPECON;

487     S3C24X0_REG32    GPEDAT;

488     S3C24X0_REG32    GPEUP;

489     S3C24X0_REG32    res5;

490     S3C24X0_REG32    GPFCON;

491     S3C24X0_REG32    GPFDAT;

492     S3C24X0_REG32    GPFUP;

493     S3C24X0_REG32    res6;

494     S3C24X0_REG32    GPGCON;

495     S3C24X0_REG32    GPGDAT;

496     S3C24X0_REG32    GPGUP;

497     S3C24X0_REG32    res7;

498     S3C24X0_REG32    GPHCON;

499     S3C24X0_REG32    GPHDAT;

500     S3C24X0_REG32    GPHUP;

501     S3C24X0_REG32    res8;

502 

503     S3C24X0_REG32    MISCCR;

504     S3C24X0_REG32    DCLKCON;

505     S3C24X0_REG32    EXTINT0;

506     S3C24X0_REG32    EXTINT1;

507     S3C24X0_REG32    EXTINT2;

508     S3C24X0_REG32    EINTFLT0;

509     S3C24X0_REG32    EINTFLT1;

510     S3C24X0_REG32    EINTFLT2;

511     S3C24X0_REG32    EINTFLT3;

512     S3C24X0_REG32    EINTMASK;

513     S3C24X0_REG32    EINTPEND;

514     S3C24X0_REG32    GSTATUS0;

515     S3C24X0_REG32    GSTATUS1;

516     S3C24X0_REG32    GSTATUS2;

517     S3C24X0_REG32    GSTATUS3;

518     S3C24X0_REG32    GSTATUS4;

519 #endif

520 } /*__attribute__((__packed__))*/ S3C24X0_GPIO;

通过设置MPLLCON和UPLLCON来改变时钟频率:

修改时钟设置宏定义如下:


------- /board/mini2440/mini2440.c -------

33 //#define FCLK_SPEED 1

34 #define FCLK_SPEED 200

...

44 #elif FCLK_SPEED==200

45 #define M_MDIV    0x5C

46 #define M_PDIV    0x1

47 #define M_SDIV    0x2

...

50 //#define USB_CLOCK 1

51 #define USB_CLOCK 48

...

61 #elif USB_CLOCK==48

62 #define U_M_MDIV    0x38

63 #define U_M_PDIV    0x2

64 #define U_M_SDIV    0x2

在board_init函数中通过时钟设置的宏定义对时钟频率进行修改:


------- /board/mini2440/mini2440.c -------

83     /* to reduce PLL lock time, adjust the LOCKTIME register */

84     clk_power->LOCKTIME = 0xFFFFFF;

85 

86     /* the CLKDIVN register, FCLK:HCLK:PCLK=4:2:1 */

87     clk_power->CLKDIVN = 0x3;

88     __asm__(

89             "mrc p15, 0, r0, c1, c0, 0n"

90             "orr r0, r0, #0xC0000000n"

[1] [2] [3] [4] [5] [6]
关键字:U-Boot  移植  MINI2440开发板 编辑:什么鱼 引用地址:U-Boot-1.1.6移植到MINI2440开发板(4) —— 源码分析第二阶段(1)

上一篇:U-Boot-1.1.6移植到MINI2440开发板(2) —— S3C2440相关修改
下一篇:U-Boot-1.1.6移植到MINI2440开发板(3) —— 源码分析第一阶段

推荐阅读

uCGUI 移植到S3C44B0X实验
一、实验目的1. 初步掌握uCGUI底层硬件驱动函数;2. 掌握将uCGUI移植到ARMS3C44BOX上的方法和步骤。二、实验内容移植uCGUI到ARM处理器S3C44BOX上,并编写Hello World程序,在Micetek 44B0实验平台的LCD上显示“Hello World!”字符串,在LCD显示平面坐标(20,20)处,显示一个小于10000的整数,该整数不断循环加1,每次加1后立即更新显示,从而反应出显示输出的速度。三、预备知识1. uCGUI的体系结构:uCGUI包含三个总的文件夹:ApplicaTIon,Config,GUI.其中:Ⅰ ApplicaTIon是应用程序的文件夹,它中间包含主函数文件,其它资源文件。
发表于 2023-02-02
基于S3C2410开发板U-BOOT移植解决方案
引言随着嵌入式系统的日趋复杂,它对大容量数据存储的需求越来越紧迫。而嵌入式设备低功耗、小体积以及低成本的要求,使硬盘无法得到广泛的应用。NAND闪存设备就是为了满足这种需求而迅速发展起来的。目前关于U-BOOT的移植解决方案主要面向的是微处理器中的NOR 闪存,如果能在微处理器上的NAND 闪存中实现U-BOOT的启动,则会给实际应用带来极大的方便。U-BOOT简介U-BOOT 支持ARM、 PowerPC等多种架构的处理器,也支持Linux、NetBSD和VxWorks等多种操作系统,主要用来开发嵌入式系统初始化代码bootloader。bootloader是芯片复位后进入操作系统之前执行的一段代码,完成由硬件启动到操作系统启动的
发表于 2023-01-11
基于S3C2410<font color='red'>开发板</font>的<font color='red'>U-BOOT</font><font color='red'>移植</font>解决方案
U-boot在S3C2440上的移植详解(五)
一、移植环境主 机:VMWare--Fedora 9开发板:Mini2440--64MB Nand,Kernel:2.6.30.4编译器:arm-linux-gcc-4.3.2.tgzu-boot:u-boot-2009.08.tar.bz2二、移植步骤9)实现u-boot对yaffs/yaffs2文件系统下载的支持。 注意:此篇对Nand的操作是基于MTD架构方式,在“u-boot-2009.08在2440上的移植详解(三)”中讲到过。 通常一个Nnad Flash存储设备由若干块组成,1个块由若干页组成。一般128MB以下容量的Nand Flash芯片,一页大小为528B,被依次分为2个256B的主数据区和16B的额外空间;12
发表于 2023-01-11
<font color='red'>U-boot</font>在S3C2440上的<font color='red'>移植</font>详解(五)
关于uboot的功能分析透彻方案
如果我们想快速的移植uboot,那么我们就要先将我们用到的uboot的功能分析透彻,uboot最终目的就是**引导内核**,但是在实际开发中为了方便开发调试,我们将uboot加入了很多功能,比如tftp下载,nfs启动,串口打印等功能;那么我们先按着执行的顺序来分析代码。uboot并没有对2440进行支持,所以我们分析阶段先分析smdk2410的相关代码,分析完成以后我们在根据s3c2440的技术手册在2410的基础上进行移植。Makefile分析首先我们根据编译过程进行分析,编译需要执行命令:make smdk2410_config我们查看根目录下Makefile文件,搜索smdk2410_config得到如下代码:smdk241
发表于 2023-01-11
s3c2440移植openharmony
s3c2440移植openharmony。OpenHarmony是开放原子开源基金会的一个孵化项目,OpenHarmony完全开源开放,OpenHarmony轻量和小型系统比较适合内存小的IOT设备。OpenHarmony同时提供许多可选的系统组件,设备开发者能够按需配置。系统能够把这些能够选择的组件合成一个系列的系统能力让设备开发者更好的理解和开发。想对OpenHarmony进行开发、编译、烧录、调测能够使用DevEco Device Tool。现在的openharmony轻量和小型系统搭建系统环境Windows版本不支持在Windows平台编译,Hi3861除外,其它的只能在Ubuntu平台下编译。
发表于 2023-01-09
基于S3C2410处理器目标板的Linux移植
引言嵌 人式系统就是以应用为中心、以计算机技术为基础,软硬件可裁剪,适应应用系统对功能、可靠性、成本、体积、功耗等严格要求的专用计算机系统。ARM嵌人式 芯片是一种高性能、低功耗的RISC芯片。它由英国ARM公司设计,世界上几乎所有的主要半导体生产商都生产基于ARM体系机构的通用芯片,或在其专用芯 片中应用相关ARM技术。在2001年基于ARM内核的处理器占市场份额的75%,成为业界的龙头。Linux 是免费发行的、快速高效的操作系统 ,Linux的出现在计算机世界引发了一场革命。Linux操作系统以代码开放、功能强大又易于移植成为嵌入式操作新兴力量。嵌人式Linux是按照嵌人 式操作系统的要求设计的一种小型操作系统,由一个内核以及
发表于 2023-01-06
小广播
设计资源 培训 开发板 精华推荐

何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2023 EEWORLD.com.cn, Inc. All rights reserved