精华内容
下载资源
问答
  • 实现网络升级stm32 实现协议为tftp http,可以远程升级
  • STM32网络升级app程序

    2017-07-17 11:04:49
    STM32 网络APP示例,采用W5500作为网络的硬件接口,通过网络实现远程升级
  • STM32F4x7 通过以太网在线升级固件
  • 说明:该程序与我之前编写的《STM32F407通过SD卡进行程序升级(把bin文件烧写到FLASH的方式)》程序整合起来就可以实现SD卡+网络升级,即可以通过SD卡进行程序升级,如果升级失败自动跳转 去进行网络升级,也可以...
  • stm32远程升级

    2019-02-27 17:16:02
    STM32F103平台,通过2G通讯进行设备远程升级,完整代码实现,实用案例
  • STM32网络升级BootLoader

    2017-07-17 11:01:52
    STM32升级BootLoader接收程序。
  • stm32_IAP远程升级程序_STM32+W5500+IAP,现在项目正在使用,基于http的get和post两种模式。
  • 一个STM32平台uCOS在线网络升级的例子
  • stm32F107网络升级程序

    2019-04-18 11:36:12
    STM32F107芯片,用LWIP实现网络升级,从官方网站的程序更改过来。 进入升级状态: 串口发送数据: a0 00 00 0F 00 F1 00 00 00 00 00 00 00 5E AF 使APP重启 通过TFTPD32升级程序 结束升级状态,用网络调试助手...
  • STM32单片机可用的差分升级(增量升级)算法软件(非源码,请联系微信deiois) 介绍博客:https://blog.csdn.net/zhou74281/article/details/117777684 DiffIAP – STM32单片机可用的差分升级(增量升级),适用于物联网车...
  • 包含STM32F407LWIP+TFTP的IAP程序,应用程序APP,上位机软件。 文档说明:查找我的资源。
  • 基于CAN总线的在线程序升级文档,使用平台为STM32F107,对于DSP等嵌入式系统同样具有较强的借鉴意义。
  • 基于STM32的GPRS远程在线系统升级的设计实现,解决STM32远程升级问题
  • 网络升级的优点传输速度快,但是驱动复杂,升级场地局限(必须要有上位机)。U 盘升级的优点不受场地限制,传输速度快,但是驱动有点复杂。不过 ST官方已经将 USB 的驱动提供给大家,这样我们需要的编写的就更集中在...
  • STM32远程升级(IAP)

    2020-12-15 15:10:12
    嵌入式系统的主要升级方式有ICP、IAP、ISP。 ISP(In-SystemProgramming)为在系统中编程,出厂时ST公司已经在ROM中写入了BootLoader,通过通信接口就可以擦除与编程用户程序; IAP(In-ApplicationProgram)为在应用...

    1、烧写程序三种方式

    嵌入式系统的主要升级方式有ICP、IAP、ISP。

    1. ISP(In-SystemProgramming)为在系统中编程,出厂时ST公司已经在ROM中写入了BootLoader,通过通信接口就可以擦除与编程用户程序;
    2. IAP(In-ApplicationProgram)为在应用程序中编程,用户在运行程序的时候,通过BootLoader程序对指定的Flash区域进行烧写,除了ST公司出厂时写入的BootLoader外,用户可以自己写入一个BootLoader程序来运行存储在Flash中指定区域的程序,在程序的运行过程中我们就可以通过任何通讯方式,把接收到的bin文件写入到指定区域的Flash中,然后进行应用程序的升级;
    3. ICP(In-CircuitProgramming)为在电路编程,这是一种串行编程方式,可以使用JTAG或者SWD接口来对STM32进行程序烧写。

    2、远程升级实现

    首先,我的思路是将STM32的FLASH区域化分为四大区域,例如我使用的是STM32F103VET6,该芯片的FLASH区域有512K。第一块区域大小为50K,用来存放BOOTLOADER程序。第二块与第三块区域可以每个分200K大小,用来存放用户应用程序一(APP1)与用户应用程序二(APP2)。第四部分就用来存放各种标志位,比如当前运程的程序标志、应用程序版本标志等等。如果当前是运行在APP1下,那么接收到的升级程序就要写在APP2的区域内。我采用的是MQTT协议来实现远程升级,设备端使用Wi-Fi连接至互联网,通过MQTT协议连接至云端服务器。这里用的MQTT服务器为EMQX,并使用python作为另一个客户端(paho-mqtt)连接至服务器,这样就实现了python写的客户端与设备终端之间的通讯。

    终端设备程序流程图(示意):
    在这里插入图片描述

    (1) BOOTLOADER

    BOOTLOADER程序程序负责根据升级FLAG去跳转至对应的APP程序,没有其他工作。在编译时要制定FLASH空间,分配50K的大小。跳转的程序就不列出来了,有很多可以参考的例程。
    在这里插入图片描述

    (2)用户应用程序一(APP1)

    使用ESP8266模块连接Wi-Fi,并通过MQTT协议连接至云端服务器。由于我的应用程序中使用了ucOSIII与emwin所以,bin文件会比较大。此时使用MQTT协议一次发送数据包过大可能会引起数据丢失等错误。所以为了避免这些错误。经测试,一次发送4K左右的数据包时可以保证数据的完整度。所以当bin文件大小为200K左右时,需要将其分成50个数据包来发送数据。如果要实现多台设备终端升级时,可以考虑先订阅一个升级包,收到该主题的消息后就取消订阅。这样两个设备之间不会相互影响。
    APP1的地址要避开其他。
    在这里插入图片描述
    一定要在main函数中加入这条。放在最前面,设置中断向量表的偏移。

    SCB->VTOR = FLASH_BASE | 0x0800C800;
    

    (2)用户应用程序二(APP2)

    同APP1
    在这里插入图片描述
    同样要在main函数中首先设置中断向量偏移。

    SCB->VTOR = FLASH_BASE | 0x803E800;
    

    3、Bootloader程序

    1.首先先给主函数的例子

    // 设置FLASH保存地址(必须为偶数,且其值要大于本代码所占用FLASH的大小)
    // Bootloader 程序空间50k
    /* 第一个APP的起始位置 IAP程序空间留有(100k)每一个APP大小为200K */
    #define FLASH_APP1_ADDR	0X0800C800
    /* 第二个APP的起始位置为250K */
    #define FLASH_APP2_ADDR	0X0803E800
    /* APP_FLAG存储起始位置为450K */
    #define FLASH_FLAG_ADDR	0X08070800
    
    #define Flag_Size 5
    int main(void)
    {
    	USARTx_Init();
    	uint8_t Read_Flag[5];
    
    	STMFLASH_Read(FLASH_FLAG_ADDR,(uint16_t *)Read_Flag,Flag_Size);
    	while(1)
    	{
    		if(strcmp((char *)Read_Flag,"0") == 0)
    		{
    			printf("开始执行用户代码(app1)!\n");
    			if(((*(vu32*)(FLASH_APP1_ADDR+4))&0xFF000000)==0x08000000)
    			{
    				iap_load_app(FLASH_APP1_ADDR);
    			}
    			else
    				printf("FLASH地址有误!\n");
    		
    		}
    		if(strcmp((char *)Read_Flag,"1") == 0)
    		{
    			printf("开始执行用户代码(app2)!\n");
    			if(((*(vu32*)(FLASH_APP2_ADDR+4))&0xFF000000)==0x08000000)
    			{
    				iap_load_app(FLASH_APP2_ADDR);
    			}
    			else
    				printf("FLASH地址有误!\n");
    		}
    	}
    }
    

    2.iap_load_app()函数

    typedef void (*iapfun) (void);  
    iapfun jump2app;
    void iap_load_app(uint32_t app_addr)
    {
    		// 检查栈顶地址是否合法.
    	if(((*(vu32*)app_addr)&0x2FFE0000)==0x20000000)	
    	{
    		jump2app = (iapfun)*(vu32*)(app_addr + 4);
    		MSR_MSP(*(vu32*)app_addr);
    		jump2app();
    	}
    }
    

    3.这样就完成每次读取(FLASH_FLAG_ADDR 0X08070800)这个地址的存放的数据,然后根据读出的标志是0还是1来跳转至相应的APP区域执行程序。

    4.关于升级文件的接收

    首先我们的单片机要连接到EMQ X服务器,然后订阅相关的升级Topic。当单片机发送升级请求时,使用python编写的MQTT客户端接收到请求,根据所要升级的文件大小,将其分成若干个小包(我这里测试过每包分为4K的大小单片机可以正常接收数据)。每个小包为一个Topic,然后将数据发送至单片机。单片机每接收一个topic,经过检查后将其写入FLASH。接收完所有的升级包后,将FLASH_FLAG_ADDR中的标志位置0或1,通过软复位来进入bootloader程序。然后bootloader程序根据标志位跳转相应的APP区。

    4.后期还会继续加更完整程序(狗头)

    关于MQTT程序https://blog.csdn.net/qq_40893726/article/details/109449151
    在这篇文章有介绍

    展开全文
  • 实现了STM32F107以太网在线升级,包含了详细的操作说明,及完整的源代码。
  • HTTP网页服务器实验_APP ,以太网远程升级例程_IAP
  • STM32CubeMx开发之路—在线升级OTA(1/4)—基础知识 STM32CubeMx开发之路—在线升级OTA(2/4)—BootLoader STM32CubeMx开发之路—在线升级OTA(3/4)—App STM32CubeMx开发之路—在线升级OTA(4/4)—测试 运行环境 ...
  • 随着4G网络的普及,使野外实时监测...文章提出了通过4G网络实现以STM32为微控制器的设备的远程系统升级方案。从而实现远程对野外设备的系统升级,大大的提高了生产效率,并且可以及时对设备运行过程中发现的bug进行修复。
  • Stm32F4xx系列官方IAP升级程序,支持串口下载程序、读取固件内容,使用Ymode协议进行文件传输。
  • 该上位机用于给STM32进行串口IAP固件升级,上位机升级原理可以移植到其他控制器实现STM32单片机远程固件升级,亲测稳定可用
  • 主控板CPU:STM32F105;GPRS模组:SIM7600CE;大概思路:主控板上电后,检测到APP有升级需求后SIM7600CE连接网络,通过FTP方式下载最新的app固件,烧写成功后重启进入APP(当中包括校验等操作)。工程是实际项目在用...
  • 使用STM32+W5500 OTA升级,一定会使用到服务器,可以考虑自己搭建一个,因为我并不是搞这一块的,但是觉得这个写的挺不错的,也挺简单的,所以上传了。
  • STM32_IAP远程升级及C#上位机

    千次阅读 2018-11-28 10:57:17
    STM32的IAP功能在一些需要升级维护的场景下显得十分的重要,当然在实际项目中,我们需要远程发送升级指令,使得主控进入升级模式,进而将固件下发升级。很多网上的资源中,只有IAP跳转至APP,并且不带有任何协议,...

    STM32的IAP功能在一些需要升级维护的场景下显得十分的重要,当然在实际项目中,我们需要远程发送升级指令,使得主控进入升级模式,进而将固件下发升级。很多网上的资源中,只有IAP跳转至APP,并且不带有任何协议,直接将bin文件一次性下发。但是这样的话,在项目实际使用过程中,会非常不稳定。还有一些是有代码,但是上位机代码或者stm32的代码不给你,只是提供思路。也是挺麻烦的一件事情。

    我先讲讲自己的思路,C#上位机方面,首先打开串口,串口的波特率使用115200(上位机中没有给出设置界面)。打开需要升级的bin文件,左侧textbox显示文件绝对路径,下侧textbox显示文件大小。此程序将bin文件分成2k字节一个包,并且在每个包的头部加入0x5a的包头,再接着包的序号。以及包尾部加入0xaa。总共2051字节一包。下位机接收并保存之后,返回0x5a,包序号,0xaa。上位机接收到返回之后,继续下发后序bin包。其中最后一包序号为0xa5。下位机接收到0xa5序号的包时,下位机开始跳转至APP。

    下位机跳转至APP之后,上位机点击进入升级模式按钮后,上位机下发AA,BB,CC,DD,EE指令,下位机接收到指令,跳转回IAP程序,等待固件的下发。若一分钟后没有收到固件,重新跳转回APP。

    下面是bin文件组包。

            public byte[] SplitArray(byte[] Source, int StartIndex, int EndIndex,byte Block)
            {
                try
                {
                    byte[] result = new byte[EndIndex - StartIndex + 1+2+1];//加入帧头(2 bytes)尾(1 byte)
                    result[0] = 0x5a;
                    result[1] = Block;
                    for (int i = 0; i <= EndIndex - StartIndex; i++) result[i+2] = Source[i + StartIndex];
                    result[EndIndex - StartIndex + 1 + 2] = 0xaa;
                    return result;
                }
                catch (IndexOutOfRangeException ex)
                {
                    throw new Exception(ex.Message);
                }
            }

    接收到返回之后继续下发后序bin文件包

     int recl;
                if (serialPort1.BytesToRead > 0)
                {
                    timer1.Stop();
                    recl = serialPort1.BytesToRead;//读取串口接收的长度
                    byte[] recFile = new byte[recl];
                    for (int i = 0; i < recl; i++)
                    {
                        recFile[i] = (byte)(serialPort1.ReadByte());
                    }
                    if (recFile[0] == 0x5a && recFile[2] == 0xaa)
                    {
                        if (recFile[1] == 0xa5)//接收完成
                        {
                            progressBar1.Value = 100;
                            sendflag = false;
                            textBox2.AppendText("单片机升级完成\r\n");
                        }
                        else if(recFile[1] == 0xff)
                        {
                            textBox2.AppendText("单片机已经进入升级模式\r\n");
                        }
                        else if ((file_len - read_len * recFile[1]) / read_len < 1)
                        {
                            progressBar1.Value = read_len * recFile[1] * 100 / file_len;
                            textBox2.AppendText("单片机升级........." + progressBar1.Value + "%\r\n");
                            try
                            {
                                sendchar = SplitArray(binchar, read_len * recFile[1], file_len - 1, 0xa5);
                                serialPort1.Write(sendchar, 0, file_len - read_len * recFile[1] + 3);
                                timer1.Start();
                            }
                            catch (Exception)
                            {
    
                            }
                        }
                        else
                        {
                            progressBar1.Value = read_len * recFile[1] * 100 / file_len;
                            textBox2.AppendText("单片机升级......." + progressBar1.Value + "%\r\n");
                            try
                            {
                                sendchar = SplitArray(binchar, read_len * recFile[1], read_len * (recFile[1] + 1) - 1, (byte)((recFile[1] + 1) & 0xff));
                                serialPort1.Write(sendchar, 0, read_len + 3);
                                timer1.Start();
                            }
                            catch (Exception)
                            {
    
                            }
                        }
    
                    }
                    else
                    {
                        if (sendflag == true)
                        {
                            textBox2.AppendText("单片机接收错误,请重新发送\r\n");
                            sendflag = false;
                        }
                    }
                }
            }

    下位机方面:IAP跳转程序

    //跳转到应用程序段
    //appxaddr:用户代码起始地址.
    void iap_load_app(u32 appxaddr)
    {
    	u8 i;
    	if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000)	//检查栈顶地址是否合法.
    	{ 
    		jump2app=(iapfun)*(vu32*)(appxaddr+4);		//用户代码区第二个字为程序开始地址(复位地址)		
    		MSR_MSP(*(vu32*)appxaddr);					//初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
    		for(i = 0; i < 8; i++)
    		{			
    			NVIC->ICER[i] = 0xFFFFFFFF;	/* 关闭中断*/
    			NVIC->ICPR[i] = 0xFFFFFFFF;	/* 清除中断标志位 */
    		}
    		jump2app();									//跳转到APP.
    	}
    }	

    跳转之前,需要将中断关闭,APP中使用了串口IDLE的中断,不清楚为什么,一定需要在程序中将其DISABLE,不然跳转回IAP之后,不能跳回APP。

    APP中采用了FreeRTOS实时系统,APP程序起始偏移如下。

    NVIC_SetVectorTable(FLASH_APP1_ADDR,0);

    说明:STM32程序大部分参考正点原子例程。稍作修改。

    源码位置:https://download.csdn.net/download/qq_23229787/10807490

    上传的c#程序有mysql的登录和注册,可以注册再登录,也可以在登录界面点击版本号进入系统。对了,本该将bin文件分包之后,采用较为标准的协议,但是自己为了方便就自定义了协议。另外代码中有什么不好之处还请大家提出,一起学习。

    展开全文
  • STM32串口在线升级IAP+ymodemDown,包括pc端C#源码;STM32串口在线升级IAP+ymodemDown MDK源码,C# ymodem协议源码;
  • [小制作]古董万年历升级WiFi授时 STM32+ESP8266故事,还得从一只蝙蝠说起…先来看一下前后对比硬件方面升级之前升级之后功能方面调用序列图-这里只放个大概 详细的还得结合程序说程序流程图STM32流程图ESP8266流程图...
  • 这是全网独有的,可以实现远程stm32网络远程IAP下载,所移植的是uip协议栈
  • 1,STM32F10x_AN2557_FW_V3.3.0官方F1xx的例程 2,实验48 串口IAP实验-库函数版--原子旗舰板的例程 3,STM32 IAP源码和测试代码.rar 4,stm32f4_iap_using_usart官方F4xx的例程.zip 5,Stm32iap.rar 6,红龙407...
  • 目的是为了在GPRS和网口远程更新上用的,支持串口和网络远程升级
  • stm32 以太网 LWIP TFTP IAP 远程升级

    万次阅读 热门讨论 2016-11-19 10:27:06
    本例采用的PHY层芯片是DP83848,相当于物理层,STM32F107自带的MAC层相当于数据链路层,而LWIP协议栈提供的就是网络层、传输层的功能,应用层是需要我们自己根据自己想要的功能去实现的。升级程序由bootloader和APP...

    一.综述
    本文是基于STM32F107的LWIP协议栈通过TFTP的文件传输协议进行IAP程序升级。本例采用的PHY层芯片是DP83848,相当于物理层,STM32F107自带的MAC层相当于数据链路层,而LWIP协议栈提供的就是网络层、传输层的功能,应用层是需要我们自己根据自己想要的功能去实现的。升级程序由bootloader和APP两部分组成。将stm32 flash划分为两个分区,bootloader和APP区,bootloader存放升级引导程序,可以根据具体的Code大小确定bootloader的扇区,APP就是用户程序即需要升级的程序代码,APP存放的地址紧接bootloader的末地址之后。如果空间允许并且安全性要求高的话,可以将flash划分为三个分区,分别为bootloader、app和backups区。增加一个备份区,存放原运行程序,对原有运行程序进行拷贝,如果升级失败则运行备份程序,至于以系统不会瘫痪。如图:
    这里写图片描述
    二.Bootloader
    作用是引导升级启动。
    相关重点程序设置:

    //设置APP用户程序起始地址
     #define USER_FLASH_FIRST_PAGE_ADDRESS  0x8003000
    //设置擦除的flash结束扇区地址
     #define USER_FLASH_LAST_PAGE_ADDRESS   0x801FFFF 
    //设置堆栈指针
    __set_MSP(*(__IO uint32_t*) USER_FLASH_FIRST_PAGE_ADDRESS);
    //复位中断,跳转到APP运行
     Jump_To_Application();
    
    

    三.APP用户程序

    1.设置向量表偏移地址
    #define VECT_TAB_OFFSET  0x3000
    
    
    2.设置flash程序起始地址 0x8003000
    
    

    这里写图片描述
    3.编译产生bin文件
    这里写图片描述
    四.相关代码:
    下面来分析相关代码:
    Main函数是相关外设初始化,主要是应用程序跳转程序:

    if (((*(__IO uint32_t*)USER_FLASH_FIRST_PAGE_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
        {  
         // __disable_irq(); /* disable interrupts. */
    			/* disable and clean up all interrupts. */
        {
            int i;
            for(i = 0; i < 8; i++)
            {
               /* disable interrupts. */
              NVIC->ICER[i] = 0xFFFFFFFF;
               /* clean up interrupts flags. */
              NVIC->ICPR[i] = 0xFFFFFFFF;
            }
        }
          /* Jump to user application */
          JumpAddress = *(__IO uint32_t*) (USER_FLASH_FIRST_PAGE_ADDRESS + 4); 
          Jump_To_Application = (pFunction) JumpAddress;
          /* Initialize user application's Stack Pointer */
          __set_MSP(*(__IO uint32_t*) USER_FLASH_FIRST_PAGE_ADDRESS);
          Jump_To_Application();
    }
    
    

    在LWIP初始化后创建TFTP服务器,TFTP是简单文件传送协议,采用的UDP协议,默认端口号为69。创建TFTP服务器,创建一个UDP PCB,且绑定69端口,最后指定该UDP PCB的数据接收回调函数。

    void IAP_tftpd_init(void)
    {
      err_t err;
      unsigned port = 69; 
      /* 69 is the port used for TFTP protocol initial transaction */
      /* create a new UDP PCB structure  */
      UDPpcb = udp_new();
      if (!UDPpcb)
      {
        /* Error creating PCB. Out of Memory  */
        return ;
      }
      /* Bind this PCB to port 69  */
      err = udp_bind(UDPpcb, IP_ADDR_ANY, port);
      if (err == ERR_OK)
      {
        /* Initialize receive callback function  */
        udp_recv(UDPpcb,tftp_recv_callback, NULL);
      } 
    }
    
    

    接下来在回调函数中根据TFTP协议进行协议解释、数据处理以及写入flash的过程,写入flash之前须解锁flash-擦除flash扇区-写入flash。如下:

    int IAP_tftp_write(struct udp_pcb *upcb, struct ip_addr *to, int to_port)
    {
      tftp_connection_args *args = NULL;
      /* This function is called from a callback,
      * therefore interrupts are disabled,
      * therefore we can use regular malloc   */
      args = mem_malloc(sizeof *args);
      if (!args)
      {
        IAP_tftp_cleanup_wr(upcb, args);
        return 0;
      }
      args->op = TFTP_WRQ;
      args->to_ip.addr = to->addr;
      args->to_port = to_port;
      /* the block # used as a positive response to a WRQ is _always_ 0 */
      args->block = 0;
      args->tot_bytes = 0;
      /* set callback for receives on this UDP PCB (Protocol Control Block) */
      udp_recv(upcb, IAP_wrq_recv_callback, args);
      total_count =0;
      /* init flash */
      FLASH_Unlock();
      /* erase user flash area */
      FLASH_Erase(USER_FLASH_FIRST_PAGE_ADDRESS);
      Flash_Write_Address = USER_FLASH_FIRST_PAGE_ADDRESS;    
      /* initiate the write transaction by sending the first ack */
      IAP_tftp_send_ack_packet(upcb, to, to_port, args->block);
      return 0;
    }
    
    

    需要注意的是bootloader需要关闭中断,不能关总中断,最好是循环分次关闭。(不关闭中断程序跑飞或者运行异常)。
    最后实现如下:
    这里写图片描述
    更多技术文章浏览请关注:

    百家号:
    https://author.baidu.com/home?context=%7B%22app_id%22%3A%221646108714303504%22%7D&wfr=bjh

    头条号:
    https://www.toutiao.com/c/user/8115738721/#mid=1646025109246987

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,604
精华内容 1,041
关键字:

网络升级stm32