ARM处理器如何编写Bootloader

前面给大家分享过bootloader从应用角度执行的相关文章,今天从底层原理来给大家描述arm处理器如何编写bootloader,以及底层流程。
关于bootloader
bootloader顾名思义就是引导加载程序,是在操作系统或应用程序运行之前的一段程序,是在系统上电后执行的一段程序代码。
bootloader是严重地依赖于硬件而实现的,特别是在嵌入式平台。因此,在嵌入式平台里建立一个通用的bootloader几乎是不可能的。尽管如此,我们仍然可以对bootloader归纳出一些通用的概念来,以指导用户特定的bootloader设计与实现。
---来源百度百科
bootloader在手机、电脑、众多嵌入式系统中都存在,它的作用有很多,比如:初始化底层应用驱动、加载应用程序、更新应用程序等。
不同的设备,bootloader可能差异很大,通常来说bootloader比较依赖底层硬件和实际项目需求。
如何编写bootloader
bootloader是一段引导加载程序代码,它更新用户的应用程序代码,可以使用很多硬件下载通道(例如usb、网络端口)获得新代码。
在执行引导rom之后,将执行bootloader程序,并在需要时进行更新,然后执行最终用户应用程序。
引导加载程序和用户应用程序应作为两个独立的project或object进行编写和编译,从而产生两个独立且可执行的(bin/hex)文件。
引导加载程序的主要任务是在必要时对用户应用程序进行重新编程/替换,并跳转至用户应用程序以执行该程序,应用程序不一定需要知道引导加载程序的存在。
引导加载程序通常位于芯片闪存基址,下面通过一张图来描述内存和flash代码映射关系:
有很多方法可以引导bootloader进入编程模式,以将用户应用程序重新编程到flash中,或者直接跳转到现有的用户应用程序来执行。最简单的方法是检查gpio引脚以确定是否应进入编程模式。
大多数芯片供应商为用户提供了一种方便的方式,例如 isp 和 iap 接口,bootloader将使用它们来更新闪存内容。
当flash内容已更新或已经是最新时,引导加载程序将跳转到用户应用程序。在执行用户应用程序之前,这需要许多步骤:
1.确保cpu处于特权模式。
2.禁用nvic中所有启用的中断。
3.禁用所有可能产生中断请求的使能外设,并清除这些外设中的所有未使用中断标志。
4.清除nvic中所有未使用的中断请求。
5.禁用systick并清除其异常挂起位。
6.如果引导加载程序使用了单个故障处理程序,请禁用它们。
7.如果发现内核当前与psp一起运行,则激活msp(由于编译器可能仍在使用堆栈,因此在此之前需要将psp复制到msp)。
8.将用户应用程序的向量表地址加载到scb-> vtor寄存器中。确保地址符合对齐要求。
9.最后一部分是将msp设置为用户应用程序向量表中找到的值,然后将用户应用程序的重置向量值加载到pc中,也就是跳转功能。
比如通过调用下面的示例bootjump()这样的函数来完成此操作:
static void bootjump(uint32_t *address){ //1.确保cpu处于特权模式。  if( control_npriv_msk & __get_control()) { /* not in privileged mode */    enableprivilegedmode() ; } //2.禁用nvic中所有启用的中断。 disable_all_peripherals(); //3.禁用所有可能产生中断请求的使能外设,并清除这些外设中的所有未使用中断标志。 nvic->icer[ 0 ] = 0xffffffff; nvic->icer[ 1 ] = 0xffffffff; nvic->icer[ 2 ] = 0xffffffff; nvic->icer[ 3 ] = 0xffffffff; nvic->icer[ 4 ] = 0xffffffff; nvic->icer[ 5 ] = 0xffffffff; nvic->icer[ 6 ] = 0xffffffff; nvic->icer[ 7 ] = 0xffffffff; //4.清除nvic中所有未使用的中断请求。 nvic->icpr[ 0 ] = 0xffffffff; nvic->icpr[ 1 ] = 0xffffffff; nvic->icpr[ 2 ] = 0xffffffff; nvic->icpr[ 3 ] = 0xffffffff; nvic->icpr[ 4 ] = 0xffffffff; nvic->icpr[ 5 ] = 0xffffffff; nvic->icpr[ 6 ] = 0xffffffff; nvic->icpr[ 7 ] = 0xffffffff; //5.禁用systick并清除其异常挂起位。 systick->ctrl = 0; scb->icsr |= scb_icsr_pendstclr_msk; //6.如果引导加载程序使用了单个故障处理程序,请禁用它们。 scb->shcsr &= ~( scb_shcsr_usgfaultena_msk | scb_shcsr_busfaultena_msk | scb_shcsr_memfaultena_msk ) ; //7.如果发现内核当前与psp一起运行,则激活msp  if( control_spsel_msk & __get_control()) { /* msp is not active */    __set_msp( __get_psp()) ;    __set_control( __get_control() & ~control_spsel_msk); } //8.将用户应用程序的向量表地址加载到scb-> vtor寄存器中。 scb->vtor = ( uint32_t )address ; //9.跳转  bootjumpasm( address[ 0 ], address[ 1 ]);}  再次说明bootloader与底层硬件和实际需求有关,以上代码仅供参考,主要是提供思路,方便大家理解。
如果还不能理解,建议结合bootloader实际项目进行理解,比如之前给大家分享过的:stm32官方iap例程详细说明  


详解智能座舱关键通信技术
什么是解常温常压超导体?室温超导“热潮”已掀开
Kubernetes Operator最佳实践介绍
谷歌无人驾驶成立新公司Waymo,这场与百度的竞争能赢吗?
先导集团半导体和燃料电池装备制造基地在无锡高新区启动建设
ARM处理器如何编写Bootloader
硅频率控制器(SFC)技术
动力电池充电机多样化导热散热方案简介
ERG推出可兼容替代CCFL逆变器的LED驱动器
无纺布表面瑕疵在线检测设备的原理、性能及特点
应用不敢删,iPhone空间不足怎么办?升级苹果iOS11这些问题统统帮你解决
看看最牛显卡公司怎么做PCB板设计的
17课:单片机定时器/计数器的方式控制字
在全球制造业四级梯队格局中,中国处于第三梯队
探讨玻璃绝缘子生产车间数字孪生建模和信息处理的基础研究
从物联网架构来看区块链与物联网结合的三个层面
国产工业机器人与“四大家族”的差距到底在哪?
c2c交易平台系统开发,深圳数字资产c2c交易平台搭建商
红米Note7S真机照公布 后置双摄呈纵向排布支持背部指纹识别
FPGA在边缘设备上的发展将依靠物联网的助力