本帖最后由 香水城 于 2017-8-17 14:01 编辑
使用外部 SRAM 导致死机
问题:
该问题由某客户提出,发生在 STM32F407IGT6 器件上。据其工程师讲述:为了满足软件对大容量内存的需求,将软件中的部变量从内部 SRAM 转移到片外的 SRAM当中。而这一改变,导致该软件不能运行,每次复位后,随即便发生死机。在此之前,对 FSMC 的初化代码,以及片外 SRAM 的读写匀做过测试,并确认是没有问题的。其内存分配如表(一)所示,FSMC 的初始化代码如表(二)所示。
调研:
使用 Keil MDK 创建工程,测试其所用的 FSMC 初始化代码,结果表明该段代码正确无误。修改内存分配,删除其中对外部 SRAM 的分配,如表(三)所示。重新对其软件编译,运行,结果表明,在这种内存分配方式下,其软件可以正常运行。修改其软件代码,在初始化 FSMC 之后加入对外部 SRAM 的读写测试,重新编译运行。测试结果表明,此时对外部 SRAM 的读写是正确的。查找其软件对 FSMC 初始化函数调用的位置,发现该函数是在该软件的 main()函数中调用的。修改代码,将该函数的调用位置移至 SystemInit()中,并且恢复原来的内存分配,如表(一)。重新编译并运行,此时该软件可以正确的运行。
结论:
软件中对 FSMC 做初始化的位不对,导致程序在访问外部 SRAM 时 FSMC 还未被初始化,从而造成总线访问出错,从而产生 Hard Fault 中断,最终程序流程停留在 Hard Fault中断服务程序中,使得程序对外表出“死机”的现象。
处理:
修改软件,将对 FMSC 初始化函数的调用位置放在 SystemInit()函数中,以保证在 C 语言初始化之前完成对 FMSC 的初始化。
建议:
一般来说 main()函数是 C 语言的入口函数,C 语言代码从这里开始执行。然而,整个应用程序的执行起点却不是这里。通常在 main()函数执行之前,要有一段初始化代码,为 C 语言代码的执行创建一个运行环境。比如要对 C 语言代码所使用的内存清零,还要对 C 语所定义的全局变量、静态变量付初值等等。这段初始化代码是由 C 语言开发工具中的链接器(Linker)加到应用程序当中的。它在做 C 语言运行环境初始化的时候,会访问相关的存贮器。如果此时,对应的存贮器不可用,就会出现错误。所以,对 FSMC 的初始化一定要在 C 语言运行环境初始化之前完成。在 ST 的标准外设库中给出的工程模板中,有一个能在 C 语言初始化之前得以执行的函数,就是 SystemInit()函数。于是,可以把有以上要求的初始化函数,在该函数中调用。因为 SystemInit()函数是在 C 语言初始化之前执行,所以,如果该函数,或者被该函数调用的函数中使用了全局变量或者静态变量,只能自行付初值,否则这些变量的初值是随机的。
对应的pdf:使用外部 SRAM 导致死机
更多实战经验请看:【ST MCU实战经验汇总贴】
|