STM32F4通过U盘升级程序

昨天的文章中介绍F4系列单片机的内部Flash读写,包括之前文章中介绍了FatFS文件系统读写U盘的操作。本篇文章就是将两者结合,实现F4系列单片机程序的U盘升级。

首先对内部Flash空间进行划分,前128K用于存储BootLoader程序,后面的空间用于存储App程序。定义如下:

#define IAP_SIZE                           ((uint32_t)0x20000)   /* 128Kbytes as IAP size */
#define APPLICATIONADDRESS                 ((uint32_t)0x08020000) /* User start code space */
#define APPLICATIONSIZE                    ((uint32_t)0xE0000)

之所以分配了128K给BootLoader程序,是因为这部分程序中移植了FatFs文件系统和emWin程序,程序比较大。当然emWin程序不是必须的,这里只是通过液晶屏来显示升级进度等信息。

上电后先运行BootLoader程序,可以通过多种方式来判断是否需要进行程序升级,比如标志位、按键、触摸屏状态等。如果需要程序升级,则读取U盘中的.bin文件,然后写入到APPLICATIONADDRESS地址。如果不需要升级,则直接跳转到App程序运行。

程序升级部分代码如下:

int writeNewProgram()
{
    int rtn;
    int i;
    int isFinish = 0;
    FIL fil;
    int sectorFlag[12];//用于标记一下此sect是否已经擦除


    for( i=0; i<12; i++ )
        sectorFlag[i] = 0;


    GUI_DispStringAt("start write new program", 0, y);
    y+=16;
    HAL_FLASH_Unlock();//解锁flash
    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);


    rtn = f_open(&fil, filename, FA_READ );//打开程序文件
    if(rtn)
    {
        sprintf(str,"open %s error:%d\r\n",filename,rtn);
        GUI_DispStringAt(str, 0, y);
        y+=16;
    }
    else
    {
        sprintf(str,"open %s sucess\r\n",filename);
        GUI_DispStringAt(str, 0, y);
        y+=16;
    }


    uint32_t startaddress = APPLICATIONADDRESS;
    uint32_t endaddress = APPLICATIONADDRESS + APPLICATIONSIZE;


    GUI_DispStringAt("start program", 0, y);
    y+=16;
    while( startaddress < endaddress && isFinish == 0 )
    {
        rtn = f_read(&fil, buf, BUF_SIZE, (UINT*)&bytesread);//读取128K数据
        if(rtn)
        {
            sprintf(str,"read address 0x%X error:%d",startaddress,rtn);
            GUI_DispStringAt(str, 0, y);
            break;
        }
        else
        {
            sprintf(str,"read address 0x%X sucess! rbytes=0x%X",startaddress,bytesread);
            GUI_DispStringAt(str, 0, y);
        }
        y+=16;
        for( i=0; i<bytesread; i+=4 )
        {
            int sect = GetSectorFromAddress(startaddress);
            if( sect >= 0 )
            {
                if( sectorFlag[sect] == 0 )//0表示此sect还没有被擦除
                {
                    sectorFlag[sect] = 1;
                    FLASH_Erase_Sector(sect,FLASH_VOLTAGE_RANGE_3);
                    sprintf(str,"erase sector %d",sect);
                    GUI_DispStringAt(str, 0, y);
                }
            }




            uint32_t *p;
            p = (uint32_t *)&buf[i];
            rtn = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,startaddress,*p);//写入Flash


            if( rtn != 0 )
            {
                isFinish = 1;
                sprintf(str,"HAL_FLASH_Program Err:%X",startaddress);
                GUI_DispStringAt(str, 0, y);
                break;
            }
            startaddress +=4;
        }


        if( bytesread < BUF_SIZE )
        {
            isFinish = 1;
        }
    }
    y+=16;
    rtn = f_close(&fil);
    if(rtn)
    {
        sprintf(str,"close %s error:%d",filename,rtn);
        GUI_DispStringAt(str, 0, y);
        y+=16;
    }
    else
    {
        sprintf(str,"close %s sucess",filename);
        GUI_DispStringAt(str, 0, y);
        y+=16;
    }
    HAL_FLASH_Lock();
    GUI_DispStringAt("end write program", 0, y);
    y+=16;
    return isFinish;
}

程序流程如下:解锁Flash后,打开U盘中的程序文件,然后每次读取128K数据(128K正好是一个Sector的大小,F429单片机RAM也足够大,所以可以每次读取较多的数据,效率更高),然后擦除Sector,再写入。直到所有数据写入完成再对Flash上锁。之后再跳转到App程序运行即可。

跳转部分代码如下:

typedef  void (*pFunction)(void);
pFunction Jump_To_Application;
uint32_t JumpAddress;


void jumpToApp()
{
    if (((*(__IO uint32_t*)APPLICATIONADDRESS) & 0x2FFE0000 ) == 0x20000000)
    {
      /* Jump to user application */
      JumpAddress = *(__IO uint32_t*) (APPLICATIONADDRESS + 4);
      Jump_To_Application = (pFunction) JumpAddress;
      /* Initialize user application's Stack Pointer */
      __set_MSP(*(__IO uint32_t*) APPLICATIONADDRESS);
      Jump_To_Application();
    }
}

实际运行效果:

视频中升级之前对单片机内的程序进行了备份,再进行写入。可以看到,500多KB的程序升级用了几秒钟,速度还是可以的。

总结

以上介绍的内容只是实现了基本的程序升级功能,实际应用中可能还需要对数据进行校验、加密等操作。

推荐阅读:

程序 | STM32F4内部Flash读写

程序 | STM32CubeMX之FatFS读写U盘

电路 | 两种常用压控电流源设计

欢迎关注公众号"嵌入式技术开发",大家可以后台给我留言沟通交流。如果觉得该公众号对你有所帮助,也欢迎推荐分享给其他人。

  • 10
    点赞
  • 82
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值