背景
最近搞keaz128的flash读写时需要向一个寄存器写入0x80,发现其中一段代码很有意思,代码如下
volatile uint8 s_flash_command_run[] = {0x00, 0xB5, 0x80, 0x21, 0x01, 0x70, 0x01, 0x78, 0x09, 0x06, 0xFC, 0xD5, 0x00, 0xBD};
typedef void (*flash_run_entry_t)(volatile uint8 *reg);
flash_run_entry_t s_flash_run_entry;
//内部使用
uint8 FlashCmdStart(void)
{
while(FTF->FSTAT & FTMRE_FSTAT_MGBUSY_MASK){}; //等待前一个命令执行完成
DisableInterrupts;
FTF->FSTAT |= FTMRE_FSTAT_CCIF_MASK | FTMRE_FSTAT_FPVIOL_MASK | FTMRE_FSTAT_ACCERR_MASK;
s_flash_run_entry = (flash_run_entry_t)((uint32)s_flash_command_run + 1);
s_flash_run_entry(&FTF->FSTAT);
// FTF->FSTAT |=FTMRE_FSTAT_CCIF_MASK;
EnableInterrupts;
while(!(FTF->FSTAT & FTMRE_FSTAT_CCIF_MASK)); //等待命令完成
//while(FTF->FSTAT & FTMRE_FSTAT_ACCERR_MASK); //检测到总线错误
if(FTF->FSTAT & (FTMRE_FSTAT_ACCERR_MASK | FTMRE_FSTAT_FPVIOL_MASK | FTMRE_FSTAT_MGSTAT_MASK))
{
return 1; //出现错误
}
return 0; //成功
}
分析
其中让我感到迷惑的是这两句
s_flash_run_entry = (flash_run_entry_t)((uint32)s_flash_command_run + 1);
s_flash_run_entry(&FTF->FSTAT);
经过分析,并查看反汇编代码,结果如下
首先s_flash_command_run定义为一个数组首地址为0x1FFFF000,所以经过强制转换s_flash_run_entry函数的入口地址即为0x1FFFF001。

查看反汇编发现数组中的内容正好是二进制代码,和数组内容一一对应。

非常牛逼
文章分析了在keaz128设备中,向寄存器写入特定值以执行flash命令的过程,涉及volatile数组、函数指针和中断管理。作者揭示了一个巧妙的编程技巧,通过将数组地址加1作为函数入口地址,并通过反汇编验证了这种映射方式。
15万+

被折叠的 条评论
为什么被折叠?



