gcc - 在运行时确定 ARM Cortex M3 RAM 大小

标签 gcc arm runtime ram cortex-m3

我正在为基于 STM32F103 的 ARM 微 Controller (使用 GCC 编译)开发一些软件。我的一些用户希望能够对同一芯片的不同版本(具有更多 RAM)使用相同的二进制文件,因此我需要一种方法来找出运行时我有多少 RAM。

有一个地址 (0x1FFFF7E0) 包含闪存大小,但似乎没有包含 RAM 大小的地址!

显而易见的解决方案是运行内存地址检查哪些是可读/可写的,但我已经尝试过这个和芯片 HardFaults 从太高的 RAM 地址读取时(我不知道如何恢复)。

关于解决这个问题的最佳方法有什么想法吗?理想情况下,我会以实验方式进行,因为某些芯片(例如我现在使用的 STM32F103RCT6)实际上似乎具有 64kB 的 RAM,即使数据表表明它们有 48 个。例如,0x1FFFF7E0 寄存器报告 256kB 的可用闪存,即使 512kB 可用.

看起来我可以在 CCR 寄存器中设置 BFHFNMIGN 位,然后尝试从软件中断中访问内存 - 但是我不知道如何在 GCC+STM32 中调用或创建软件中断

最佳答案

是的,我终于在 ST 论坛上的用户的帮助下弄清楚了这一点。

首先,您需要启用 BusFault IRQ:
SCB->SHCSR |= SCB_SHCSR_BUSFAULTENA;
然后,您需要定义一个 BusFault 处理程序,它将程序计数器增加 2 以跳过违规指令(赌它实际上是一个 2 字节指令):

__attribute__ ((naked)) void BusFault_Handler(void) {
  /* NAKED function so we can be sure that SP is correct when we
   * run our asm code below */

  // DO NOT clear the busfault active flag - it causes a hard fault!

  /* Instead, we must increase the value of the PC, so that when we
   * return, we don't return to the same instruction.
   *
   * Registers are stacked as follows: r0,r1,r2,r3,r12,lr,pc,xPSR
   * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0337e/Babedgea.html
   *
   * So we want PC - the 6th down * 4 bytes = 24
   *
   * Then we add 2 - which IS DANGEROUS because we're assuming that the op
   * is 2 bytes, but it COULD be 4.
   */
  __asm__(
      "ldr r0, [sp, #24]\n"  // load the PC
      "add r0, #2\n"         // increase by 2 - dangerous, see above
      "str r0, [sp, #24]\n"  // save the PC back
      "bx lr\n"              // Return (function is naked so we must do this explicitly)
  );
}

现在 - 最后 - 我们可以尝试从任意内存位置读取。如果错误,则调用 BusFault 处理程序,但我们跳过读或写指令,就好像它不存在一样。

这意味着写入内存位置然后读回相对容易 - 如果你得到相同的东西,你就知道它是有效的(你只需要确保你的代码不会被 str 和 ldr 作为无操作)。

关于gcc - 在运行时确定 ARM Cortex M3 RAM 大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23411824/

相关文章:

debugging - 暂停调试器时 STM32 卡住外围设备

linux - 无法让 Rebol3 在 Linux-ARMhf 上运行

if-statement - Julia 中的一个简单的 'if' 语句将我的主筛的运行时间增加了 15 倍——为什么?

java - Servlet 和命令模式,编译还是运行时?

macos - 无法在 Mac 上升级 gcc

适用于 68HC12/68HC12X 的 GCC 工具链

c - 哪个初始化程序适合 int64_t?

arm - 从 linux 交叉编译到 ARM-ELF (armv5tejl )

python - Ctypes 找不到我加载的 dll 的 dll 依赖项

c - Libcurl 问题 - "initializer element is not constant"