背景
最近搞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。
查看反汇编发现数组中的内容正好是二进制代码,和数组内容一一对应。
非常牛逼