一.Bootloader
是 ARM体系的开机程序,用汇编言语编写,完结体系的初始化操作.是体系上电复位后,操作体系或用户使用程序运转前,首要有必要运转的一段程序.
效果:1,初始化硬件; 2,树立内存空间的映射图(有的CPU没有内存映射功用如S3C44B0).
二. 发动流程
2种发动方法:
- 直接从Flash 发动
- 将紧缩的内存映像文件从Flash中仿制,解压到RAM,再从RAM发动
(节约Flash资源,进步速度)
发动流程图:
1. 发动代码的第一步是设置中止和反常向量
2. 完结体系发动一切必要的最小装备.
某些处理器芯片包含一个或几个大局寄存器,这些寄存器有必要在体系发动的开端进行装备.
3. 设置看门狗,支持设置的部分外围电路假如有必要在体系发动时初始化,就能够放在这一步.
4. 装备体系所运用的寄存器,包含Flash,SRAM,DRAM等,并为他们分配地址空间.假如体系运用了DRAM或其他外设,就需求设置相关的寄存器,以确认其改写频率,数据总线宽度等信息,初始化存储器体系
有些芯片可经过寄存器编程初始化存储器体系,而关于较杂乱体系一般集成有 MMU 来办理内存空间。
5. 为处理器的每个作业形式设置栈指针. ARM 处理器有多种作业形式,每种作业形式都需求设置独自的栈空间。 6. 变量初始化.
这儿的变量指的是在软件中界说的现已赋好初值的大局变量,发动进程中需求将这部分变量从只读区域,也便是 Flash 复制到读写区域中,由于这部分变量的值在软件运转时有或许从头赋值。还有一种变量不需求处理,便是现已赋好初值的静态大局变量,这部分变量在软件运转进程中不会改动,因而能够直接固化在只读的 Flash 或 EEPROM 中。 7. 数据区预备
关于软件中一切未赋初值的大局变量,发动进程中需求将这部分变量地点区域悉数清零。 8. 调用高档言语函数.比方 main 函数等。 三.程序剖析
下面依据实践经过测验的代码具体叙述体系的发动进程。 .text/* 将此操作符开端的代码编译到代码段或代码段子段中 */
/* 集成开发环境( IDE )能够经过链接脚本文件将下面的句子定位在零开端地址,体系上电后 CPU 从此处开端履行 */ ENTRY:/*用于指定汇编程序的进口点*/ b ResetHandler/* 跳至 ResetHandler ,此句被定位在零开端地址 */ /* 除用户形式外的其他 6 种形式称为特权形式。特权操作形式首要处理反常和监控调用(有时称为软件中止),它们能够自在的拜访体系资源和改动形式。特权形式中除体系形式以外的 5 种形式又称为反常形式,下面的代码用于呈现反常时 CPU 就会依据以下的句子主动跳转到对应的反常处理程序处 */ b HandlerUndef /* handlerUndef */ b HandlerSWI /* SWI interrupt handler */ b HandlerPabort /* handlerPAbort */ b HandlerDabort /* handlerDAbort */ b . /* handlerReserved */ b HandlerIRQ b HandlerFIQ … … ResetHandler:/* 上电后跳转到此处开端履行 */ LDR R0, =WTCON/* 制止看门狗 */ LDR R1, =0x0 STRR1, [R0] LDRR0, =INTMSK /* 屏蔽一切中止请求 */ LDR R1, =0x07FFFFFF
STRR1, [R0] /* 设置时钟操控寄存器 */ ldrr0,=LOCKTIME ldrr1,=0xfff strr1,[r0] .if PLLONSTART ldrr0,=PLLCON/* 设置 PLL */ ldrr1,=((M_DIV<<12)+(P_DIV<<4)+S_DIV)/*Fin=8MHz,Fout=64MHz*/ strr1,[r0] .endif ldr r0,=CLKCON ldr r1,=0x7ff8 /* 一切单元时钟答应 */ str r1,[r0] /* 为 BDMA 设置复位值 */ ldr r0,=BDIDES0 ldr r1,=0x40000000 /* BDIDESn 复位值应为 0x40000000 */ str r1,[r0] ldr r0,=BDIDES1 ldr r1,=0x40000000 /* BDIDESn 复位值应为 0x40000000 */ str r1,[r0] /* 设置存储器操控寄存器,存储器的装备数据都存储在 SMRDATA 为开端地址的数据表中,下面的代码能够一次将预先装备好的初始化数据存入与存储器操控器相关的 13 个寄存器,这些寄存器则是以 0x01c80000 为开端地址的 13 个接连的 32 位寄存器 */ ldr r0,=SMRDATA ldmia r0,{r1-r13} ldr r0,=0x01c80000 /* BWSCON 存储操控寄存器地址 */ stmia r0,{r1-r13} /* 初始化仓库 */ /* CPU 复位后是处于办理形式下的,所以首要要初始化办理形式下的仓库寄存器 */ ldr sp, =SVCStack /* 由于处理器的每种运转形式都要有自己独立的物理仓库寄存器 R13 ,在用户使用程序的初始化部分,一般都要初始化每种形式下的 R13 ,使其指向该运转形式的栈空间,这样,当程序的运转进入反常形式时,能够将需求维护的寄存器放入 R13 所指向的仓库,而当程序从反常形式回来时,则从对应的仓库中康复,选用这种方法能够确保反常产生后程序的正常履行 */ bl InitStacks/* 跳转至其它仓库初始化程序并回来 */ /* 设置 IRQ 中止处理 */ /*44B0 有两种中止形式:一种是没有中止向量表;一种是运用了中止向量表,运用中止向量表只能是 IRQ 方法。当运用中止向量表的时分,中止产生时由 S3C44B0 的中止操控器依据中止向量表,运用硬件方法主动跳转到相应的中止处理服务程序地点的方位;不运用中止向量表时按下面的代码,运用软件方法跳转而进行中止处理,由于 S3C44B0 有 30 个中止源,所以需求程序判别以确认调用那个中止服务程序 */ ldr r0,=HandleIRQ/* 假如在 0x18 和 0x1c 地址处无 “subs pc,lr,#4”*/ ldr r1,=IsrIRQ/* 为了中止正常回来这些句子是有必要的 */ str r1,[r0] /* 复制读写区域数据 / 数据区预备,将体系需求读写的数据和变量从 ROM 复制到 RAM 里。 Image_RO_Limit 、 Image_RW_Base 、 Image_ZI_Base 等这些符号还会在别的的链接脚本文件中呈现,这些符号是用来定位程序各个段的参阅信息。集成开发环境在编译链接的时分会依据咱们编写的程序,把它们转换成用来对各个段定位的地址信息 */ LDR r0, =Image_RO_Limit/* 取只读数据区域地址指针 */ LDR r1, =Image_RW_Base/* 预备履行复制操作 */ LDR r3, =Image_ZI_Base CMP r0, r1 /* 查看是否相同 */ BEQ F1 /* 相同则越过复制操作 */ F0: CMP r1, r3/* 履行复制操作 */ LDRCC r2, [r0], #4 STRCC r2, [r1], #4 BCC F0 F1: LDR r1, =Image_ZI_Base/* 零数据预备区开端地址 */ MOV r2, #0 F2: CMP r3, r1 /* 履行数据区清零 */ STRCC r2, [r3], #4 BCC F2
MRSr0, CPSR B%&&&&&%r0, r0, #NOINT /* 中止请求答应 */ MSRCPSR_cxsf, r0 /* 跳转到 C 进口程序 */ BLMain B .
四 . 总结: 发动进程中的初始化程序便是初始化 CPU 内部各个要害的寄存器、装备外围硬件电路相关寄存器、树立中止向量表等,然后跳转到一般由高档言语编写的主函数的使用程序代码去履行,这样就能够运用高档言语来编写完结体系设计所要求的各种功用。初始化的进程对大多数初学者来说,比较难了解的是中止的处理和一些罕见的操作符号,这些符号多是一些宏界说或体系用于在内存空间中对各个段的定位标识符号。把握了S3C44B0的发动代码之后,对体系功用程序设计会起到很大的协助,是进行下一步程序设计的根底。
|