| 【HAL库每天一例】系列例程从今天开始持续更新。。。。。 我们将坚持每天至少发布一个基于YS-F1Pro开发板的HAL库例程,
 该系列例程将带领大家从零开始使用HAL库,后面会持续添加模块应用例程。
 同样的,我们还程序发布基于HAL库的指导文档和视频教程,欢迎持续关注,并提出改进意见。
 例程下载:
 资料包括程序、相关说明资料以及软件使用截图
 链接:https://pan.baidu.com/s/1i574oPv
 密码:r3s3
 (硬石YS-F1Pro开发板HAL库例程持续更新\1. 软件设计之基本裸机例程(HAL库版本)\YSF1_HAL-062. IAP-串口IAP)
 /**
 ******************************************************************************
 *                           硬石YS-F1Pro开发板例程功能说明
 *
 *  例程名称: IAP-Bootloader
 *
 ******************************************************************************
 * 说明:
 * 本例程配套硬石stm32开发板YS-F1Pro使用。
 *
 * 淘宝:
 * 论坛:硬石电子社区
 * 版权归硬石嵌入式开发团队所有,请勿商用。
 ******************************************************************************
 */
 
 【1】例程简介
 固件更新或升级在我们日常生活是非常常见的,比如Windows系统更新、手机系统更新、软件在线
 更新、APP在线更新,本例程实现STM32的IAP(在线升级)功能,更新文件是由“LED-FLASH”或
 “LED-RAM”例程生成的“YS-F1Pro.bin”文件,通过串口调试助手把该文件内容发送给运行本例程
 的开发板,然后实现运行“YS-F1Pro.bin”文件代码功能。
 
 【2】跳线帽情况
 ******* 为保证例程正常运行,必须插入以下跳线帽 **********
 丝印编号     IO端口      目标功能引脚        出厂默认设置
 JP1        PA10        TXD(CH340G)          已接入
 JP2        PA9         RXD(CH340G)          已接入
 JP3        PB0           LED1               已接入
 JP4        PG6           LED2               已接入
 JP5        PG7           LED3               已接入
 
 【3】操作及现象
 运行本例程之前,先打开“LED-FLASH”或“LED-RAM”例程编译生成“YS-F1Pro.bin”文件(路径:
 ..\LED-FLASH\Project\MDKARM(uV5)\YS-F1Pro.bin)。
 使用开发板配套的MINI USB线连接到开发板标示“调试串口”字样的MIMI USB接口(需要安装驱动),
 在电脑端打开串口调试助手工具,设置参数为115200 8-N-1。下载完程序之后,在串口调试助手窗口可
 接收到信息,如果我们不需要更新程序直接按下KEY2按键即可运行原本程序。如果需要更新程序,在没有
 按下KEY2之前,在串口调试助手发送“YS-F1Pro.bin”文件给开发板(通过串口调试助手文件发送功能发
 送即可)。然后按下KEY1按键实现在线升级,最后按下KEY2即可运行新程序。
 
 /******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/
 
 
 bsp_iap.h文件内容
 
 复制代码#ifndef __BSP_IAP_H__
#define        __BSP_IAP_H__
/* 包含头文件 ----------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
/* 类型定义 ------------------------------------------------------------------*/
/************************** IAP 数据类型定义********************************/
typedef  void ( * pIapFun_TypeDef ) ( void ); //定义一个函数类型的参数.
/* 宏定义 --------------------------------------------------------------------*/
/************************** IAP 宏参数定义********************************/
 //是否更新 APP 到 FLASH,否则更新到 RAM
#define User_Flash                                        
#ifdef User_Flash
  #define APP_START_ADDR       0x8010000          //应用程序起始地址(存放在FLASH)
#else
  #define APP_START_ADDR       0x20001000          //应用程序起始地址(存放在RAM)
#endif
/************************** IAP 外部变量********************************/
#define APP_FLASH_LEN                             56320u       //定义 APP 固件最大容量,55kB=55*1024=56320
/* 扩展变量 ------------------------------------------------------------------*/
extern struct  STRUCT_IAP_RECIEVE      //串口数据帧的处理结构体
{
        uint8_t   ucDataBuf[APP_FLASH_LEN];
        uint16_t  usLength;
} strAppBin;
/* 函数声明 ------------------------------------------------------------------*/
void IAP_Write_App_Bin( uint32_t appxaddr, uint8_t * appbuf, uint32_t applen);        //在指定地址开始,写入bin
void IAP_ExecuteApp( uint32_t appxaddr );                                                      //执行flash里面的app程序
#endif /* __BSP_IAP_H__ */
/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/
 bsp_iap.c文件内容
 
 复制代码/**
  ******************************************************************************
  * 文件名程: bsp_iap.c 
  * 作    者: 硬石嵌入式开发团队
  * 版    本: V1.0
  * 编写日期: 2015-10-04
  * 功    能: IAP底层驱动实现
  ******************************************************************************
  * 说明:
  * 本例程配套硬石stm32开发板YS-F1Pro使用。
  * 
  * 淘宝:
  * 论坛:http://www.ing10bbs.com
  * 版权归硬石嵌入式开发团队所有,请勿商用。
  ******************************************************************************
  */
/* 包含头文件 ----------------------------------------------------------------*/
#include "IAP/bsp_iap.h"
#include "stmflash/stm_flash.h"
/* 私有类型定义 --------------------------------------------------------------*/
/* 私有宏定义 ----------------------------------------------------------------*/
/* 私有变量 ------------------------------------------------------------------*/
#if defined ( __CC_ARM )  // 使用Keil编译环境
struct STRUCT_IAP_RECIEVE strAppBin  __attribute__((at(0x20001000)))={{0},0};
#elif defined ( __ICCARM__ ) // 使用IAR编译环境
struct STRUCT_IAP_RECIEVE strAppBin;//={{0},0};
#endif
static uint16_t ulBuf_Flash_App[1024];
/* 扩展变量 ------------------------------------------------------------------*/
/* 私有函数原形 --------------------------------------------------------------*/
/* 函数体 --------------------------------------------------------------------*/
void IAP_Write_App_Bin ( uint32_t ulStartAddr, uint8_t * pBin_DataBuf, uint32_t ulBufLength )
{
        uint16_t us, usCtr=0, usTemp;
        uint32_t ulAdd_Write = ulStartAddr;                                //当前写入的地址
        uint8_t * pData = pBin_DataBuf;
        
        for ( us = 0; us < ulBufLength; us += 2 )
        {                                                    
                usTemp =  ( uint16_t ) pData[1]<<8;
                usTemp += ( uint16_t ) pData[0];          
                pData += 2;                                                      //偏移2个字节
                ulBuf_Flash_App [ usCtr ++ ] = usTemp;            
                if ( usCtr == 1024 )
                {
                        usCtr = 0;
                        STMFLASH_Write ( ulAdd_Write, ulBuf_Flash_App, 1024 );        
                        ulAdd_Write += 2048;                                           //偏移2048  16=2*8.所以要乘以2.
                }
        }
        if ( usCtr ) 
    STMFLASH_Write ( ulAdd_Write, ulBuf_Flash_App, usCtr );//将最后的一些内容字节写进去.  
}
#if defined ( __CC_ARM )  // 使用Keil编译环境
__asm void MSR_MSP ( uint32_t ulAddr ) 
{
    MSR MSP, r0                                            //set Main Stack value
    BX r14
}
#elif defined ( __ICCARM__ ) // 使用IAR编译环境
void MSR_MSP ( uint32_t ulAddr ) 
{
    asm("MSR MSP, r0");                                            //set Main Stack value
    asm("BX r14");
}
#endif
//跳转到应用程序段
//ulAddr_App:用户代码起始地址.
void IAP_ExecuteApp ( uint32_t ulAddr_App )
{
        pIapFun_TypeDef pJump2App; 
        
        if ( ( ( * ( __IO uint32_t * ) ulAddr_App ) & 0x2FFE0000 ) == 0x20000000 )          //检查栈顶地址是否合法.
        { 
                pJump2App = ( pIapFun_TypeDef ) * ( __IO uint32_t * ) ( ulAddr_App + 4 );        //用户代码区第二个字为程序开始地址(复位地址)                
                MSR_MSP( * ( __IO uint32_t * ) ulAddr_App );                                                                    //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
                pJump2App ();                                                                                                            //跳转到APP.
        }
}                
/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/
   
   
   
   
 
 
 | 
https://www.stmcu.org.cn/module/ ... &fromuid=331315
(出处: 意法半导体STM32/STM8技术社区)
可是还有一个新的问题想请教
升级完程序之后怎么自动跳转?有自动跳转函数了的
int main(void)
{
/*!< At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
file (startup_stm32f2xx.s) before to branch to application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f2xx.c file
*/
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//0 bits for pre-emption priority 4 bits for subpriority
//2 bits for pre-emption priority 2 bits for subpriority
#ifdef DEBUG_LED_FLASH
SysTick_Config(120000000/100);//ÅäÖÃ10msµÄʱÖÓÖжÏ
#endif
LED_init();
LED10_ON();
REDLED_ON();
FLASH_If_Init();
POWER_VCC3V_Open();
Alarm_key_init();//if the key is press ,update
LCD_GPIO_Init();
delay_nms(10);
LCD_SPI1_Init();
delay_nms(10);
while (1)
{
#ifdef DEBUG_LED_FLASH
for(;;)
{
if(time_flag.flag500ms == 1 )
{
time_flag.flag500ms = 0;
if(led_flash)
{
LED10_ON();
REDLED_ON();
led_flash = 0;
}
else
{
LED10_OFF();
REDLED_OFF();
led_flash = 1;
}
}
}
#endif
if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_12) == 1)
{
JumpToMainApp();
}
else
{
REDLED_OFF();
SysTick_Config(120000000/100);
SGW_Update();
JumpToMainApp();
}
}
}
//Run To Main
static void JumpToMainApp(void)
{
pFunction Jump_To_Application;
uint32_t JumpAddress;
if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
{
/* Jump to user application */
JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
Jump_To_Application();
}
}