gpt4 book ai didi

c - STM32F7-从RAM和闪存执行代码

转载 作者:行者123 更新时间:2023-11-30 16:20:11 25 4
gpt4 key购买 nike

我相信我的链接描述文件有问题,但是我不确定这是否是真正的罪魁祸首。

背景:

我在一个项目上使用了STM32F730。 uC具有64K闪存和256K RAM。其中,64K是TCM,192k是常规RAM。该项目将超过内部闪存的64k,因此我打算从RAM运行额外的代码。板上有外部闪存,因此在启动时,uC将从板载闪存执行加载例程,该例程通过SPI读取板载闪存并将数据存储到RAM中的正确位置。此部分有效,但仅有时有效。板载闪存可以通过几种方式进行编程,但是我相信所需的代码位于此处。此外,从调试器运行时发生错误,并且绕过了片外闪存的加载。

所有问题都涉及从调试器运行。目前没有代码从片外闪存加载。

我打开了很长的函数调用,以允许跳转到RAM,这确实解决了我遇到的一个问题,但没有解决这个问题。

问题:

有时,通过调试器加载后,代码可以完美运行。有时,代码根本不起作用,并且存在严重的错误。我不是嵌入式专家(我主要从事PCB设计和FPGA工作),但我设法逐步完成了组装工作,并找到了引起问题的奇怪原因,但没有找到导致问题的原因。我当前的项目已将IMU驱动程序加载到RAM中,并且应该通过USB CDC发送回数据。当完全加载到Flash中但不总是加载到RAM中时,此方法有效。例如,当我打开调试优化时,它可以工作,但是没有优化会导致故障。

我修改了链接器,如下所示:

/* Specify the memory areas */
MEMORY
{
TCM_RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K
CODE_RAM (xrw) : ORIGIN = 0x20010000, LENGTH = 64K
DATA_RAM (xrw) : ORIGIN = 0x20020000, LENGTH = 112K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 64K
}

/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH

/* NP 2019-03-15 - RAM Executable code should be linked to RAM */
/* NOTE: With code linked this way it WILL NOT RUN WITHOUT THE DEBUGGER OR BOOTLADED */
/* Any loaded code will be wiped from RAM on a power cycle. */
.coderam :
{
. = ALIGN(4);
__RAM_CODE_SECTION_START = .;
*(.text.imu*)
. = ALIGN(4);
__RAM_CODE_SECTION_END = .;

}>FLASH//CODE_RAM


/* The program code and other data goes into FLASH */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)

KEEP (*(.init))
KEEP (*(.fini))

. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH


每个imu驱动程序函数都以imu *开头,因此我试图通过 *(.text.imu*)行将所有imu函数加载到RAM,我试图指定imu.o,但是经过大量搜索和查找后却找不到正确的语法反复试验。我通过注释位在将imu。*存储在闪存和RAM之间进行切换。请注意,当我使用闪存时,它将其存储在地址0x0中,为什么呢?我认为这是一个非常初学者的问题,但是我不知道不明白为什么。

问题:
我在初始化函数中遇到问题,这是对RAM代码的第一个函数调用。这是C代码片段:

uint8_t imu_init(void)
{
uint8_t retry_cnt = 0U;

imu_trans.device_csn_bank = IMU_CSN_BANK;
imu_trans.device_csn_pin = IMU_CSN_PIN;
imu_trans.device = DEVICE_IMU;
imu_trans.speed = SPI_SPEED_6_75MBIT;
imu_trans.rxBuf = imuRxBuf;
**Continues, but hard fault occurs earlier**


通过查看程序集,从RAM运行时,以下代码在我的init函数中运行:

                                          imu_init:
20010000: 0x000080b5 imu_init+0 push {r7, lr}
20010002: 0x000082b0 imu_init+2 sub sp, #8
20010004: 0x000000af imu_init+4 add r7, sp, #0
69 uint8_t retry_cnt = 0U;
20010006: 0x00000023 imu_init+6 movs r3, #0
20010008: 0x00000000 imu_init+8 movs r0, r0
71 imu_trans.device_csn_bank = IMU_CSN_BANK;
2001000a: 0x00001d4b imu_init+10 ldr r3, [pc, #116] ; (0x20010080 <imu_init+128>)
2001000c: 0x00000000 imu_init+12 movs r0, r0
2001000e: 0x00000060 imu_init+14 str r0, [r0, #0]
72 imu_trans.device_csn_pin = IMU_CSN_PIN;
20010010: 0x00fb7100 imu_init+16 ; <UNDEFINED> instruction: 0xfb000071
20010014: 0x0000001d imu_init+20 adds r0, r0, #4
20010016: 0x00004a5a imu_init+22 ldrh r2, [r1, r1]
73 imu_trans.device = DEVICE_IMU;
20010018: 0x0000001b imu_init+24 subs r0, r0, r4
2001001a: 0x00004b4f imu_init+26 ldr r7, [pc, #300] ; (0x20010148 <imu_process_vals+4>)
2001001c: 0x0000f400 imu_init+28 lsls r4, r6, #3
74 imu_trans.speed = SPI_SPEED_6_75MBIT;


显然,它在 20010010: 0x00fb7100 imu_init+16 ; <UNDEFINED> instruction: 0xfb000071行上进行了故障修复。有趣的是(这是我没有得到的),它不在十六进制文件中!!!

*snip*
:020000042001D9
:1000000080B582B000AF0023FB711D4B1D4A5A60C2
:100010001B4B4FF480721A80194B01221A72184B35
*snip*


第三行的开头是hardfault指令!
但是内存浏览器显示:

0x0000000020010000  B082B580 2300AF00 4B1D0000  .µ.°.¯.#...K
0x000000002001000C 60000000 0071FB00 5A4A1D00 ...`.ûq...JZ


因此,看起来RAM中似乎有一条错误的指令,但是为什么!看起来0x2001000C也损坏了,因为它与十六进制文件不匹配。最初,我认为加载过程中正在执行某些操作,但是如果我也在重置处理程序中设置了断点,也会发生这种情况,因此我不了解原因。我当时以为是SWD损坏,但每次都一样,因此我不确定这也是一个因素。我本来以为其中一些指令是等待状态(mov r0,r0),但现在我认为它们是损坏的值?

毫不奇怪,加载到闪存中的代码与十六进制文件读取的内容相同:

0x000000000800AEC4  B082B580 2300AF00 4B1D71FB 605A4A1D F44F4B1B 801A7280  .µ.°.¯.#ûq.K.JZ`.KOô.r..
0x000000000800AEDC 22014B19 4B18721A 729A2202 4A184B16 4B1560DA 611A4A17 .K.".r.K.".r.K.JÚ`.K.J.a


因此,TL; DR:
1.如果我将所有内容都加载到Flash中,则可以正常工作
2.如果我将imu驱动程序加载到RAM以及其他所有内容都存储在闪存中,则它会发生故障
3.如果我打开调试优化-Og,它可以再次工作,但是可能会将错误移到其他地方。

任何帮助将不胜感激,我花了大约30个小时试图使这个看似简单的东西开始工作(它确实起作用了,然后停止了),并且我没有足够的想法去尝试。

谢谢,
缺口

编辑

我想我可能已经对此进行了进一步的追溯...我尝试从ST链接实用程序加载相同的文件并查看内存,然后尝试加载调试器并查看内存。

当然,调试器加载的代码与ST Link util加载的代码不同。 ST链接工具加载的代码按预期方式工作-USB枚举并发送数据。

我进行了比较,第二个RAM地址之后的所有内容(0x20010008之后的所有内容)都损坏了。

因此,这可能是调试器设置问题?我正在通过SWD使用STlinkV3-该项目是否需要特殊的设置才能从RAM运行?同样,有时它可以从RAM正常运行,但其他时候则不能。

最佳答案

这最终成为truestudio的问题。我不确定这是否是我正在使用的特定版本,但是在truestudio中使用调试功能时,调试器将不会始终对RAM进行编程。

解决方法是使用STM32CubeProg,但这意味着不进行调试。

有趣的是,仅将ST链接配置为外部工具即可正常工作。
https://info.atollic.com/hubfs/AppNotes/st_link_utility_as_ext-tool.pdf

现在,代码可以从flash / ram运行/执行,并且它们之间的过渡没有问题。

关于c - STM32F7-从RAM和闪存执行代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55389711/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com