2021-06-13

本文介绍了如何在STM32F103上实现一个简易的Bootloader,通过ESP8266实现无线烧录。主要步骤包括内存分配、中断向量表偏移量设置、跳转到APP程序的实现以及生成APP的Bin文件。在Bootloader主函数中,程序接收并写入串口下载的APP Bin文件,然后跳转执行。经过测试,成功实现了从串口下载并运行应用程序。
摘要由CSDN通过智能技术生成

stm32f103简易bootloader实现

      因为之前调试代码时经常要插线烧录,觉得麻烦,就想结合下手头的ESP8266做个无线烧录器,这就需要在stm32上做个bootloader。

关于bootloader,网上有很多资料,结合开发板例程做了个简易的BootLoader。bootloader的核心就是如何在运行时

跳转到设定的应用程序段,其他的跟平常写程序没什么区别。主要步骤如下:

   1、分配bootloader和APP的内存

看你想要分配多少内存给BootLoader

bootloader:

APP:

编译完后可以去Map文件下查看是否设置成功,双击工程目录就会弹出来

这样就设置好了。如果不是这样的话,去Linker查看又没有设置好,我之前就是因为这个浪费了半天时间

没√选的话也可以手动设置,将0x08000000修改一下也行。

2、设置中断向量表偏移量

     中断向表得默认起始地址是0x08000000,因为APP程序地址改变了,APP程序想要进入中断的话,对应的中断向量表也要相应偏移。

VECT_TAB_OFFSET就是偏移量,默认是0。在system_stm32f10x.c文件下将VECT_TAB_OFFSET修改成设置的偏移量,就行了

 

3、跳转到APP程序

其主要是从FLASH中读出程序起始地址,然后跳转,主要靠下面两个函数进行

typedef void (*APP_FUNC)(void);//void类型的函数指针

_asm  void MSR_MSP(vu32 addr)  //设置堆栈指针
{
	MSR MSP, r0
	BX r14
}

//跳转到应用程序段
//appaddr:用户代码起始地址.
void iap_load_app(u32 appaddr)
{
	int i;
	APP_FUNC jump2app;
	if(((*( vu32*)appaddr)&0x2FFE0000)==0x20000000)	//检查栈顶地址是否合法.不同的型号可能会有所不同
	{ 
		
		jump2app=(APP_FUNC)*( vu32*)(appaddr+4);		//用户代码区第二个字为程序开始地址(复位地址)		
		MSR_MSP(*( vu32*)appaddr);					//初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
		
		for(i = 0; i < 8; i++)
		{			
			NVIC->ICER[i] = 0xFFFFFFFF;	// 在跳转是最好关闭中断
			NVIC->ICPR[i] = 0xFFFFFFFF;	// 清除中断标志位
		}
		jump2app();									//跳转到APP.
		
	}
	else 
		printf("没有APP\r\n");
 
}

4、生成APP代码的Bin文件

因为下载Flash的文件要是Bin格式的。user下写入fromelf --bin -o "$L@L.bin" "#L"

User下设置成这样就好了。

 

 

最后进行简单测试,从串口处下载APP的bin文件并运行程序,看看是否跑通。

bootloader主函数

int main()
{
	u32 countold=0,applen;
	u8 flag=0,i=0;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	Systick_Init(72);
	ALL_GPIO_Init();
	LED=0;
	delay_ms(500);
	USART1_Init(115200);
	printf("进入bootloader\r\n");
	printf("s---开始串口下载APP\r\nr---读取flash中的APP\r\n");
	while(1)
	{
		if(USART_RX_CNT&&flag==2)
		{
			if(countold==USART_RX_CNT&&USART_RX_CNT>3)
			{
				applen=USART_RX_CNT;
				countold=0;
				USART_RX_CNT=0;
				printf("用户程序接收完成!\r\n");
				printf("代码长度:%dBytes\r\n",applen);
				iap2_write_app(0x08003000,&USART_REC_BUF[1],applen);//将串口接收的bin文件写入flash
				printf("文件写入完成\r\n");
				flag=1;
			}
		else 
			countold=USART_RX_CNT;
		}
		
		if(USART_REC_BUF[0]=='s')//接收数组第一位作为控制命令
		{
			
			USART_REC_BUF[0]=0;
			flag=2;
			printf("开始接收APP文件\r\n");
		}
		if(flag==1||USART_REC_BUF[0]=='r')
		{
			  
			  printf("5s后开始运行APP\r\n");
				delay_ms(1000);
				delay_ms(1000);
				delay_ms(1000);
				delay_ms(1000);
				delay_ms(1000);
				iap_load_app(0x08003000);
		}
			
		
		if(i==5)
		{
			i=0;
		  LED=!LED;
		}
		i++;
		delay_ms(100);
	}
}

APP测试函数:

int main()
{
	__enable_irq();//打开中断
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	Systick_Init(72);
	ALL_GPIO_Init();
	LED=0;
	delay_ms(500);
	USART1_Init(115200);
	printf("欢迎来到应用程序区域!\r\n");
	while(1)
	{
		LED=!LED;
		printf("hello hello\r\n");
		delay_ms(1000);
	}
}

 

结果:

 

成功跳转。

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值