在运行时确定 ARM Cortex M3 RAM 大小 [英] Determining ARM Cortex M3 RAM Size at run time

查看:23
本文介绍了在运行时确定 ARM Cortex M3 RAM 大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm developing some software for STM32F103-based ARM microcontrollers (compiling with GCC). A few of my users want to be able to use the same binary with different versions of the same chip (that have more RAM), so I need a way of finding out how much RAM I have at runtime.

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

There's an address (0x1FFFF7E0) that contains the flash size, but it seems there isn't one that contains the RAM size!

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

The obvious solution is just to run up the memory addresses checking which ones are read/writable, but I've tried this and the chip HardFaults when reading from a RAM address that's too high (and I'm not sure how to recover).

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

Any thoughts on the best way to figure this out? Ideally I would do it experimentally as some chips (like the STM32F103RCT6 I'm using now) actually appear to have 64kB of RAM even though the datasheet suggests they have 48. For instance the 0x1FFFF7E0 register reports 256kB of available flash even though 512kB is usable.

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

It looks like I might be able to set the BFHFNMIGN bit in the CCR register, and then try and access the memory from within a software interrupt - however I have no idea how to call or create a software interrupt in GCC+STM32

推荐答案

好的,我终于在 ST 论坛上的用户的帮助下解决了这个问题.

Right, I finally figured this out with the help of users on ST's forum.

首先,您需要启用 BusFault IRQ:

First, you need to enable the BusFault IRQ:

SCB->SHCSR |= SCB_SHCSR_BUSFAULTENA;

然后,您需要定义一个 BusFault 处理程序,它将程序计数器加 2 以跳过违规指令(赌它实际上是一条 2 字节指令):

Then, you need to define a BusFault handler which will increment the program counter by 2 in order to skip over the offending instruction (taking a gamble that it is in fact a 2-byte instruction) :

__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 处理程序,但我们会跳过读或写指令,就好像它不存在一样.

And now - FINALLY - we can try and read from an arbitrary memory location. If it's wrong, the BusFault handler gets called, but we skip over the read or write instruction as if it wasn't there.

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

This means that it's relatively easy to write to a memory location and then read back - and if you get the same thing, you know it's valid (you just need to make sure that your code isn't fooled by having both str and ldr as no-ops).

这篇关于在运行时确定 ARM Cortex M3 RAM 大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆