STM32F103C86使用串口来进行IAP升级

在这里插入图片描述
STM32单片机的bootloader运行流程
直接上代码
照抄都可以

main.c


//全局变量的定义
uint8_t iap_buff[iap_len];
uint32_t Iap_CNt=0;
uint32_t Iap_C1=0;
uint8_t Iap_sign[1];
uint8_t T_sign[1]={0};



HAL_Read_Flash(0x08007800,T_sign,1);	//从flahs中读取T_sign的标志
 __HAL_TIM_CLEAR_IT(&htim3,TIM_IT_UPDATE);    //初始化完成之后以防立马进入中断,必须先清除一下

  while (1)
  {

	if(T_sign[0]==1)
	{
		iap_load_app(USER_FLASH_ADDR);
	}
    if(Iap_sign[0]==1&&T_sign[0]==0)
	{
		HAL_Flash_Write(USER_FLASH_ADDR,iap_buff,Iap_C1);
		//Iap_sign=0;
		T_sign[0]=1;
		HAL_Delay(1000);
		HAL_Flash_Write(0x08007800,T_sign,4);
		iap_load_app(USER_FLASH_ADDR);
		__disable_irq(); //关闭总中断
	}
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
  }

mian.h

extern uint32_t Iap_CNt;
extern uint8_t iap_buff[iap_len];
extern uint32_t Iap_C1;
extern uint8_t Iap_sign[1];
extern uint8_t T_sign[1];

flash.c


#include "flash.h"
#include <string.h>


FLASH_EraseInitTypeDef flashEraseInit;
uint32_t pageError = 0;
iapfun jump2app;

// 读取Flash数据
void HAL_Read_Flash(uint32_t addr, uint8_t *data, uint32_t len)
{
    memcpy(data, (uint8_t*)addr, len);
}

// 写入Flash数据
/*************************************************************************************
 * name: ADD:开始的flash地址,DATA:数据,LEN:长度
 * msg: 
 * Time: time
 * Input: void
 * Output: None
 * Return: void
 * param {uint32_t} addr
 * param {uint8_t} *data
 * param {uint32_t} len
 *************************************************************************************/
void HAL_Flash_Write(uint32_t addr, uint8_t *data, uint32_t len)
{
    HAL_FLASH_Unlock(); // 解锁Flash

    // 擦除扇区
    flashEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
    flashEraseInit.PageAddress = addr;
    flashEraseInit.NbPages = 1;
    HAL_FLASHEx_Erase(&flashEraseInit, &pageError);

    // 写入数据
    for(uint32_t i = 0; i < len; i += 4)
    {
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr + i, *(uint32_t*)(data + i));
    }
    HAL_FLASH_Lock(); // 锁定Flash
	//	Iap_sign=0;
}



//********************************IAP升级********************************//

/*************************************************************************************
 * name: 设置栈顶地址
 * msg:  addr: 栈顶地址
 * Time: time
 * Input: void
 * Output: None
 * Return: void
 * param {uint32_t} addr
 *************************************************************************************/
void sys_msr_msp(uint32_t addr)
{
    __set_MSP(addr);  /* 设置栈顶地址 */
}
/*************************************************************************************
 * name: iap升级,跳转到app用户程序
 * msg: appxaddr:起始地址
 * Time: time
 * Input: void
 * Output: None
 * Return: void
 * param {uint32_t} appxaddr
 *************************************************************************************/
void iap_load_app(uint32_t appxaddr)
{
    if (((*(volatile  uint32_t *)appxaddr) & 0x2FFE0000) == 0x20000000)     /* 检查栈顶地址是否合法.可以放在内部SRAM共64KB(0x20000000) */
    {
        /* 用户代码区第二个字为程序开始地址(复位地址) */
        jump2app = (iapfun) * (volatile uint32_t *)(appxaddr + 4);
        
        /* 初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址) */
        sys_msr_msp(*(volatile uint32_t *)appxaddr);
        
        /* 跳转到APP */
        jump2app();
    }
}

flahs.h


#include "main.h"

//定义APP的占用地址
#define iap_len     6*1024
typedef void (*iapfun)(void);                   /* 定义一个函数类型的参数 */

// 定义Flash地址
#define FLASH_BASE_ADDR 0x08000000
#define USER_FLASH_ADDR FLASH_BASE_ADDR + 0x2000 // 用户Flash地址,从0x0300开始

// 定义Flash大小
#define FLASH_SIZE 32 // 单位为KB

// 定义Flash扇区大小
#define FLASH_SECTOR_SIZE 1024 // 单位为字节

// 定义Flash扇区数量
#define FLASH_SECTOR_NUM FLASH_SIZE * 1024 / FLASH_SECTOR_SIZE

// 定义Flash写操作相关变量
#define FLASH_TIMEOUT 5000 // Flash写入超时时间,单位为毫秒

uint32_t endian_swap(uint32_t x);
void HAL_Read_Flash(uint32_t addr, uint8_t *data, uint32_t len);
void HAL_Flash_Write(uint32_t addr, uint8_t *data, uint32_t len);
void sys_msr_msp(uint32_t addr);
void iap_load_app(uint32_t appxaddr);

中断

/中断
//此bootloader中使用了 串口的接收中断和TIM的定时中断

void TIM3_IRQHandler(void)
{
  /* USER CODE BEGIN TIM3_IRQn 0 */
  Iap_C1=Iap_CNt;
	Iap_CNt=0;
  HAL_TIM_Base_Stop_IT(&htim3);//停止使能 TIM3 中断。这个 TIM3_IRQn 被中断后不会再
  __HAL_TIM_CLEAR_IT(&htim3,TIM_IT_UPDATE);//清除TIM3上的上一次增值中断。
	Iap_sign[0]=1;
	T_sign[0]=0;
  /* USER CODE END TIM3_IRQn 0 */
  HAL_TIM_IRQHandler(&htim3);
  /* USER CODE BEGIN TIM3_IRQn 1 */

  /* USER CODE END TIM3_IRQn 1 */
}

/**
  * @brief This function handles USART1 global interrupt.
  */
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
        uint8_t BUFF;
        // 接收到数据,将数据存入接收缓存区
				BUFF=USART1->DR; 
				//HAL_UART_Receive(&huart1,&BUFF,1,0x1000); //读取串口信息到BUFF中
        if(Iap_CNt<=iap_len)  //设定长度大于接收长度
        {
        iap_buff[Iap_CNt]=BUFF; //把当前接收到的字节赋值给iap_buff数组进行存储起来
        Iap_CNt++;//对接收长度进行计数

        __HAL_TIM_CLEAR_IT(&htim3,TIM_IT_UPDATE);//清除定时器溢出中断
        __HAL_TIM_SET_COUNTER(&htim3,0);  //当接收到第一个字节,就清空定时器(相当于喂狗,若没有产生接收中断,此数据就不会清空)
        HAL_TIM_Base_Start_IT(&htim3);//开始计时

        }
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白的ST开发之路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值