看了很多,自己总结一部分。
其实这个功能可以这么理解,好比是一台电脑进行分区,我们现在要分成C:和D:。C盘就好比是Bootloader,主要存放系统引导文件,D盘就是我们放文件的地方,好比是APP。这样来进行快速理解吧。
所以项目要建立两部分:Bootloader和APP。
一、首先建立Bootloader项目
利用STM32FCubeMX 来建立,详细步骤不写了,需要用到一个GPIO口(LED指示)和USART3,主要用于查看程序运行状态。
在“usart.c”中键入如下代码:实现printf打印输出
#include "stdio.h"
/**
* 函数功能: 重定向c库函数printf到定义的串口
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
在“main.c”中键入如下代码:
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define APP_ADDR 0x08002000 //应用程序首地址定义
typedef void (*APP_FUNC)(); //函数指针类型定义
APP_FUNC jump2app;
/* USER CODE END PD */
/* USER CODE BEGIN PFP */
void run_app(uint32_t app_addr);
/* USER CODE END PFP */
/* USER CODE BEGIN 2 */
__disable_irq();
run_app(0x08002000);
/* USER CODE END 2 */
/* USER CODE BEGIN 4 */
/**
* @brief
* @param
* @retval
*/
void run_app(uint32_t app_addr)
{
uint32_t reset_addr = 0;
APP_FUNC jump2app;
printf("执行程序跳转程序段\r\n");
/* 跳转之前关闭相应的中断 */
__disable_irq();
/* 栈顶地址是否合法 */
if(((*(uint32_t *)app_addr)&0x2FFFE000) == 0x20000000)
{
/* 获取复位地址 */
reset_addr = *(uint32_t *)(app_addr+4);
jump2app = ( APP_FUNC )reset_addr;
__set_MSP((*(__IO uint32_t *) app_addr));
jump2app();
}
else
{
printf("APP 未找到!\r\n");
}
}
/* USER CODE END 4 */
在下面箭头处将0X10000改成0X2000
好了,执行编译和烧录,将程序代码烧录进单片机。Bootloader部分就算完工了。
二、建立APP项目
也是用CubeMX建立,需要增加GPIO和USART3。
首先USART3 一样插入如上代码,实现pritnf打印输出,不重复写了。
插入如下代码
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define APP_ADDR 0x08002000 //应用程序首地址定义
/* USER CODE END PD */
/* USER CODE BEGIN 2 */
__enable_irq();
/* USER CODE END 2 */
while (1)
{
/* USER CODE END WHILE */
printf("成功\r\n");
HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
HAL_Delay(500);
/* USER CODE BEGIN 3 */
}
点击魔术棒,修改箭头这里。
打开"system_stm32f1xx.c"修改如下箭头所指处。
编译烧录APP程序。我用的是ST-LINK V2 烧的,这里注意,选择擦除选中区
效果:
串口输出两段程序中的printf字符串。同时LED在闪烁,我就不放照片了。