zoukankan      html  css  js  c++  java
  • STM32 IAP 固件升级设计/U盘升级固件

    源:STM32 IAP 固件升级设计/U盘升级固件

    固件升级的基本思路是: 将stm32 的flash划分为两个区域:

              1.Bootloader区:存放bootloader的代码,bootloader代码完成的主要功能就是,判断外部条件,如果需要更新固件,则从指定位置(外接的U盘?板子上的外置存储器如 SD卡,NandFlash等)读取bin文件,然后写入到stm32 Flash的APP区,完成后跳转到APP区执行更新过的代码; 如果不需要更新,则直接跳转到APP区执行主程序代码。

              2.APP区:存放应用程序代码,就是我们产品的固件了。

    目做了两个升级方式,都是USB的:

              一个是USB host:开机进boot,boot检测是否有U盘插入,U盘中是否包含APP的bin文件,包含则更新并跳转到APP;           一个是USB device:在APP区,做了usb device的代码,将板上的nandflash作为U盘的存储器,通过USB线链接PC,则PC显示U盘,将APP的bin文件复制到U盘里,并设置一个标志文件,下次开机进boot会判断nandfalash里是否有需要更新的固件,如果有,则将nandflash里存放的APPbin文件写入stm32 flash的APP区,完成更新后跳转。

    bootloader代码要点:

    1. 需要包含USB Host和 nandflash以及  fatfs文件系统的驱动代码。(这部分是需要仔细研究做好的,就不多说了)

    2.关于Bootloader区: 我使用stm32f429,bootlaoder代码编译下来有50K左右,所以使用flash 0x80000000  ~ 0x8000FFFF这块共64K的区域,注意Bootloader代码一定要从 flash的起始地址0x80000000开始,这样一开机就首先运行boot程序。

    具体在keil 中的设置是   target中设置好flash的起始地址和size; debug中settings,flash选择1M的(我的429是1Mflash)然后在下面的开始和结束地址中输入正确地址;

    3.关于APP区: 使用剩下的0x80010000~0x800FFFFF 区域,keil具体设置和2一样。

    4.关于读取并写入bin文件到flash:  如上面所说,这个比较灵活,可以从外部U盘中读取bin文件到 内存buf然后写入flash,也可以从板上已有的外设存储器读取bin文件到内存buf然后写入flash,具体代码可以参考官方固件库中的例子。

    5.关于跳转: 可以看到官方代码

    pFunction Jump_To_Application;

    uint32_t JumpAddress;

    JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);

    Jump_To_Application = (pFunction) JumpAddress;

    /* Initialize user application's Stack Pointer */

     __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);

    Jump_To_Application();

    具体分析可以看网上别人的详细解释,这里我遇到的问题是:经常跳转之后就直接死机,可能有以下几种情况:

    1. APP代码main函数中第一句必须要

     NVIC_SetVectorTable (NVIC_VectTab_FLASH, 0x10000);

    __enable_irq();

    将向量表偏移地址设置为我们的0x10000;

    2.关于中断,可能跳转之前,某些外设中断是开启的,跳转之后,中断产生了,但是APP代码中没有处理对应该中断的中断处理函数,所以就直接死机了;

    对应网上的一些方法是  跳转之前,关闭所有中断:  __disable_irq();

    在APP中偏移地址设置完毕后,再次开启所有中断:    __enable_irq();

    有些人发现跳入APP之后,很多中断都不响应了,可能就是跳转之前,关了中断但是APP中没有再次开启。

    我一开始这样用,每次从U盘更新完固件之后跳转就死机了,从nandflash跳转就不会有问题,参考了一些网上的资料,

    推测可能还是 __disable_irq()没有把USB中断关闭,或者关闭之后,USB的某个中断仍旧是置位的,APP中再次开启中断后,直接寻找USB中断服务程序,找不到就死机了。

    这里为了更加稳妥,我决定在跳转之前,将所有boot中用到的外设都关闭,但是只用了一句

    NVIC_DisableIRQ(OTG_FS_IRQn);

    之后,就一切OK了。

    但是建议大家在写boot的时候,跳转之前还是把所有用到的外设时钟关闭,中断也禁止。

  • 相关阅读:
    STM32 -- 硬件知识
    PCIe相关的操作命令
    [转载]PCI/PCIe基础——配置空间
    [转载]网络虚拟化中的 offload 技术:LSO/LRO、GSO/GRO、TSO/UFO、VXLAN
    [转载]TSO、UFO、GSO、LRO、GRO和RSS介绍
    Linux应用函数 -- 字符串
    初级PLC
    中断方式下进行串口通讯的正确方法
    [altium] Altium Designer2013 13.3.4 (10.1881.28608) 完美版
    32个最热CPLD-FPGA论坛
  • 原文地址:https://www.cnblogs.com/LittleTiger/p/5799254.html
Copyright © 2011-2022 走看看