[AUTOSAR][Fls模块] Flash Driver Module
Flash Driver Module--jianqiang.xue
- 一、 简介
- 二、 措施
- 方式一:将FLASH操作程序作为Bootloader组件的一部分固化在存储器中
- 方式二:通过通讯口将该部分代码从上位机下载到指定的RAM
- 方式三:将Flash功能函数作为数据运行(推荐!!!)
- 使用Demo
一、 简介
在汽车ECU软件运行中,软件代码运行安全性是第一,在代码中尽可能的不要固化有flash_erase、flash_write操作存在,主要是防止当出现异常情况时,程序跑飞,误调用erase、write对flash操作,使得原软件受到破坏,以致ECU不能正常工作。
Flash访问代码(Access Code)不能存储在被操作的Flash物理块中,例如我要擦除一个Flash中某一个扇区内容,这个擦除动作的代码不能存在这个Flash物理块中(Flash中代码运行时,相当于读操作,此时不能擦写)
PFlash的访问代码在Fls_17_Dmu_ac.c文件中,而该文件的代码又被烧写进PFlash中,所以,PFlash不能直接进行Write/Erase操作
解决方案就是PFlash进行Write/Erase操作前,将Write/Erase访问代码存储到RAM中,函数实际上是在RAM中执行
在AUTOSAR的负责范围内,DF0_EEPROM不会存放任何访问代码。
二、 措施
方式一:将FLASH操作程序作为Bootloader组件的一部分固化在存储器中
为了实现在线更新功能,Bootloader程序需要对flash进行操作。一般情况下,我们将FLASH操作程序作为Bootloader组件的一部分固化在存储器中,在需要执行flash擦除或烧写操作时,先将该部分代码复制到RAM中,再做调用。操作代码的复制工作也可以在Bootloader启动阶段完成。
方式二:通过通讯口将该部分代码从上位机下载到指定的RAM
两级Bootloader方案,没有在flash存储器中固化flash擦写代码,而是通过通讯口将该部分代码从上位机下载到指定的RAM出,在需要指出flash擦除或烧写操作时,再调用RAM中的该代码。
jianqiang.xue
方式三:将Flash功能函数作为数据运行(推荐!!!)
- 根据MCU新建Flash Driver工程
- 编写flash_erase和flash_write两个函数
- 编译生成bin文件,通过.map文件查看这两个函数的位置
- 在生成的bin文件中提取出这两个函数信息,注意地址是偶数。
func_addr = (map_addr-1)
func_size = (map_size+4)
const uint8_t McuFlashErasePageBuf[] = {0xB0, 0xB5, 0x11, 0x4A, 0x30, 0x21, 0x11, 0x70, 0x14, 0x1F, 0x00, 0x23, 0x23, 0x70, 0x0A, 0x25,0x15, 0x71, 0x05, 0x0C, 0xD5, 0x70, 0x01, 0x25, 0x25, 0x70, 0xFC, 0x24, 0x04, 0x40, 0xD4, 0x70,0x00, 0x0A, 0x10, 0x71, 0x85, 0xF3, 0x10, 0x88, 0x80, 0x20, 0x10, 0x70, 0x10, 0x78, 0x40, 0xB2,0x00, 0x28, 0xFB, 0xD5, 0x10, 0x78, 0x00, 0x07, 0xFC, 0xD4, 0x12, 0x78, 0x83, 0xF3, 0x10, 0x88,0x0A, 0x40, 0x50, 0x42, 0x50, 0x41, 0xB0, 0xBD, 0x05, 0x00, 0x02, 0x40, 0x10, 0xB5, 0x8C, 0xB0,
};const uint8_t McuFlashWritePageBuf[] = {0xF8, 0xB5, 0x14, 0x46, 0x04, 0x43, 0x01, 0x23, 0xA4, 0x07, 0x4D, 0xD1, 0x00, 0x29, 0x4B, 0xD0,0x00, 0x2A, 0x49, 0xD0, 0x00, 0x23, 0x25, 0x4C, 0x00, 0x93, 0x30, 0x26, 0x26, 0x71, 0x00, 0x9D,0x25, 0x70, 0x06, 0x25, 0x25, 0x72, 0x05, 0x0C, 0xE5, 0x71, 0x01, 0x27, 0x27, 0x70, 0x05, 0x0A,0x25, 0x72, 0xFC, 0x25, 0x05, 0x40, 0xE5, 0x71, 0x02, 0x25, 0x25, 0x70, 0x4D, 0x78, 0x25, 0x72,0x0D, 0x78, 0xE5, 0x71, 0x03, 0x25, 0x25, 0x70, 0xCD, 0x78, 0x25, 0x72, 0x8D, 0x78, 0xE5, 0x71,0x1D, 0x1D, 0x95, 0x42, 0x0F, 0xD2, 0x04, 0x25, 0x25, 0x70, 0x4D, 0x79, 0x25, 0x72, 0x0D, 0x79,0xE5, 0x71, 0x05, 0x25, 0x25, 0x70, 0xCD, 0x79, 0x25, 0x72, 0x8D, 0x79, 0xE5, 0x71, 0x08, 0x30,0x08, 0x33, 0x08, 0x31, 0x02, 0xE0, 0x00, 0x1D, 0x09, 0x1D, 0x2B, 0x46, 0x87, 0xF3, 0x10, 0x88,0x80, 0x25, 0x25, 0x71, 0x04, 0x25, 0x65, 0x57, 0x00, 0x2D, 0xFB, 0xD5, 0x25, 0x79, 0x2D, 0x07,0xFC, 0xD4, 0x27, 0x79, 0x00, 0x25, 0x85, 0xF3, 0x10, 0x88, 0x37, 0x40, 0x93, 0x42, 0x01, 0xD2,0x00, 0x2F, 0xBA, 0xD0, 0x7B, 0x42, 0x7B, 0x41, 0x18, 0x46, 0xF8, 0xBD, 0x01, 0x00, 0x02, 0x40,
};
- 提取数据并存放数组,这些数据不能直接使用,因为无法到达AUTOSAR初衷。
处理数据:
(1) 数组数据全部取反,这样程序炮灰也不会误触发。
(2) 使用flash_erase和flash_write时,需要取反数据,再使用,使用结束后,再清除数据。
// 这里的数据全部取反才是真正函数,防止指针跑飞误执行。
#pragma pack (4)
const uint8_t gc_McuFlashErasePageBuf[] = {0x73, 0x4f, 0xfe, 0x57, 0x00, 0x08, 0xa6, 0x00, 0xfb, 0x67,0xf3, 0xb6, 0x77, 0xbd, 0xee, 0x2c, 0xea, 0xb3, 0xfd, 0xde,0x9e, 0xa9, 0xff, 0xd6, 0x04, 0x2a, 0xf7, 0xb6, 0x00, 0x08,0xe4, 0x00, 0xbe, 0xe1, 0xc0, 0xdf, 0xf7, 0xbf, 0xdf, 0x8f,0xde, 0x87, 0xb6, 0x4d, 0xff, 0xd6, 0x05, 0x2a, 0xf3, 0x4f,0xef, 0x42, 0xfc, 0x5f, 0xf7, 0x5e, 0xd6, 0xdd, 0xff, 0x0f,0x41, 0x07, 0xbf, 0xbd, 0xf0, 0xff, 0x9c, 0x93, 0x94, 0xd1,0x99, 0x8d, 0x8e, 0xa0, 0x9d, 0x8a, 0x8c, 0xdf, 0xc1, 0x4f
};
const uint8_t gc_McuFlashWritePageBuf[] = {0x07, 0x4a, 0xeb, 0xb9, 0xfb, 0xbc, 0xfe, 0xdc, 0x5b, 0xf8,0xb2, 0x2e, 0xff, 0xd6, 0xb4, 0x2f, 0xff, 0xd5, 0xb6, 0x2f,0xff, 0xdc, 0xda, 0xb3, 0xff, 0x6c, 0xcf, 0xd9, 0xd9, 0x8e,0xff, 0x62, 0xda, 0x8f, 0xf9, 0xda, 0xda, 0x8d, 0xfa, 0xf3,0x1a, 0x8e, 0xfe, 0xd8, 0xd8, 0x8f, 0xfa, 0xf5, 0xda, 0x8d,0x03, 0xda, 0xfa, 0xbf, 0x1a, 0x8e, 0xfd, 0xda, 0xda, 0x8f,0xb2, 0x87, 0xda, 0x8d, 0xf2, 0x87, 0x1a, 0x8e, 0xfc, 0xda,0xda, 0x8f, 0x32, 0x87, 0xda, 0x8d, 0x72, 0x87, 0x1a, 0x8e,0xe2, 0xe2, 0x6a, 0xbd, 0xf0, 0x2d, 0xfb, 0xda, 0xda, 0x8f,0xb2, 0x86, 0xda, 0x8d, 0xf2, 0x86, 0x1a, 0x8e, 0xfa, 0xda,0xda, 0x8f, 0x32, 0x86, 0xda, 0x8d, 0x72, 0x86, 0x1a, 0x8e,0xf7, 0xcf, 0xf7, 0xcc, 0xf7, 0xce, 0xfd, 0x1f, 0xff, 0xe2,0xf6, 0xe2, 0xd4, 0xb9, 0x78, 0x0c, 0xef, 0x77, 0x7f, 0xda,0xda, 0x8e, 0xfb, 0xda, 0x9a, 0xa8, 0xff, 0xd2, 0x04, 0x2a,0xda, 0x86, 0xd2, 0xf8, 0x03, 0x2b, 0xd8, 0x86, 0xff, 0xda,0x7a, 0x0c, 0xef, 0x77, 0xc8, 0xbf, 0x6c, 0xbd, 0xfe, 0x2d,0xff, 0xd0, 0x45, 0x2f, 0x84, 0xbd, 0x84, 0xbe, 0xe7, 0xb9,0x07, 0x42, 0xfe, 0xff, 0xfd, 0xbf
};uint8_t McuFlashErasePageBuf[80] = {0};
uint8_t McuFlashWritePageBuf[176] = {0};
#pragma pack ()
/****************************变量定义******************************/
typedef uint8_t (*McuFlashWritePageHandler)(uint32_t addr, uint8_t* buff, uint32_t len);
typedef uint8_t (*McuFlashErasePageHandler)(uint32_t addr);
/****************************常量定义******************************/
/****************************函数原型******************************/
static void Retrieval(uint8_t *s_buf, uint8_t *l_buf, uint32_t size) {for(uint32_t i = 0; i < size; i++) {l_buf[i] = ~s_buf[i];}
}
void McuFlashInstall(void) {// 装载FlashDriver驱动函数Retrieval((uint8_t *)gc_McuFlashErasePageBuf, McuFlashErasePageBuf, 80);Retrieval((uint8_t *)gc_McuFlashWritePageBuf, McuFlashWritePageBuf, 176);
}void McuFlashUnInstall(void) {// 卸载FlashDriver驱动函数memset(McuFlashErasePageBuf, 0, 80);memset(McuFlashWritePageBuf, 0, 176);
}/******************************************************************* 函数名称:McuFlashWritePage* 入口参数:addr 写地址;buff 数据缓存;len 数据长度* 出口参数:0 指令操作失败,1 指令操作成功* 函数说明:向指定地址写入一定长度的数据* 地址必须4字节对齐且在有效操作范围内;buff本身不能低于len* 设置的长度;len必须为4的整数倍;写入的空间必须已经擦除******************************************************************/
McuFlashWritePageHandler McuFlashWritePage = (McuFlashWritePageHandler)(McuFlashWritePageBuf + 1);/******************************************************************* 函数名称:McuFlashErasePage* 入口参数:addr 页所在地址* 出口参数:0 指令操作失败,1 指令操作成功* 函数说明:擦除页所在地址的一页内容******************************************************************/
McuFlashErasePageHandler McuFlashErasePage = (McuFlashErasePageHandler)(McuFlashErasePageBuf + 1);/******************************变量声明*****************************/
typedef uint8_t (*McuFlashWritePageHandler)(uint32_t addr, uint8_t* buff, uint32_t len);
typedef uint8_t (*McuFlashErasePageHandler)(uint32_t addr);// 未安装flash驱动,调用下面函数会直接跑飞
extern McuFlashWritePageHandler McuFlashWritePage;
extern McuFlashErasePageHandler McuFlashErasePage;
LiSun–xuejianqiang

使用Demo
// 写入McuFlashInstall();McuFlashWritePage(LS_ADDR, data, len);McuFlashUnInstall();
// 擦除McuFlashInstall();McuFlashErasePage(LS_ADDR);McuFlashUnInstall();
相关文章:
[AUTOSAR][Fls模块] Flash Driver Module
Flash Driver Module--jianqiang.xue一、 简介二、 措施方式一:将FLASH操作程序作为Bootloader组件的一部分固化在存储器中方式二:通过通讯口将该部分代码从上位机下载到指定的RAM方式三:将Flash功能函数作为数据运行(推荐!&#…...
如何正确选择好用的投票平台微信公众平台投票链接链接投票平台
“年度人物楷模”网络评选投票_免费链接投票_作品投票通道_扫码投票怎样进行现在来说,公司、企业、学校更多的想借助短视频推广自己。通过微信投票小程序,网友们就可以通过手机拍视频上传视频参加活动,而短视频微信投票评选活动既可以给用户发…...
gocd部署应用
产品需要在多个环境部署测试,为了提高部署测试效率,故计划使用CD工具,jenkins确实足够强大,但是使用部署功能是需要安装插件的,再说自己本身只用部署功能,故决定找一个小巧的CD工具,经过一番查找…...
P2P视频聊天技术分析
整个P2P视频过程需要知道双方的媒体类型、流和候选者,所以这里就会用到一下技术: 信令服务器socket.io 状态机 ICE服务器 WebRTC框架 媒体协商 信令服务器Socket.io 信令服务器说白了作用就是发消息的中转站,A把msg发到…...
MyBatis 的一级、二级缓存机制
目录标题缓存什么是缓存为什么使用缓存什么样的数据能使用缓存,什么样的数据不能使用适用于缓存不适用于缓存MyBatis 一级缓存、二级缓存关系1. 一级缓存1.1 什么是一级缓存mybatis1.2 一级缓存配置1.3 什么情况下会命中一级缓存mybatis清除一级缓存的几种方法1.4 内…...
剑指 Offer 65. 不用加减乘除做加法
摘要 剑指 Offer 65. 不用加减乘除做加法 一、位运算 有符号整数通常用补码来表示和存储,补码具有如下特征: 正整数的补码与原码相同;负整数的补码为其原码除符号位外的所有位取反后加 11。可以将减法运算转化为补码的加法运算来实现。符…...
5年软件测试年薪30w+,我的坎坷之路谁又知道
在深圳做了五年软件测试工作,从之前的一脸懵的点点点,到现在会自动化测试,说一点点非计算机专业人员从事软件测试的心得体会,仅供参考交流。 大部分测试在公司没啥地位,当然如果你懂技术就还行,单纯点点点…...
【Opencv--自适应图像二值化】cv2.adaptiveThreshold()
【Opencv–adaptiveThreshold】自适应阈值图像二值化 文章目录【Opencv--adaptiveThreshold】自适应阈值图像二值化1. 介绍2. adaptiveThreshold函数2.1 函数调用2.2 补充说明3. 代码示例4. 效果4.1 原图(ori.img)4.2 处理后5. 参考1. 介绍 在这里 cv2.…...
洛谷P8601[蓝桥杯][2013年第四届真题]剪格子
题目描述如图 11 所示,33 的格子中填写了一些整数。我们沿着图中的红色线剪开,得到两个部分,每个部分的数字和都是 60。本题的要求就是请你编程判定:对给定的 mn 的格子中的整数,是否可以分割为两个部分,使…...
配置alias实现快速生成.gitignore文件
git工具:版本控制开发工具。 cscope工具:用于浏览C源码的工具,类似于ctags。在代码根目录下执行cscope -Rbq,然后产生三个索引文件(cscope.out、cscope.in.out和cscope.po.out三个文件)。 在Linux下使用vi…...
MySQL数据库调优————GROUP BY及DISTINCT优化
GROUP BY 三种处理GROUP BY的方式 松散索引扫描(Loose Index Scan)紧凑索引扫描(Tight Index Scan)临时表(Temporary table) 三种方式的性能一次递减 松散索引扫描 无需扫描满足条件的所有索引键即可返…...
LRU缓存算法
双向链表哈希表(非线程安全) https://leetcode.cn/problems/lru-cache/solutions/259678/lruhuan-cun-ji-zhi-by-leetcode-solution/ /*** LRU算法: 哈希表双向链表实现* 1. 双向链表按照被使用的顺序来存储, 靠近头部的节点是最近使用的, 靠近尾部的节…...
@Configuration注解
Configuration注解介绍 Configuration注解,用于标注一个类是一个spring的配置类(同时,也是一个bean),配置类中可以使用ComponentScan、Import、ImportResource 和 Bean等注解的方式定义beanDefinition。 Target(Elem…...
基于springboot+vue的食疗系统
基于springbootvue的食疗系统 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取项目下载方式🍅 一、项目背景介绍&…...
sklearn学习-朴素贝叶斯
文章目录一、概述1、真正的概率分类器2、sklearn中的朴素贝叶斯二、不同分布下的贝叶斯1、高斯朴素贝叶斯GaussianNB2、探索贝叶斯:高斯朴素贝叶斯擅长的数据集3、探索贝叶斯:高斯朴素贝叶斯的拟合效果与运算速度总结一、概述 1、真正的概率分类器 算法…...
分享112个HTML艺术时尚模板,总有一款适合您
分享112个HTML艺术时尚模板,总有一款适合您 112个HTML艺术时尚模板下载链接:https://pan.baidu.com/s/1D3-mfPOud-f3vy9yLl-bmw?pwdfph2 提取码:fph2 Python采集代码下载链接:采集代码.zip - 蓝奏云 时尚平面模特网站模板 潮…...
用GDB远程调试运行于QEMU的程序
1. 前言 限于作者能力水平,本文可能存在谬误,因此而给读者带来的损失,作者不做任何承诺。 2. 测试环境 本文使用 Ubuntu 16.04.4 LTS QEMU 环境进行调试。 3. 用 GDB 调试 QEMU 内程序 3.1 编写用来调试的程序 我们用 ARM32 来进行调试…...
20 堆排序
文章目录1 堆排序的概念2 堆排序基本思想3 堆排序步骤图解说明4 堆排序的代码实现1 堆排序的概念 1) 堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为 O(nlogn)…...
2023最新文件快递柜系统网站源码 | 匿名口令分享 | 临时文件分享
内容目录一、详细介绍二、效果展示1.部分代码2.效果图展示三、学习资料下载一、详细介绍 2023最新文件快递柜系统网站源码 | 匿名口令分享 | 临时文件分享 很多时候,我们都想将一些文件或文本传送给别人,或者跨端传递一些信息,但是我们又不…...
分片策略(二)
分片策略 基本概念 分片键 用于分片的字段,是将数据库或表拆分的字段,比如,我可以使用user_id作为分片键将用户数据分到不同的表中,这里的user_id就是分片键,除了这种单字段分片,ShardingSphere还支持多…...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...
嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...
认识CMake并使用CMake构建自己的第一个项目
1.CMake的作用和优势 跨平台支持:CMake支持多种操作系统和编译器,使用同一份构建配置可以在不同的环境中使用 简化配置:通过CMakeLists.txt文件,用户可以定义项目结构、依赖项、编译选项等,无需手动编写复杂的构建脚本…...
VisualXML全新升级 | 新增数据库编辑功能
VisualXML是一个功能强大的网络总线设计工具,专注于简化汽车电子系统中复杂的网络数据设计操作。它支持多种主流总线网络格式的数据编辑(如DBC、LDF、ARXML、HEX等),并能够基于Excel表格的方式生成和转换多种数据库文件。由此&…...
Java后端检查空条件查询
通过抛出运行异常:throw new RuntimeException("请输入查询条件!");BranchWarehouseServiceImpl.java // 查询试剂交易(入库/出库)记录Overridepublic List<BranchWarehouseTransactions> queryForReagent(Branch…...
医疗AI模型可解释性编程研究:基于SHAP、LIME与Anchor
1 医疗树模型与可解释人工智能基础 医疗领域的人工智能应用正迅速从理论研究转向临床实践,在这一过程中,模型可解释性已成为确保AI系统被医疗专业人员接受和信任的关键因素。基于树模型的集成算法(如RandomForest、XGBoost、LightGBM)因其卓越的预测性能和相对良好的解释性…...
Redis上篇--知识点总结
Redis上篇–解析 本文大部分知识整理自网上,在正文结束后都会附上参考地址。如果想要深入或者详细学习可以通过文末链接跳转学习。 1. 基本介绍 Redis 是一个开源的、高性能的 内存键值数据库,Redis 的键值对中的 key 就是字符串对象,而 val…...
验证redis数据结构
一、功能验证 1.验证redis的数据结构(如字符串、列表、哈希、集合、有序集合等)是否按照预期工作。 2、常见的数据结构验证方法: ①字符串(string) 测试基本操作 set、get、incr、decr 验证字符串的长度和内容是否正…...
