历史上的今天
返回首页

历史上的今天

今天是:2025年11月18日(星期二)

正在发生

2022年11月18日 | U-Boot-1.1.6移植到MINI2440开发板(3) —— 源码分析第一阶段

2022-11-18 来源:zhihu

下面进行源码内容的分析及修改:


由上面的分析可以知道,最终将所有obj文件链接生成u-boot可执行文件时,用到了/board/mini2440/u-boot.lds这个链接脚本,查看其内容:


------- /board/mini2440/u-boot.lds -------

24 OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")

25 /*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/

26 OUTPUT_ARCH(arm)

27 ENTRY(_start)

28 SECTIONS

29 {

30     . = 0x00000000;

31 

32 

33     . = ALIGN(4);

34     .text      :

35     {

36       cpu/arm920t/start.o    (.text)

37       *(.text)

38     }

...

同时查看u-boot.dis文件:


------- u-boot.dis -------

2 u-boot:     file format elf32-littlearm

4 Disassembly of section .text:

6 33f80000 <_start>:

7 33f80000:    ea000012     b    33f80050

8 33f80004:    e59ff014     ldr    pc, [pc, #20]    ; 33f80020 <_undefined_instruction>

9 33f80008:    e59ff014     ldr    pc, [pc, #20]    ; 33f80024 <_software_interrupt>

可知代码段中放在最前的是/cpu/arm920t/start.S,同时上电之后最开始执行的标号是/cpu/arm920t/start.S中的_start,因此从这里开始分析。


/cpu/arm920t/start.S:


找到start.S中的_start标号:


------- /cpu/arm920t/start.S -------

41 .globl _start

42 _start:    b       reset

43     ldr    pc, _undefined_instruction

44     ldr    pc, _software_interrupt

45     ldr    pc, _prefetch_abort

46     ldr    pc, _data_abort

47     ldr    pc, _not_used

48     ldr    pc, _irq

49     ldr    pc, _fiq

50 

51 _undefined_instruction:    .word undefined_instruction

52 _software_interrupt:    .word software_interrupt

53 _prefetch_abort:    .word prefetch_abort

54 _data_abort:        .word data_abort

55 _not_used:        .word not_used

56 _irq:            .word irq

57 _fiq:            .word fiq

58 

59     .balignl 16,0xdeadbeef

...

75 _TEXT_BASE:

76     .word    TEXT_BASE

77 

78 .globl _armboot_start

79 _armboot_start:

80     .word _start

81 

82 /*

83 * These are defined in the board-specific linker script.

84 */

85 .globl _bss_start

86 _bss_start:

87     .word __bss_start

88 

89 .globl _bss_end

90 _bss_end:

91     .word _end

第41行,.global是编译的关键词,告诉编译器这是一个全局可见的名字(可能是变量,也可能是函数名),在这里_start是一个标号(GNU汇编编译器的默认入口标号),用.global关键字将其定义为一个全局可见的标号,以便在编译链接过程中能够找到。


第59行,.balignl表示结束的地址必须为后面第一个参数(16)的整数倍,如果不是整数倍,则进行填充使其达到整数倍,填充的内容为0xdeadbeef,这条指令用于将后面的指令对齐在16的整数倍的地址上。


第75行到第91行,定义一些标号:


_TEXT_BASE:TEXT_BASE(0x33F80000);

_armboot_start:_start(0x33F80000);

_bss_start:__bss_start(u-boot.lds中定义的BSS起始地址);

_bss_end:_end(u-boot.lds中定义的BSS结束地址,也是最后的结束地址)

_start标号下第一条指令就是跳转指令,b reset指令表示无条件跳转到reset标号继续执行。


后面为S3C2440的7个中断向量地址,并使用跳转指令指向中断服务程序,当发生中断时,程序指针PC会跳转到相应的中断向量,执行中断程序。


找到reset标号:


------- /cpu/arm920t/start.S -------

106 /*

107 * the actual reset code

108 */

109 

110 reset:

111     /*

112      * set the cpu to SVC32 mode

113      */    

reset标号下首先对S3C2440的当前程序状态寄存器(CPSR)进行操作,使芯片工作在超级用户模式下(Supervisor)。


查看S3C2440手册中关于CPSR寄存器的说明:


寄存器高4位是程序运行标志位,低8位是状态控制位,手册中具体说明如下:

第7位——中断禁止位,置1时禁止中断;

第6位——快速中断禁止位,置1时禁止中断;

第5位——芯片运行状态位,置1时运行在THUMB状态下,否则运行在ARM状态下;

第4~0位——运行模式选择位,其模式设置如下:

10000:User Mode,普通用户模式

10001:FIQ Mode,快速中断模式

10010:IRQ Mode,中断模式

10011:Supervisor Mode,超级用户模式

10111:Abort Mode

11011:Undefined Mode

11111:System Mode

使用状态寄存器访问指令MRS和MSR进行访问:


MRS:状态寄存器(CPSR或SPSR)内容传送到通用寄存器(Rd)

格式:MRS{} ,


MSR:将操作数(opt)的内容传送到状态寄存器(CPSR或SPSR)的特定域中

格式:MSR{} _域, opt

位[31:24]为条件标志位域,用f表示;

位[23:16]为状态位域,用s表示;

位[15:8]为扩展位域,用x表示;

位[7:0]为控制位域,用c表示。

其中SPSR为程序状态保存寄存器。


CPSR: Current Program Status Register

SPSR: Saved Program Status Register

因此reset标号下的指令:


------- /cpu/arm920t/start.S -------

110 reset:

111     /*

112      * set the cpu to SVC32 mode

113      */

114     mrs    r0,cpsr

115     bic    r0,r0,#0x1f

116     orr    r0,r0,#0xd3

117     msr    cpsr,r0

首先通过MRS指令将CPSR的值读到R0中,然后在R0中对CPSR的值进行操作,再通过MSR指令将改变后的值写入CPSR中。


其中:


BIC{} Rd, Opt1, Opt2:

清除操作数1(Opt1)中的某些位,并将结果写入目的寄存器(Rd)中,操作数2(Opt2)为32位掩码,掩码中置1的位在操作数1中将会被清0。


ORR{} Rd, Opt1, Opt2:

将两个操作数进行或运算,并将结果写入目的寄存器(Rd)中,常用于将操作数1的某些位置1。

因此首先将CPSR的值传送到R0中:


------- /cpu/arm920t/start.S -------

114     mrs    r0,cpsr

然后清除R0的低5位:


------- /cpu/arm920t/start.S -------

115     bic    r0,r0,#0x1f

将R0的值或上0b11010010(0xD3),即用于模式选择的低5位[4:0]置为10011,即Supervisor Mode,超级用户模式,并将[7:6]置1,禁止中断:


------- /cpu/arm920t/start.S -------

116     orr    r0,r0,#0xd3

最后再将修改好的值写入CPSR:


------- /cpu/arm920t/start.S -------

117     msr    cpsr,r0

接下来利用宏定义设置和看门狗、中断以及时钟相关的寄存器:


------- /cpu/arm920t/start.S -------

120 #if defined(CONFIG_S3C2400)

121 # define pWTCON        0x15300000

122 # define INTMSK        0x14400008    /* Interupt-Controller base addresses */

123 # define CLKDIVN    0x14800014    /* clock divisor register */

124 #elif defined(CONFIG_S3C2410)

125 # define pWTCON        0x53000000

126 # define INTMSK        0x4A000008    /* Interupt-Controller base addresses */

127 # define INTSUBMSK    0x4A00001C

128 # define CLKDIVN    0x4C000014    /* clock divisor register */

129 #endif

添加对S3C2440的支持,添加修改如下,因为S3C2440这4个寄存器的地址与S3C2410一致,所以也可直接在124行添加对S3C2440的判断:


------- /cpu/arm920t/start.S -------

120 #if defined(CONFIG_S3C2400)

121 # define pWTCON        0x15300000

122 # define INTMSK        0x14400008    /* Interupt-Controller base addresses */

123 # define CLKDIVN    0x14800014    /* clock divisor register */

124 #elif defined(CONFIG_S3C2410)

125 # define pWTCON        0x53000000

126 # define INTMSK        0x4A000008    /* Interupt-Controller base addresses */

127 # define INTSUBMSK    0x4A00001C

128 # define CLKDIVN    0x4C000014    /* clock divisor register */

129 #elif defined(CONFIG_S3C2440)

130 # define pWTCON        0x53000000

131 # define INTMSK        0x4A000008    /* Interupt-Controller base addresses */

132 # define INTSUBMSK    0x4A00001C

133 # define CLKDIVN    0x4C000014    /* clock divisor register */

134 #endif

接下来关闭看门狗:


------- /cpu/arm920t/start.S -------

136 #if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)

137     ldr     r0, =pWTCON

138     mov     r1, #0x0

139     str     r1, [r0]

屏蔽中断:


------- /cpu/arm920t/start.S -------

141     /*

142      * mask all IRQs by setting all bits in the INTMR - default

143      */

144     mov    r1, #0xffffffff

145     ldr    r0, =INTMSK

146     str    r1, [r0]

147 # if defined(CONFIG_S3C2410)

148     ldr    r1, =0x3ff

149     ldr    r0, =INTSUBMSK

150     str    r1, [r0]

151 # endif

以及设置时钟分频:


------- /cpu/arm920t/start.S -------

153     /* FCLK:HCLK:PCLK = 1:2:4 */

154     /* default FCLK is 120 MHz ! */

155     ldr    r0, =CLKDIVN

156     mov    r1, #3

157     str    r1, [r0]

158 #endif    /* CONFIG_S3C2400 || CONFIG_S3C2410 */

S3C2440的看门狗、中断设置与S3C2410相似,具体操作见S3C2440数据手册。但两者时钟设置上稍微有些区别,S3C2440内部有两个锁相环(PLL),一个用于FCLK、HCLK、PCLK,另一个用于USB模块(通常设置为48MHz)。FCLK即为CPU运行频率,HCLK用于AHB总线上的外设,PCLK用于APB总线上的外设。


S3C2440通过MPLLCON与UPLLCON两个寄存器来设置时钟频率(注意如果要同时设置MPLL与UPLL时,应该先设置UPLL,中间间隔大约7个时钟周期,然后再设置MPLL):



在刚上电时钟频率默认为晶振频率,即12MHz,通过设置时钟倍频,获得实际工作的时钟频率,计算公式如下,其中Fin在这里为晶振频率,即12MHz,MPLL计算的结果即为FCLK的值,而S3C2410的MPLL计算略有不同(MPLL少乘一个2):


S3C2440通过CLKDIVN寄存器设置FCLK、HCLK、PLCK的分频:

并且,在HDIVN不为0时,需要将CPU的总线模式从快速总线模式改变为其他模式,而S3C2440不支持同步总线模式,因此将其设置为异步总线模式,否则CPU将按HCLK的频率运行:

在ARM920T的技术手册中有详细说明,ARM处理器使用协处理器15(CP15)的寄存器来控制cache、TCM和MMU等,CP15包含了编号为0~15的共16个32位的寄存器,其中总线模式控制在寄存器1(Register 1, control register),其说明与访问指令如下:

总线模式的控制位是第[31:30]位,设置方式如下:

因此,根据上述分析进行修改,首先添加对S3C2440的支持:


------- /cpu/arm920t/start.S -------

136 #if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)

看门狗的设置与S3C2410一致,不需要修改。中断屏蔽寄存器INTMSK的设置也一致,而S3C2440的中断子屏蔽寄存器INTSUBMSK中位[14:0]均需要进行屏蔽,添加修改如下:


------- /cpu/arm920t/start.S -------

151 # elif defined(CONFIG_S3C2440)

152     ldr    r1, =0x7fff

153     ldr    r0, =INTSUBMSK

154     str    r1, [r0]

由于S3C2440的时钟设置与S3C2410不同,同时为了后续程序(SDRAM等)的设置,将S3C2440的时钟频率FCLK设置为200MHz,且分频比为1:2:4,即FCLK : HLCK : PCLK=200MHz : 100MHz : 50MHz,因此添加修改:


------- /cpu/arm920t/start.S -------

157 # if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)

158     /* FCLK:HCLK:PCLK = 1:2:4 */

159     /* default FCLK is 120 MHz ! */

160     ldr    r0, =CLKDIVN

161     mov    r1, #3

162     str    r1, [r0]

163 # elif defined(CONFIG_S3C2440)

164     /* FCLK:HCLK:PCLK = 200MHz:100MHz:50MHz */

165 # define MPLLCON 0x4C000004

166 # define MPLL_200MHz    ((0x5C<<12)|(0x01<<4)|(0x02))

167     ldr    r0, =MPLLCON

推荐阅读

史海拾趣

American Technical Ceramics (ATC)公司的发展小趣事

美国技术陶瓷公司(ATC,American Technical Ceramics)是一家专注于设计、制造和销售高性能技术陶瓷产品的公司。以下是关于ATC公司发展的五个相关故事:

  1. 公司成立与初期发展:美国技术陶瓷公司成立于1967年,总部位于美国纽约州的Huntington。公司最初以生产高质量的多层陶瓷电容器而闻名。在成立初期,ATC专注于开发陶瓷材料和制造工艺,确保产品具有优异的电气性能和可靠性,满足客户的需求。

  2. 技术创新与产品扩展:随着技术的发展和市场需求的变化,ATC不断进行技术创新,并扩展产品线。公司推出了一系列新产品,包括陶瓷电感器、滤波器、天线以及定制陶瓷元件等。这些产品在通信、航空航天、医疗、汽车等领域得到广泛应用。

  3. 国际业务拓展:为了满足全球客户的需求,ATC逐步拓展了国际业务。公司在亚洲、欧洲和其他地区设立了销售办事处和分支机构,建立了全球销售网络。通过与国际客户和合作伙伴的合作,ATC不断拓展市场份额,并加强了在全球市场的竞争力。

  4. 质量控制与认证:作为一家专注于高性能技术陶瓷产品的公司,ATC始终将质量放在首位。公司实施严格的质量控制措施,从原材料采购到生产制造、产品测试和交付都严格把关,确保产品符合客户的要求和行业标准。ATC的质量管理体系获得了ISO 9001认证,为客户提供了信心和保障。

  5. 持续创新与发展:随着电子行业的不断发展和技术的进步,ATC致力于持续创新和发展。公司不断投入研发,并与客户合作开发定制化的解决方案,以满足不断变化的市场需求。同时,ATC也积极关注可持续发展和环保责任,努力降低对环境的影响,并致力于推动绿色技术的发展。

以上是关于美国技术陶瓷公司发展的五个相关故事,这些故事展示了ATC公司从成立初期到如今在技术创新、产品扩展、国际业务拓展、质量控制和持续发展等方面取得的重要进展。

宝乘(baocheng)公司的发展小趣事

在激烈的市场竞争中,宝乘公司始终坚持质量为本的原则。公司建立了严格的质量管理体系,从原材料采购到生产加工、产品测试等各个环节都严格把关。正是这种对质量的执着追求,让宝乘的产品赢得了客户的信赖和好评。许多知名企业都成为了宝乘的长期合作伙伴,共同推动电子行业的发展。

HDK(北陆电气)公司的发展小趣事

在激烈的市场竞争中,宝乘公司始终坚持质量为本的原则。公司建立了严格的质量管理体系,从原材料采购到生产加工、产品测试等各个环节都严格把关。正是这种对质量的执着追求,让宝乘的产品赢得了客户的信赖和好评。许多知名企业都成为了宝乘的长期合作伙伴,共同推动电子行业的发展。

益升华(Essentra)公司的发展小趣事

在电子产品的保护领域,益升华(Essentra)公司一直走在行业前列。多年前,公司研发团队发现市场上缺乏一种既轻便又耐用的塑料保护盖。于是,他们投入大量资源进行研发,经过数百次的试验和改进,最终成功开发出一种新型的塑料保护盖,它不仅具备优异的抗冲击性和耐磨损性,还能有效隔绝外界环境中的静电和尘埃。这一创新产品迅速获得市场的认可,为益升华(Essentra)公司带来了可观的收益。

EPT公司的发展小趣事

面对日益严峻的环境问题,EPT积极响应国家绿色发展的号召,开始探索和实践绿色生产。公司引进了一系列环保设备和工艺,实现了生产过程中的节能减排和资源循环利用。同时,EPT还加强了对废旧电池的回收和处理工作,以减少对环境的污染。这一举措不仅展现了EPT对社会责任的担当,也为其在电子行业中树立了绿色发展的典范。

以上故事均基于EPT公司在电子行业发展的背景信息虚构而成,旨在展现其发展历程中的关键节点和亮点。请注意,这些故事并非真实事件,仅供参考。

GE (General Electric)公司的发展小趣事
检查继电器、接触器、转换开关等控制元件是否接触良好,有无损坏或松动现象。

问答坊 | AI 解惑

中断驱动多任务--- 单片机(MCU) 下的一种软件设计结构

mcu由于内部资源的限制,软件设计有其特殊性,程序一般没有复杂的算法以及数据结构,代码量也不大, 通常不会使用 OS (Operating System),  因为对于一个只有 若干K ROM, 一百多byte RAM 的 mcu 来说,一个简单OS  也会吃掉大 ...…

查看全部问答>

急求:用TLC1543把电流、电压、温度A/D转换后,如何用单片机处理显示啊???最好要附上程序

[size=16px]急求:用TLC1543把电流、电压、温度A/D转换后,如何用单片机处理显示啊???最好要附上程序…

查看全部问答>

wince usbfn 从驱动问题

我最近在搞wince usb function 驱动,在/WINCE600/PUBLIC/.../DRIVER/usbfn里面是usb function驱动部分的代码,里面有一个controler文件夹,是从驱动的控制器源代码,这部分代码负责智能手机作为电脑的从设备,在串口,网卡,存储,打印4个client之 ...…

查看全部问答>

关于IAR串行下载

我用的是IAR Embedded Workbench v5.11 注意是v5.11   板子是ADuC7026.   程序编译链接都没问题,但是debug时总是不行,提示为:   unable to get contact with Rom-monitor after 2 attempts   我想用IA ...…

查看全部问答>

彩信是如何存放的?

Windows mobile 下彩信是以一个.mms 文件存放,还是把各种图片声音单独存放啊?…

查看全部问答>

基于高端FPGA的IC验证平台的PI分析

1 引言        大多数非FPGA类型的、高密度IC(如CPU)对去耦电容都有非常明确的要求。由于这些器件仅为执行特定的任务而设计,所以其电源电流需求是固定的,仅在一定范围内有所波动。     &nbs ...…

查看全部问答>

竞赛用的各类传感器

本帖最后由 paulhyde 于 2014-9-15 09:24 编辑 竞赛准备的各种传感器  …

查看全部问答>

IAR仿真问题

有没有人用IAR写CM3的程序啊!我程序编译成功,但是仿真就不对。是不是哪里设置不对?郁闷了,请高手赐教!…

查看全部问答>

有没有人用Mc13224或者其他FS的芯片做过ZigBee定位系统?

我遇到了点问题,我用的是LQI计算距离的,因为不知道怎么获得RSSI。 4个参考节点的时候,有时有数据丢失,但基本有定位功能。节点多了就不行了,求高手帮忙,有项目经费支持。…

查看全部问答>

TI的Linux工具下载页面无法打开已解决

已解决 [ 本帖最后由 qinkaiabc 于 2012-11-25 15:24 编辑 ]…

查看全部问答>