STM32L4xx基于UART的IAP实现(实验详解)

STM32L4xx基于UART的IAP实现(实验详解)

最近刚接触到STM32L452RET6(STM32L4xx系列)芯片,使用LL库配置(LL库更接近硬件层,直接操作寄存器。)可以先使用STM32CubeMX软件生成一个基础工程,再进一步添加配置。以下是学习了2天IAP后的总结,其实并没有想象中的那么难懂;

一.实现目标

实现通过MCU的UART接收来自电脑发送的bin文件进行IAP程序更新。

二.IAP单项进入APP 实现流程

我选用的STM32L452的FLASH有512K大小,地址在0x08000000~0x08080000之间。

1.先将FLASH划分成3块区域,一个IAP引导程序,两个APP应用程序:

一般IAP引导程序越小越好,给之后的APP应用程序留下更多空间,这里我不会太刻意节省空间。

将IAP引导程序起始地址分到0x08000000,APP1应用程序1起始地址分到0x08020000,APP2应用程序2起始地址分到0x08040000。

IAP引导程序有0x00000-0x20000,有(0x20000-0x00000)/1024=128K;

APP1应用程序1有0x20000-0x40000,有(0x40000-0x20000)/1024=128K;

APP2应用程序2有0x40000-0x80000,有(0x80000-0x40000)/1024=256K;

2.新建APP应用程序获得bin文件:

STM32L4xx系列芯片设置中断偏移时需要修改VECT_TAB_OFFSET,可以通过直接修改宏定义进行中断向量表的偏移
在这里插入图片描述
在这里插入图片描述
例如我把APP1应用程序1起始地址定义在了0x08020000,所以把VECT_TAB_OFFSET修改成0x20000的偏移量,同时修改下图红色标记作为程序起始地址,橙色标记加上红色标记是FLSAH总容量,我现在需要偏移0x20000,就改成下图所示:
在这里插入图片描述
接着进行设置,在RUN中写入fromelf --bin --output F:\MyFile\Project\STM32L471VE\Project_STM32L471_IAPFLASH\OBJ\Project .bin F:\MyFile\Project\STM32L471VE\Project_STM32L471_IAPFLASH\OBJ\Project.axf,路径写成Output里面生成的路径,生成的文件名与Output生成文件名保持一致,不然在编译时会报错:在这里插入图片描述

接着写一个简单的程序闪烁LED灯的程序:

void main(void)//APP1应用程序1
{
	LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_5, LL_GPIO_MODE_OUTPUT);//LED初始化
	while(1)
	{
		LL_GPIO_TogglePin(GPIOA, LL_GPIO_PIN_5);
		LL_mDelay(200);
	}
}

编译通过后会在设置的路径里生成程序的bin文件;

3.编写IAP引导程序,此时就跟平常一样不用对Keil进行任何设置:

void IAPMain(void)
{
	u32	oldcount=0;
	u32	applenth=0;
	IAP_Usart_Init(9600);//UART初始化IAP
	while(1)
	{
		#if USE_DOG
			LL_WWDG_SetCounter(WWDG, 0X7E);//喂狗
		#endif
		if(USART3_RX_DATA_BUF_CNT)
		{
			if(oldcount == USART3_RX_DATA_BUF_CNT)//新周期内没有数据认为接收完毕
			{
				applenth = USART3_RX_DATA_BUF_CNT;
				oldcount = 0;
				USART3_RX_DATA_BUF_CNT = 0;
				if (((*(__IO uint32_t*)(SaveAddress + 0x00000004)) & 0xFF000000 ) == 0x08000000)//检查地址是否合法
					iap_write_appbin(AppAddress1, USART3_RxData, applenth);//更新程序,串口接收数据写入APP地址
				if (((*(__IO uint32_t*)(AppAddress1 + 0x00000004)) & 0xFF000000 ) == 0x08000000)//检查地址是否合法
					iap_load_app(AppAddress1);//跳转到APP地址
			}
			else
				oldcount = USART3_RX_DATA_BUF_CNT;
		}
		LL_mDelay(10);
	}
}

大致逻辑就是串口初始化,等到bin文件通过UART接收完成后,把接收的数据写到AppAddress1下,再进行IAP跳转到指定地址,AppAddress1就是0x08020000;编译后,下载程序,刚开始灯时熄灭的,再通过电脑串口工具把之前获得的APP1应用程序1的bin文件通过UART发送给MCU,成功进行IAP跳转到APP1后灯会闪烁起来,这是一个IAP->APP的单向实验;

三.IAP单项进入APP1,APP1和APP2相互切换 实现流程

和之前的操作类似,设置Keil,main函数改成如下,通过改变#if来区分LED的快闪和慢闪程序,还有不同的跳转地址,编译后获得两个bin文件,还是下载IAP引导程序,通过UART发送bin文件进行跳转:

void main(void)
{
	u32	oldcount=0;
	u32	applenth=0;
	IAP_Usart_Init(9600);//初始化IAP
	LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_5, LL_GPIO_MODE_OUTPUT);//LED初始化
	while(1)
	{
		LL_GPIO_TogglePin(GPIOA, LL_GPIO_PIN_5);
		#if 1  //偏移0x20000时
		LL_mDelay(200);
		if(USART3_RX_DATA_BUF_CNT)
		{
			if(oldcount == USART3_RX_DATA_BUF_CNT)//新周期内没有数据认为接收完毕
			{
				applenth = USART3_RX_DATA_BUF_CNT;
				oldcount = 0;
				USART3_RX_DATA_BUF_CNT = 0;
				if (((*(__IO uint32_t*)(SaveAddress + 0x00000004)) & 0xFF000000 ) == 0x08000000)//检查地址是否合法
					iap_write_appbin(AppAddress2, USART3_RxData, applenth);//更新程序,串口接收数据写入APP地址
				if (((*(__IO uint32_t*)(AppAddress2 + 0x00000004)) & 0xFF000000 ) == 0x08000000)//检查地址是否合法
					iap_load_app(AppAddress2);//跳转到APP地址
			}
			else
				oldcount = USART3_RX_DATA_BUF_CNT;
		}
		#else	//偏移0x40000时
		LL_mDelay(1000);
		if(USART3_RX_DATA_BUF_CNT)
		{
			if(oldcount == USART3_RX_DATA_BUF_CNT)//新周期内没有数据认为接收完毕
			{
				applenth = USART3_RX_DATA_BUF_CNT;
				oldcount = 0;
				USART3_RX_DATA_BUF_CNT = 0;
				if (((*(__IO uint32_t*)(SaveAddress + 0x00000004)) & 0xFF000000 ) == 0x08000000)//检查地址是否合法
					iap_write_appbin(AppAddress1, USART3_RxData, applenth);//更新程序,串口接收数据写入APP地址
				if (((*(__IO uint32_t*)(AppAddress1 + 0x00000004)) & 0xFF000000 ) == 0x08000000)//检查地址是否合法
					iap_load_app(AppAddress1);//跳转到APP地址
			}
			else
				oldcount = USART3_RX_DATA_BUF_CNT;
		}
		#endif
	}
}

上面的程序和IAP引导程序类似,就是串口读数据,写FLASH,再跳转。实现IAP->APP1,再APP1->APP2,再从APP2->APP1。

只会再在UART上连接上Bluetooth、RFID或者NB-Lot就可以实现远程无线更新固件了。

这是我上传的IAP.c和IAP.h文件
https://download.csdn.net/download/qq_39735462/11952466

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
STM32L4xx系列使用UART HAL实现与串行设备的通信。UART HALSTM32Cube固件套件中的一部分,专门用于简化STM32微控制器的串行通信编程。 UART(通用异步收发传输)是一种常见的串行通信协议,它允许设备之间通过单条数据线进行双向通信。在STM32L4xx系列中,UART HAL提供了一组函数来配置和控制UART外设。 使用UART HAL,我们可以进行以下操作: 1. 初始化UART外设:使用HAL_UART_Init函数来初始化UART外设,设置波特率、数据位、停止位等参数。 2. 发送数据:使用HAL_UART_Transmit函数发送数据,将要发送的数据写入发送缓冲区,并通过UART发送出去。 3. 接收数据:使用HAL_UART_Receive函数接收数据,将从UART接收到的数据写入接收缓冲区。 4. 中断处理:使用HAL_UART_IRQHandler和HAL_UART_RxCpltCallback函数来处理接收中断。当收到数据时,可以在回调函数中处理数据。 5. DMA传输:使用DMA传输模式可以实现在不使用CPU的情况下进行数据传输,提高系统性能。使用HAL_UART_Transmit_DMA和HAL_UART_Receive_DMA函数启动DMA传输。 6. 中断和DMA的组合:可以同时使用中断和DMA来处理UART数据传输,实现更灵活和高效的通信。 总之,STM32L4xx系列使用UART HAL可以简化串行通信的编程过程,提供了丰富的功能和灵活的配置选项,使得与串行设备的通信变得更加易于实现和管理。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值