stm32程序太大远程升级怎么解决_分享一个STM32 BootLoader远程更新例程

本文介绍了一个STM32 BootLoader的远程更新例程,包括如何处理程序过大问题,涉及中断向量表重新初始化、EEPROM数据写入、Flash编程等关键步骤,以实现应用程序的无缝升级。
摘要由CSDN通过智能技术生成

#include "usart.h"

#include "string.h"

///

//函数名称:main                                                ///

//功能描述:程序入口,处理程序更新                              ///

//作    者:baishuyuan                                          ///

//注意事项:程序不可大于APP起始地址                             ///

///

const u8 FLASHKEY = 0xFF;//APP标志位

#define MAIN_USER_Start_ADDR     ((uint32_t)0x8000+0xB00-4)//用户代码的起始地址

#define MIN_USER_Start_ADDR     (MAIN_USER_Start_ADDR+4)//用户代码的起始地址 字节偏移5个字节

u16 APP_BIT_ADDR   =  0x1000;//用户代码的起始地址

#define PWR_HOLD_GPIO           GPIOD

#define PWR_HOLD_GPIO_Pin           GPIO_Pin_0

/*******************************************************************************

**函数名称:void delay(unsigned int ms)     Name: void delay(unsigned int ms)

**功能描述:大概延时

**入口参数:unsigned int ms   输入大概延时数值

**输出:无

******************************************************************************/

void delay(unsigned int ms)

{

unsigned int x , y;

for(x = ms; x > 0; x--)           /*  通过一定周期循环进行延时*/

for(y = 1000 ;  y > 0 ; y--);

}

//定义指向函数的指针类型

typedef void ( *AppMainTyp)(void);

uint32_t FLASH_ReadWord(uint32_t Address)

{

return(*(PointerAttr uint32_t *) (uint16_t)Address);

}

#include "stm8l15x_itc.h"

//重新初始化STM8的中断向量表  把它重新定义到APP的中断向量中

void STM8_HanderIqr_Init(void)

{

disableInterrupts();   //关闭中断

uint8_t Index;

FLASH_Unlock(FLASH_MemType_Program);

for(Index = 1; Index < 0X20;Index++)

{

if(FLASH_ReadWord(0X8000+4*Index)!=(0X82000000+MIN_USER_Start_ADDR+Index*4))

{

FLASH_ProgramWord(0X8000+4*Index,0X82000000+MIN_USER_Start_ADDR+Index*4);

}

}

FLASH_Lock(FLASH_MemType_Program);

}

//跳转到用户代码

void goto_app(void)

{

//重定义STM8的中断向量

STM8_HanderIqr_Init();

//跳转至APP

asm("LDW X,  SP ");

asm("LD  A,  $FF");

asm("LD  XL, A  ");

asm("LDW SP, X  ");

asm("JPF $8B00");

}

/*******************************************************************************

**函数名称:void EEPROM_Byte_Write(unsigned int address , unsigned char date)

**功能描述:向EEPROM中固定地址写入一个字节数据

**入口参数:unsigned int address , unsigned char date

address  :要写入数据的存储地址

date   :一个字节数据

**输出:无

*******************************************************************************/

void EEPROM_Byte_Write(unsigned int address , unsigned char date)

{

FLASH_SetProgrammingTime(FLASH_ProgramTime_TProg); //设定编程时间为标准编程时间

//MASS 密钥,解除EEPROM的保护

FLASH_Unlock(FLASH_MemType_Data);

FLASH_ProgramByte(address , date);  //把数据写入相应的存储地址

while(FLASH_GetFlagStatus(FLASH_FLAG_EOP) == 1);     //等待编程结束

}

/**********************************************************************

* 函数名称:  XOR_Inverted_Check

* 功能描述:数据的异或取反校验

* para:

inBuf: 需检测的字符串

inLen: 所需检测的字符串长度

***********************************************************************/

u8  XOR_Inverted_Check(unsigned char* inBuf, unsigned char inLen)

{

u8 check = 0, i;

for (i = 0; i < inLen; i++)

{

check ^= inBuf[i];

}

check = ~check;

return check;

}

u8 Write_App(u8 * Write_Data,u8 Write_Len)

{

static u32 addr = MIN_USER_Start_ADDR;//得到flash地址

u8 i = 0;

for(i=3;i

{

if(i

{

FLASH_ProgramByte(addr , USART_RX_BUF[i]);  //把数据写入相应的存储地址

}

addr++;//为下次写入做准备

}

if(Write_Len<24)

{

EEPROM_Byte_Write(APP_BIT_ADDR,FLASHKEY);

addr=MAIN_USER_Start_ADDR;//重置flash写地址

}

return i;

}

void Memset()

{

memset(USART_RX_BUF,0,USART_RX_STA);

USART_RX_STA=0;

}

void main()

{

u8 STR[]={0x7b,0x05,0xf2,0x03,0x70,'\r','\n','\0'};

u32 i=0;

disableInterrupts();   //关闭系统总中断

GPIO_DeInit(GPIOD);

/* Port D in output push-pull 0 */

GPIO_Init(GPIOD,GPIO_Pin_All, GPIO_Mode_Out_PP_Low_Slow);

GPIO_Init(PWR_HOLD_GPIO, PWR_HOLD_GPIO_Pin, GPIO_Mode_Out_PP_Low_Slow); //默认all电源为关 D0 推挽-输出低-高速

GPIO_SetBits(PWR_HOLD_GPIO, PWR_HOLD_GPIO_Pin);

CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1); //内部时钟为1分频 = 16Mhz

FLASH_Unlock(FLASH_MemType_Program);//MASS 密钥,解除FLASH的保护

FLASH_Unlock(FLASH_MemType_Data);//MASS 密钥,解除EEPROM的保护

FLASH_SetProgrammingTime(FLASH_ProgramTime_TProg); //设定编程时间为标准编程时间

while(FLASH_GetFlagStatus(FLASH_FLAG_PUL) == RESET);

//如果用户代码更新完成标记存在  则表示当前已经有APP代码  直接运行

if(FLASH_ReadByte(APP_BIT_ADDR+1)==0 && FLASH_ReadByte(MIN_USER_Start_ADDR)==0x82)//出厂首次烧录入口

{

//    FLASH_ProgramByte(APP_BIT_ADDR , FLASHKEY);  //写入更新完成标志位

//    goto_app();  //运行APP

}

else if(FLASH_ReadByte(MIN_USER_Start_ADDR)==0x82 && FLASH_ReadByte(APP_BIT_ADDR)==FLASHKEY && FLASH_ReadByte(APP_BIT_ADDR+1)!=0)//关机重启设备入口

{

//    goto_app();  //运行APP

}

else//更新APP入口

{

//    if( FLASH_ReadByte(APP_BIT_ADDR)!=0x00)//标志位清空 这段是APP的

//    {

//      FLASH_EraseByte(APP_BIT_ADDR);

//    }

//    for(i=MAIN_USER_Start_ADDR;i<0x9FF0;i++)//限定地址不可超过0x9FF0,清空flash

//    {

//      FLASH_EraseByte(i);  //把数据写入相应的存储地址

//    }

}

enableInterrupts();   //使能系统总中断

//等待USART1接收字符中断产生,中断服务函数在  stm8l15x_it.c文件里的 函数 INTERRUPT_HANDLER(USART1_RX_TIM5_CC_IRQHandler,28)

UART1_Init(9600);//串口初始化

UART1_TX_STR(STR);//接收第一帧数据

while(1)

{

UART1_TX_STR(STR);//发送测试数据

delay(1000);//短暂延迟

i=0xFFFFF;

while(i>10)

{

i--;

};

if(UPDATE_APP_OK)UPDATE_APP_OK++;//串口接收完成标志位

if(UPDATE_APP_OK>5)//接收完成了

{

UPDATE_APP_OK=0;

if((USART_RX_BUF[USART_RX_STA-1])==//CRC

(XOR_Inverted_Check(USART_RX_BUF,USART_RX_STA-1)))

{

if(USART_RX_STA>5 && USART_RX_STA<=USART_RX_LEN)

{

if(Write_App(USART_RX_BUF,USART_RX_STA)==(USART_RX_LEN-1))

{

UART1_TX_STR(STR);//持续接收

}

else

{

Memset();

STR[3]=0x05;

STR[4]=0x76;

UART1_TX_STR(STR);//go to app sending data

//            goto_app();//进入更新后的APP

}

}

}

Memset();

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值