c - 从 RAM 而不是闪存运行代码块
问题描述
在下面的程序中,这行代码是什么意思
fnRAM_code((volatile unsigned char *)FLASH_STATUS_REGISTER); // execute the command from SRAM
在下面的代码部分。我对这里发生的事情有一些想法,为了克服读写冲突,使用上面的代码行将代码从闪存复制到 RAM。但是这些行的确切含义是什么。
static int fnProgram(unsigned long *ptrWord, unsigned long *ptr_ulWord)
{
while ((FTFL_FSTAT & FTFL_STAT_CCIF) == 0) {} // wait for previous commands to complete
if ((FTFL_FSTAT & (FTFL_STAT_ACCERR | FTFL_STAT_FPVIOL | FTFL_STAT_RDCOLERR)) != 0) { // check for errors in previous command
FTFL_FSTAT = (FTFL_STAT_ACCERR | FTFL_STAT_FPVIOL | FTFL_STAT_RDCOLERR); // clear old errors
}
FTFL_FCCOB0 = FCMD_PROGRAM; // enter the command sequence
FTFL_FCCOB1 = (unsigned char)(((CAST_POINTER_ARITHMETIC)ptrWord) >> 16); // set address in flash
FTFL_FCCOB2 = (unsigned char)(((CAST_POINTER_ARITHMETIC)ptrWord) >> 8);
FTFL_FCCOB3 = (unsigned char)((CAST_POINTER_ARITHMETIC)ptrWord);
FTFL_FCCOB7_4 = *ptr_ulWord++; // enter the long word to be programmed
FTFL_FCCOBB_8 = *ptr_ulWord; // enter the second long word to be programmed
uDisable_Interrupt(); // protect this region from interrupts
fnRAM_code((volatile unsigned char *)FLASH_STATUS_REGISTER); // execute the command from SRAM
uEnable_Interrupt(); // safe to accept interrupts again
return (FTFL_FSTAT & (FTFL_STAT_ACCERR | FTFL_STAT_FPVIOL | FTFL_STAT_MGSTAT0)); // if there was an error this will be non-zero
}
需要在 RAM 中的唯一代码是:
static void fnFlashRoutineInRam(volatile unsigned char *ptrFTFL_BLOCK)
{
*ptrFTFL_BLOCK = FTFL_STAT_CCIF; // launch the command - this clears the FTFL_STAT_CCIF flag (register is FTFL_FSTAT)
while ((*ptrFTFL_BLOCK & FTFL_STAT_CCIF) == 0) {} // wait for the command to terminate
}
解决方案
这看起来像旧的 NXP(前飞思卡尔/摩托罗拉)HCS08、HCS12 或 Coldfire。在这些设备上,您在编写闪存驱动程序时有不同的情况:您可以从闪存执行它,或者您不能。这完全取决于程序闪存属于哪个“存储库”:通常,您无法在 MCU 上执行与当前正在编程的闪存存储库相同的代码。
因此,理想情况下,您将闪存编程代码放在另一个存储区中,但有些设备只有一个闪存存储区。然后他们通过从 RAM 中执行代码来提供解决方法,这是一种快速而肮脏的修复。
通常,他们通过提供一组原始数据操作码来解决这个问题。这个操作码数组被复制到 RAM 中,然后他们设置一个函数指针指向 RAM 地址。我怀疑fnRAM_code
是这样一个函数指针。该(volatile unsigned char *)FLASH_STATUS_REGISTER
部分只是传递闪存状态寄存器的地址。FLASH_STATUS_REGISTER 可能与 FSTAT 同义。
和应该分别对应于uDisable_Interrupt();
和,阻止所有可屏蔽中断在闪存写入期间触发,这可能会导致写入失败或程序挂起。uEnable_Interrupt();
asm SEI
asm CLI
应该有可用的应用说明来详细描述所有这些。
请注意,此代码非常接近硬件,并且依赖于大量定义不明确的行为。除了 Codewarrior 编译器之外,我不会指望它按预期编译。例如,gcc 会吐出许多严格的别名错误。
推荐阅读
- toad - Toad for Oracle Grid 是只读的
- android - 强制 RTL 布局方向不起作用
- java - BIGINT UNSIGNED 自动增量被 mybatis 破坏
- python - 从 HEC-RAS 中提取数据
- google-maps - 将 Google Maps Static API 归属移动到右上角
- android - Retrofit - 如果字段的数据类型不同,我该如何忽略它?
- rdf - 如何根据其他 ObjectProperty 的断言使用 1 个对象属性,然后在 OWL 中对个体进行推理
- python - 按文本顺序对列表中的句子进行排序
- javascript - IOS/Safari 下拉菜单是预选的
- python - 我正在尝试从 python 中的网站中提取数据