AT32-F403A-IAP应用笔记
工程背景:
很多产品,后期会批量生产装壳,留出来的通讯接口只有串口,升级软件版本只能通过串口。
!!没法通过烧录口,烧录口得拆壳子,会被技术支持和生产骂!!
什么叫IAP呢?不严谨来说,先通过烧录口把bootloader烧进MCU,以后就可以通过串口发送bin文件给MCU,以此达到后续串口升级软件版本的目的,这个过程就叫IAP.
当然,升级软件的办法还有很多,蓝牙,WiFi什么的也能升级,只要让MCU收得到新的代码,应该是都行,我暂时只会这个……
使用文档:
AN0001_AT32_IAP_using_the_USART_ZH_V2.0.2.pdf (arterytek.com)
文档解读:
AT32 USART IAP快速使用方法
step1
按照文档,只需要两个keil工程(bootloader和APP)和一个IAP上位机软件,就可以完成这一应用的验证。bootloader是必不可少的启动引导文件,一般的MCU厂家提供的官方例程里面都会有,在此基础上根据自己的实际应用稍作修改就行,APP就是我们自己编写的项目代码。
step2
可以按照这个快速使用教程先熟悉一下这个IAP升级软件的流程,然后再学习其中的原理。
AT32 USART IAP程序设置
step1
代码分为bootloader code和app code两部分,它们在MCU里的位置大概是app code紧接在bootloader code的尾部。
bootloader code的起始地址为0x8000000,大小设定为16K,换算出来就是0x4000。也就是说,从0x8000000到0x8004000这部分都是bootloader code的;那么app code紧接着就是从0x8004000开始,大小可以根据实际情况做调整,这里给的大小是256K,换算出来是0x40000.
换算方法:十六进制0x4000,转换成十进制为16384,16384除以1024等于16.
这个地址分布在实际应用中,主要就是修改对keil的设置。只需要根据文档上的指示,将这些值填好即可。当然,code部分也要根据实际稍作调整。
bootloader code 中宏定义APP_START_ADDR 的值要跟keil设置里的保持一致。
app code 主要就是修改中断向量表偏移地址,这个值的大小取决于给bootloader code设置的大小,也就是开头bootloader code的size.
到这里,完全按照文档进行操作,基本可以实现一次IAP的操作。
!!需要提醒的是,如果你使用的是开发板AT32-START-F403A V1.2 那么你需要将板子上的0欧电阻R9、R10取掉,不然板子上的USART1是不能使用的,IAP下载会一直报错。!!
当然,如果只是验证官方例程的话,以上内容都不需要修改。下面这部分,是如何根据实际情况,对工程进行修改移植。
bootloader/app与上位机串口通信协议
step1
首先,要弄清楚IAP整个的通讯流程,下图是上位机(IAP软件)通信协议。
点击上位机,也就是IAP软件的下载按钮后,软件会发送“0x5AA5”给下位机,也就是单片机的MCU.
MCU收到后,回复“ACK”给上位机。
整个流程我们不需要深究,就软件移植而言,我们只要确保MCU(此时MCU正在运行的是app code)能收到上位机发送的第一条信息——0x5AA5,并成功解析,将相关标志置位即可。
官方例程app code使用USART1接收完成中断,在中断服务函数中完成对接收内容的判断和相关标志置位。
即下面这段例程代码。
void USART1_IRQHandler(void)
{
uint16_t reval;
if(usart_flag_get(USART1, USART_RDBF_FLAG) != RESET)
{
reval = usart_data_receive(USART1);
if((reval == 0x5A) && (iap_flag == IAP_REV_FLAG_NO))
iap_flag = IAP_REV_FLAG_5A;
else if((reval == 0xA5) && (iap_flag == IAP_REV_FLAG_5A))
iap_flag = IAP_REV_FLAG_DONE;
else
iap_flag = IAP_REV_FLAG_NO;
}
}
以上通信协议,是工程移植的关键!!
step2
回归到项目工程,我这边的工程通讯接口只留了USART6,而且因为USART6在接收上位机发来的信息的同时还需要在程序运行过程中接收其他数据,所以app code配置的USART6还加了空闲中断和DMA.
void USART6_IRQHandler(void)
{
uint8_t clear;
uint8_t cnt;
uint16_t reval;
if(usart_flag_get(USART6, USART_IDLEF_FLAG) != RESET) //串口空闲标志判断
{
clear=USART6->sts;
clear=USART6->dt;
clear&=0;
sta = 1;
cnt = USART6_RX_BUFFER_SIZE-dma_data_number_get(DMA1_CHANNEL2);
cut6 = cnt;
memcpy(usart6_deal,usart6_rx_buffer,cut6); //将接收到的内容转存在数组usart6_deal[]中
usartdmarecv(usart6_rx_buffer,USART6_RX_BUFFER_SIZE,USART6,DMA1_CHANNEL2,DMA1_FDT2_FLAG);
cnt = 0;
sta = 0;
}
}
USART6通过DMA搬运数据,使能空闲中断,在中断服务函数中已经将接收到的内容转存在数组usart6_deal[]中,只需要判断usart6_deal[0]是否为“5A”,usart6_deal[1]是否为“A5”即可。
if((usart6_deal[0] == 0x5A) && (iap_flag == IAP_REV_FLAG_NO))
iap_flag = IAP_REV_FLAG_5A;
else if((usart6_deal[1] == 0xA5) && (iap_flag == IAP_REV_FLAG_5A))
iap_flag = IAP_REV_FLAG_DONE;
else
iap_flag = IAP_REV_FLAG_NO;
这段判断还是app code里面的内容,按照通信协议流程,iap_flag置位之后,MCU程序就会从app code跳转运行到bootloader code.
bootloader code使用的串口同步修改为USART6就行,其他不做修改。
!!app code、bootloader 使用同一串口,同一波特率!!
工程源码:
链接: https://pan.baidu.com/s/1WArfINcBDaMgrIvsIJ3FYw?pwd=0523
提取码: 0523