在汽车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. 【翻译】FluentValidation验证组件的使用

    由于本文是翻译,所以将原文原原本本的搬上来,大家看原文有什么不懂的也可以对照这里. 给出地址:https://fluentvalidation.net/ FluentValidation fluent ...

  2. laravel创建项目

    composer create-project --prefer-dist laravel/laravel=5.5.* blog

  3. C# Note3:大话Ninject

    前言 之所以研究Ninject,是因为初入职在开发XX项目的ComponentService部分时用到了它,一下子发现了它的强大.渐渐地发现在项目中,有时会用到优秀的第三方开源库,这些都是前人智慧的结 ...

  4. Android常用的技术框架与博客社区

    技术框架 图片加载 Glide Fresco Volley Picasso Universal Image Loader 网络请求 okhttp retrofit Volley android-asy ...

  5. Linux基础学习笔记5-软件管理

    包管理器 二进制应用程序的组成部分: 二进制文件.库文件.配置文件.帮助文件 程序包管理器: debian:deb文件.dpkg包管理器 redhat:rpm文件.rpm包管理器 rpm:Redhat ...

  6. 996.ICU

    996.ICU https://github.com/996icu/996.ICU https://www.zhihu.com/question/317722302 LICENSE https://g ...

  7. js外部调用layui.use中的函数的写法

    layui模块化的写法固然不错,但也有让人不适应的一些地方 外部调用函数的写法就让人不太舒服 需要在函数名前面加上window这个前缀,就不太舒服 补充:window前缀,是全局变量的声明方式 如下: ...

  8. PreparedStement 用户登录!

    一.准备工作 在qy66数据库下,新建一个denglu表.添加 name password  . package cn.zhouzhou; import java.sql.Connection; im ...

  9. python安装与配置

    首先下载python地址: https://www.python.org/downloads/release/python-361/ 下载页面中有多个版本: web-based installer 是 ...

  10. How to write to an event log by using Visual C#

    using System; using System.Diagnostics; namespace WriteToAnEventLog_csharp { /// Summary description ...