【发布时间】:2020-08-07 17:50:42
【问题描述】:
我正在使用类似 arduino 的微控制器(ARM 指令集),它具有一些不连续的 32 位内存映射寄存器(控制/状态寄存器,CSR),如下所示:
#define Comparator0_CSR0 0xA000
(No 0xA004 register)
#define Comparator0_CSR2 0xA008
#define Comparator0_CSR3 0xA00C
#define Comparator1_CSR0 0xB000
#define Comparator1_CSR1 0xB004
(No 0xB008 register)
#define Comparator1_CSR3 0xB00C
.... on and on, the 0xF000 field ranges from 0x3000-0xD000, the 0xF field ranges from 0>0xC in steps of 0x4 (32b)
我正在尝试调试一些代码,并且需要将整个内存区域从 0x3000 到 0xD00C 读取到设备崩溃时我可以读取的持久存储中(这就是 read_and_store(register_address) 函数的作用)。
不幸的是,我剩下的代码空间非常有限,无法编写可以独立读取每个寄存器的长代码(相信我,我试过了,下面的示例)
我已经提出了一个合理的基于循环的可能解决方案(由于下面描述的原因不起作用),它适合代码空间:
for(int i=3;i<=0xD;i++)
{
for(int j=0;j<=0x10;j+=4)
{
read_and_store_register((0x1000 * i) + (0x4 * j))
}
}
但我显然正在阅读不存在的内存,这导致我的设备崩溃。有什么方法可以让我通过在读取之前检查它是否存在或其他方法来安全地读取此内存?
尝试读取一个代码块中的所有寄存器会占用比我更多的代码空间:
{
read_and_store_register(Comparator0_CSR0)
read_and_store_register(Comparator0_CSR2)
read_and_store_register(Comparator0_CSR3)
read_and_store_register(Comparator1_CSR0)
....
}
所以我需要某种受控循环。
我还想知道是否可以将所有寄存器名称#define 为宏,并在宏中为那些没有与之关联的真实寄存器的寄存器执行某种 read(0),然后执行以下操作:
#define COMP_NAME(x,y) Comparator##x##CSR##y
for(int i=3;i<=0xD;i++)
{
for(int j=0;j<=0x4;j+=1)
{
read_and_store_register(COMP_NAME(i,j))
}
}
但显然这不是 x##y##z 宏的工作方式(它试图读取一个字面上名为 COMPARATORiCSRj 的寄存器,这根本不是我想要的)
如果答案是否合理,我会接受这个答案。但我觉得我不得不问。感谢您的宝贵时间。
【问题讨论】:
-
你要读取多少个寄存器,
read_and_store_register是做什么的?也许您可以定义一个包含所有寄存器地址的常量数组并循环遍历该数组? -
(0xD-0x3)*4=40,在本例中,但无论我需要阅读的数字如何,问题都存在。 Read_and_store 将内存复制到设备崩溃时我可以读取的持久存储系统,我已相应地编辑了问题,谢谢。
-
如果 CPU 在无效访问时引发中断,则有可能使用 ISR 中止读取/存储的特定调用并推动 for 循环。
-
您必须研究您的特定设备提供了什么,以测试特定寄存器是否存在,或者如果不存在如何恢复。这个问题没有通用的答案——C 语言本身当然没有这样的概念。因此,为了获得答案,您必须更具体地了解您的设备、编译器、环境等(并请相应地标记)。
-
在我看来,Bodo 对数组的建议最多需要
(0xd - 0x3 + 1) * 4 * 2 bytes = 88 bytes。然后你可以编写一个小而简单的循环来遍历数组。或者,您可以拥有一个不存在的寄存器数组,循环整个集合并跳过数组中的每个寄存器。如果数组是有序的,那么这也不难。
标签: c microcontroller c99