STM32_IAP远程升级及C#上位机

发布者:平和的心情最新更新时间:2019-07-23 来源: eefocus关键字:STM32  IAP  远程升级  上位机 手机看文章 扫描二维码
随时随地手机看文章

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("单片机升级完成rn");

                    }

                    else if(recFile[1] == 0xff)

                    {

                        textBox2.AppendText("单片机已经进入升级模式rn");

                    }

                    else if ((file_len - read_len * recFile[1]) / read_len < 1)

                    {

                        progressBar1.Value = read_len * recFile[1] * 100 / file_len;

                        textBox2.AppendText("单片机升级........." + progressBar1.Value + "%rn");

                        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 + "%rn");

                        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("单片机接收错误,请重新发送rn");

                        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  远程升级  上位机 引用地址:STM32_IAP远程升级及C#上位机

上一篇:STM32移植lwip之建立web服务器
下一篇:stm32以太网LWIP学习笔记之UDP通信

推荐阅读最新更新时间:2024-11-02 13:20

STM32学习之:DMA详解
DMA部分我用到的相对简单,当然,可能这是新东西,我暂时还用不到它的复杂功能吧。下面用问答的形式表达我的思路。 DMA有什么用? 直接存储器存取用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU的干预,通过DMA数据可以快速地移动。这就节省了CPU的资源来做其他操作。 有多少个DMA资源? 有两个DMA控制器,DMA1有7个通道,DMA2有5个通道。 数据从什么地方送到什么地方? 外设到SRAM(I2C/UART等获取数据并送入SRAM); SRAM的两个区域之间; 外设到外设(ADC读取数据后送到TIM1控制其产生不同的PWM占空比); SRAM到外设(SR
[单片机]
<font color='red'>STM32</font>学习之:DMA详解
STM32 APB1总线时钟配置问题
调试载波通信系统的时候遇到这样一个问题:两台设备分别为A何B,他们都使用了定时器2~4来进行通讯,A设备的PCLK1配置为HCLK,而B设备的PCLK1配置为1/2HCLK,通讯过程发现A,B两个设备偶尔能通讯偶尔不能通讯,表现出通讯部稳定。理论上应该完全不能通讯才是,深入研究STM32F101C8T6的数据手册发现问题所在,截图如下: 图1 STM32功能框图 图2 STM32 时钟系统 从图1可以看到APB1总线挂接了TIM2~4,UART2~2...WWD等设备。然后从图2中可以看到只有外设直接使用了APB1的时钟作为实际时钟,而TIM2~4根据APB1的时钟进行了调整。因此当设备B的PCLK1配置为1/2HCL
[单片机]
<font color='red'>STM32</font> APB1总线时钟配置问题
STM32 JTAG复用相关方法
STM32F10x系列的MCU复位后,PA13/14/15 & PB3/4默认配置为JTAG功能。有时我们为了充分利用MCU I/O口的资源,会把这些端口设置为普通I/O口。具体方法如下: GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE); // 改变指定管脚的映射 GPIO_Remap_SWJ_Disable SWJ 完全禁用(JTAG+SW-DP) GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE); // 改变指定管脚的映射 GPIO_Remap_SWJ_JTAGDisable ,JTAG-DP
[单片机]
STM32使用模拟IIC操作EEPROM
贴出stm32f103vet6使用模拟IIC操作EEPROM的代码: 头文件部分i2c.h #ifndef _i2c_H_ #define _i2c_H_ #include stm32f10x.h #define countof(a) (sizeof(a)/sizeof(*(a))) #define GPIOA_IDR_Addr (GPIOA_BASE + 8) //0x40010808 #define GPIOB_IDR_Addr (GPIOB_BASE + 8) // /*位带操作,实现51类似的GPIO控制功能*/ /*IO口操作宏定义 */ #define BITBAND(addr, bitnum) (
[单片机]
基于 STM32 设计的指针式电子钟与日历
1. 项目简介 这是基于 STM32 设计的一个指针式电子钟+万年历小项目,采用 3.5 寸的 LCD 屏显示时钟,日历、温度、天气,支持触摸屏调整设置时间,设置闹钟,查看日历等等。整体项目主要是技术点就是 LCD 屏的图形绘制。比如: 时钟的时针绘制、分针、秒针、表盘、日历绘制等等。 时钟的时间是直接采用 STM32 本身的 RTC 时钟,室内的室温数据采用 DS18B20 温度传感器获取,STM32 芯片的具体型号是 STM32F103ZET6,只要是 STM32F1 系列的开发板,代码都是可以通用的。 LCD 显示屏采用的正点原子的 3.5 寸 TFT 显示屏,支持 8080 时序,自带触摸屏功能,触摸屏是电阻屏,驱动芯片是
[单片机]
ST全新多合一软件工具 让STM32用户烧写代码更方便
中国,2017年12月22日 -- 意法半导体 STM32CubeProgrammer (STM32CUBEPROG) 软件工具,在一个统一的多平台的用户可配置的环境内,为用户提供 STM32 微控制器代码烧写和固件升级功能。 STM32CubeProgrammer支持Windows®、Linux、MacOS® 三大操作系统,可以使用各种文件格式向STM32微控制器内部闪存/RAM或外部存储器烧写代码。具体功能包括存储器整体或扇区擦写选项字节。用户还可以生成程序安全烧写(固件安全安装更新)功能所需的加密文件,验证生产线上安装的软件的真伪,保护知识产权。 有了这个通用工具后,用户烧写 STM32微控制器 既可使用片上SWD
[嵌入式]
ST全新多合一软件工具 让<font color='red'>STM32</font>用户烧写代码更方便
STM32固件库SYSTEM文件夹介绍
SYSTEM 文件夹里面的代码,此文件夹里面的代码由 ALIENTEK 提供,包含了几乎每个实验都可能用到的延时函数,位带操作,串口打印代码等。SYSTEM 文件夹下包含了 delay、 sys、 usart 等三个文件夹。分别包含了 delay.c、 sys.c、usart.c 及其头文件 delay.h,sys.h,usart.h。 delay 文件夹代码介绍 delay 文件夹内包含了 delay.c 和 delay.h 两个文件,这两个文件用来实现系统的延时功能,其中包含 3 个函数: void delay_init(u8 SYSCLK); //该函数用来初始化 2 个重要参数:fac_us 以及 fac_ms;同时把
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved