在汽车ECU软件运行中,软件代码运行安全性是第一,在代码中尽可能的不要固化有flash_erase、flash_write操作存在,主要是防止当出现异常情况时,程序跑飞,误调用erase、write对flash操作,使得原软件受到破坏,以致ECU不能正常工作。

Bootloader也称为启动引导加载程序,这段程序是硬件设备在上电复位之后执行的第一段软件代码。

方式一、为了实现在线更新功能,Bootloader程序需要对flash进行操作。一般情况下,我们将FLASH操作程序作为Bootloader组件的一部分固化在存储器中,在需要执行flash擦除或烧写操作时,先将该部分代码复制到RAM中,再做调用。操作代码的复制工作也可以在Bootloader启动阶段完成。

方式二、两级Bootloader方案,没有在flash存储器中固化flash擦写代码,而是通过通讯口将该部分代码从上位机下载到指定的RAM出,在需要指出flash擦除或烧写操作时,再调用RAM中的该代码。

方式三、Bootloader制作下载引导程序,此软件不固化flash擦写代码,通过通讯口下载另外Bootloader(包含flash擦写操作)到指定的RAM中,跳转到RAM运行升级流程。

现在我们做简单的测试,按照方式二测试,Bootloader中没有擦写falsh操作代码,我们把flash_erase和flash_write编译后生成的bin信息保存在Bootloader软件的一个数组中(PS:RAM中就是存放全局变量等信息,通过上位机下载也是存放在指定RAM中,我们可以使下载保存在数组中,效果一样)。

1、新建flash工程;
2、flash.c文件中主要包含:uint32_t flash_erase(uint32_t u32addr)和uint32_t flash_write(uint32_t u32addr, uint32_t u32data),两个函数,注意:这两个函数中不能存在调用外部函数、全局变量信息;

3、编译生成bin文件,通过.map文件查看这两个函数的位置;

4、在生成的bin文件中提取出这两个函数信息,重新生成新的bin文件;注意地址是偶数

或者上位机直接下载此bin文件(原始bin文件),在MCU端需要从0x218地址处提取数据;

5、在boot中开辟擦、写两个函数code长度的数组,为下载擦、写函数的数据存放在RAM中做准备,以数组形式放在ram中;
6、 将数组地址强制类型转换为函数指针;

7、在调用这个函数的地址,用函数指针来调;

  1.  
    #define FMC_ISPCMD_PROGRAM 0x21 /*!< ISP Command: Program Flash */
  2.  
    #define FMC_ISPCMD_PAGE_ERASE 0x22 /*!< ISP Command: Page Erase Flash */
  3.  
     
  4.  
    uint32_t flash_erase(uint32_t u32addr)
  5.  
    {
  6.  
    FMC->ISPCMD = FMC_ISPCMD_PAGE_ERASE; /* Set ISP Command Code */
  7.  
    FMC->ISPADR = u32addr; /* Set Target ROM Address. The address must be page alignment. */
  8.  
    //__set_PRIMASK(1);
  9.  
    __asm("CPSID I");
  10.  
    FMC->ISPTRG = 0x1; /* Trigger to start ISP procedure */
  11.  
    __ISB(); /* To make sure ISP/CPU be Synchronized */
  12.  
    while(FMC->ISPTRG); /* Waiting for ISP Done */
  13.  
    //__set_PRIMASK(0);
  14.  
    __asm("CPSIE I");
  15.  
     
  16.  
    /* Check ISPFF flag to know whether erase OK or fail. */
  17.  
    if(FMC->ISPCON & FMC_ISPCON_ISPFF_Msk) {
  18.  
    FMC->ISPCON |= FMC_ISPCON_ISPFF_Msk;
  19.  
    return 1;
  20.  
    }
  21.  
    return 0;
  22.  
    }
  23.  
    uint32_t flash_write(uint32_t u32addr, uint32_t u32data)
  24.  
    {
  25.  
    FMC->ISPCMD = FMC_ISPCMD_PROGRAM; /* Set ISP Command Code */
  26.  
    FMC->ISPADR = u32addr; /* Set Target ROM Address. The address must be word alignment. */
  27.  
    FMC->ISPDAT = u32data; /* Set Data to Program */
  28.  
    // __set_PRIMASK(1);
  29.  
    __asm("CPSID I");
  30.  
    FMC->ISPTRG = 0x1; /* Trigger to start ISP procedure */
  31.  
    __ISB(); /* To make sure ISP/CPU be Synchronized */
  32.  
    while(FMC->ISPTRG); /* Waiting for ISP Done */
  33.  
    //__set_PRIMASK(0);
  34.  
    __asm("CPSIE I");
  35.  
     
  36.  
    if(FMC->ISPCON & FMC_ISPCON_ISPFF_Msk) {
  37.  
    FMC->ISPCON |= FMC_ISPCON_ISPFF_Msk;
  38.  
    return 1;
  39.  
    }
  40.  
    return 0;
  41.  
    }

下面我们来是测试代码:

  1. <code class="language-cpp">//编译生成的擦、写文件,此处直接加载到数组中,而非通过上位机下载
  2. //__align(4) :对齐方式
  3. __align(4) uint8_t flash_erase_buf[]={
  4. 0x01,0x46,0x22,0x20,0x11,0x4A,0xD0,0x60,0x10,0x46,0x41,0x60,0x72,0xB6,0x01,0x20,
  5. 0x10,0x61,0x00,0xBF,0x00,0xBF,0x00,0xBF,0xBF,0xF3,0x6F,0x8F,0x00,0xBF,0x00,0xBF,
  6. 0x00,0xBF,0x00,0xBF,0x09,0x48,0x00,0x69,0x00,0x28,0xFB,0xD1,0x62,0xB6,0x07,0x48,
  7. 0x00,0x68,0x40,0x22,0x10,0x40,0x00,0x28,0x06,0xD0,0x04,0x48,0x00,0x68,0x10,0x43,
  8. 0x02,0x4A,0x10,0x60,0x01,0x20,0x70,0x47,0x00,0x20,0xFC,0xE7,0x00,0xC0,0x00,0x50,
  9. };
  10. __align(4) uint8_t flash_write_buf[]={
  11. 0x02,0x46,0x21,0x20,0x12,0x4B,0xD8,0x60,0x18,0x46,0x42,0x60,0x81,0x60,0x72,0xB6,
  12. 0x01,0x20,0x18,0x61,0x00,0xBF,0x00,0xBF,0x00,0xBF,0xBF,0xF3,0x6F,0x8F,0x00,0xBF,
  13. 0x00,0xBF,0x00,0xBF,0x00,0xBF,0x0A,0x48,0x00,0x69,0x00,0x28,0xFB,0xD1,0x62,0xB6,
  14. 0x07,0x48,0x00,0x68,0x40,0x23,0x18,0x40,0x00,0x28,0x06,0xD0,0x04,0x48,0x00,0x68,
  15. 0x18,0x43,0x03,0x4B,0x18,0x60,0x01,0x20,0x70,0x47,0x00,0x20,0xFC,0xE7,0x00,0x00,
  16. 0x00,0xC0,0x00,0x50
  17. };
  18. typedef void (*flash_erase_handler)(uint32_t u32addr);
  19. typedef void (*flash_write_handler)(uint32_t u32addr, uint32_t u32data);
  20. flash_erase_handler flash_erase = (flash_erase_handler)(flash_erase_buf + 1); // cortex-mo 使用thumb指纹,函数地址低位为1
  21. flash_write_handler flash_write = (flash_write_handler)(flash_write_buf + 1);
  22. int main(void)
  23. {
  24. main_powerOnInit();
  25. SYS_UnlockReg();
  26. DrvFMC_Open();
  27. DrvFMC_EnableAPUpdate();
  28. DrvFMC_Erase(SPIFLAG_ADDR);
  29. DrvFMC_Write(SPIFLAG_ADDR,0x88776655);
  30. DrvFMC_DisableAPUpdate();
  31. DrvFMC_Close();
  32. SYS_LockReg();
  33. //DisableInterrupts;
  34. SYS_UnlockReg();
  35. DrvFMC_Open();
  36. DrvFMC_EnableAPUpdate();
  37. flash_erase(SPIFLAG_ADDR);
  38. flash_write(SPIFLAG_ADDR,0xAABBCCDD);
  39. DrvFMC_DisableAPUpdate();
  40. DrvFMC_Close();
  41. SYS_LockReg();
  42. //EnableInterrupts;
  43. for (;;);
  44. }</code>

测试结果显示,的确能够写法flash中。

下面附上车载诊断升级示意流程图:

Bootloader升级方式一————擦、写flash在RAM中运行的更多相关文章

  1. NOR flash和NAND flash区别,RAM 和ROM区别

    ROM和RAM指的都是半导体存储器,ROM是Read Only Memory的缩写,RAM是Random Access Memory的缩写.ROM在系统停止供电的时候仍然可以保持数据,而RAM通常都是 ...

  2. NOR flash和NAND flash区别,RAM 和ROM区别d

    ROM和RAM指的都是半导体存储器,ROM是Read Only Memory的缩写,RAM是Random Access Memory的缩写.ROM在系统停止供电的时候仍然可以保持数据,而RAM通常都是 ...

  3. NOR Flash擦写和原理分析

    NOR Flash擦写和原理分析 1. NOR FLASH 的简单介绍 NOR FLASH 是很常见的一种存储芯片,数据掉电不会丢失.NOR FLASH支持Execute On Chip,即程序可以直 ...

  4. NOR Flash擦写和原理分析 (二)

    Nor Flash上电后处于数据读取状态(Reading Array Data).此状态可以进行正常的读.这和读取SDRAM/SRAM/ROM一样.(要是不一样的话,芯片上电后如何从NorFlash中 ...

  5. NOR Flash擦写和原理分析 (一)

    1. NOR FLASH 的简单介绍 NOR FLASH 是很常见的一种存储芯片,数据掉电不会丢失.NOR FLASH支持Execute On Chip,即程序可以直接在FLASH片内执行(这意味着存 ...

  6. 【转】NOR Flash擦写和原理分析

    1. NOR FLASH 的简单介绍 NOR FLASH 是很常见的一种存储芯片,数据掉电不会丢失.NOR FLASH支持Execute On Chip,即程序可以直接在FLASH片内执行(这意味着存 ...

  7. 如何提高单片机Flash的擦写次数

    所谓提高flash的擦写次数,并不是真正的提高flash擦写次数,而是通过以"空间换时间"概念,在软件上实现“操作的次数大于其寿命”.详见链接: http://bbs.eeworl ...

  8. 转载:NOR Flash擦写和原理分析

    1. NOR FLASH 的简单介绍 NOR FLASH 是很常见的一种存储芯片,数据掉电不会丢失.NOR FLASH支持Execute On Chip,即程序可以直接在FLASH片内执行(这意味着存 ...

  9. nrf52——DFU升级USB/UART升级方式详解(基于SDK开发例程)

    摘要:在前面的nrf52--DFU升级OTA升级方式详解(基于SDK开发例程)一文中我测试了基于蓝牙的OTA,本文将开始基于UART和USB(USB_CDC_)进行升级测试. 整体升级流程: 整个过程 ...

随机推荐

  1. Windows Docker 安装

    win7.win8 .win10等需要利用 docker toolbox 来安装,国内可以使用阿里云的镜像来下载,下载地址:http://mirrors.aliyun.com/docker-toolb ...

  2. # 【Python3练习题 004】输入某年某月某日,判断这一天是这一年的第几天?

    # [Python练习题 004]输入某年某月某日,判断这一天是这一年的第几天? # 思路:先判断是否为闰年,这关系到 2 月份的天数.# 之后再根据月份值把前几个月的天数累积加起来,最后再加上个“日 ...

  3. IdentityServer4【QuickStart】之利用OpenID Connect添加用户认证

    利用OpenID Connect添加用户认证 利用OpenID Connect添加用户认证 在这个示例中我们想要通过OpenID Connect协议将交互用户添加到我们的IdentityServer上 ...

  4. js中this指向、箭头函数

    普通函数:this指向分为4种情况,1. obj.getName();//指向obj2.getName();//非严格模式下,指向window,严格模式下为undefined3. var a = ne ...

  5. python爬虫scrapy之登录知乎

    下面我们看看用scrapy模拟登录的基本写法: 注意:我们经常调试代码的时候基本都用chrome浏览器,但是我就因为用了谷歌浏览器(它总是登录的时候不提示我用验证码,误导我以为登录时不需要验证码,其实 ...

  6. 取得数据表中前N条记录,某列重复的话只取第一条记录

    项目需要筛选出不重复数据,以前没有做过,第一反应就是利用distinct处理,但是弄了好久也没搞出来,大家有知道的望告知下. 这次筛选没有使用distinct ,是利用group by ,利用id为唯 ...

  7. c提取文件路径、文件名和后缀名

    /* MAKEPATH.C */ #include <stdlib.h> #include <stdio.h> void main( void ) { char path_bu ...

  8. 配置 BizTalk Server

    使用“基本配置”或“自定义配置”配置 BizTalk Server. 基本配置与自定义配置       如果配置使用域组,则进行“自定义配置”. 如果配置使用自定义组名称而不是默认组名称,则进行“自定 ...

  9. 当页面上需要的字段不在model中时候,需要自行设置该字段

    当页面上需要的字段不在model中时候,需要自行设置该字段

  10. 训练赛-Building Numbers

    题意:首先告诉你,一个数字从1开始有两种变换方式:1.当前数字的值加1 2.当前的数字值乘2: 思路:首先把数组里的数字需要的变换次数算出来,然后用前缀和解决: 代码: #include<ios ...