【全球快播报】KeilMDK制作FlashDriver
①在ECU OTA 程序升级过程中,需要执行一段比较特殊的代码,这段代码实现对自身flash的擦除与写入,又称flash driver;②为了安全的考虑,会尽可能的避免在代码中固化有对flash空间进行擦除或写入的操作,主要为了避免在程序跑飞时误调用该部分代码,使软件代码部分受到破坏;③在OTA开始后,会先传入flash driver到RAM中,再开始刷写APP④在OTA完成之后,会执行11 01 MCU复位的操作,复位前会清除这部分RAM空间,或者重新给ECU上电后,flash driver就失能了。⑤本文参考自github的SummerFalls:UDS_S32K144_FlashDriver 工程链接:https://github.com/SummerFalls/UDS_S32K144_FlashDriver
(资料图)
这部分可以参考芯片手册(建议选一块单独的flash空间)
#define DAFLASH_START 0x01010000#define DAFLASH_SIZE 0x00010000 /* 64KB */1.2、定义函数存储的地址段同理,
这部分数据也可以自定义①RW_IROM_FlashDrvOffset :这部分用于存储偏移量地址,比如有擦除和写入两个函数,那么就是0x1010000 0x00000008,我这边有三个,所以是0x0000000C②RW_IROM_FlashDrv :这部分用于存储flash driver函数
LR_IROM3 DAFLASH_START DAFLASH_SIZE ; 定义加载空间地址和大小,对应工程设置的IROM3。LR_IROM3是加载空间的名称{RW_IROM_FlashDrvOffset 0x01010000 0x0000000C{ *(.Flash_Driver_Section_Offset)}RW_IROM_FlashDrv 0x0101000C 0x000005C4{ *(.Flash_Driver_Section)}}2、定义相关结构体、数据类型和宏定义2.1、数据宏定义说明
#define FLASH_DRV_OFFSET (0x0101000C) //用于定位驱动函数起始地址段#define CAL_OFFSET(funcPtr) ((uint32_t)(funcPtr) - FLASH_DRV_OFFSET) //用于定位驱动函数的起始地址#define FLASH_DRIVER_SECTION __attribute__((section (".Flash_Driver_Section"))) //用于指定驱动函数存放的地址段#define FLASH_DRIVER_SECTION_OFFSET __attribute__((section (".Flash_Driver_Section_Offset"))) //用于指定驱动函数偏移量存放的地址段2.2、数据类型定义说明
这部分的三个函数,可以参考芯片的SDK库进行定义
typedef ResultStatus_t (*tpfFLASH_WaitCmdComplete) (flash_cb_t callBack);typedef ResultStatus_t (*tpfFLASH_WaitEraseAllComplete) (flash_cb_t callBack);typedef ResultStatus_t (*tpfFLASH_ExecuteCommandInt) (FLASH_CMD_t cmd);2.3、结构体定义说明
此部分三个函数指针,用于之后映射flash驱动函数
typedef struct{ tpfFLASH_WaitCmdComplete pfFLASH_WaitCmdComplete; tpfFLASH_WaitEraseAllComplete pfFLASH_WaitEraseAllComplete; tpfFLASH_ExecuteCommandInt pfFLASH_ExecuteCommandInt;} tFlashDriverAPIInfo;3、将驱动函数存放到指定区域3.1、函数声明
将操作Flash的几个驱动函数存放到指定地址,注意这几个函数里边不能再包含其他函数或者全局变量,如果有调用其他函数的话,需要使用do...while语句进行展开
__attribute__((used)) FLASH_DRIVER_SECTION static ResultStatus_t FLASH_WaitCmdComplete(flash_cb_t callBack);__attribute__((used)) FLASH_DRIVER_SECTION static ResultStatus_t FLASH_WaitEraseAllComplete(flash_cb_t callBack);__attribute__((used)) FLASH_DRIVER_SECTION static ResultStatus_t FLASH_ExecuteCommandInt(FLASH_CMD_t cmd);__attribute__((used)) NVM_DRIVER_SECTION_OFFSET static const tFlashDriverAPIInfo gs_FlashDriverAPI = { (tpfFLASH_WaitCmdComplete) CAL_OFFSET(FLASH_WaitCmdComplete), (tpfFLASH_WaitEraseAllComplete) CAL_OFFSET(FLASH_WaitEraseAllComplete), (tpfFLASH_ExecuteCommandInt) CAL_OFFSET(FLASH_ExecuteCommandInt),};3.2、编译后查看map文件,获取地址信息
可以看到3.1的3个函数地址已经明确了
3.3、提取hex文件编译后,找到hex文件,利用hexview提取相应信息:(这里我已经删除了其他地址的数据)
这里需要注意的是,map文件中的起始地址需要向前一位开始复制:
FuncionName | Address |
FLASH_WaitCmdComplete | 0x0101000C-0x0101004B |
FLASH_WaitEraseAllComplete | 0x0101004C-0x0101008B |
FLASH_ExecuteCommandInt | 0x0101008C-0x010100C3 |
将对应地址的hex数据提取出来,存放到一个数组(注意需要对齐,可以参考__):
3.5、将函数指针重定向将之前定义的函数指针进行重定向:
tpfFLASH_WaitCmdComplete FLASH_WaitCmdComplete = (WaitCmdComplete_Handler)(u8WaitCmdComplete + 1);tpfFLASH_WaitEraseAllComplete FLASH_WaitEraseAllComplete = (WaitEraseAllComplete_Handler)(u8WaitEraseAllComplete + 1);tpfFLASH_ExecuteCommandInt FLASH_ExecuteCommandInt = (ExecuteCommandInt_Handler)(u8ExecuteCommandInt + 1);
这里+1的原因是,在ARM体系结构中,指令的最低有效位(LSB)被用来区分ARM指令和Thumb指令。当LSB为0时,表示该指令是一个32位的ARM指令;当LSB为1时,表示该指令是一个16位的Thumb指令。在某些情况下,为了兼容不同指令集的代码,在进行指令访问时可能会对地址进行微调。当访问Thumb指令时,将地址的最低位设置为1,以表示要访问的是Thumb代码;当访问ARM指令时,将地址的最低位设置为0,以表示要访问的是ARM指令。
3.6、Debug测试开始Debug调试......:先定义两个测试函数:
先把0x01010000开始的这部分地址数据擦掉:
这里后边有数据是因为最小写入16个字节
到这里就验证完了。
4、生成FalshDriver文件4.1、用hexview操作把提取到的文件在hexview中打开,然后在左上角窗口cut这部分数据
然后粘贴到指定地址(因为这部分数据是要传到RAM里边的,所以起始地址需要在RAM部分),我这里是存在了0x200039F0开始的地址
然后在keil里边利用之前创建的函数指针重定向这部分数据先定义好函数的起始地址:
#define FLS_WAIT_CMD_ADD 0x200039FC#define FLS_WAIT_ERASE_ADD 0x20003A3C#define FLS_EXEC_CMD_INT_ADD 0x20003A7C
然后将函数指针重定向:
void FlashApiInit(){ FLASH_WaitCmdComplete = (tpfFLASH_WaitCmdComplete)(FLS_WAIT_CMD_ADD + 1); FLASH_WaitEraseAllComplete = (tpfFLASH_WaitEraseAllComplete)(FLS_WAIT_ERASE_ADD + 1); FLASH_ExecuteCommandInt = (tpfFLASH_ExecuteCommandInt )(FLS_EXEC_CMD_INT_ADD + 1);}
只需要在传入FlashDriver后,调用这个函数即可,注意存放这部分的RAM空间在这过程中应该是没有被其他代码使用的,不然可能会出错。
三、End被这部分折磨了挺久,好在终于搞定了,如果对大家有帮助的话,点个赞把。
关键词:
- 骑士队的第三巨头凯文·乐福沦落为替补 场均总出手数不过10.3次
- 女童不慎掉入20米深井 18岁小姨三次下井成功营救
- 西安3个区域12月28日起每日开展全员核酸 官方提倡民众居家健身
- 浙江乐清一核酸检测结果异常人员 复采复检为阴性
- 浙江本轮疫情报告确诊病例490例 提倡“双节”非必要不出省
- 西安警方通报6起涉疫违法案件
- 西安新一轮核酸筛查日检测能力达160万管
- 西安市累计报告本土确诊病例811例
- 重庆曝光4起违反中央八项规定精神典型问题 警示党员干部清新过节
- 云南清水河边检站查获走私玉石和玉石毛料65公斤
-
广东启用涉疫风险人员排查12320专号
中新网广州12月28日电 (记者 蔡敏婕)广东省28日正式启用涉疫风险人员排查12320专号。即日起,涉疫风险人员来(返)粤前可在“粤省事”
-
武汉协和医院开设互联网儿童医学中心
中新网武汉12月28日电 (聂文闻 彭锦弦 陈有为)记者28日从华中科技大学附属协和医院(以下简称“武汉协和医院”)获悉,该院在湖北省首
-
四川:力争三年完成638个历史遗留矿山生态修复
中新网成都12月28日电 (杨予頔)28日,四川省自然资源厅发布消息称,近日,四川省自然资源厅印发了《四川省历史遗留矿山生态修复三年行
-
不同养老模式共同推进 提升老年福祉 让老人享受“温暖夕阳”
我为群众办实事 | 不同养老模式共同推进 提升老年福祉 让老人享受“温暖夕阳” 央视网消息:近期,各地在“我为群众办实事”实
-
各地创新举措 把实事办好 把好事落细 温暖民心
我为群众办实事 | 各地创新举措 把实事办好 把好事落细 温暖民心 央视网消息:近期,各地在“我为群众办实事”实践活动中,
-
新疆伊犁州新源县发生3.3级地震 震源深度13千米
中新网12月28日电 中国地震台网正式测定:12月28日15时14分在新疆伊犁州新源县(北纬43 37度,东经82 65度)发生3 3级地震,震源深度13千米。
-
2021,比个心吧!
-
高风险岗位人员出行,会受到限制吗?
【两节防疫提示】高风险岗位人员出行,会受到限制吗?
-
【两节防疫提示】健康码“变黄”,对出行有何影响?
-
【挑战365天正能量速写画】第028期:卫国戍边英雄王焯冉表弟入伍
从小就怀揣着从军报国梦的盛冠杰,5年前就曾和哥哥王焯冉相约报名参军。却因当时体检未达标,遗憾错过军营,上了大学。去年哥哥卫国戍
X 关闭
战时防疫用!宝安首批667间集中居住板房移交管理
西安新增本土确诊病例150例 详情发布
广东最低气温跌至-6℃现冰挂 部分道路及海上交通受影响
“2022科学跨年系列活动”启动 提高公众对科学类流言“免疫力”
珠科院多举措助力大湾区抗旱防咸保供水
X 关闭
环球观速讯丨原浆酒(原浆酒是什么意思)
武汉硚口区金马大厦拟3.196亿元拍卖 项目总建面3.84万平米
端午小长假短途线路受青睐 部分线路车票售罄
世界热点!粽子吃不完可以放水里保存吗