实现USART_IAP升级功能
IAP目的实现远程升级或者用其他方式升级
IAP_Bootloader程序逻辑
这次用STM32F407VET6
1.配置串口接受数据
2.擦写APP区域数据
3.写入完毕跳转APP运行区域
HAL库随便配置配只,只要一个串口
keil勾选Use MicroLIB弱函数库
只需编写两个文件
BootLoader引入程序部分
BootLoader.h
/**
******************************************************************************
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __BOOTLOADER_H__
#define __BOOTLOADER_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* USER CODE BEGIN Private defines */
#define UART_BUF_SIZE 16*1024
#define APPLICATION_ADDRESS ((uint32_t)0x08008000)
/* USER CODE END Private defines */
/* USER CODE BEGIN Prototypes */
void test(void);
void jumpl_application(void);
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __USART_H__ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
BootLoader.c
#include "Bootloader.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "usart.h"
#include "Flash.h"
/* Configer */
/* Bootloader */
typedef void (*pFunction)(void);
pFunction JumpToApplication;
uint32_t JumpAddress;
uint8_t buf[UART_BUF_SIZE];
void jumpl_application(void){
/* 接收处理 */
printf("Bootloader wait\r\n");
memset(buf, 0, 200);
HAL_UART_Receive(&huart1, buf, 4, 5000); //等待5S指令
if(buf[0]=='D'&&buf[1]=='O'&&buf[2]=='W'&&buf[3]=='N')
{
printf("Dowm readly\r\n");
memset(buf, 0, UART_BUF_SIZE);
HAL_UART_Receive(&huart1, buf, UART_BUF_SIZE, 15000);
uint32_t len=strlen((const char *)buf);
if(len==0)
printf("File timeout, please resend\r\n");
else
{
printf("Data length:%d\r\n",len);
printf("Please waitting latter\r\n");
Flash_clear();
STMFLASH_Write(APPLICATION_ADDRESS,buf,sizeof(buf)/sizeof(buf[0]));
}
}
/* JUMP APPLICATION*/
if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000){//判读堆栈
printf("APP CREAT OK\r\n");
HAL_UART_DeInit(&huart1);
HAL_SuspendTick();
/* execute the new program */
JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
/* Jump to user application */
JumpToApplication = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
JumpToApplication();
}
else
{
printf("no down app \r\n");
}
}
Flash.h
/**
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __FLASH_H__
#define __FLASH_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes */
/* USER CODE BEGIN Private defines */
/* Base address of the Flash sectors */
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base address of Sector 0, 16 Kbytes */
#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) /* Base address of Sector 1, 16 Kbytes */
#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) /* Base address of Sector 2, 16 Kbytes */
#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) /* Base address of Sector 3, 16 Kbytes */
#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) /* Base address of Sector 4, 64 Kbytes */
#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) /* Base address of Sector 5, 128 Kbytes */
#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000) /* Base address of Sector 6, 128 Kbytes */
#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000) /* Base address of Sector 7, 128 Kbytes */
/* USER CODE END Private defines */
/* USER CODE BEGIN Prototypes */
#define STMFLASH_ReadWord(faddr) (*(uint32_t*)(faddr))
void Flash_clear(void);
void STMFLASH_Write(uint32_t WriteAddr,uint8_t *pBuffer,uint32_t len);
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __USART_H__ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Flash.c
#include "Flash.h"
/* Flash */
/* 要擦除内部FLASH的起始地址 */
#define FLASH_USER_START_ADDR ADDR_FLASH_SECTOR_2
/* 要擦除内部FLASH的结束地址 */
#define FLASH_USER_END_ADDR ADDR_FLASH_SECTOR_7
static uint32_t GetSector(uint32_t Address);
/* 块 名称 块基址 大小
扇区 0 0x0800 0000 - 0x0800 3FFF 16 KB
扇区 1 0x0800 4000 - 0x0800 7FFF 16 KB
扇区 2 0x0800 8000 - 0x0800 BFFF 16 KB
扇区 3 0x0800 C000 - 0x0800 FFFF 16 KB
扇区 4 0x0801 0000 - 0x0801 FFFF 64 KB
扇区 5 0x0802 0000 - 0x0803 FFFF 128 KB
扇区 6 0x0804 0000 - 0x0805 FFFF 128 KB
?
扇区 11 0x080E 0000 - 0x08OF FFFF 128 KB
系统存储器 0x1 FFF 0000 - 0x1 FFF 77FF 30 KB
OTP区域 0x1 FFF 7800-0X1FFF 7A0F 528 字 W
选项字节 0x1 FFF C000 - 0x1 FFF C00F 16字节 */
void Flash_clear(void){
FLASH_EraseInitTypeDef EraseInitStruct;
uint32_t FirstSector = 0;
uint32_t NbOfSectors = 0;
uint32_t SECTORError = 0;
/* FLASH 解锁 ********************************/
/* 使能访问FLASH控制寄存器 */
HAL_FLASH_Unlock();
FirstSector = GetSector(FLASH_USER_START_ADDR);
NbOfSectors = GetSector(FLASH_USER_END_ADDR)- FirstSector + 1;
/* 擦除用户区域 (用户区域指程序本身没有使用的空间,可以自定义)**/
/* Fill EraseInit structure*/
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;/* 以“字”的大小进行操作 */
EraseInitStruct.Sector = FirstSector;
EraseInitStruct.NbSectors = NbOfSectors;
/* 开始擦除操作 */
if (HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError) != HAL_OK)
{
/*擦除出错*/
printf("Flash Erase Error\r\n");
}
else
printf("Flash Erase OK\r\n");
HAL_FLASH_Lock();
}
void STMFLASH_Write(uint32_t WriteAddr,uint8_t *pBuffer,uint32_t len){
HAL_FLASH_Unlock(); //解锁
uint32_t CountNum=0;
uint32_t flat=0;
for(uint32_t i=0; i<len; i++)
{
if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, WriteAddr, pBuffer[i])==HAL_OK)
{
CountNum++;
// printf("speed of progress start\r\n");
if((CountNum>(len/4))&&(CountNum<(len/2))&&(flat==0))
{
flat++;
printf("speed of progress 1/4\r\n");
}
if((CountNum>(len/2))&&(CountNum<(len/4*3))&&(flat==1))
{
flat++;
printf("speed of progress 2/4\r\n");
}
if((CountNum>(len/4*3))&&(CountNum<=len)&&(flat==2))
{
flat++;
printf("speed of progress 3/4\r\n");
}
if(CountNum>=len)
{
printf("speed of progress 4/4\r\n");
printf("Down Ok\r\n");
}
}
else
printf("Flash write error\r\n");
WriteAddr++;
}
HAL_FLASH_Lock(); //上锁
// printf("%d\r\n",STMFLASH_ReadWord(FLASH_USER_START_ADDR));
}
/**
* @brief 根据输入的地址给出它所在的sector
* 例如:
uwStartSector = GetSector(FLASH_USER_START_ADDR);
uwEndSector = GetSector(FLASH_USER_END_ADDR);
* @param Address:地址
* @retval 地址所在的sector
*/
static uint32_t GetSector(uint32_t Address)
{
uint32_t sector = 0;
if((Address < ADDR_FLASH_SECTOR_1) && (Address >= ADDR_FLASH_SECTOR_0))
{
sector = FLASH_SECTOR_0;
}
else if((Address < ADDR_FLASH_SECTOR_2) && (Address >= ADDR_FLASH_SECTOR_1))
{
sector = FLASH_SECTOR_1;
}
else if((Address < ADDR_FLASH_SECTOR_3) && (Address >= ADDR_FLASH_SECTOR_2))
{
sector = FLASH_SECTOR_2;
}
else if((Address < ADDR_FLASH_SECTOR_4) && (Address >= ADDR_FLASH_SECTOR_3))
{
sector = FLASH_SECTOR_3;
}
else if((Address < ADDR_FLASH_SECTOR_5) && (Address >= ADDR_FLASH_SECTOR_4))
{
sector = FLASH_SECTOR_4;
}
else if((Address < ADDR_FLASH_SECTOR_6) && (Address >= ADDR_FLASH_SECTOR_5))
{
sector = FLASH_SECTOR_5;
}
else if((Address < ADDR_FLASH_SECTOR_7) && (Address >= ADDR_FLASH_SECTOR_6))
{
sector = FLASH_SECTOR_6;
}
else/*(Address < FLASH_END_ADDR) && (Address >= ADDR_FLASH_SECTOR_23))*/
{
sector = FLASH_SECTOR_7;
}
return sector;
}
重定向fputc
APP段
加上这两句
fromelf --bin !L --output printf.bin
完结撒花!!!!!
版权声明:本文为CSDN博主「一只大苗子」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_53560025/article/details/121908900
暂无评论