Bootloader

Bootloader 以其本身的含义来讲就是下载和启动系统,它类似于 PC 中的 BIOS,大部

分芯片厂商所提供的嵌入式系统都提供有这样的程序,而且都比较成熟,大可不必自行编写。

为研究其工作原理,清扫上个章节裸机程序中的知识盲点,本章节将通过vivi单独介绍Bootloader的技术细节。vivi由三星提供,韩国 mizi 公司原创,开放源代码,必须使用 arm-linux-gcc 进行编译,主要适用于三星 S3C24xx 系列 ARM 芯片,用以启动 Linux 系统,支持串口下载和网络文件系统启动等常用简易功能。

vivi编译源码

vivi需要在linux环境下编译。本文给出的viv源码交叉编译器版本为arm-linux-gcc-2.95.3。从官网下载gcc,解压到/usr/local/arm/2.95.3目录。下载vivi-20090630.tar.gz,解压到合适目录。cd进入vivi目录,输入make命令进行编译。编译完成后生成vivi二进制文件,使用jlink或者其他BootLoader将其烧录到nand flash中。

vivi源码解析(一)

vivi源码目录层次结构如下:

arch目录包含了芯片启动初始化相关代码。drivers目录为外设相关的驱动代码,包括FLASH、以太网、串口。init目录包含了main主程序和版本信息相关代码。其他目录包含的工具相关的辅助代码

首先解析‘vivi/arch/s3c2440/head.S’这个汇编文件。该文件是芯片上电后最开始执行的代码。地址为0x00000000。从下一章节“Nand Flash驱动”章节可知,上电后,硬件会自动将nand flash中前4K代码加载到内部的SRAM缓冲区中运行,映射的起始地址为0x00000000。此处的head.S即对应前4K代码。因Flash内部的SRAM缓冲区只有4K,无法存放bootloader全部功能的代码,故该缓存区代码主要功能是将Nand Flash中存储的vivi代码全部复制到SDRAM中,让其具备足够的内存空间运行。

1       #include "config.h"

2       #include "linkage.h"

3       #include "machine.h"

4       #define CONFIG_DEBUG_LL

5       #define CONFIG_SERIAL_UART0 1

6       ENTRY(_start)

7       ENTRY(ResetEntryPoint)

8       @ 0x00: Reset

9                b       Reset

10

11     UndefEntryPoint:

12              b       HandleUndef

13

14     SWIEntryPoint:

15              b       HandleSWI

16

17     PrefetchAbortEnteryPoint:

18              b       HandlePrefetchAbort

19

20     DataAbortEntryPoint:

21              b       HandleDataAbort

22

23     NotUsedEntryPoint:

24              b       HandleNotUsed

25

26     IRQEntryPoint:

27              b       HandleIRQ

28

29     FIQEntryPoint:

30              b       HandleFIQ

31

32     @ 0x20: magic number so we can verify that we only put

33              .long   0

34     @ 0x24:

35              .long   0

36     @ 0x28: where this vivi was linked, so we can put it in memory in the right place

37              .long   _start

38     @ 0x2C: this contains the platform, cpu and machine id

39              .long   ARCHITECTURE_MAGIC

40     @ 0x30: vivi capabilities

41              .long   0

42     #ifdef CONFIG_PM

43     @ 0x34:

44              b       SleepRamProc

45     #endif

46     #ifdef CONFIG_TEST

47     @ 0x38:

48     @     b       hmi

49     #endif

50     Reset:

51              @ disable watch dog timer

52              mov r1, #0x53000000

53              mov r2, #0x0

54              str    r2, [r1]

55              @ disable all interrupts

56              mov r1, #INT_CTL_BASE

57              mov r2, #0xffffffff

58              str    r2, [r1, #oINTMSK]

59              ldr    r2, =0x7ff

60              str    r2, [r1, #oINTSUBMSK]

61              @ initialise system clocks

62              mov r1, #CLK_CTL_BASE

63              mvn r2, #0xff000000

64              str    r2, [r1, #oLOCKTIME]

65

66              mov r1, #CLK_CTL_BASE

67              ldr    r2, clkdivn_value

68              str    r2, [r1, #oCLKDIVN]

69

70              mrc  p15, 0, r1, c1, c0, 0           @ read ctrl register

71              orr    r1, r1, #0xc0000000                  @ Asynchronous

72              mcr  p15, 0, r1, c1, c0, 0           @ write ctrl register

73

74              mov r1, #CLK_CTL_BASE

75              @ldr         r2, mpll_value                    @ clock default

76              ldr   r2, =0x5C011   @mpll_value_USER                  @ clock user set @0x7f021

77              str    r2, [r1, #oMPLLCON]

78              mov         r2, #0x05

79              str    r2, [r1, #oCLKDIVN]

80              bl      memsetup

81

82     #ifdef CONFIG_PM

83              @ Check if this is a wake-up from sleep

84              ldr    r1, PMST_ADDR

85              ldr    r0, [r1]

86              tst    r0, #(PMST_SMR)

87              bne  WakeupStart

88     #endif

89

90              @ All LED on

91              mov r1, #GPIO_CTL_BASE

92              add  r1, r1, #oGPIO_B

93              ldr    r2,=0x155555

94              str    r2, [r1, #oGPIO_CON]

95              mov r2, #0xff

96              str    r2, [r1, #oGPIO_UP]

97              mov r2, #0xAA

98              str    r2, [r1, #oGPIO_DAT]

99

100           mov r0, #0x1

101           bl ShowLedVal

102           mov r0, #120

103           bl Delay_ms

104           mov r0, #0x2

105           bl ShowLedVal

106           mov r0, #120

107           bl Delay_ms

108           mov r0, #0x4

109           bl ShowLedVal

110           mov r0, #120

111           bl Delay_ms

112           mov r0, #0x8

113           bl ShowLedVal

114           mov r0, #120

115           bl Delay_ms

116           mov r0, #0x0

117           bl ShowLedVal

118

119  #ifdef CONFIG_S3C2440_SMDK

120           mov r1, #GPIO_CTL_BASE

121           add  r1, r1, #oGPIO_H

122           ldr    r2, =0x00faaa

123           str    r2, [r1, #oGPIO_CON]

124           ldr    r2, =0x7ff

125           str    r2, [r1, #oGPIO_UP]

126  #endif

127           bl      InitUART

128

129            mov r1, #UART0_CTL_BASE @old is SerBase

130            mov r0, #'\r'

131            bl      PrintChar

132            mov r0, #'\n'

133            bl      PrintChar

134            mov r0, #'1'

135            bl      PrintChar

136            mov r0, #'@'

137            bl      PrintChar

138            mov r0, pc

139            bl      PrintHexWord

140

141            mov r0, #'B'

142            bl      PrintChar

143            mov r0, #':'

144            bl      PrintChar

145            ldr    r0, =on_the_ram

146            bl      PrintHexWord

147

148            mov r0, #'@'

149            bl      PrintChar

150            bl      copy_myself

151

152            mov r1, #GPIO_CTL_BASE

153            add  r1, r1, #oGPIO_F

154            mov r2, #0x00

155            str    r2, [r1, #oGPIO_DAT]

156

157            @ jump to ram

158            ldr    r1, =on_the_ram

159            add  pc, r1, #0

160            nop

161            nop

167  1:      b       1b              @ infinite loop

168

169  on_the_ram:

170            @ Print current Program Counter

171            mov r1, #UART0_CTL_BASE

172            mov r0, #'\r'

173            bl      PrintChar

174            mov r0, #'\n'

175            bl      PrintChar

176            mov r0, #'2'

177            bl      PrintChar

178            mov r0, #'@'

179            bl      PrintChar

180            mov r0, pc

181            bl      PrintHexWord

182

183            mov r1, #UART0_CTL_BASE

184            ldr    r0, STR_STACK

182            bl      PrintWord

183            ldr    r0, DW_STACK_START

184            bl      PrintHexWord

185

186            ldr    sp, DW_STACK_START     @ setup stack pointer

187            mov fp, #0                           @ no previous frame, so fp=0

188            mov a2, #0                          @ set argv to NULL

189

190            bl      main                            @ call main

191

192           mov pc, #FLASH_BASE              @ otherwise, reboot

193

194  copy_myself:

195            mov r10, lr

196            @ get read to call C functions (for nand_read())

197            ldr    sp, DW_STACK_START     @ setup stack pointer

198            mov fp, #0                           @ no previous frame, so fp=0

199

200            mov r1, #GPIO_CTL_BASE

201            add  r1, r1, #oGPIO_F

202            mov r2, #0xe0

203            str    r2, [r1, #oGPIO_DAT]

204

205            @ copy vivi to RAM

206            ldr    r0, =VIVI_RAM_BASE

207            mov     r1, #0x0

208            mov r2, #0x20000

209

210            bl      nand_read_ll

211

212            ldr    r1, =VIVI_RAM_BASE

213            ldr    r0, [r1, #0x0]

214            bl      PrintHexWord

215            ldr    r0, [r1, #0x4]

216            bl      PrintHexWord

217            ldr    r0, [r1, #0x8]

218            bl      PrintHexWord

219            ldr    r0, [r1, #0xC]

220            bl      PrintHexWord

221

222            mov r1, #GPIO_CTL_BASE

223            add  r1, r1, #oGPIO_F

224            mov r2, #0xb0

225            str    r2, [r1, #oGPIO_DAT]

226            bl      PrintHexWord

227            tst    r0, #0x0

228            beq  ok_nand_read

229  bad_nand_read:

230            ldr    r0, STR_FAIL

231            ldr    r1, SerBase

232            bl      PrintWord

233  1:      b       1b              @ infinite loop

234

235  ok_nand_read:

236            ldr    r0, STR_OK

237            ldr    r1, SerBase

238            bl      PrintWord

239            mov     r0, #'_'

240      bl      PrintChar

241            mov     r0, #'c'

242     bl      PrintChar

243            mov     r0, #'p'

244     bl      PrintChar

245            mov     r0, #'\r'

246     bl      PrintChar

247            mov     r0, #'\n'

248     bl      PrintChar

249

250            @ verify

251            mov r0, #0

252            ldr    r1, =0x33f00000

253            mov r2, #0x400        @ 4 bytes * 1024 = 4K-bytes

254  go_next:

255            ldr    r3, [r0], #4

256            ldr    r4, [r1], #4

257            teq   r3, r4

258            bne  notmatch

259            subs r2, r2, #4

260            beq  done_nand_read

261            bne  go_next

262  notmatch:

263            sub   r0, r0, #4

264            ldr    r1, SerBase

265            bl      PrintHexWord

266            ldr    r0, STR_FAIL

267            ldr    r1, SerBase

268            bl      PrintWord

269            mov r0, r3

270            bl      PrintHexWord

271            mov r0, r4

272            bl      PrintHexWord

273            ldr    r1, =0x33f00004

274            ldr    r4, [r1], #4

275            mov r0, r4

276            bl      PrintHexWord

277

278  1:      b       1b

279  done_nand_read:

280            ldr    r0, STR_OK

281            ldr    r1, SerBase

282            bl      PrintWord

283

284            mov r1, #GPIO_CTL_BASE

285            add  r1, r1, #oGPIO_F

286            mov r2, #0x70

287            str    r2, [r1, #oGPIO_DAT]

288

289            mov pc, r10

Line9         b       Reset即对应0x00000000。此处是一个跳转指令,跳转到Reset标识处。

Line52~54禁用看门狗。Line56~60禁用所有中断。

Line62~79用于设置时钟。

Line80 初始化内存,具体设置的值此处忽略。

Line82~88判断是否从睡眠模式中唤醒

Line91~98点亮LED灯

Line100~117依次点亮每个LED灯。ShowLedVal和Delay_ms可在串口启用前调试代码,将需要Debug的值,输入到ShowLedVal中,配合Delay_ms观测LED点灯情况。

Line120~127设置串口,后续可使用串口打印log方式调试bootloader程序。

Line129~139通过串口打印出了PC寄存器的值,通过观察可知,值为0x00000140。

Line145~146打印出了on_the_ram标识处的地址,即0x33F00188。该地址也可以通过map文件找到。

Line150 跳转到Line194

Line195保存返回地址

Line197~198准备C语言调用的环境

Line200~203设置GPIOF端口

Line206~210向C语言函数nand_read_ll传入3个参数0x33F00000(0x30000000+0x04000000-0x00100000),0,0x20000。用于从flash读取数据到RAM中。详细流程,参看下一章“Nand Flash驱动”

Line212~220串口输出copy进RAM前16个字节的数据,即“EA00000B,EA000111,EA000116,EA00011B”

Line227~228用于检测nand_read_ll的返回值是否为0,是则串口输出“OK”“_cp”字样。

Line251~261比较RAM中0~4K-1和刚copy的数据是否一致,是则输出“OK”字样。

Line289代码段copy_myself返回,跳转到Line152。

Line158~159 跳转到on_the_ram,此处跳转为直接地址跳转,跳转到地址0x33F00188。根据字面含义,程序已经跳转到了SDRAM空间运行

Line171~181串口依次输出’\r\n2@’以及PC寄存器地址,此处为0x33F001B4。从这里看到,程序已经跳转到了我们copy的ram地址区域中了。

Line183~184(代码处数字有误,此处指第一个183到第二个184处),串口输出“STKP”字样,以及堆栈指针,0x33DEFFFC

Line186~190初始化C语言堆栈指针、fp指针、main函数参数,最后跳转到main函数。

至此程序已进入main主函数。

串口输出信息如下:

1@00000140

B:33F00188

@EA00000B

EA000111

EA000116

EA00011B

00000250

OK

_cp

OK

2@33F001B4

STKP

33DEFFFC

VIVI version 0.1.4 (root@summertree-desktop) (gcc version 2.95.3 20010315 (release)) #0.1.4 Thu Sep 23 21:18:06 CST 2021

MMU table base address = 0x33DFC000

Succeed memory mapping.

NAND device: Maf Id:236, dev Id:218

NAND device: Manufacture ID: 0xec, Chip ID: 0xda (Samsung K9F2G08U0B)

Found default vivi parameters

Press Return to start the LINUX now, any other key for vivi

type "help" for help.

FriendlyARM>

FriendlyARM> help

Usage:

flash [{cmds}]                      -- Manage Flash memory

cpu [{cmds}]                         -- Manage cpu clocks

bon [{cmds}]                                   -- Manage the bon file system

reset                              -- Reset the system

param [eval|show|save [-n]|reset]          -- set/get parameter

part [add|del|show|reset]                -- Manage MTD partitions

mem [{cmds}]                      -- Manage Memory

load [{cmds}]                       -- Load a file to RAM/Flash

go <addr> <a0> <a1> <a2> <a3>      -- jump to <addr>

dump <addr> <length>              -- Display (hex dump) a range of memory.

call <addr> <a0> <a1> <a2> <a3>    -- jump_with_return to <addr>

boot [{cmds}]                       -- Booting linux kernel

help [{cmds}]                       -- Help about help?

FriendlyARM>

FriendlyARM>

S3C2440驱动开发(七)相关推荐

  1. S3C2440驱动开发(四)

    裸机程序开发之蜂鸣器程序 程序实现了控制蜂鸣器输入pwm频率和开关功能.输入数字1开启蜂鸣器,输入数字0关闭蜂鸣器,输入字符+增加蜂鸣器输入pwm频率,输入字符-减少蜂鸣器输入pwm频率.代码如下: ...

  2. S3C2440驱动开发(二)

    裸机程序开发之LED程序 以下代码段实现了一个简单的LED显示程序,程序比较简单,共53行. 1       #include "def.h" 2       #include & ...

  3. windows xp 驱动开发(七)WDK源码 UsbSamp例子的编译及使用

    转载请标明是引用于 http://blog.csdn.net/chenyujing1234 参考文章: http://msdn.microsoft.com/zh-cn/library/windows/ ...

  4. Windows驱动开发学习笔记(七)—— 多核同步内核重载

    Windows驱动开发学习笔记(七)-- 多核同步 基础知识 并发与同步 分析 InterlockedIncrement 原子操作相关API 内核文件 多核同步 临界区 示例一:错误的临界区 示例二: ...

  5. Linux USB 驱动开发实例(七)—— 基于USB 总线的无线网卡浅析

    回顾一下USB的相关知识 USB(Universal Serial Bus)总线又叫通用串行外部总线, 它是20世纪90年代发展起来的.USB接口现在得到了广泛的应用和普及,现在的PC机中都带有大量的 ...

  6. linux 内核驱动开发

    一.为什么要学习内核? 有些人要学习内核,而有些人则可以不学习它.你如果以后要从事系统研发或驱动开发的话,就要学习内核. 刚刚接触内核,主要学习内核的接口函数.不要深入的去读内核,因为你读也读不懂,内 ...

  7. MF Porting之USB驱动开发

    花费了近三个礼拜的时间,终于完成了TI开发板的USB驱动开发,现在回头想一想,其实也没有什么,具体硬件方面的通信由DM355实现了,软件层面的数据交互由MF Porting实现了,所做的也就是熟悉了解 ...

  8. Exynos4412 IIC总线驱动开发(一)—— IIC 基础概念及驱动架构分析

    关于Exynos4412 IIC 裸机开发请看 :Exynos4412 裸机开发 -- IIC总线 ,下面回顾下 IIC 基础概念 一.IIC 基础概念 IIC(Inter-Integrated Ci ...

  9. Linux设备驱动开发详解 第3版 (即 Linux设备驱动开发详解 基于最新的Linux 4 0内核 )前言

    Linux从未停歇脚步.Linus Torvalds,世界上最伟大的程序员之一,Linux内核的创始人,Git的缔造者,仍然在没日没夜的合并补丁,升级内核.做技术,从来没有终南捷径,拼的就是坐冷板凳的 ...

最新文章

  1. java 环境配置 mac_Java:配置环境(Mac)——JDK
  2. Angular 如何自定义 pipe 管道以及参数传递问题
  3. java学习(43):值参数传递
  4. python包里面的dll是什么_使用R的程序包提示我们无法使用怎么回事?因为计算机丢失jvm.dll...
  5. 推荐几个好评率超高的公众号,有远见的程序员都关注了!
  6. Java:集合系列目录(Category)
  7. 792. 高精度减法
  8. vscode中vue-cli项目es-lint的配置
  9. openstack 报错
  10. 对2016年android就业的一些看法
  11. Python多进程实现原理
  12. 计算机专业英语词汇缩写,计算机专业英语词汇中英文对照其他缩写,外语网
  13. 使用深度森林(Deep Forest)进行分类-Python
  14. 利用mongodb实现分布式WEB图片存储
  15. 成都VS上海,先锋设计机构与未来建筑的“双城battle”
  16. 网站实现记住我(自动登录)的方法总结
  17. String类练习:我国的居民身份证号码,由由十七位数字本体码和一位数字校验码组成。
  18. Web3对于我们普通人意味着什么?
  19. Python作业题整理
  20. GILT市场方兴未艾

热门文章

  1. 2021年熔化焊接与热切割作业考试题库及熔化焊接与热切割模拟考试系统
  2. Alex.Koo摄影砖家简介
  3. 2023/4/15 C语言学习(补)
  4. (SQL版)天堂二私服架設
  5. 隆重给大家拜早年了,并顺道推荐几部影片
  6. CSS中的canvas元素
  7. hao123网址之家--智能计算器 html源代码
  8. 广东开放大学形考任务安全与生活(专,2022春)第三次形成性考核(20分)答案
  9. 5G/4G智慧灯杆边缘网关
  10. 学校计算机室的作用,学校计算机管理人员职责