搜索
bottom↓
回复: 23

CORTEX-M4单片机boot跳转app不成功,悬赏求帮助?

[复制链接]

出0入0汤圆

发表于 2017-10-7 11:05:05 | 显示全部楼层 |阅读模式
单片机型号为ATMEL-SAM4E16,内核为CORTEX-M4,boot跟app是两个不同的IAR工程,开发环境是IAR6.5,
单片机的内部ROM地址范围0x400000~0x46FFFF,内部flash的地址范围是0x20000000~0x2001ffff,
boot代码的起始地址是0x400000,app跳转地址为0x404000 + 4,
跳转前关闭中断的函数为 { __ASM volatile ("cpsid i"); };

boot的ICF文件中的关键参数设置为
define symbol __ICFEDIT_intvec_start__ = 0x00400000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_RAM_start__  = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__    = 0x2001FFFF;
define symbol __ICFEDIT_region_ROM_start__  = 0x00400000;
define symbol __ICFEDIT_region_ROM_end__    = 0x0046FFFF;

app工程的ICF文件中的关键参数设置为
define symbol __ICFEDIT_intvec_start__ = 0x00404000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_RAM_start__  = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__    = 0x2001FFFF;
define symbol __ICFEDIT_region_ROM_start__  = 0x00404000;
define symbol __ICFEDIT_region_ROM_end__    = 0x0046FFFF;
APP的代码中main函数执行前,会设置新的中断向量表,代码如下
uint32_t *pSrc = __section_begin(".intvec");
        __set_MSP(*pSrc);
        SCB->VTOR = 0x404000;
中断向量表跟堆栈指针的起始地址都是设置的同一个值,0x404000;
main函数执行的第一步是重新初始化时钟,然后再打开中断,打开中断的函数为__enable_irq();
上述的启动代码及跳转地址的设置都是参考CM3单片机修改的,之前在CM3中可以很好的运行。
我单独调试APP工程是可以运行的,单独调试时把APP工程的ICF文件修改一下,用JLINK下载
到板上就能够运行,现在加了BOOT后,怎么样都跑不起来,APP的代码中就算只开启一个串口
只用来打印也不行,因为是两个不同的工程,所以用JLINK调试BOOT工程时每次把APP代码的bin文件
下载后,执行到跳转地址的代码时,调试就会进入 BusFault_Handler。
现在寻求帮助,可以提供一些调试思路或者解决办法,或者帮分析一下问题可能出在哪一部分(boot还是app)。

出0入0汤圆

发表于 2017-10-7 11:05:06 | 显示全部楼层
本帖最后由 shangdawei 于 2017-10-7 12:05 编辑

>>单片机的内部ROM地址范围0x400000~0x46FFFF,内部flash的地址范围是0x20000000~0x2001ffff,

单片机的内部Flash地址范围0x400000~0x46FFFF,内部RAM的地址范围是0x20000000~0x2001ffff,

https://stackoverflow.com/questi ... -loaded-application

  1. int main(void){
  2.      // Init and downloading the .bin to Flash
  3.      binary_exc((void*) 0x404000);
  4. }



  5. int binary_exec(void * vStart){
  6.     int i;
  7.     // -- Check parameters
  8.     // Should be at least 32 words aligned
  9.     if ((uint32_t)vStart & 0x7F)
  10.     return 1;

  11.     Disable_global_interrupt();
  12.     // Disable IRQs
  13.     for (i = 0; i < 8; i ++) NVIC->ICER[i] = 0xFFFFFFFF;
  14.     // Clear pending IRQs
  15.     for (i = 0; i < 8; i ++) NVIC->ICPR[i] = 0xFFFFFFFF;

  16.     // -- Modify vector table location
  17.     // Barriars
  18.     __DSB();
  19.     __ISB();
  20.     // Change the vector table
  21.     SCB->VTOR = ((uint32_t)vStart & SCB_VTOR_TBLOFF_Msk);
  22.     // Barriars
  23.     __DSB();
  24.     __ISB();

  25.     Enable_global_interrupt();

  26.     // -- Load Stack & PC
  27.     _binExec(vStart);
  28.     return 0;
  29. }

  30. void _binExec (void * l_code_addr){
  31.     __asm__ ("mov   r1, r0        \n"
  32.     "ldr   r0, [r1, #4]  \n"
  33.     "ldr   sp, [r1]      \n"
  34.     "blx   r0"
  35.     );
  36. }
复制代码

出0入0汤圆

 楼主| 发表于 2017-10-7 15:12:07 | 显示全部楼层
shangdawei 发表于 2017-10-7 12:04
>>单片机的内部ROM地址范围0x400000~0x46FFFF,内部flash的地址范围是0x20000000~0x2001ffff,

单片机的内 ...

谢谢你的指正,前面写的地址范围是写错了,现在按照您给的链接中的参考修改后,boot能够成功跳转到app,
在app的代码中我使用了freeRTOS,在代码中多添加了几句代码(为了测试,我添加的代码都是串口打印),
app就不能执行了,这种情况会是堆栈溢出吗?还是编译器把app代码中的最开始执行的部分编译到了其他地址,
导致跳转不到正确的地址?

出0入0汤圆

发表于 2017-10-7 16:52:13 | 显示全部楼层
可以连接仿真器调试看看在哪里死掉了。

出0入0汤圆

发表于 2017-10-7 19:24:03 | 显示全部楼层
注意JUMP之前要要关掉已打开的中断。
我这个能用,不过是不是ATMEL的。你的相应的改一下试一下。
void flashJumpApplication(uint32_t address)
{
    typedef void (*funcPtr)(void);

    uint32_t jumpAddr = *(volatile uint32_t*)(address + 0x04); /* reset ptr in vector table */
    funcPtr usrMain = (funcPtr)jumpAddr;

    SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
   
    /* Reset all interrupts to default */
    __disable_irq();

    /* Clear pending interrupts just to be on the save side */
    SCB->ICSR &= ~SCB_ICSR_PENDSVSET_Msk;

    /* Disable all interrupts */
    int i;
    for(i = 0; i < 8; ++i)
        NVIC->ICER[i] = NVIC->IABR[i];
   
    /* Set stack pointer as in application's vector table */
    __set_MSP(*(volatile uint32_t*)address);
//    __set_CONTROL(0);
//    SCB->VTOR = 0x08010000UL;
   
    usrMain();
}

出0入0汤圆

 楼主| 发表于 2017-10-8 08:38:04 来自手机 | 显示全部楼层
wanglei1984 发表于 2017-10-7 19:24
注意JUMP之前要要关掉已打开的中断。
我这个能用,不过是不是ATMEL的。你的相应的改一下试一下。
void flas ...

您的这段代码应该stm32的吧,谢谢您的参考,现在已经可以成功跳转了,出现了新的问题是多添加代码就会导致跳转不了了

出0入8汤圆

发表于 2017-10-8 10:18:10 | 显示全部楼层
既然能用 JLINK 调试的话,那就去跟踪一下 SP 在跳转前后的值,是否符合预期。
跳转的地址,是否符合预期。

现在你所给的信息是不够分析问题的,只能靠猜,先自己去 debug 吧。

出0入0汤圆

 楼主| 发表于 2017-10-8 16:15:56 | 显示全部楼层
security 发表于 2017-10-8 10:18
既然能用 JLINK 调试的话,那就去跟踪一下 SP 在跳转前后的值,是否符合预期。
跳转的地址,是否符合预期。 ...

现在可以成功跳转了,但是我多了几个串口打印的函数就会导致跳转后不能执行,因为boot跟app是不同的两个工程,
我现在在boot工程用JLINK调试的时候发现,跳转后可以执行的bin文件,调试的时候可以看到反汇编的语句,
但是调试不能执行的bin文件的时候,全速运行就会导致JLINK死掉,会连不上芯片,需要断电重启,我在APP
的工程中单独调试就不会死掉。

出0入8汤圆

发表于 2017-10-8 16:25:26 | 显示全部楼层
dengmengcan 发表于 2017-10-8 16:15
现在可以成功跳转了,但是我多了几个串口打印的函数就会导致跳转后不能执行,因为boot跟app是不同的两个 ...

那你就看看正常的 bin 和异常的 bin,在调试时,SP 的值、汇编语句,有什么差异。

出0入8汤圆

发表于 2017-10-8 16:30:44 | 显示全部楼层
另外,SP 的切换,处理时机,要在 BOOT 端完成。
不要放在 APP 中去处理。

不然,main 如果需要用栈,一开始用的是 BOOT 的栈,而你却在 main 的后续处理中,切换了 SP,将会导致后续的异常。

出0入8汤圆

发表于 2017-10-9 17:26:02 | 显示全部楼层
LZ 同学,问题怎么样了,
解决的话,分享一下?

出0入0汤圆

 楼主| 发表于 2017-10-9 19:54:44 | 显示全部楼层
security 发表于 2017-10-9 17:26
LZ 同学,问题怎么样了,
解决的话,分享一下?

谢谢您的一直跟进,现在我加了RTOS后,也能够正常执行,但是把RTOS相关的代码注释掉以后,就是相当于裸机,
这样就执行不了,我单独调试这段裸机代码发现并没有问题。
加上RTOS后app也可以执行,跳转的代码跟前面用到的是一样的,是因为我把IAR编译器的优化给全部关闭后就可以了,
之前用的是最高的优化级别,所以我现在怀疑这段裸机代码用app的方式不能执行,是不是也跟IAR编译器的设置有关系?


出0入0汤圆

 楼主| 发表于 2017-10-9 20:01:15 | 显示全部楼层
security 发表于 2017-10-8 16:30
另外,SP 的切换,处理时机,要在 BOOT 端完成。
不要放在 APP 中去处理。

现在可以执行的代码也是在app中做栈的初始化以及重新映射中断向量表,boot中只做了关闭中断跟跳转地址的动作,但是我
调试的时候发现,IAR编译器会在main函数开始前加入很多跟编译器有关的函数,例如(__iar_program_start、__iar_init_vfp、
__iar_zero_init3、__iar_data_init3、_call_main等),跟keil下开发STM32有些不同,因为涉及到很多知识跟编译器有关,在这
方面的积累太薄弱,也没深入去研究了。

出0入0汤圆

发表于 2017-10-9 20:14:24 | 显示全部楼层
dengmengcan 发表于 2017-10-9 19:54
谢谢您的一直跟进,现在我加了RTOS后,也能够正常执行,但是把RTOS相关的代码注释掉以后,就是相当于裸机 ...

楼主有没有看工程里的“.map”文件啊,里面是否有地址分配重复的地方?编译器有时优化级太高就会出现这问题

出0入0汤圆

 楼主| 发表于 2017-10-9 20:26:47 | 显示全部楼层
yayagepei 发表于 2017-10-9 20:14
楼主有没有看工程里的“.map”文件啊,里面是否有地址分配重复的地方?编译器有时优化级太高就会出现这问 ...

我现在已经把优化关闭了,".map"文件之前开优化的时候看过,也没看到地址重复的

出100入101汤圆

发表于 2017-10-9 21:22:45 | 显示全部楼层
dengmengcan 发表于 2017-10-9 20:01
现在可以执行的代码也是在app中做栈的初始化以及重新映射中断向量表,boot中只做了关闭中断跟跳转地址的 ...

mdk一样会加

出0入8汤圆

发表于 2017-10-10 08:51:36 | 显示全部楼层
dengmengcan 发表于 2017-10-9 20:01
现在可以执行的代码也是在app中做栈的初始化以及重新映射中断向量表,boot中只做了关闭中断跟跳转地址的 ...

这是启动代码的范畴。
BOOT 需要启动代码,APP 也需要启动代码。完成 C 运行环境的搭建。

SP 的切换,你还是改到 BOOT 端吧,不然在你执行 main 中的 set sp 之前,用的都是旧的 SP 的值(BOOT 的取值),
你就想象一下,如果没有 BOOT,你这个 APP 的栈,在 main 之前,用的都是 APP 的栈,因为硬件会自动去中断向量表取 SP 的值,
而你现在加了 BOOT,执行流,与这个是不一样的,一开始用的是 BOOT 的栈。

至于裸机 + 高等级优化出问题的现象,我想问题的症结应该跟这个栈的切换有关,去看看汇编的变化,结合这点去看看。

出0入296汤圆

发表于 2017-10-10 20:37:05 | 显示全部楼层
dengmengcan 发表于 2017-10-9 19:54
谢谢您的一直跟进,现在我加了RTOS后,也能够正常执行,但是把RTOS相关的代码注释掉以后,就是相当于裸机 ...

看了你的描述,我可以很肯定的说,你的问题和IAR无关或者说跟编译器都是无关的。
Bootloader在切换到APP运行之前,应该做必要的现场恢复,这就包括正确的配置配置
栈,并且使用正确的栈(MSP),关闭所有中断,并设置Cortex-M使用Thread模式,并
开启特权访问——基本原则就是,Bootloader应该恢复系统的状态到基本上相当于刚刚
复位的样子。Cortex-M复位以后,系统会从中断向量表第一个WORD里面加载栈顶指针,
所以,切换到APP之前,你也要读取APP向量表的第一个WORD,并初始化MSP。系统复
位后,进入的是Thread模式,使用MSP并且处于特权状态。那么,基于这一点,你不光
要配置VTOR使用APP的中断向量表,而且要正确配置Thread模式的栈以及特权模式。

在你的描述中,使用RTOS可以正常运行,但是使用裸机却不行,实际上就告诉我们,你
遇到的问题就是由于Bootloader在切换前没有做好必要的现场回复工作。为什么这么说呢?
因为RTOS一般都会为自己做现场配置(RTOS通常并不使用默认的栈和堆配置,并不使用
保存在向量表里面的栈顶指针,而是另起炉灶的配置一下——这是可移植性的需要)。

也就是说,RTOS会打扫屋子,你的APP不会打扫屋子,那么Bootloader在用完房间以后
没有打扫,就导致了你现在遇到的问题。

你现在在APP里面做打扫房间的工作,是一个保险措施,但是这只不过是掩盖了Bootloader
没有做现场回复的错误。

出0入0汤圆

 楼主| 发表于 2017-10-12 20:19:24 | 显示全部楼层
Gorgon_Meducer 发表于 2017-10-10 20:37
看了你的描述,我可以很肯定的说,你的问题和IAR无关或者说跟编译器都是无关的。
Bootloader在切换到APP ...

谢谢版主这么认真的回复,现在问题已经解决了,boot跳转app的代码是没有问题的,问题出在boot接收app的bin文件的时候,
写入内部flash的时候出错了,最后通过把app与boot的bin文件用工具合并成一个新的bin文件,下载到芯片发现是能够正常跳转的,
调试的时候用JLINK把芯片里的代码读出来(用xmodem协议通过串口接收写入到内部flash),两个bin文件对比会发现在写flash的
时候,把bin文件放在了错误的位置,导致boot启动时一直读到不完整的bin文件,因此造成跳转失败。

出0入0汤圆

发表于 2017-10-22 20:05:47 | 显示全部楼层
"把bin文件放在了错误的位置"?楼主在APP代码里写FLASH的偏移地址 是否设置正确啊?

出0入0汤圆

 楼主| 发表于 2017-11-1 19:29:35 | 显示全部楼层
yayagepei 发表于 2017-10-22 20:05
"把bin文件放在了错误的位置"?楼主在APP代码里写FLASH的偏移地址 是否设置正确啊? ...

bin文件是由boot下载的,下载的时候因为单片机的关系,之前的数据校验做的不对,导致下载的时候最后的数据下载不对。

出0入0汤圆

发表于 2017-12-14 14:51:53 | 显示全部楼层
dengmengcan 发表于 2017-10-9 19:54
谢谢您的一直跟进,现在我加了RTOS后,也能够正常执行,但是把RTOS相关的代码注释掉以后,就是相当于裸机 ...

请问一下,你使用什么工具合并 bin 文件啊,能否发上来共享一下啊 ??

出0入0汤圆

 楼主| 发表于 2017-12-18 18:37:45 | 显示全部楼层
hpdell 发表于 2017-12-14 14:51
请问一下,你使用什么工具合并 bin 文件啊,能否发上来共享一下啊 ??

JLINK装驱动的时候,会自动安装 J-FLASH ,用的就是这个工具。

出0入0汤圆

发表于 2017-12-19 10:09:45 | 显示全部楼层
dengmengcan 发表于 2017-12-18 18:37
JLINK装驱动的时候,会自动安装 J-FLASH ,用的就是这个工具。

多谢多谢啊

目前一直都还木有这么用过这个东东的功能,有空搞一下看看
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-4-20 19:00

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

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