从0开始写bootloader

所谓bootloader就是引导加载程序,类似于windows里面的BIOS,用于程序运行之前的一些环境的加载以及必要的初始化。
而单片机的bootloader主要是用于OTA升级的,作用是初始化完必要的运行环境之后,判断是否要进行升级,如果要进行升级,则将已经下载好的升级程序复制到单片机的运行flash中,然后通过指针的方式跳转到APP程序运行地址,如果不升级则直接跳转到APP程序运行地址。

bootloader 实现功能示意图
在这里插入图片描述
就是实现一个跳转。

实现bootloaer并运行程序要有两份文件:
1.bootloader程序工程
在这里插入图片描述
1.设置bootloader的程序起始位置,如1所示,一般情况下不更改。
2.设置bootloader程序的大小,如图二所示,一般是使用比实际bootloaer程序稍大的空间即可。
2.APP程序设置
在这里插入图片描述
同bootloader一样的意思,但是APP运行地址需要便宜你设置的bootloader的地址大小,在2中同样需要减少你设置bootlader的程序大小
在这里插入图片描述
也可以在这里更改程序起始位置,但不建议在这里更改,这里使用默认的就好。

注:SP栈指针是不用更改的,是因为bootloader和APP在同一时刻只用一个程序在运行,所以只会有一个程序在使用栈。

APP程序
1.不需要异常向量表
在这里插入图片描述
不需要异常向量表那么直接跳转到APP程序起始地址执行即可。

2.需要异常向量表
在这里插入图片描述
在程序进行跳转时,如果你直接使用地址作为指针使用,则要主注意,Thumb指令集和ARM指令集的区别。

typedef void(*IapAppFun)(void); 	//定义一个函数指针,用于跳转到APP程序
#define 	FLASH_APP_ADDR  0x08010000		//定义APP程序起始地址
void main
{
	IapAppFun JumpApp;
	//	bootloader要进行的一些列初始化
	if (((*(__IO uint32_t *)FLASH_APP_ADDR) & 0xFF000000) == 0x08000000) 
	{
		__disable_irq();//关闭中断
		JumpApp = (IapAppFun)*(__IO uint32_t *)(FLASH_APP_ADDR +4);
		SCB->VTOR = FLASH_BASE|0x10000; //芯片内部FLASH起始地址加上偏移地址就会等于APP程序的起始地址,设置中断向量表
		JumpApp();
	}
	printf("APP is invalid!\r\n");//如果执行到这里表示跳转失败
}

if (((*(__IO uint32_t )FLASH_APP_ADDR) & 0xFF000000) == 0x08000000)
这句话的目的是用来判断FLASH_APP_ADDR这个地址上存放的值是用来跳转到flash运行还行SRAM或其他地方运行,如果M3为例子,那么如果是SRAM运行就应该改成
if (((
(__IO uint32_t *)FLASH_APP_ADDR) & 0x2FF80000) == 0x20000000) 表示从SRAM开始运行

这个看你写的升级程序想从哪里开始运行。
例子:我当时使用的一款MCU单片机跳转之后实在SRAM中存放,其SRAM起始地址是0x10000000,所以栈顶指针的最高位一定是1,所以可以使用(((*(__IO uint32_t *)FLASH_APP_ADDR) & 0xFF000000) == 0x10000000) 来判断你的升级文件包是否错误,也可以防止MCU跑飞变成砖。

JumpApp = (IapAppFun)*(__IO uint32_t *)(FLASH_APP_ADDR +4);
这句话的目的是因为,FLASH_APP_ADDR 上存储的是异常向量表的地址,加4之后的地址表示里面存放的是程序起始地址,所以要用解引用加其中的值取出来赋予给函数指针,用来跳转执行APP程序。

SCB->VTOR = FLASH_BASE|0x10000;
这句话的目的是更改APP程序的异常向量表,因为APP的程序相对于0x08000000已经偏移了0x10000,所以偏移之后的第一个地址存放的是异常向量表。

如果是M0内核的MCU,那么其做中断向量的重映射的时候,因为没有SCB->VROR寄存器可供使用,所以可使用两种办法进行中断向量表的重新映射:
1.在跳转到APP区时将中断向量表保存到SRAM的起始位置(注意这里所被占用的SRAM空间将不可以再被APP区域使用,所以可以再keil工程中将SRAM地址往后移动中断向量表大小的空间),可参考如下博文:
参考博文
2.在bootloader中的中断函数使用函数指针跳转到APP区域的中断函数,这种办法是可以bootloader和APP区域共用一个中断向量表不用进行重新映射,在APP区域发生中断时会跳入BootLoader的中断向量表,然后在bootlader的中断函数中使用函数指针将APP中断的中断服务函数的地址取出来用存入函数指针进行跳转,这样就可以共用一个中断向量表了。这样有一个弊处就是bootloader不能使用中断了(至少在我的应用中不能使用的,可能是我没注意某些地方我没发现,有人知道可以私信我,非常感谢),如果你的bootloader只是用来单纯的跳转那么这个弊处将不再是弊处。

void SysTick_Handler(void)
{
	void (*Int_Entry) (void); //定义函数指针
	Int_Entry = (void(*)())(*(uint32_t *)(Read_Flash + AllIint_Vector_Offset + SysTick_Handler_Offset)); 
	//取出APP区域的中断服务函数偏移,Read_Flash + AllIint_Vector_Offset存放的是APP区域函数的中断向量起始地址(即SP堆栈指针,栈顶指针),
	//SysTick_Handler_Offset是系统滴答中断服务函数相对于APP起始向量表的偏移
  	(*Int_Entry)(); //进行函数跳转
}

以上纯属个人见解,有误之处还望大家指正。

  • 5
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
PX4固件的过程包括刷bootloader和刷PX4固件本身。刷bootloader是为了将设备进入fastboot模式,然后再切换到Android镜像目录,通过命令将镜像刷到设备中。具体操作如下: 1. 使用命令行工具(如cmd)输入"adb reboot bootloader",使设备进入fastboot模式。 2. 切换到Android镜像目录,执行"fastboot flashall -w"命令,将镜像刷到设备中。刷完成后等待设备重启,即可运行原生Android系统。 关于刷PX4固件部分,可以按照以下步骤进行操作: 1. 按照指导设置好刷环境,点击右下角加载固件。 2. 在加载固件时选择最新的f4bl固件,并点击下载。下载完成后拔掉USB连接线。 总结起来,刷PX4固件包括刷bootloader和刷PX4固件本身。刷bootloader的过程是通过命令将设备进入fastboot模式,并将镜像刷到设备中。刷PX4固件的过程是根据指导设置好环境,选择最新的固件并下载,然后拔掉USB连接线。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Android12 源码编译及刷Piexl6设备](https://blog.csdn.net/Jian_0216/article/details/126020486)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [PX4装机教程(四)F4飞控刷PX4](https://blog.csdn.net/qq_38768959/article/details/106988811)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值