BootLoader和App1和App2三个程序之间的跳转

BootLoader和App1和App2三个程序之间的跳转

1 、说明:

三个程序是
(1)BootLoader 亮两个LED灯,1秒后进入App1.
(2)app1	LED1闪烁,长按按键后进入App2.
(3)app2 LED2闪烁,长按按键后进入App1.

2、跳转程序:

三个程序的公共部分,包括boot和LED程序

//boot.c
#include "main.h"
#include "boot.h"

/* 开关全局中断的宏 */
#define ENABLE_INT()	__set_PRIMASK(0)	/* 使能全局中断 */
#define DISABLE_INT()	__set_PRIMASK(1)	/* 禁止全局中断 */

#if 1

//uint32_t ApplicationAddress = 0x08000000+0x2800;
typedef  void (*pFunction)(void);
pFunction Jump_To_Application;//做为全局变量,函数内局部时跳转失败。

void jumpToApplication(uint32_t addr)
{

	/* 关闭全局中断 */
	DISABLE_INT();

	/* 关闭滴答定时器,复位到默认值 */
	SysTick->CTRL = 0;
	SysTick->LOAD = 0;
	SysTick->VAL = 0;

	/* 设置所有时钟到默认状态, 使用 HSI 时钟 */
	LL_RCC_DeInit();

	/* 关闭所有中断,清除所有中断挂起标志 */
	for (uint8_t i = 0; i < 8; i++)
	{
		NVIC->ICER[i]=0xFFFFFFFF;
		NVIC->ICPR[i]=0xFFFFFFFF;
	}

	/* 使能全局中断 */
	ENABLE_INT();


	uint32_t JumpAddress;
//	/* 跳转,首地址是 MSP,地址+4 是复位中断服务程序地址 */
	JumpAddress = *(__IO uint32_t *)(addr + 4);
	Jump_To_Application = (pFunction)JumpAddress;

	/* 设置主堆栈指针 */
	__set_MSP(*(__IO uint32_t *)addr);
	

	Jump_To_Application();

	/* 跳转成功的话,不会执行到这里,用户可以在这里添加代码 */
	while (1)
	{

	}
}
#endif

//boot.h
#ifndef _BOOT_H_
#define _BOOT_H_

void jumpToApplication(uint32_t addr);

#endif

LED部分:

#define GPIO_PORT_LED1  GPIOB
#define GPIO_PIN_LED1	LL_GPIO_PIN_3

#define GPIO_PORT_LED2  GPIOD
#define GPIO_PIN_LED2	LL_GPIO_PIN_2
#ifndef __BSP_LED_H
#define __BSP_LED_H

/* 供外部调用的函数声明 */
void bsp_InitLed(void);
void bsp_LedOn(uint8_t _no);
void bsp_LedOff(uint8_t _no);
void bsp_LedToggle(uint8_t _no);
uint8_t bsp_IsLedOn(uint8_t _no);

#endif

3、BootLoader程序

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "bsp_led.h"
#include "bsp_key.h"
#include "boot.h"

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
	uint8_t Itimer_f=0;
	uint8_t Itimer=0;
	static uint8_t s_count = 0;
#define BOOT_APP	1
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
void sIncTick();

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void KeyProc();


/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
#if (!BOOT_APP)
	bsp_Init();
#endif

//	SerialPutString("\r\n======================================================================");
//	SerialPutString("\r\n=              boot                								  =");
//	SerialPutString("\r\n=                                                                    =");
//	SerialPutString("\r\n======================================================================");
//	SerialPutString("\r\n\r\n");

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	while (1)
	{
#if BOOT_APP

		HAL_Delay(1000);
		jumpToApplication((uint32_t) 0x08002800);
#else
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

		KeyProc();
		if(READ_BIT(Itimer_f,1<<0))
		{
			CLEAR_BIT(Itimer_f,1<<0);

			if(++s_count %10 !=0) continue;
			if(s_count ==250) s_count = 0;
			bsp_KeyScan();

			if (++Itimer % 50 !=0)continue;
			if (Itimer == 250 )	
			{
				Itimer=0;
				
				// while(1);
			}	
			
			bsp_LedToggle(2);
//			bsp_LedToggle(1);
			
		}
#endif


	}
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  LL_FLASH_SetLatency(LL_FLASH_LATENCY_2);

   if(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_2)
  {
    Error_Handler();  
  }
  LL_RCC_HSE_Enable();

   /* Wait till HSE is ready */
  while(LL_RCC_HSE_IsReady() != 1)
  {
    
  }
  LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE_DIV_1, LL_RCC_PLL_MUL_9);
  LL_RCC_PLL_Enable();

   /* Wait till PLL is ready */
  while(LL_RCC_PLL_IsReady() != 1)
  {
    
  }
  LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
  LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_2);
  LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
  LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);

   /* Wait till System clock is ready */
  while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
  {
  
  }
  LL_SetSystemCoreClock(72000000);

   /* Update the time base */
  if (HAL_InitTick (TICK_INT_PRIORITY) != HAL_OK)
  {
    Error_Handler();  
  };
}

/* USER CODE BEGIN 4 */

void sIncTick()
{
	SET_BIT(Itimer_f,1<<0);

}
void KeyProc()
{
	uint8_t ucKeyCode; /* 按键代码 */
	int GetKey;

	/* 按键滤波和检测由后台systick中断服务程序实现,我们只要调用bsp_GetKey读取键即可 */
		ucKeyCode = bsp_GetKey();	/* 读取键 , 无键按下时返  KEY_NONE = 0 */
		if (ucKeyCode != KEY_NONE)
		{
			switch (ucKeyCode)
			{
				case KEY_DOWN_K1:			/* K1键按  */
					
					
					break;
				case KEY_UP_K1:
				{
					
				}break;
				case KEY_LONG_K1:
				{
					
				}break;
				default:
					/* 其它的键值不处理 */
					break;
			}
		}

}



/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{ 
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

有用的只有两行

在这里插入图片描述

(1)配置地址和大小

占用flash大小为10k,也可不用配置
在这里插入图片描述

4、App1程序

(1)程序
程序和BootLoader相同,
复制一份BootLoader程序,需要改的是
#define BOOT_APP	0

在main里最前面加入中断向量表,就是APP1的开始地址:
SCB->VTOR =0x2800;

在按键长按里加入跳转地址:
jumpToApplication(0x08002800+0xD800);//这里是APP2的地址

如下图:
在这里插入图片描述在这里插入图片描述在这里插入图片描述

(2)配置地址和大小

开始地址是0x08002800 大小是0xD800

在这里插入图片描述

连接器里面要勾选左边,不然上面的地址和大小就不起用了,就会按照右边填写的。

不勾选也行,把上面那步的数据填到右边。

在这里插入图片描述

擦除,要扇区擦除,

在这里插入图片描述
调试在.S 程序开头打一个断点,然后运行,能停在这里说明跳转成功:

在这里插入图片描述

向上翻,可以看从0x2800开始放的是向量表:

在这里插入图片描述

可以看到地址0x2800以前是全是0xFFFFFFFF,这是BootLoader没用到的剩余空间,分配了10k的空间其实只用了一半多。

(3)程序现象

全速运行,蓝色LED2闪烁。

5、APP2程序

(1)程序
程序和APP1相同,
复制一份app1程序,需要改的是
在main里最前面的中断向量表,就是App2的开始地址:
SCB->VTOR =0X2800+0xD800;

在按键长按里加入跳转地址:
jumpToApplication(0x08002800);//这里是APP1的地址和BootLoader里面相同

改动部分如下图所示:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

(2)配置地址和大小

开始地址是0X2800+0xD800=0x10000,即从0x08010000开始,剩下的空间大小全部给APP2。

在这里插入图片描述

其它的连接器,擦除方法和App1相同。

调试,发现程序一直在运行,打开汇编窗口,可以看到在0x08010000开始是向量表了。

在这里插入图片描述

长按按键程序停在断点处,说明跳转成功,继续全速运行绿色LED1闪烁。

在这里插入图片描述

(3)程序现象

断电,上电,全速运行。蓝色LED2闪烁,长按按键绿色LED1闪烁。再按一次蓝色LED2闪烁,如此反复。

6、综述

三个程序,每个里面都要有不一样的开始地、程序所占空间大小、中断向量表,跳转地址。

上电顺序是BootLoader,App1,按键App,按键App2。

也可以改一下地址,按照App1,按键BootLoader,App2的顺序。

也可以很多个程序一起玩。

可以用STM32CubeProgrammer来烧写hex文件或者bin文件,hex文件里面带有地址,开始地址这里不用填写,bin文件需要填写地址。

烧写无顺序。

在这里插入图片描述

  • 4
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值