首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在运行时确定ARM的M3内存大小

在运行时确定ARM的M3内存大小
EN

Stack Overflow用户
提问于 2014-05-01 16:21:04
回答 5查看 5.1K关注 0票数 6

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

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

最明显的解决方案是运行内存地址,检查哪些地址是可读/可写的,但当从内存地址太高(我不知道如何恢复)时,我尝试了这个和芯片HardFaults。

有什么办法能解决这个问题吗?理想情况下,我会进行实验,因为一些芯片(比如我现在使用的STM32F103RCT6 )看起来实际有64 48的内存,尽管数据表显示它们有48 48。例如,0x1FFFF7E0寄存器报告了256 is的可用闪存,尽管512 is是可用的。

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

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2014-05-08 16:46:39

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

首先,您需要启用BusFault IRQ:

SCB->SHCSR |= SCB_SHCSR_BUSFAULTENA;

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

代码语言:javascript
复制
__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都是空操作而被愚弄)。

票数 3
EN

Stack Overflow用户

发布于 2017-04-10 23:59:22

我发现,通过设置FAULTMASK位(禁用所有中断和故障处理程序),同时设置BFHFNMIGN位,可以探测访问地址是否会在不引发异常的情况下生成总线故障。不引发异常的好处意味着您不必编写异常处理程序。下面的示例是一个执行探测的C函数:

代码语言:javascript
复制
/**
 * @brief Probe an address to see if can be read without generating a bus fault
 * @details This function must be called with the processor in privileged mode.
 *          It:
 *          - Clear any previous indication of a bus fault in the BFARV bit
 *          - Temporarily sets the processor to Ignore Bus Faults with all interrupts and fault handlers disabled
 *          - Attempt to read from read_address, ignoring the result
 *          - Checks to see if the read caused a bus fault, by checking the BFARV bit is set
 *          - Re-enables Bus Faults and all interrupts and fault handlers
 * @param[in] read_address The address to try reading a byte from
 * @return Returns true if no bus fault occurred reading from read_address, or false if a bus fault occurred.
 */
bool read_probe (volatile const char *read_address)
{
    bool address_readable = true;

    /* Clear any existing indication of a bus fault - BFARV is write one to clear */
    HWREG (NVIC_FAULT_STAT) |= NVIC_FAULT_STAT_BFARV;

    HWREG (NVIC_CFG_CTRL) |= NVIC_CFG_CTRL_BFHFNMIGN;
    asm volatile ("  CPSID f;");
    *read_address;
    if ((HWREG (NVIC_FAULT_STAT) & NVIC_FAULT_STAT_BFARV) != 0)
    {
        address_readable = false;
    }
    asm volatile ("  CPSIE f;");
    HWREG (NVIC_CFG_CTRL) &= ~NVIC_CFG_CTRL_BFHFNMIGN;

    return address_readable;
}

该代码是为德州仪器ARM编译器编写的,使用德州仪器TivaWare软件进行注册定义,并在基于Cortex-M4F的TM4C设备上进行测试。理论上,它应该在其他的Cortex-M3或Cortex-M4设备上工作。

票数 1
EN

Stack Overflow用户

发布于 2019-05-03 21:27:54

在具有不同SRAM大小的MCU上运行相同二进制程序的一个相关问题是,堆栈指针(SP)在重置时以0的值初始化。通常,在构建程序时,编译器/启动文件/链接器脚本将SRAM顶部的值(适当地对齐)放置在0位置。因此,当您的二进制文件放在具有更多SRAM的机器上时,堆栈现在不再位于SRAM的顶部。如果要利用更大的SRAM大小,程序必须将堆栈重新定位到SRAM的真正顶部。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23411824

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档