IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> Tiva C(TM4C)的bootloader和启动过程与stm32对比 -> 正文阅读

[嵌入式]Tiva C(TM4C)的bootloader和启动过程与stm32对比

gossip:

? ? ? ? 最近在咸鱼捡了个123GXL的板子,板子没到就先装好了环境,然后看了看资料,前天板子到了,先点了个灯,然后把板子扔到一边又继续看资料去了emmm...

? ? ? ? 看资料的时候发现有些东西挺有意思的:比如它竟然出厂时在ROM中固化了库函数的二进制代码,用户程序可以直接跳转到ROM中去执行这些函数,那么Flash中就不必再存这些代码从而有更多的空间存其它数据了。

boot loader:

????????这玩意学习stm32时根本没听说过,倒是以前给手机刷机时知道要进这个地方,好像叫做程序引导器。在看Tiva C的资料时总看到这个东西,于是深入研究了一下,竟然发现原来stm32也有这玩意。简单来说,它也是一个程序,用于接收上位机发来的程序数据并把数据烧写到Flash里面,完成用户程序的更新。至于究竟是怎么一回事,还得从ARM核MCU的启动过程说起。

启动过程:

????????按照ARM的规定,系统的0x00处存放程序的栈顶指针,0x04开始就是中断向量表(加4是因为一个地址占32位),且第一个中断向量为reset中断向量。

????????单片机上电后,首先初始化堆栈,然后读取0x00处的栈顶指针,接着将0x04处的reset中断服务函数地址载入PC寄存器,之后跳转执行reset的中断服务函数,并根据该中断服务函数内的指示跳转执行main函数。

stm32的boot loader:

?????????stm32是可以根据两个特定的引脚选择程序启动位置的,三个可以选择的启动区域分别是SRAM,FLASH和System Memory,如下所示:

? ? ? ? ?一般来说,用户程序存放到Flash当中,SRAM并不常用。选择从Flash启动程序就是选择执行用户程序。

????????那么还有一个System Memory又是咋回事呢,其实从这个区域启动就会执行boot loader程序,当我们手头上没有调试器,要从串口给单片机烧写程序的时候,就得切换到这个模式。这时候我们可以用一些工具比如FlyMCU等,就可以将程序通过串口发送到单片机,此时单片机正执行的boot loader程序就会接收串口数据(也就是用户程序)并写到Flash当中,从而完成用户程序的更新。当切换回Flash启动方式后,就会运行新的用户程序了。

存储器重映射:

? ? ? ? stm32的boot loader的作用讲完了,但是还没弄清楚为什么切换引脚可以启动不同的程序,按照arm的规定,程序是从0x0000 0000处开始执行的,可这个位置的值不是固定的吗,不应该只能执行一个程序?这就涉及到地址的重映射了:

? ? ? ? ?如上图所示,stm32的0x0000 0000地址到0x07FF FFFF地址其实就是用来做重映射的,需要注意的是这里的地址是逻辑地址而不是物理地址,是人为规定出来的,因而完全可以再定义这段地址在逻辑上与Flash相连,这种定义,就是重映射。

????????如果这么做,就是说将Flash的地址映射到了系统0x00处那段位置。当程序去读0x00时,实际上读的是Flash的首地址处的值,也就是用户程序的堆栈地址,接下来读0x04处的值,读的其实是0x0800 0004处的值,也就是用户程序的中断向量表的第一个中断向量。这么一来,单片机执行的就是用户程序了。

????????同理,如果将system memory映射到0x00开始的那段位置,那么一开始就能读到System Memory的首地址的值了,这里存放的是boot loader这个程序的堆栈地址值,接着还能读到这个程序的第一个中断向量,从而执行了boot loader程序。

Tiva C的ROM中的Boot loader:

? ? ? ? 按照官方文档所说,Tiva C系列可以有两个boot loader,一个是出厂固化在ROM中的,另外一个是在Flash中的。

? ? ? ? 首先需要知道的是,Tiva C系列的逻辑地址分配与stm32不同,它没有像32一样预留给专门做重映射的空白区域,而是直接把Flash的地址安排在了0x00开始的一段区域,因此单片机一开始从0x00处读到的值就是Flash首地址里面的值。

? ? ? ? 当芯片出厂的时候,ROM中固化了boot loader和库函数代码以及其它一些内容,而Flash是空的,那么就可以通过启动芯片的boot loader程序,然后利用串口或者其它的外设接口给Flash写入程序了。流程是这样的:当单片机启动时,它会去读0x00处的值,然后发现,欸,这个值好像不是一个地址欸,然后又发现0x04处的值好像也不是一个中断函数的函数地址,于是这时候就会把ROM的boot loader程序开始的位置直接重映射到0x00处,然后按照启动流程启动boot loader程序,接下来就可以使用LM Flash Programmer这个应用给芯片写入用户程序了。

? ? ? ? 当下次重启时,系统发现0x00和0x04处的值都好像是一个地址的样子欸,于是就不去启动ROM中的boot loader程序了,而是按照正常流程去读取Flash中的堆栈地址以及中断函数地址,启动用户程序。

? ? ? ? 在我看来,这个ROM的boot loader跟32中的那个比较相似,程序都是固化在了某一个只读存储区域,都只能使用某几个固定的外设接口来更新用户程序(比如串口0)。区别在于,stm32可以通过引脚来选择随时启动这个boot loader,而Tiva C系列的这个boot loader只有在以下情况能启动:

? ? ? ? ?需要注意的是,我看到的芯片手册里面,EN默认是置位的,引脚启动功能也是默认禁用的。因此只有情况3能启动这个boot loader,这个情况3简单地说就是用户程序不对劲的时候或者FLASH全为空的时候。如果不下心已经把程序写入了Flash,而程序中又没有去改变BOOTCFG这个寄存器的值,那么以后启动ROM中的boot loader程序就十分困难了。

?

Tiva C的Flash中的Boot loader:

? ? ? ? 接下来说说FLASH中的boot loader。既然是Flash中的东西,就是可以修改的啦,因此可以比较灵活,比如说boot loader可以使用串口0,或者串口1,或者SSI3,或者以太网等来更新用户程序。这个boot loader不是自带的,官方给了代码,需要我们自己编译后弄到Flash里面。在Tivaware的例程目录下,有一个叫做boot_serial的文件夹,里面就是一个用串口更新的boot loader程序。

? ? ? ? 如果使用这个boot loader的话,就得把Flash分成两个区域,每个区域存一个程序,分区大小需要根据boot loader这个程序的大小来设定,用户程序的首地址最好设置为除boot loader外第一个空白sector。如下图所示:

? ? ? ? ?首先,在boot loader程序中,要有一个APP_START_ADDRESS,这个变量存放的是用户程序的首地址,按照上图也就是0x2800。然后,boot loader程序中还有一个CheckForceUpdate()函数,它要来检测APP_START_ADDRESS开始的几个值正不正常,这跟ROM的boot loader差不多,只是地址多了一个偏移而已。如果APP_START_ADDRESS开始的值能够确定是堆栈地址和reset的中断函数地址,就认为用户程序存在,就跳转去执行用户程序,否则进入更新状态。当然,CheckForceUpdate()函数中也可以写一些根据引脚状态来确定是否进入更新的代码,官方例程也留下了接口如下:

? ? ? ? ?如果把boot loader弄到了Flash里面,相应的,用户程序也要更改一些地方,主要就是编译时候设置程序起始位置。正常来说,用户程序直接烧写到Flash开头就好了,比如stm32要设置程序位置为0x0800 0000(这是stm32的Flash的首地址),而Tiva C系列则设置为0x00(这是Tiva C的Flash首地址),但是现在Flash开头已经被boot loader占用了,因而需要把用户程序的起始地址改一下:

????????上面那张图是keil里面的魔术棒的设置,下面这个是ccs的cmd文件的配置,根据自己的情况改一下程序的起始地址就行。

? ? ? ? 都设置好之后,首先要把boot loader通过调试器烧写到Flash的起始位置。单片机重新上电,因为此时0x00是boot loader所以执行的是boot loader程序,该程序会执行一个CheckForceUpdate()去检测0x2800开始的一段位置,或者说检测设置的GPIO引脚的状态来确定是否执行更新,如果不执行,则跳转0x2800去执行用户程序,否则进入更新状态,配置特定外设并等待数据的到来。

总结:

? ? ? ? 简而言之,无论boot loader在哪里,当它被触发启动后,就可以发送程序到单片机的特定外设,boot loader程序会接收俺们的程序并帮我们写入Flash。boot loader的触发启动方式各不相同,stm32通过两个引脚的电平情况触发,而Tiva C是根据某些地址的值或者IO的值来触发执行。

? ? ? ? 这么看来,Tiva C的触发条件还是比较苛刻得,一般只有全新芯片才能触发ROM的boot loader,如果没有调试器,如果第一次不小心写了个程序进0x00处,那么很难再启动ROM的boot loader,此时Flash的boot loader也没有被存进去Flash,更加启动不了了。想不通Ti这么做的意义何在。

????????所以还是调试器大法好啊阿巴阿巴......

????????看了好久资料,看得迷迷糊糊,现在把自己对boot loader和启动过程的理解写出来,也不知道能写清楚,还望大家前来指正与交流啦~

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-08-11 12:35:13  更:2021-08-11 12:35:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/13 6:31:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码