资讯 更多 >>
KeilMDK制作FlashDriver 环球短讯
全球简讯:独家|抖音外卖测试独立板...
最低1970元最高22792元!我市调整住...
速递!154期九哥福彩3D预测奖号:组...
上影节丨陈可辛:我有危机感,但相...
花乡沭阳人民政府官网_沭阳花乡沭阳...
前4月完成交通固定资产投资1万亿元...
用心呵护高原儿童健康
五月快递发展指数同比增长近四成_环...
当前观点:头的笔顺(上的笔顺)
动态更多 >>
你们,温暖了2021
西安市新增27个中风险地区 目前有1...
广西新增本土确诊病例1例
哈尔滨市全域均为低风险地区
寒潮将影响我国中东部地区 四川盆...
昆明至哈尔滨一航班发现1名入境复阳...
陕西研考:封控区内考生在原报考点...
北京今日最高气温仅5℃ 明起强冷空...
那年今日 | 历史上的12月22日发生...
我要找债主
会展 更多 >>
美籍酿酒师在崇礼:中国是第二故乡...
河南项城报告2名疑似新冠肺炎病例 ...
浙江绍兴确诊病例首次零新增 上虞...
广西东兴实行全员居家隔离 启动口...
新疆全方位推进乡村振兴 “富春山...
云南瑞丽市主城区全员核酸检测结果...
内蒙古满洲里累计治愈出院本土确诊...
孙海洋夫妻驱车山东阳谷:还在为孙...
大国工匠追梦“玉米强国”40载:用...
让南海“海洋热带雨林”斑斓多彩
专题报道 
当前位置: 资讯 > >> 正文
 
KeilMDK制作FlashDriver 环球短讯
来源:博客园     时间:2023-06-13 12:11:10

一、前言

①在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

二、FlashDriver的生成1、修改加载文件1.1、定义FLASH空间的地址和大小:

这部分可以参考芯片手册(建议选一块单独的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文件中的起始地址需要向前一位开始复制:

FuncionNameAddress
FLASH_WaitCmdComplete0x0101000C-0x0101004B
FLASH_WaitEraseAllComplete0x0101004C-0x0101008B
FLASH_ExecuteCommandInt0x0101008C-0x010100C3
3.4、提取hex文件数据

将对应地址的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

被这部分折磨了挺久,好在终于搞定了,如果对大家有帮助的话,点个赞把。

关键词:

热门推荐
猜你喜欢