bootloader程序设计
- 格式:wps
- 大小:2.47 MB
- 文档页数:13
嵌入式系统中Bootloader 的设计与实现马学文1,朱名日1,2,程小辉1 (1. 桂林工学院电子与计算机系,桂林541004;2.中南大学信息物理工程学院,长沙410083)—97—作者所承研的项目中硬件平台是基于ARM7TDMIRISC 内核的三星公司S3C4510B 微处理器,采用的嵌入式Linux 系统为uCLinux。
系统有64MB SDRAM, 其地址从0x 0800.0000 ~0x0bff.ffff, 还有32MB Flash, 其地址从0x0c00.0000~0x0dff.ffff。
32MB Flash 具体规划如下:从0x0c00.0000 开始的第1 个1MB 放Bootloader,从0x0c10.0000开始的2MB放Linux kernel, 从0x0c30.0000开始的余下部分都给rootdisk。
64MB SDRAM 启动后的具体程序分布示意图如图2 所示。
图2 64MB SDRAM 的程序分布示意图Bootloader 一般有几个文件组成。
先是START.s,也是唯一的一个汇编程序,其余的都是C 语言写成的,START.s主要用来初始化堆栈:_start:ldr r1,=StackInit /* r1 是参数字符串的地址*/ldr sp,[r1]int main().equ StackInitValue,_end_data+0x1000/* 在连结脚本中指定4K __end_data*/StackInit:.long StackInitValue.global JumpToKernelJumpToKernel: /*拷贝内核的代码*/mov pc, r0 /*获得Kernel 地址*/.global JumpToKernel0x /*用来扩展内核*/JumpToKernel0x: /*拷贝获得的扩展内核*/mov r8, r0mov r0, r1mov r1, r2mov r2, r3mov r3, r4mov pc, r8.section“.data.boot”.section“.bss.boot”其中main 函数的C 语言实现过程如下:int main(){U32 *pSource, *pDestin, count;U8 countDown, bootOption;U32 delayCount;U32 fileSize, i;char c;char *pCmdLine;char *pMem;init(); /*初始化Flash 控制器和CPU 时钟*/EUARTinit(); /*串口初始化*/EUARTputString("\n\n Linux Bootloader\n"); /*打印信息*/ EUARTputString((U8 *)cmdLine); /*command_line 支持, 用于定制内核*/EUARTputString("\n\n");用command_line 可以给内核传一些参数,自己定制内核的行为。
stm32f103vet bootloader例程摘要:1.概述:介绍STM32F103VET单片机及其bootloader2.STM32F103VET单片机简介a.性能特点b.应用领域3.Bootloader概述a.作用b.工作原理4.Bootloader例程介绍a.程序结构b.重要函数及功能5.Bootloader例程实现a.硬件连接b.程序编写c.编译下载及验证6.总结与展望正文:1.概述:介绍STM32F103VET单片机及其bootloaderSTM32F103VET是一款基于ARM Cortex-M3内核的微控制器,具有高性能、低功耗、多功能的特点。
本文将介绍如何使用STM32F103VET单片机实现bootloader功能,以及相关的例程。
2.STM32F103VET单片机简介STM32F103VET是基于ARM Cortex-M3内核的32位单片机,最高工作频率可达72MHz。
它具有丰富的外设接口,如I2C、SPI、UART等,适用于各种嵌入式应用领域。
3.Bootloader概述Bootloader(引导程序)是嵌入式系统中的一个重要组成部分,主要负责初始化系统硬件、加载和执行应用程序。
通常,bootloader存储在系统闪存中,可在系统上电或复位时自动执行。
4.Bootloader例程介绍本文以一款基于STM32F103VET单片机的bootloader例程为例,介绍其程序结构及重要函数功能。
该例程主要包括以下部分:a.程序结构- 初始化部分:配置系统时钟、GPIO等外设- 下载模式部分:与上位机通信,接收并执行固件更新- 运行模式部分:执行用户应用程序b.重要函数及功能- 系统时钟配置:根据实际需求配置系统时钟,以满足不同工作场景的性能要求- 与上位机通信:通过UART、I2C等接口与上位机通信,接收固件更新命令及数据- 固件更新:将接收到的固件数据写入系统闪存,实现固件更新- 用户应用程序:执行用户编写的应用程序,实现具体功能5.Bootloader例程实现a.硬件连接根据实际硬件设计,连接STM32F103VET单片机相关引脚,如时钟、复位、通信接口等。
毕设级项目:基于单片机从零写bootloader摘要:1.引言2.单片机bootloader 简介3.单片机bootloader 设计与实现a.目标平台与工具选择b.代码烧写流程c.代码结构与组织d.重要函数与实现4.遇到的问题及解决方案a.硬件问题b.软件问题5.总结与展望正文:基于单片机的毕设项目,从零开始编写bootloader,对于学习和实践嵌入式系统的设计与开发具有很大的价值。
本文将详细介绍这一过程,包括bootloader 的设计思路、实现步骤以及遇到的问题和解决方案。
首先,我们需要了解什么是bootloader。
bootloader(引导加载程序)是嵌入式系统中的一个关键部分,它负责在系统加电后初始化硬件并执行系统启动代码。
通常情况下,bootloader 会被固化在单片机的非易失性存储器中,以保证系统能够从断电状态恢复。
接下来,我们将详细讨论单片机bootloader 的设计与实现。
首先,我们需要选择一个合适的单片机平台和相应的开发工具。
这里我们以STC89C52 单片机为例,采用Keil uVision5 作为开发环境。
在设计和实现bootloader 时,我们需要关注代码烧写流程。
一般来说,bootloader 的烧写过程可以分为以下几个步骤:1.下载程序到单片机:通过ISP(In-System Programming)或JTAG 接口将程序下载到单片机内部的非易失性存储器中。
2.跳转到bootloader 入口:单片机加电后,会从非易失性存储器中执行bootloader 的入口地址。
3.初始化硬件:bootloader 会对单片机内部和外部的硬件进行初始化,例如初始化时钟、复位和串口等。
4.烧写应用程序:bootloader 会将从串口接收到的应用程序代码烧写至单片机的程序存储器中。
5.跳转到应用程序入口:完成代码烧写后,bootloader 会跳转到应用程序的入口地址,开始执行。
基于Xilinx FPGA特点的嵌入式Bootloader设计与实现Bootloader程序是指嵌入式系统在正常工作之前,配置系统运行环境,引导操作系统的一小段程序。
通过这段程序,我们可以初始化硬件设备、建立内存空间映射等,从而将系统的软硬件环境带到一个合适的环境,为系统的正常运行做好准备。
对于不使用操作系统的嵌入式系统而言,应用程序的运行同样也需要依赖一个准备好的软、硬件环境,因此从这个意义上来讲,BootLoader程序对于嵌入式系统是必需的。
BootLoader程序与硬件系统密切相关,依赖于具体的嵌入式板级硬件设备的配置。
比如板卡的硬件地址配置、微处理器的类型和其他外设的类型等。
也就是说,即使是基于相同嵌入式微处理器构建的不同嵌入式目标板,BootLoader程序也不是完全通用的,仍需要修改其源程序。
与ARM等嵌入式系统的启动过程所不同的是,FPGA必须先将内部硬件逻辑配置完成之后,才能运行程序代码。
虽然可以直接将程序代码例化到片内BRAM中,但是由于FPGA 内部的BRAM资源有限,而且硬件逻辑配置时就会占用其中的资源,因此遇到大型系统设计时(例如带有TCP/IP协议的大型程序),片内BRAM资源不够,就必须使用外部的RAM来储存程序代码和堆栈,这就需要设计Bootloader程序来完成用户程序的引导。
本文结合Xilinx FPGA的特点详细给出了Bootloader程序设计和实现过程。
本设计所实现的Bootloader程序是在FPGA硬件配置完毕之后在MicroBlaze软核处理器上运行的一段启动代码,用来把Flash中的用户程序传输至外部RAM,并引导系统从用户程序中开始运行。
一、系统硬件平台的实现本设计的实现是以Xilinx公司的Spartan-3E FPGA、STMicroelectronics公司的SPI串行Flash(M25P16)、Micron Technology公司的DDR SDRAM (MT46V32M16)为主要器件构建硬件平台。
stc单片机bootloader程序编写随着科技的不断发展,单片机在各个领域的应用越来越广泛。
而在单片机的开发过程中,Bootloader程序的编写是非常重要的一环。
本文将介绍STC单片机Bootloader程序的编写方法。
首先,我们需要了解什么是Bootloader程序。
Bootloader程序是位于单片机内部的一段特殊代码,它的作用是在单片机上电或复位时,负责初始化硬件设备,并加载用户程序到内存中运行。
因此,Bootloader程序的编写质量直接影响到单片机的启动速度和稳定性。
在STC单片机中,编写Bootloader程序需要以下几个步骤:1. 确定Bootloader程序的存储空间:在STC单片机中,Bootloader 程序通常存储在内部Flash中。
因此,我们需要确定Bootloader程序的存储地址和大小。
一般情况下,Bootloader程序的大小应该尽量小,以便为用户程序留出更多的空间。
2. 编写Bootloader程序的初始化代码:在Bootloader程序中,我们需要编写初始化代码,用于初始化单片机的硬件设备,如时钟、GPIO 等。
这些初始化代码的编写需要根据具体的单片机型号和硬件配置来进行。
3. 实现用户程序的加载功能:Bootloader程序的核心功能是加载用户程序到内存中运行。
在STC单片机中,我们可以通过串口通信或其他外部设备来实现用户程序的加载。
例如,我们可以通过串口接收用户程序的数据,并将其写入到内存中。
4. 实现用户程序的跳转功能:当用户程序加载完成后,Bootloader 程序需要实现跳转到用户程序的功能。
在STC单片机中,我们可以通过设置程序计数器(PC)的值来实现跳转。
具体的跳转地址需要根据用户程序的存储地址来确定。
5. 添加Bootloader程序的升级功能:为了方便后续的固件升级,我们可以在Bootloader程序中添加升级功能。
通过升级功能,我们可以通过串口或其他外部设备将新的Bootloader程序写入到单片机中,从而实现Bootloader程序的更新。
详解汽车Bootloader设计BootLoader(下文简称Boot)也称为引导程序,其主要用于软件更新。
这就带来一个问题,ECU的软件更新方式有很多,比如通过JTAG 调试更新软件,为什么要Boot呢?由于ECU软件中难免会有BUG存在,以及要满足整车OTA需求,必须可以在不开盖的情况下更新软件。
而ECU控制器对外的接口通常只有总线、电源和控制IO等。
出于最大化复用接口(减少线束的重量和成本)考虑,通常采用基于UDS的Boot,而最常用的总线为CAN。
为什么不用JTAG口呢?主要是ECU 装车后,直接通过烧录器或者仿真器更新软件的很不方便,难以实现远程更新,另外由于JTAG口的权限很高,可以任意修改内部程序,安全风险很大。
01BootLoader的设计需求Boot除了正常满足更新软件需求外,还需满足以下需求。
1、安全需求Boot和APP应该放在不同的内存区域,防止相互干扰。
Boot中不应集成Flash Driver,避免程序在正常运行时非法修改FLash,导致软件异常,通常在刷写App或者标定数据时,先将Flash Driver下载至芯片的RAM中。
另外,在Boot执行App或者标定数据更新时,应该具有多重安全检查机制,确保刷入正确的软件。
首先在执行刷写流程之前,上位机对需要更新的软件包进行检查,通常包括两项,其一是在生成软件包时,开发人员会在特定位置增加一个与上位机约定的特定的ID,当上位机加载软件包时,会去检查软件包中存储的ID是否与上位机中相同,如果不同,则终止刷写,这样可以防止刷入其他ECU的软件包。
其二是在生成软件包时,会对特定地址区域进CRC计算,通常采用CRC32,并将该CRC值存储在特定的地址,通常是程序的末尾,在上位机加载软件包时,按照相同的CRC算法进行计算,并与软件包中存入的进行比较,如果相同则进行下面的流程。
这也是俗称的完整性检查。
在以上确认软件包本身没有问题后,开始准备将软件刷入到车内的ECU中,在此之前需要对当前车辆的刷写条件进行检查,其中主要包括当前是否有车速,档位是否在P档,蓄电池电压是否过低,对于新能源车而言,还需检查高压继电器是否闭合等。
讲解BOOTLOADER(启动代码)的运行机制,代码功能与实现方法。
1.为什么要编写启动代码启动代码是系统上电或复位以后运行的第一段代码,他的作用是在用户程序运行之前对系统硬件及软件环境进行必要的初始化并在最后使程序跳到用户程序.在此之前系统的所有硬件都是不好用的,初始化代码直接对ARM处理器内核及硬件控制器进行编程,所执行的操作与具体的目标系统紧密相关。
2.两种启动方式以及其中的区别根据代码存放位置,以及地址启动位置的区别,ARM支持两种方式的启动:Nor FLASH和 Nand FLASH2.1Nor FLASH启动代码运行方式从Nor FLASH启动时,与nGCS0相连的Nor FLASH就被映射到了nGCS0片选的空间,其地址被映射为0x00000000;因为Nor FLASH支持系统运行,所以不必考虑程序的搬移,只需保证系统上电后或者复位时代码从0开始即可。
2.2Nand FLASH启动代码运行方式从Nand FLASH启动时,芯片内部自带一块容量为 4K的BootSRAM会被映射到nGCS0片选的空间,起始地址被映射为0x00000000,因此,编写的启动代码要保证在0开始的地址处。
系统上电后,BootSRAM没有任何代码,ARM芯片通过硬件机制将Nand FLASH前4K的内容拷贝到其中,然后在BootSRAM中运行这4K的代码(0地址处),此种情况下要保证启动代码放在Nand FLASH的0地址处,启动代码要小于4K(只要RAM 初始化,搬移程序小于4K即可)。
所有程序编译链接后代码量小于4K时,程序不用考虑从 Nand FLASH搬移到SDRAM的问题,因为所有程序在启动时已全部在BootSRAM中,运行即可。
所有程序编译链接后代码量大于4K时,启动代码不只要有初始化内容,还要有一段搬移代码,将全部程序从Nand FLASH搬移到SDRAM,也就是系统启动时需要两次搬运,第一次将前4K搬移到BootSRAM,第二次将所有代码搬移到SDRAM中,其中第一次无需人工干预,硬件机制自动实现,第二次需要程序员编写代码实现。
3.启动代码的功能与实现启动代码的主要功能 1.建立异常向量表 2.初始化系统堆栈 3.初始化硬件4.应用程序执行环境初始化5.跳转至主函数3.1异常向量表的建立异常向量表位于启动代码的起始部分,是用户程序与启动代码之间以及启动代码的各个部分之间联系的纽带。
它由一个个跳转函数组成,当系统发生异常时,ARM处理器会通过硬件机制强行将PC指针指向异常向量表中对应的异常跳转函数存储地址,之后跳到相应的异常中断服务程序中执行。
其中关键字ENTRY是指定编译器保留这段代码,链接的时候要确保这段代码被链接在整个程序的入口地址,当ARM启动时,PC指针会自动寻找该关键字从该关键字处执行。
3.1.1正常上电或者复位的运行ARM要求异常向量表必须存储在0地址,当开发板上电或者复位时,PC 会指向0地指出,进而跳到复位异常处理函数ResetHandler ,这个函数负责完成系统的初始化,即初始化堆栈、初始化硬件、初始化应用程序执行环境、跳至主函数。
3.1.2未定义异常处理函数当ARM处理器不认识当前指令时,就会将该指令发送至协处理器,如果协处理器也不认识就会产生未定义异常。
未定义异常后,CPU会将函数的返回地址及此时的 CPSR(current program status register) 保存到未定义异常专用的R14和SPSR中,然后在修改CPSR 使系统进入未定义异常模式运行,PC被强制指向0x00000004,然后程序就跳至未定义异常的处理函数,上述过程由硬件实现不需人工干预。
3.1.3 软中断异常处理函数软件中断异常是由用户定义的中断指令,用于用户模式下的程序调用特权模式下的操作指令,例如修改CPSR值,从而进入其他特权模式等。
处理器相应SWI(Software Interrupt)异常的流程:1.保存CPSRR142.修改CPSR进入管理模式,进制IRQ (Interrupt Request)中断3.强制PC转向0x00000008,并跳入软中断异常处理函数。
SWI中断举例3.1.4取指终止异常处理函数当处理器预取的指令地址不存在或者地址不允许当前指令访问,产生该异常。
处理的方式:1. 异常地址之前的指令正常执行,到该指令发生异常。
2. 处理返回地址(PC-4)以及保存CPSR3.切换模式到取指异常模式4.强制PC转向0x0000000c,并跳入处理函数,通常只要不涉及MMU(Memory Management Unit),一般处理函数为死循环。
3.1.5数据中止异常处理函数产生条件:数据访问指令的目标地址不存在或者该地址不允许此指令访问。
处理方式同取指终止异常3.1.6 IRQ中断异常处理函数ARM内核为了处理外部设备向CPU发出的服务请求,尤其是一些紧急事件而特别作出的设计,来中断时进中断处理中断函数,结束后返回继续执行主程序。
条件:外部中断请求引脚拉低,IRQ中断使能(I位清零)处理方式1. 保存CPSR和返回地址到专用的R14以及SPSR2.修改CPSR禁止新的IRQ产生,切换模式到IRQ模式3.强制PC转向0x00000018,并跳入处理函数注意事项:编写IRQ中断处理程序是,要注意中断的重入性,即在有些IRQ中断处理函数中,允许新的IRQ产生,但这种情况会刷新掉一些以前的寄存器值,例如LR,所以在允许新中断产生之前要把一些寄存器保护一下,避免产生混乱。
IRQ中断举例:3.1.7FIQ异常中断处理函数系统对实时性比较敏感,如数据大页面的传输或通道处理时就需要非常短的中断响应时间,而FIQ就是响应这种类型的中断。
硬件结构对FIQ的支持:FIQ具有8个专用寄存器,系统从其他模式切换到FIQ模式不用寄存器进栈,节约了时间。
FIQ异常入口位于异常向量表最后。
处理方式:保存CPSR和返回地址到专用的R14以及SPSR修改CPSR禁止新的IRQ、FIQ产生,切换模式到FIQ模式强制PC转向0x0000001C,并跳入处理函数3.2系统堆栈的初始化系统堆栈的初始化主要是给处理器的各个模式分配堆栈空间。
堆栈是为中断或程序跳转服务的,当发生中断或程序跳转的时候,需要将当前处理器的状态以及一些参数保留在堆栈中,当处理完了之后再将堆栈内的数据恢复,以保证原来程序的正确运行。
系统初始化的准备工作:堆栈初始化的顺序:堆栈初始化的顺序决定系统最后运行在哪种处理器模式,最后初始化哪种模式的堆栈,系统就运行在哪种模式。
一般系统最后要运行在特权模式,因为如果运行在用户模式无法操作CPSR,将对接下来的程序产生影响。
最后初始化系统模式的堆栈。
注意:启动代码中如果是通过BL指令跳转到堆栈初始化函数的话,需要注意一点:堆栈初始化后如果系统运行在非管理模式,则堆栈初始化函数最后不应该通过MOV PC,LR返回。
因为系统上电或复位后系统运行在管理模式,而各种特权处理器模式下都有自己对应的LR,上面的这条指令放入的是最后初始化的模式的LR,而不是管理模式的LR,所以无法实现正确返回,正确的方法是在刚进入对战初始化函数时将LR保存在一个通用寄存器,函数返回时将这个寄存器的值放入PC即可,如果最后初始化的是管理模式则可通过MOV PC,LR返回。
3.3初始化硬件目的:初始化硬件的目的是为主程序的运行创造一个合适的硬件环境,这一部分是和具体的应用系统密切相关的。
初始化的内容:关闭开门狗屏蔽所有中断初始化时钟和PLL初始化存储系统3.3.1关闭开门狗看门狗是为了防止程序跑飞,但是系统上电或者复位以后,默认看门狗是打开的,这样如果不喂狗会给程序带来麻烦,造成复位的循环,因此在初始化程序中必须把它关掉。
代码:3.3.2屏蔽中断中断服务程序一般在用户程序中实现,启动代码中无需处理终端,另外为了避免在启动过程中触发中断,所以一般采用屏蔽中断方法避免麻烦的产生。
代码:3.3.3初始化PLL和时钟时钟是处理器运行的脉搏,在进入主函数之前应该对其进行设置。
PLL,锁相环,起作用是将外部晶振的输入频率倍频到一个较高的频率。
S3C2410有两个锁相环:MPLL和UPLL。
MPLL用于CPU以及其他外设,通过MPLL 产生三个时钟频率:FCLK、HCLK、PCLK。
FCLK就是时钟,HCLK用于驱动AHB总线设备如(SDRAM),PCLK用于驱动APB总线设备(如uart)。
UPLL用于USB模块。
设置PLL以及时钟的代码:3.3.4初始化存储系统S3C2410的存储地址空间为0-0x3FFFFFFF,共1G,这些地址空间被分为8个BANK,每个BANK有128M字节的存储空间。
8个BANK的读写位宽可以通过编程来设定,具体要看挂载的存储器的类型,BANK0可以配置为16位或者32位,其他BANK可以配置8、16、32位。
前6个BANK可以挂载ROM、SRAM等类型存储设备,后两个可以挂载ROM、SRAM、SDRAM等类型存储设备。
BANK0-BANK6起始地址固定,BAN7的起始地址可以调整。
存储系统的初始化代码:○1将存储器配置值得数据表的地址放入寄存器R0;○2将总线数据宽度和等待控制寄存器的地址放入寄存器R1,因为寄存器的地址是在S3C2410的头文件中定义好的,不会改变,所以用LDR指令。
○3到○6给一些列的寄存器赋值,一共13个值。
3.3.5应用程序执行环境的初始化文件类型的转化源文件(.c或.s)经过ARM编译器的编译生成ELF(Executable and Linkable Format)格式的目标文件(后缀名.o),目标文件经过链接器以后生成ELF格式的映像文件(后缀名为.axf),此映像文件还有一些调试信息,经过第三方软件再将其转换为适合ROM运行的.bin文件,烧进FLASH中运行。
可执行文件的分区加载域,映像文件在存储器中存放的地址运行域,映像文件运行时候的地址每个域右1-3个输出段组成,每个输入段由1-3个输入段组成输入段的组成每个输入段包含程序代码、已经初始化的数据、未经初始化的存储区、被初始化为0的存储区。
输入段的属性RO(只读,包含代码和常量)RW(可读写,包含已经初始化的全局变量和静态变量)ZI(未初始化的变量,需初始化为0)链接器把具有相同属性的输入段放在一起组成输出段,因此输出段也分为三种,域根据RO在前,RW在中间,ZI在最后的方式存储,其中RW和RO可以不连续,ZI输出段紧挨RW。
映像文件的映射关系:前4K被复制到SRAM种,SRAM被映射的地址为0x00000000,程序从此处开始运行,由于Nand FLASH不能运行程序,所以前4K代码中必须包含一段代码,将RW和ZI这两部分是必须转移到可写的RAM里去,其中ZI要进行初始化为0的操作。