• 基于STM32F4系列的ETH IAP在线升级程序


    目录

    1、前言

    2、以太网的移植(无操作系统)

    3、移植FATS 系统

    4、移植ETH 驱动及 DP83848驱动

    5、Tftp 服务程序

    6、注意事项 

    ​7、代码

    资料下载地址:基于STM32F4系列的ETH IAP在线升级程序

    1、前言

            此bootloader程序可以通过http或tftp方式更新STm32应用程序,是否进入BOOTLOADER程序可以根据读取板载外接存储器中的字节判断,能够做到做到了现场快速更改程序,省时省力!

    2、以太网的移植(无操作系统)

            打开LWIP1.4.1 移植文件,需要移植的src 文件port文件。其中port文件移植ethernetif.c/.h文件;src文件移植①api文件中所有.c文件,②core文件中除ipv6及snmp文件外所有文件,③ include中除ipv6及posix外所有的.h文件。由于此处移植无操作系统,所以在IAP_SERVICE 文件中定义了sys_arch.c,其中只有返回外部时间函数return  get_systick()。注意KEIL5相应的路径页需要包含对应的头文件。

    3、移植FATS 系统

            FTFP传输文件是512k block形式传送的,需要移植 FATS 文件系统。此处不多说,有比较多的资料讲这块。

    4、移植ETH 驱动及 DP83848驱动

            ETH 驱动是从官网上直接移植的,DP83848驱动通过lan8720修改过来的,区别就是lan8720的硬启动需要一定的时延,而DP83848基本上不需要硬重启的时间。需要注意的是在PHY驱动中,有些系统PHY 驱动中启动了MAC中断,那么在主程序中就可以不轮询ETH_CheckFrameReceived()函数,及ETH_DMA 是否接受到数据。反之,如果不启动MAC中断,则需要轮询ETH_CheckFrameReceived()函数。

    5、Tftp 服务程序

            Tftp 协议是在udp协议上升级而来,保证了文件传输的准确性。是在udp传输数据的基础上加上了特殊的包头与报位,并且有特定检验传输数据是否有问题的机制。报文格式如图1所示。

            如图2所示,为tftp的传输数据实现过程。在tftpserver.c/h 函数中有详细的TFTP函数实现。在IAP_tftp_process_write()函数中,起始完udp_recv()函数后,起始FLASH开始写文件。需要注意的是,在函数IAP_wrq_recv_callback()中检验是否写完,当接收返回的数据小于512+2+2KB时,说明传输文件完成,需要置标志位,并锁上STM32内部FLASH。

    6、注意事项 

            程序中以系统时钟作为TCP、ARP定时器(SystickCnt计数变量),在stm32f4xx_it.c 中可以看到,lwip以此时钟为基准调用LwIP_Periodic_Handle(SystickCnt)函数。在中断中,把接收到的缓冲区数据给lwip 处理ethernetif_input(&netif)。
            而在netcongf.c 文件中,必须把ARPTimer和TCPTimer的初始值给一个未定义的数值的变量localtime才能传输。

     7、代码

    1. /**
    2. * @file main.c
    3. * @author WB R&D Team - openmcu666 Debuger by Lyu Xin
    4. * @version V1.0
    5. * @date 2017.03.09
    6. * @brief Main Program body
    7. */
    8. #include "stm32f4xx.h"
    9. #include "Gpio.h"
    10. #include "usart.h"
    11. #include "main.h"
    12. #include "stm32f4x7_eth.h"
    13. #include "netconf.h"
    14. #include "eth_bsp.h"
    15. #include "Gpio.h"
    16. #include "tftpserver.h"
    17. #include "httpserver.h"
    18. #include "eeprom.h"
    19. //uint8_t data[40] = "bootloadering...";
    20. uint8_t tftp_flag = 0; //文件传输完成标识
    21. __IO uint32_t SystickCnt = 0;
    22. typedef void (*pFunction)(void);
    23. pFunction Jump_To_Application;
    24. uint32_t JumpAddress;
    25. static void delay(__IO uint32_t nCount)
    26. {
    27. __IO uint32_t index = 0;
    28. for(index = 80000*nCount; index != 0; index--)
    29. {
    30. }
    31. }
    32. uint32_t get_systick(void)
    33. {
    34. return SystickCnt;
    35. }
    36. //从扇区5开始擦除 ,偏移128KB ,为0x08020000,作为APP起始地址
    37. //可用HTTP或TFTP方式,默认TFTP,如需更改,见main.h文件
    38. /*****************************************************************************
    39. ** Main Function main()
    40. ******************************************************************************/
    41. int main(void)
    42. {
    43. uint8_t write_buf = 0;
    44. uint8_t read_buf = 0;
    45. I2C_EE_Init();
    46. #ifdef BOOTLOADER_EN
    47. write_buf = 0x66;
    48. I2C_EE_BufferWrite(&write_buf,1,1); //第0块第0字节
    49. #endif
    50. #ifdef APP_EN
    51. write_buf = 0x55;
    52. I2C_EE_BufferWrite(&write_buf,1,1); //第0块第0字节
    53. #endif
    54. I2C_EE_BufferRead(&read_buf,1,1);
    55. if( read_buf == 0x55 ){
    56. iap();
    57. }
    58. else if(read_buf != 0x55 ){
    59. SysTick_Config(SystemCoreClock / 1000); //systick必须在以太网初始化之前配置
    60. eth_init();
    61. LwIP_Init();
    62. #ifdef USE_IAP_HTTP
    63. IAP_httpd_init();
    64. #endif
    65. #ifdef USE_IAP_TFTP
    66. IAP_tftpd_init();
    67. #endif
    68. while (1)
    69. {
    70. if (ETH_CheckFrameReceived()){
    71. LwIP_Pkt_Handle();
    72. }
    73. LwIP_Periodic_Handle(SystickCnt);
    74. if(tftp_flag == 1){
    75. break;
    76. }
    77. else{
    78. // UDP_Client_Broadcast(data,40);
    79. continue;
    80. }
    81. }
    82. iap();
    83. }
    84. }
    85. void iap(void)
    86. {
    87. if (((*(__IO uint32_t*)USER_FLASH_FIRST_PAGE_ADDRESS) & 0x2FFE0000) == 0x20000000)
    88. {
    89. //跳转到用户程序
    90. JumpAddress = *(__IO uint32_t*) (USER_FLASH_FIRST_PAGE_ADDRESS + 4);
    91. Jump_To_Application = (pFunction) JumpAddress;
    92. //初始化用户程序的堆栈指针
    93. __set_MSP(*(__IO uint32_t*) USER_FLASH_FIRST_PAGE_ADDRESS);
    94. Jump_To_Application();
    95. }
    96. }

  • 相关阅读:
    尚硅谷设计模式学习(四)工厂模式
    2023年中国功能型内窥镜市场发展趋势分析:市场渗透潜力空间广阔[图]
    async和await、以及他们和promise的区别?
    java中流的分类
    原型和原型链
    Java多线程-初阶1
    Android分区存储解决方案
    如何加快Chrome谷歌浏览器下载速度?
    H5页面,上下滑动翻页(整页翻书切换效果)
    java基础
  • 原文地址:https://blog.csdn.net/qq_35654286/article/details/138163955