搜索
bottom↓
回复: 33

ARM M0中BOOT到APP跳转方法KEIL工程详解--原创

  [复制链接]

出0入0汤圆

发表于 2017-3-25 13:19:47 | 显示全部楼层 |阅读模式
好久没有贡献了,以前有发过飞思卡尔KE02的工程,有网友要求能否详细说明一下,刚好最近玩了一下NV32的国产芯片,就抽空做了一个文档与例程,欢迎转载,但拒绝用来弄什么积分下载,去积分!
我喜欢阿莫,这里什么都能搜到,什么都能下载,不要积分。
文档:

例程:



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2017-3-25 14:20:16 | 显示全部楼层
沙发,赞一个。用处很大,谢谢分享。

出0入0汤圆

发表于 2017-3-25 14:24:38 | 显示全部楼层
谢谢分享     

出0入0汤圆

 楼主| 发表于 2017-3-25 14:55:55 来自手机 | 显示全部楼层
楼主好人!一生平安!

出0入0汤圆

发表于 2017-3-25 16:27:03 | 显示全部楼层
请加上”阿莫论坛“  ,  直接爱上阿莫有点

出0入0汤圆

发表于 2017-3-25 16:44:48 | 显示全部楼层
谢谢楼主的资料!

出0入0汤圆

发表于 2017-3-25 22:44:42 | 显示全部楼层

下载下来学习下

出0入0汤圆

发表于 2017-3-25 22:49:35 | 显示全部楼层
LZ 的烧录器不错,感谢LZ 的分享。

出0入0汤圆

发表于 2017-3-25 22:59:38 来自手机 | 显示全部楼层
很历害,,,

出0入0汤圆

发表于 2017-3-26 02:46:59 | 显示全部楼层
补充解释下:说白了,选option->target就是改这个分散加载文件。这个是文本的方式,那个是IDE方式,一样一样的。

出0入0汤圆

发表于 2017-5-30 17:06:17 | 显示全部楼层
赞一个。用处很大,谢谢分享

出0入296汤圆

发表于 2017-5-30 23:50:38 | 显示全部楼层
看了一下楼主的帖子,很不错,赞,但是有一个地方是不妥当的:
设置VTOR寄存器应该是 Bootloader 的事情,而不是APP的事情,对APP来说,一个系统是否存在 Bootloader 应该是透明的(不关心的)
简单说,就是有Bootloader,APP可以正常工作;没有 Bootloader,APP也应该可以正常工作。基于这个假设,APP就应该被编译成假设
VTOR就是自己编译的位置——通常是0x00000000。一个好的Bootloader在跳转到 APP 运行之前,应该要做很多清扫环境的工作,比如
关闭 bootloader 自己打开的各类中断资源,根据 APP的 向量表正确配置MSP之类。

出0入8汤圆

发表于 2017-5-31 09:05:17 | 显示全部楼层
Gorgon_Meducer 发表于 2017-5-30 23:50
看了一下楼主的帖子,很不错,赞,但是有一个地方是不妥当的:
设置VTOR寄存器应该是 Bootloader 的事情, ...

这能做到吗?APP不用设置中断向量表?

出0入0汤圆

发表于 2017-5-31 09:52:37 | 显示全部楼层
Gorgon_Meducer 发表于 2017-5-30 23:50
看了一下楼主的帖子,很不错,赞,但是有一个地方是不妥当的:
设置VTOR寄存器应该是 Bootloader 的事情, ...

我们都是在app一开始设向量表地址的,如果可以不用设,那么调试又会变方便一点。

出0入0汤圆

 楼主| 发表于 2017-5-31 10:27:22 | 显示全部楼层
Gorgon_Meducer 发表于 2017-5-30 23:50
看了一下楼主的帖子,很不错,赞,但是有一个地方是不妥当的:
设置VTOR寄存器应该是 Bootloader 的事情, ...

先谢谢版主的回复!试过boot中处理一些中断停止什么的,但太复杂,不如直接RESET来的方便快捷无BUG。考虑了一下不在APP设置VTOR,就得去设置分散加载,开一块RAM做中断,还是麻烦,既然ARM有VTOR这个寄存器,用起来还是方便!另外,DEBUG的时候有没有BOOT都可以直接仿真!

出0入0汤圆

 楼主| 发表于 2017-5-31 10:30:26 | 显示全部楼层
lindabell 发表于 2017-5-31 09:05
这能做到吗?APP不用设置中断向量表?

我刚才考虑了一下,应该可以做到,BOOT与APP的中断向量可以指向同一块RAM,只是在加载的时候BOOT加载自己的中断函数,APP加载的也是自己的中断函数,只要用分散加载就可以做到,这个就相当于在编译的时候将指定的函数放到指定的地址位置!

出0入296汤圆

发表于 2017-5-31 16:27:11 | 显示全部楼层
本帖最后由 Gorgon_Meducer 于 2017-5-31 16:35 编辑

首先,这个事情,如果我说你们的做法是错的,你们会说,我们用很多年了。考虑到存在即合理,我
这么说吧,你们的做法只是实现了功能,但是并不是最合理的。最合理的就是APP和Boot loader之间
的透明化——只不过因为你们觉得Bootloader开发会复杂一点,就觉得这是不可行的,你们不觉得这点
很值得商榷么?
然而,实际上,Bootloader在这个问题上的开发并不复杂,我这里放一个参考代码:

  1. //! 1. Disable interrupt response.
  2. __disable_irq();                           

  3. //! 2. Disable all enabled interrupts in NVIC.
  4. memset((uint32_t *)NVIC->ICER, 0xFF, sizeof(NVIC->ICER));

  5. /*! Disable all enabled peripherals which might generate interrupt    requests.
  6.     Clear all pending interrupt flags in those peripherals.
  7.     This part is device-dependent, and you can write it by referring to device datasheet.
  8. */

  9. /*! Clear all pending interrupt requests in NVIC.
  10. */
  11. memset((uint32_t *)NVIC->ICPR, 0xFF, sizeof(NVIC->ICPR));

  12. //! 4. Disable SysTick and clear its exception pending bit.
  13. SysTick->CTRL = 0;
  14. SCB->ICSR |= SCB_ICSR_PENDSTCLR_Msk;

  15. //! 5. Load the vector table address of user application code in to VTOR.
  16. SCB->VTOR = USER_APPLICATION_VECTOR_TABLE_ADDRESS;

  17. //! 6. Use the MSP as the current SP.

  18. //! Set the MSP with the value from the vector table used by the application.
  19. __set_MSP(  ((unsigned int *)(SCB->VTOR))[0] );

  20. //! In thread mode, enable privileged access and use the MSP as the current SP.
  21. __set_CONTROL( 0 );

  22. //! 7. Enable interrupts.
  23. __enable_irq();

  24. //! 8. The reset handler address could be found with following expression
  25. //! ((unsigned int *)(SCB->VTOR))[1]

复制代码


这是跳转到APP运行前推荐的要做的事情的伪代码。另外,你们的描述中,中断向量表
需要两块RAM让我觉得很诧异——首先不应该用FLASH来节省空间么?为什么要RAM?
其次,Bootloader理论上是可以不用完整的中断向量表的,你只要保留最基础的部分,
也就是头16个WORD就足够了——我比较激进,我的代码只保留了头4个。另外,很多
芯片可以通过Fuse设置默认的VTOR地址——对于这种芯片,直接把Bootloader的向量
放到Flash的尾部,把启动的VTOR设置成Bootloader的VTOR就行了。另外,即便是不
支持VTOR的M0,也有办法做到APP和Bootloader相互透明,不过时间太短,我就暂时
不在这里介绍了。

出0入0汤圆

发表于 2017-5-31 17:32:19 | 显示全部楼层
Gorgon_Meducer 发表于 2017-5-30 23:50
看了一下楼主的帖子,很不错,赞,但是有一个地方是不妥当的:
设置VTOR寄存器应该是 Bootloader 的事情, ...

没看楼主附件,一路浏览看到你说VTOR,  印象里以前用STM32F0是没有向量偏移量的,只能选择0地址是ROM/RAM,所以APP执行前要复制前面几十个字节到RAM的起头处。貌似当时查了下CM0似乎都没向量偏移值?    看到傻孩子大神你的帖子我错乱了,难道我记错了。

出0入0汤圆

发表于 2017-5-31 17:38:41 | 显示全部楼层
Gorgon_Meducer 发表于 2017-5-31 16:27
首先,这个事情,如果我说你们的做法是错的,你们会说,我们用很多年了。考虑到存在即合理,我
这么说吧, ...


一路继续往下,终于看到你说CM0没有中断向量偏移。
BOOT和APP各有一个向量表, 如果APP的按正常的写, BOOT的每个中断里做个判断,进入中断如果当前是BOOT模式,执行BOOT中断,如果当前是APP模式,加一个固定偏移量跳转到APP的中断去执行也可以。    不过大家肯定毫无疑问会喜欢赋值向量表到RAM简单粗暴,折腾改BOOT中断劳民伤财不爱干。

出0入0汤圆

发表于 2017-5-31 17:42:47 | 显示全部楼层
本帖最后由 huangqi412 于 2017-5-31 17:44 编辑

复制向量表到RAM会引起APP内存缩水了前面几十个字节,跟没有BOOT情况会不同(FLASH缩水对程序没影响 重点一下BUILD而已),就是你说的APP不透明,要定义一个决定定位数组或者改设置地址范围让编译器知道前面几十个字节不能用。但是简单粗暴方便啊。

出0入0汤圆

发表于 2017-5-31 23:11:11 | 显示全部楼层
huangqi412 发表于 2017-5-31 17:38
一路继续往下,终于看到你说CM0没有中断向量偏移。
BOOT和APP各有一个向量表, 如果APP的按正常的写, BO ...

这样岂不是boot和app仍然不透明……

出0入296汤圆

发表于 2017-6-1 00:16:41 | 显示全部楼层
本帖最后由 Gorgon_Meducer 于 2017-6-1 00:21 编辑
huangqi412 发表于 2017-5-31 17:38
一路继续往下,终于看到你说CM0没有中断向量偏移。
BOOT和APP各有一个向量表, 如果APP的按正常的写, BO ...


Cortex-M0+ 才有VTOR
对于Cortex-M0没有VTOR其实有两个解决方案,也许你说的方案算是第三个方案,我觉得没有人会在“每一个”中断向量里面做一个判断的……

先简单说说第一个方案(傻孩子原创):
a. 首先,Bootloader 被放置在 Flash的尾部, 它的向量表只有最小的结构——两个WORD,一个给MSP,一个是Reset_Handler。
b. Bootloader的最小中断向量表放置在0x00000000地址,这点是不会改变的
c. Bootloader的Reset_Handler永远指向Bootloader,这点是不会改变的。所以永远从Bootloader启动。
关键的地方来了:
d. APP的中断向量表“也”保存在0x00000000,这样有没有Bootloader,APP都能运行,这就是“透明”的意义。
   显然,这样处理,APP的中断向量就和Bootloader的最小中断向量冲突了,怎么办呢?
最关键的地方来了:
e. Bootloader 更新 APP的时候,如果接收到 0x00000000开始的两个WORD,则将这部分替换成自己的最小向量表内容,然后再写入FLASH。
   而原来APP向量表的最初两个WORD则被保存到Bootloader自己的某个固定的FLASH空间里。APP向量表的其它内容则原样写入。
f. 当系统从 Bootloader启动时,如果要进入APP运行,则读取先前保存的 APP 向量表中的MSP值,初始化MSP,而用APP的Reset_Handler值
   跳转到APP去执行。这样就解决了启动的问题。

这个方案优点很明显,你甚至可以玩出更多花样;缺点也是很明显的,就是Boot loader不能用中断——这个对我用全状态机开发的bootloader
来说,根本不是问题,要毛中断?!!

第二个方案,类似当年AVR32的 trampoline 方案,这里就不多说了,有兴趣的朋友可以去看我的过去的帖子。


总结一下,我这个方案,对几乎一切不支持VTOR的系统都是有借鉴意义的。 还有,年轻人们,不要思路太僵化……咳咳咳

出0入0汤圆

发表于 2017-6-1 09:14:58 | 显示全部楼层
Gorgon_Meducer 发表于 2017-6-1 00:16
Cortex-M0+ 才有VTOR
对于Cortex-M0没有VTOR其实有两个解决方案,也许你说的方案算是第三个方案,我觉得 ...

额,F0是CM0 还是CM0+,印象里好像是市面上常见芯片都是CM0+
APP放前面,BOOT放后面,下载APP时候将前面几个字节替换掉这个很久很久前有过讨论,相当于只对RST中断做判断执行。CM3有向量偏移,M0没有,BOOT不好用中断了,我说的就是在这个上面修改的,所有中断 都做判断执行了。 如果真去做,也不会太麻烦,毕竟中断写法一样模板,一个芯片用下去只一个BOOT,N种APP,BOOT只要写一次.   大神说BOOT不用中断,是可以,BOOT用的资源本来就少,不过大家肯定喜欢在BOOT中继续用中断,而且更喜欢简单粗暴的实现功能,拷贝到RAM肯定是大家第一选择,不管他透不透明了,反正我是这样。

出0入0汤圆

发表于 2017-6-1 09:17:34 | 显示全部楼层
yiming988 发表于 2017-5-31 23:11
这样岂不是boot和app仍然不透明……

APP代码跟没有BOOT时候写法没有不同啊,只有BOOT折腾,但BOOT一个芯片只有一次啊。

出0入0汤圆

发表于 2017-6-1 15:23:15 | 显示全部楼层
huangqi412 发表于 2017-6-1 09:17
APP代码跟没有BOOT时候写法没有不同啊,只有BOOT折腾,但BOOT一个芯片只有一次啊。 ...

我是说boot中断里做判断再跳转到app的中断 这种方法不透明,太麻烦,因为还要跳到app的中断去。cm0里在app开始把向量表写到ram里(ram是从0地址开始的话)倒是不影响中断了,但app就必须知道当前芯片是“ram从0开始的m0”还是其他。
不是不可以,是在想是否有更完美的方法。

出0入0汤圆

发表于 2017-6-1 15:43:18 | 显示全部楼层
yiming988 发表于 2017-6-1 15:23
我是说boot中断里做判断再跳转到app的中断 这种方法不透明,太麻烦,因为还要跳到app的中断去。cm0里在ap ...

麻烦和不透明的只是BOOT,APP没多一毛钱事。一系列芯片BOOT只有一次,而所有中断都一个模板。 SO,工作量就是一系列芯片一上午,你打算一年换多少种系列?  这是对APP放前面BOOT放后面方式的补丁。 傻孩子大神也说了可以直接BOOT不用中断,就是不要这个补丁。   

出0入0汤圆

发表于 2017-6-1 21:20:16 | 显示全部楼层
huangqi412 发表于 2017-6-1 15:43
麻烦和不透明的只是BOOT,APP没多一毛钱事。一系列芯片BOOT只有一次,而所有中断都一个模板。 SO,工作量 ...

从boot中断里再跳到app中断里,肯定影响中断实时性能力
so  还是把boot放后面好一点。

出0入0汤圆

发表于 2017-6-4 17:50:14 来自手机 | 显示全部楼层
只是多了出入一下栈耗不了多少时间吧

出870入263汤圆

发表于 2017-6-15 18:21:35 | 显示全部楼层
Gorgon_Meducer 发表于 2017-5-31 16:27
首先,这个事情,如果我说你们的做法是错的,你们会说,我们用很多年了。考虑到存在即合理,我
这么说吧, ...

版主,你用memset来做M0的内核寄存器清除和设置操作不是很妥当吧!你应该知道M0内核很多寄存器只能接受WORD访问,不支持BYTE和HALFWORD读写。
如果你用memset,就很依赖编译器使用的C库了!这样恐怕换个编译器自己都拿不准好不好用了吧?

出0入296汤圆

发表于 2017-6-16 00:46:41 | 显示全部楼层
本帖最后由 Gorgon_Meducer 于 2017-6-16 00:57 编辑
armstrong 发表于 2017-6-15 18:21
版主,你用memset来做M0的内核寄存器清除和设置操作不是很妥当吧!你应该知道M0内核很多寄存器只能接受WO ...


你说的有道理。但这个代码我在主流ARM编译器上都测试过,而且ARM官方有文档解释
这个问题。既然是操作ARM处理器的核,那么本身就是针对ARM环境,在这个情况下,
我确认这个代码是安全的。

这个代码属于编译器依赖的典型例子。你批评的很好,我接受。我特此声明一下,以上代码
对以下编译器合法,可靠有效:
ARM Compiler 5
ARM Compiler 6
IAR
GCC (Cortex-M,Cortex-R)
GCC linaro (Cortex-A)

不知道这个解释你是否满意?

另外,补充说明一下,不光是Cortex-M0,实际上所有Cortex-M的内核,0xExxx xxxx 地址的
寄存器,都只支持WORD操作,且必须在特权模式下(privilege access)。也就是大家熟悉
的NVIC,SysTick,MPU,SCB,都在这个范畴内。

出0入0汤圆

发表于 2017-6-16 06:47:21 来自手机 | 显示全部楼层
感谢楼主分享

出0入0汤圆

发表于 2017-6-16 09:28:48 | 显示全部楼层
我用的IAP升级,也有bootloader

出870入263汤圆

发表于 2017-6-16 10:06:41 | 显示全部楼层
本帖最后由 armstrong 于 2017-6-16 10:10 编辑
Gorgon_Meducer 发表于 2017-6-16 00:46
你说的有道理。但这个代码我在主流ARM编译器上都测试过,而且ARM官方有文档解释
这个问题。既然是操作ARM ...


谢谢版主的答复,我对你的回复满意。
版主的答复质量很高,可见你技术功底之厚、研究态度之专是令人赞叹的!
不过Cortex-M3和Cortex-M4的NVIC寄存器有点例外,它的优先级配置寄存器IPR组(从0xE000E400地址开始)可以字节读写。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入296汤圆

发表于 2017-6-17 07:24:49 | 显示全部楼层
armstrong 发表于 2017-6-16 10:06
谢谢版主的答复,我对你的回复满意。
版主的答复质量很高,可见你技术功底之厚、研究态度之专是令人赞叹 ...

这都被你发现了,你很细心哈。不过,这几个寄存器允许字节访问也是功能的需要
因为实际上每个字节对应一个Interrupt的优先级,所以,以字节为单位提供访问是
合理的——不提供字节访问反而显得不太方便了。这类寄存器应该还有一些吧,但
记住总的来说System Control Space(SCS)地址空间里,大部分地址都是WORD
的特权访问是没有坏处的。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-24 14:34

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表