飞道的博客

STM32F4通过U盘升级程序

280人阅读  评论(0)

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

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


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

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

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

程序升级部分代码如下:


   
  1. int writeNewProgram()
  2. {
  3. int rtn;
  4. int i;
  5. int isFinish = 0;
  6. FIL fil;
  7. int sectorFlag[ 12]; //用于标记一下此sect是否已经擦除
  8. for( i= 0; i< 12; i++ )
  9. sectorFlag[i] = 0;
  10. GUI_DispStringAt( "start write new program", 0, y);
  11. y+= 16;
  12. HAL_FLASH_Unlock(); //解锁flash
  13. __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
  14. rtn = f_open(&fil, filename, FA_READ ); //打开程序文件
  15. if(rtn)
  16. {
  17. sprintf(str, "open %s error:%d\r\n",filename,rtn);
  18. GUI_DispStringAt(str, 0, y);
  19. y+= 16;
  20. }
  21. else
  22. {
  23. sprintf(str, "open %s sucess\r\n",filename);
  24. GUI_DispStringAt(str, 0, y);
  25. y+= 16;
  26. }
  27. uint32_t startaddress = APPLICATIONADDRESS;
  28. uint32_t endaddress = APPLICATIONADDRESS + APPLICATIONSIZE;
  29. GUI_DispStringAt( "start program", 0, y);
  30. y+= 16;
  31. while( startaddress < endaddress && isFinish == 0 )
  32. {
  33. rtn = f_read(&fil, buf, BUF_SIZE, (UINT*)&bytesread); //读取128K数据
  34. if(rtn)
  35. {
  36. sprintf(str, "read address 0x%X error:%d",startaddress,rtn);
  37. GUI_DispStringAt(str, 0, y);
  38. break;
  39. }
  40. else
  41. {
  42. sprintf(str, "read address 0x%X sucess! rbytes=0x%X",startaddress,bytesread);
  43. GUI_DispStringAt(str, 0, y);
  44. }
  45. y+= 16;
  46. for( i= 0; i<bytesread; i+= 4 )
  47. {
  48. int sect = GetSectorFromAddress(startaddress);
  49. if( sect >= 0 )
  50. {
  51. if( sectorFlag[sect] == 0 ) //0表示此sect还没有被擦除
  52. {
  53. sectorFlag[sect] = 1;
  54. FLASH_Erase_Sector(sect,FLASH_VOLTAGE_RANGE_3);
  55. sprintf(str, "erase sector %d",sect);
  56.                     GUI_DispStringAt(str,  0, y);
  57. }
  58. }
  59. uint32_t *p;
  60. p = ( uint32_t *)&buf[i];
  61. rtn = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,startaddress,*p); //写入Flash
  62. if( rtn != 0 )
  63. {
  64. isFinish = 1;
  65. sprintf(str, "HAL_FLASH_Program Err:%X",startaddress);
  66.                 GUI_DispStringAt(str,  0, y);
  67. break;
  68. }
  69. startaddress += 4;
  70. }
  71. if( bytesread < BUF_SIZE )
  72. {
  73. isFinish = 1;
  74. }
  75. }
  76. y+= 16;
  77. rtn = f_close(&fil);
  78. if(rtn)
  79. {
  80. sprintf(str, "close %s error:%d",filename,rtn);
  81. GUI_DispStringAt(str, 0, y);
  82. y+= 16;
  83. }
  84. else
  85. {
  86. sprintf(str, "close %s sucess",filename);
  87. GUI_DispStringAt(str, 0, y);
  88. y+= 16;
  89.     }
  90.     HAL_FLASH_Lock();
  91. GUI_DispStringAt( "end write program", 0, y);
  92. y+= 16;
  93. return isFinish;
  94. }

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

跳转部分代码如下:


   
  1. typedef void (*pFunction)(void);
  2. pFunction Jump_To_Application;
  3. uint32_t JumpAddress;
  4. void jumpToApp()
  5. {
  6. if (((*(__IO uint32_t*)APPLICATIONADDRESS) & 0x2FFE0000 ) == 0x20000000)
  7. {
  8. /* Jump to user application */
  9. JumpAddress = *(__IO uint32_t*) (APPLICATIONADDRESS + 4);
  10. Jump_To_Application = (pFunction) JumpAddress;
  11. /* Initialize user application's Stack Pointer */
  12. __set_MSP(*(__IO uint32_t*) APPLICATIONADDRESS);
  13. Jump_To_Application();
  14. }
  15. }

实际运行效果:

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

总结

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

推荐阅读:

程序 | STM32F4内部Flash读写

程序 | STM32CubeMX之FatFS读写U盘

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

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


转载:https://blog.csdn.net/zhang062061/article/details/114317576
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场