S32K144学习(16)-Bootloader

1.什么是bootloader

Bootloader(引导加载程序) 是存储在设备非易失性存储器(如 ROM、Flash)中的一段特殊程序,负责在设备上电后初始化硬件、加载操作系统(OS)或用户应用程序,并最终将控制权移交给它们。它是设备启动过程中第一个运行的软件,扮演着"启动管理者"的角色。

2.bootloader的用途

1.在启动应用程序之前,对硬件外设进行初始化,可以在某种程度上做到应用层和硬件层分离的作用

2.在启动时对硬件或者Mcu自身进行检测,在运行程序之前对异常状态进行警报

3.通过Bootloader实现在线升级,第一,接收客户端软件发来的程序;第二将接收到的程序写入mcu的flash中,片内flash编程;第二,跳转到APP运行

3.S32K144的Bootloader的分配

1.S32k144的Flash容量

2.MCU上电复位流程

3.地址分配

Bootloader 分配

App Flash分配表

向量表重映射,之前失效

4.实验流程

通过按键从bootloader跳转APP

5.S32 编译器软件配置

1. 解锁flash默认配置

进人构建配置

使能Flash配置,取消RAM勾选

配置ld文件的MEMORY区

bootloader针对性修改 32k

app 空间分配 256k

6.部分代码

1.bootloader应用程序的代码:

javascript 复制代码
 * IO配置
 * KEY1 PTC12
 * KEY2 PTC13
 * KEY3 PTB2
 * LED1 PTD16
 * LED2 PTD15
 * LED3 PTD1
 * LED4 PTD0
*/
#include "Cpu.h"
#include "delay.h"
#include "uart.h"
#include"key.h"
#include"oled.h"
#include <stdio.h>


  volatile int exit_code = 0;

#define LED1(x)  PINS_DRV_WritePin(PTD,16,!x);
#define LED2(x)  PINS_DRV_WritePin(PTD,15,!x);
#define LED3(x)  PINS_DRV_WritePin(PTD,1,!x);
#define LED4(x)  PINS_DRV_WritePin(PTD,0,!x);

#define APP_START_ADDRESS 0x00008000 //应用程序起始地址

// Bootup application function 
void Bootup_Application(uint32_t appEntry, uint32_t appStack)
{
	static void (*jump_to_application)(void);	//指向应用函数的指针
	static uint32_t stack_pointer;		//应用程序栈指针

	jump_to_application = (void (*)(void))appEntry;	//函数指针指向应用程序的复位向量表地址,强转函数指针

	stack_pointer = appStack;	//应用程序栈指针赋值

	S32_SCB->VTOR = (uint32_t) APP_START_ADDRESS;	//设置中断向量表地址为应用程序的起始地址

	__asm volatile ("cpsie i" : : : "memory");	// 关闭全局中断

	__asm volatile ("msr msp, %0\n" : : "r" (stack_pointer): "sp");	//设置主栈指针

	__asm volatile ("msr psp, %0\n" : : "r" (stack_pointer): "sp"); //设置进程栈指针

	jump_to_application();	//跳转到应用程序的复位向量表地址执行应用程序
}	



int main(void)
{
  /* Write your local variable definition here */
	uint8_t pinstate;
	int MCU_Freq;
	uint32_t appEntry,appStack;	//应用程序入口地址和栈指针地址
  /*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
  #ifdef PEX_RTOS_INIT
    PEX_RTOS_INIT();                   /* Initialization of the selected RTOS. Macro is defined by the RTOS component. */
  #endif
  /*** End of Processor Expert internal initialization.                    ***/

	CLOCK_SYS_Init(g_clockManConfigsArr, CLOCK_MANAGER_CONFIG_CNT,g_clockManCallbacksArr, CLOCK_MANAGER_CALLBACK_CNT);
	CLOCK_SYS_UpdateConfiguration(0U, CLOCK_MANAGER_POLICY_AGREEMENT);
	MCU_Freq = delay_init();//初始化delay函数
	PINS_DRV_Init(NUM_OF_CONFIGURED_PINS, g_pin_mux_InitConfigArr); //初始化IO
	I2C_MasterInit(&i2c1_instance, &i2c1_MasterConfig0);//初始化I2C外设,用于OLED通讯
	LPUART_DRV_Init(INST_LPUART1, &lpuart1_State, &lpuart1_InitConfig0); //初始化串口

	oled_init(); //OLED配置参数初始化
	OLED_TITLE((uint8_t*)"S32K144",(uint8_t*)"01_BASE");//OLED显示标题
	u1_printf("初始化完毕,MCU运行频率为 %d Mhz \r\n",MCU_Freq);
    while(1)
    {
		pinstate = KEY_Proc (0);
		if(pinstate ==BTN1_PRES )
		{
			u1_printf("KEY1 Pressed 2s enter app\r\n");
			u1_printf("Enter App\r\n");
			u1_printf("in 2 seconds\r\n");
			delay_ms(1000);
			u1_printf("in 1 seconds\r\n");
			delay_ms(1000);
			u1_printf("in 0 seconds\r\n");

			appStack  = *(uint32_t *)(APP_START_ADDRESS + 0x00);	//读取应用程序栈指针地址
			appEntry  = *(uint32_t *)(APP_START_ADDRESS + 0x04);	//读取应用程序入口地址
			Bootup_Application(appEntry,appStack);	//跳转到应用程序
		}
    }
  /*** Don't write any code pass th5is line, or it will be deleted during code generation. ***/
  /*** RTOS startup code. Macro PEX_RTOS_START is defined by the RTOS component. DON'T MODIFY THIS CODE!!! ***/
  #ifdef PEX_RTOS_START
    PEX_RTOS_START();                  /* Startup of the selected RTOS. Macro is defined by the RTOS component. */
  #endif
  /*** End of RTOS startup code.  ***/
  /*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/
  for(;;) {
    if(exit_code != 0) {
      break;
    }
  }
  return exit_code;
  /*** Processor Expert end of main routine. DON'T WRITE CODE BELOW!!! ***/
} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/

编译后:未超出32k空间

2.app代码

javascript 复制代码
 * IO配置
 * KEY1 PTC12
 * KEY2 PTC13
 * KEY3 PTB2
 * LED1 PTD16
 * LED2 PTD15
 * LED3 PTD1
 * LED4 PTD0
*/
#include "Cpu.h"
#include "delay.h"
#include "uart.h"
#include"key.h"
#include"oled.h"
  volatile int exit_code = 0;

#define LED1(x)  PINS_DRV_WritePin(PTD,16,!x);
#define LED2(x)  PINS_DRV_WritePin(PTD,15,!x);
#define LED3(x)  PINS_DRV_WritePin(PTD,1,!x);
#define LED4(x)  PINS_DRV_WritePin(PTD,0,!x);


int main(void)
{
  /* Write your local variable definition here */
	uint8_t pinstate;
	int MCU_Freq;
  /*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
  #ifdef PEX_RTOS_INIT
    PEX_RTOS_INIT();                   /* Initialization of the selected RTOS. Macro is defined by the RTOS component. */
  #endif
  /*** End of Processor Expert internal initialization.                    ***/

	CLOCK_SYS_Init(g_clockManConfigsArr, CLOCK_MANAGER_CONFIG_CNT,g_clockManCallbacksArr, CLOCK_MANAGER_CALLBACK_CNT);
	CLOCK_SYS_UpdateConfiguration(0U, CLOCK_MANAGER_POLICY_AGREEMENT);
	MCU_Freq = delay_init();//初始化delay函数
	PINS_DRV_Init(NUM_OF_CONFIGURED_PINS, g_pin_mux_InitConfigArr); //初始化IO
	I2C_MasterInit(&i2c1_instance, &i2c1_MasterConfig0);//初始化I2C外设,用于OLED通讯
	LPUART_DRV_Init(INST_LPUART1, &lpuart1_State, &lpuart1_InitConfig0); //初始化串口
  
  LED1(0);LED2(0);LED3(0);LED4(0);//LED熄灭

	oled_init(); //OLED配置参数初始化
	OLED_TITLE((uint8_t*)"S32K144",(uint8_t*)"01_BASE");//OLED显示标题
	u1_printf("初始化完毕,MCU运行频率为 %d Mhz \r\n",MCU_Freq);
    while(1)
    {
      u1_printf("App Running...\r\n");
      PINS_DRV_TogglePins(PTD, 1 << 0);
      delay_ms(1000);
      u1_printf("App Running...\r\n");
      PINS_DRV_TogglePins(PTD, 1 << 1);
      delay_ms(1000);
    }
  /*** Don't write any code pass th5is line, or it will be deleted during code generation. ***/
  /*** RTOS startup code. Macro PEX_RTOS_START is defined by the RTOS component. DON'T MODIFY THIS CODE!!! ***/
  #ifdef PEX_RTOS_START
    PEX_RTOS_START();                  /* Startup of the selected RTOS. Macro is defined by the RTOS component. */
  #endif
  /*** End of RTOS startup code.  ***/
  /*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/
  for(;;) {
    if(exit_code != 0) {
      break;
    }
  }
  return exit_code;
  /*** Processor Expert end of main routine. DON'T WRITE CODE BELOW!!! ***/
} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/

7.实验现象

将两份代码都下载进芯片中,芯片先进入bootloader.main 从定向到0x8000

再指向app_main

相关推荐
西岸行者4 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意4 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码5 天前
嵌入式学习路线
学习
毛小茛5 天前
计算机系统概论——校验码
学习
babe小鑫5 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms5 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下5 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。5 天前
2026.2.25监控学习
学习
im_AMBER5 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J5 天前
从“Hello World“ 开始 C++
c语言·c++·学习