我在拇指模式下使用 STM32L486ZG 开发板。我正在运行一个没有任何 RTOS 的简单裸机应用程序。我使用 FSM 将外部 SRAM 连接到电路板。外部 SRAM 位于地址 0x60000000。系统已初始化并以 72MHz 的频率运行(我已经在 18-80 MHz 的频率上尝试过这个问题)现在在我的主要功能中我有以下代码:
int main(){
asm volatile (
"push {r0}\n"
"mov r0, #0x60000000\n"
"add r0, #0x400\n"
"stmdb r0!, {r1-r12}\n"
"ldmia r0!, {r1-r12}\n"
"pop {r0}\n"
);
}
根据此代码,在执行此主函数后不应更改任何寄存器,但在执行以下指令后情况并非如此
ldmia r0!, {r1-r12}
即r9
执行后不正确。 stmdb
指令工作正常,但 ldmia
没有正确加载数据。我已经通过查看内存中的内容验证了这一点。
此问题对于 ldmia
中的任何参数都存在说明:始终影响第9个寄存器。
解释: 假设我正在调试这段代码,下一条要执行的指令是:
stmdb r0!, {r1-r12}
在加紧之后所有这些寄存器都被保存在内存中并且值r0
是0x600003d0
内存内容:
0x600003D0 00000000 40021008 0000000C .......@....
0x600003DC 40000000 00000000 00000000 ...@........
0x600003E8 20017FEC 00000000 00000000 ì.. ........
0x600003F4 00000000 00000000 00000000 ............
寄存器内容:
r0 0x600003d0
r1 0x00000000
r2 0x40021008
r3 0x0000000c
r4 0x40000000
r5 0x00000000
r6 0x00000000
r7 0x20017fec
r8 0x00000000
r9 0x00000000
r10 0x00000000
r11 0x00000000
r12 0x00000000
这说明所有的寄存器都成功保存到内存中了。现在我执行下一条指令
ldmia r0!, {r1-r12}
之后 这些是寄存器的内容:
r0 0x60000400
r1 0x00000000
r2 0x40021008
r3 0x0000000c
r4 0x40000000
r5 0x00000000
r6 0x00000000
r7 0x20017fec
r8 0x00000000
r9 0x555555d5
r10 0x00000000
r11 0x00000000
r12 0x00000000
如您所见,除r9
外,所有寄存器都已恢复奇怪的是它的值从 0x60000000
中“弹出”而不是 0x600003F0
.
知道是什么导致了这个问题。我正在使用 Jlink 写入闪存。
附言当寄存器保存到片上 SRAM 而不是外部 SRAM 时,不会发生此问题;
编辑 如果指令
ldmia r0!, {r1-r12}
分为两部分:
ldmia r0!, {r1-r6}
ldmia r0!, {r7-r12}
那么所有的寄存器都恢复成功
最佳答案
您需要阅读 STM32L4xx6xx 芯片限制。 FMC 不支持第 2.2.4 节读取九个字或更多字的突发访问。 ( DocID026121 Rev 4 ) 可从 ST 获得。
“对 FMC 的 CPU 读取突发访问等于或超过 9 个寄存器返回损坏的数据 从读到的第 9 个字开始。这些突发只能由 Cortex®-M4 CPU 生成 而不是其他大师(即不是 DMA)。 当堆栈重新映射到 FMC 上的外部存储器并且 POP 操作使用 9 个或更多寄存器执行。 当 LDM/VLDM 操作与 9 个或更多寄存器一起使用时,也会发生这种情况。”
关于gcc - LDMIA 指令在皮质 M4 的外部 SRAM 上无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41265112/