记录stm32F4discovery板利用stm32cubemx实现串口的usart_IAP功能全过程

本次测试是基于官方提供的IAP示例
平台:stm32F407 discovery板,一个usb转ttl串口板.
从discovery原理图里可以看出,用户按钮是PA0,串口任意一个.配置115200.0.8.1波特率
首先利用stm32cubemx生成配置
配置时钟和PA0输入,无上下拉,串口用usart1(PB6和PB7)
因为串口1的原来的管脚PA9和PA10已经被其他功能块用了,所以就改为PB管脚
QQ图片20160421215351.png

QQ图片20160421215616.png

生成工程的时候一定要勾上下图中的地方
QQ图片20160421215715.png

此时,工程生成完成后先不要打开.
 
我们去打开官方提供的iap的示例目录:
C:\stm32cubemx_lib\STM32Cube_FW_F4_V1.11.0\Projects\STM324xG_EVAL\Applications\IAP\IAP_Main
我的hal库是安装再c盘,你的自己去你的库里找..

QQ图片20160421220210.png

将上图中的四个文件复制到你刚刚新建的目录的SRC目录里面
common.c
flash_if.c
menu.c
ymodem.c
同样的,将此目录里的INC目录下的也复制过去
common.h
flash_if.h
menu.h
ymodem.h
上面都完成之后,将.c的文件添加到你的工程中,如下图

QQ图片20160421220640.png

 
以上,我们的准备工作就完成了...
楼下2楼继续...
 

>>本IAP程序在本站网盘中可得到,名称: 基于STM32Cube使用USART进行在线编程


已邀请:

admin

赞同来自: 刘拉沙

这里是2楼
此时不能急着编译,这样徽错误太多,无从下手...
我们先双击打开common.c文件
删除下面这句:
#include "main.h"
因为我们用不到.
此时顺便右击选择goto打开common.h
删除 #include "stm324xg_eval.h"
再次打开flash_if.c
此文件貌似没有头文件需要修改的...
继续打开menu.c
删除 #include "main.h"
同时看到里面有一句话 
HAL_UART_Receive(&UartHandle, &status..............
这个UartHandle不是我们定义的husart1,于是,去打开usart.c文件右击goto打开usart.h文件
看到上面有句  
extern UART_HandleTypeDef huart1;
我们就在它下面加一句话
#define UartHandle huart1
这个时候我们回到menu.c文件
头部添加
#include "usart.h"
好吧,继续打开Ymodem.c文件
修改里面的
#include "main.h"

#include "usart.h"
好了现在可以进行编译了....
3楼继续写..

 
 
 

admin

赞同来自:

3楼编译后有三处错误提示,都指明是UartHandle未定义
好吧,刚才没注意common.c文件的下面也有串口的调用,
于是再common.c文件头部添加
#include "usart.h"
再次编译,没有错误提示了...
 
这次正题开始了,准备工作结束.
打开main.c文件
我们先不直接就开始写iap
iap中利用了一个用户按钮状态来使能iap功能菜单,所以我们第一步应该先测试好这个按钮是否能够完成重任.
于是在
main函数里添加
int main(void)
{

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/* MCU Configuration----------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* Configure the system clock */
SystemClock_Config();

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();

/* USER CODE BEGIN 2 */
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) != GPIO_PIN_RESET)
{
HAL_UART_Transmit(&UartHandle,(uint8_t *)"the botton is down",18,0xff);
}
else
{
HAL_UART_Transmit(&UartHandle,(uint8_t *)"the botton is up",16,0xff);
}
/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

}
/* USER CODE END 3 */

}

QQ图片20160421230958.png

上图是运行后的结果,由于discovery的按钮是默认有个下拉电阻,所以,当我启动电源的时候串口助手会提示
the botton is up
当我按紧用户按钮,然后复位系统的时候,串口是提示the botton is down
由此判断串口和按键都正常工作....
 
以下4楼继续修改..

admin

赞同来自:

4楼..
参考iap的示例,
再main.c文件里添加
#include "menu.h"
extern pFunction JumpToApplication;
extern uint32_t JumpAddress;
在楼上的判断按键的地方修改为
   /* USER CODE BEGIN 2 */
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) != GPIO_PIN_RESET)
{
MX_USART1_UART_Init();
Main_Menu();
// HAL_UART_Transmit(&UartHandle,(uint8_t *)"the botton is down",18,0xff);
}
else
{
/* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */
if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
{
/* Jump to user application */
JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
JumpToApplication = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
JumpToApplication();
}
// HAL_UART_Transmit(&UartHandle,(uint8_t *)"the botton is up",16,0xff);
}
知道串口的初始化为什么剪切到了里面吗?
只有当按键被按下的时候才触发串口初始化,才会启动IAP功能,其他时间是不应该启动的...
重点说说APPLICATION_ADDRESS这个东西..
如原子所解释的首先检查栈顶地址是否合法.
用户代码区第二个字为程序开始地址(复位地址)  
初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
 
 
 

admin

赞同来自:

接楼上

接着可以再次编译了.没有错误提示了...好了
现在可以把这个程序下载到F4discovery的板子上面了...
此时,你可以打开一款串口调试助手看看串口菜单的样子了...
硬件连接好之后,打开串口助手,此时紧按住用户按键不放,然后按复位按键,串口会有如下提示信息:

QQ图片20160421233347.png


看到这个信息,那么恭喜你,iap的主功能已经有了..
下面楼下继续说说,iap的用户app怎么生成并使用.

admin

赞同来自:

用户APP的生成及使用和下载:
discovery板上面有四个led灯,就利用它们来看效果..
生成一个包含这四个led的程序,其他什么功能都不用.
打开这个工程文件的main.c
再main函数中添加
		for(uint16_t i=30000;i>=1;i--)
for(uint16_t j=600;j>=1;j--);
HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_14|GPIO_PIN_15);
这个是类似1S闪烁一次led.
 
也许你会问我为什么不用hal_delay()函数啊..
看了iap的文档后知道,app的中断向量都要进行偏移才能用,于是,咱现在先不用中断呗,
hal_delay就是利用了嘀嗒定时器的中断,所以不用.
 
好了,先别急着编译.要修改几处地方:

QQ图片20160421234203.png

上面框中,第一个参数是:我们再IAP中定义的用户app的起始地址就是楼上上所说的那个
APPLICATION_ADDRESS = 0x8004000
后面的那个参数是这样得来的:
F407VGT芯片的flash大小0x100000 - IAP用掉的0x4000 = 0xFC000以上修改的意思其实就是,将这段程序的起始地址修改为8004000,
特别注意:后面的那个size的数据长度绝对不能错!!!
 
编译,生成axf文件.
此时按照先前我的一个帖子,将axf文件生成对应的bin文件.
 
 
 

admin

赞同来自:

此时已经有了包含IAP功能的板子,和已经写好的一个用户APP
下面就将app通过串口烧写进片子.
利用Ymodem功能的串口工具:
我先说下我调试的时候首先用到的是一个叫 TeraTeam的串口软件,用这个软件第一次烧写没问题,以后就烧写不成功....我也是醉了,不知道哪里出了问题,我也懒得找原因了...于是就又焕了一个软件用SecureCRT就没出过问题.
我下面就直接写用SecureCRT的过程了..
 

QQ图片20160421235449.jpg


QQ图片20160421235525.png

连接好之后,手按住用户按钮userbotton不放,然后点击那个复位系统按钮,此时串口输出一串信息

QQ图片20160421235723.jpg

=================== Main Menu ============================

Download image to the internal Flash ----------------- 1

Upload image from the internal Flash ----------------- 2

Execute the loaded application ----------------------- 3

Enable the write protection -------------------------- 4

==========================================================
此时可以看到,按键盘的1 功能是下载程序到mcu
按键2功能是上传mcu的flash到电脑
按键3是用来运行用户app程序
按键4是使能或者失能写保护,
我们用到按键1功能,因为,这个时候我们按下键盘上面的数字1

QQ图片20160422000014.png

提示
Waiting for the file to be sent ... (press 'a' to abort)
等待你去上传这个bin文件..
这个时候,我们点击

QQ图片20160422000130.png

选择用Ymodem协议来发送这个bin文件,选择我们生成的那个用户app的bin文件


QQ图片20160422000337.jpg


等待一会,会看到一个进度条,然后发送100%成功提示.如下图
Starting ymodem transfer.  Press Ctrl+C to cancel.
Transferring iap_user.bin...
  100%       3 KB     440 bytes/sec 00:00:07       0 Errors 

QQ图片20160422000418.png

 
然后再次可以看到串口弹出先前那个提示,询问你进行下一步操作,此时,可以直接按下按键3运行刚刚烧写下去的程序,可以看到灯闪烁的效果了..

admin

赞同来自: 981868085@qq.com bryan823

总结:
以上就是初步调试IAP的过程.
整个过程不复杂,主要借助了st官方提供的示例,
从上面可以得出看官方示例是多么重要..
另外再补充一点信息
就是上面提到的中断向量偏移才能使用hal_delay()函数问题:
可以在main()函数刚刚开始的时候添加一个代码
SCB->VTOR = FLASH_BASE | 0x4000;
0x4000就是咱们上面的IAP主程序定义的app的起始位置了......
 
如果你的iap用了其他的起始地址,上文中提到的都要相应更改下...
 
另外: 这个起始地址可不是随便设置的啊.一般情况是0x200的整数倍
 
好了,iap功能调试结束!
 
下一步就是利用usb来做iap了,有懂或已经调通的同学可以不吝赐教.
 
 
补充:
这里在增加一种官方提供的修改中断向量表的办法
打开工程后,找到Drivers/CMSIS 目录下的
system_stm32f4xx.c 文件
在第100行附近,可以看到

#define VECT_TAB_OFFSET 0x00
这里就是直接修改中断向量表的地方,后面也提示必须是0x200整数倍

东东

赞同来自:

你好,我安装你的步骤试验在发送bin文件那就不动了,我这官方程序带CRC校验,不知道有没有关系。

Advance

赞同来自:

谢谢,学习了,我也试一下!

dxf520

赞同来自:

学习了

hzp114033329 - 繁花似锦觅安宁&淡云流水渡此生

赞同来自:

谢谢,太给力了!

Hu hope hope

赞同来自:

不管怎么说 ,非常感谢 ,谢谢分享

jiuggg

赞同来自:

谢谢

caoenq - 硬件设计大师

赞同来自:

你好版主,您的文章里说了不能用haldelay()的原因是中断向量进行了偏移,那用户的程序中肯定的使用串口中断、Tim6等中断,这个要如何解决?还望赐教。

渔舟唱晚

赞同来自:

你好棒!

蓝麒深挚

赞同来自:

请问一下你的USB IAP调通了没?


yimiyangguang

赞同来自:

学习了

overture1928

赞同来自:

学习!

overture1928

赞同来自:

楼主,CRC部分你没有介绍呀

wansaiyon

赞同来自:

楼主,之前用这个例子升级裸机程序是正常,最近升级带OS的程序,升级过程中突然卡住不动了,如下:


==========================================================


Waiting for the file to be sent ... (press 'a' to abort)

CCCCC

Starting ymodem transfer.  Press Ctrl+C to cancel.

Transferring ECU_STM32F407ZET6.bin...

   62%      46 KB      64 bytes/sec 00:07:29 ETA   0 Errors 

很奇葩的是若不停按按键加复位键,升级进程百分比会不断增加,有解决办法没有?

chenlmm

赞同来自:

学习,学习谢谢

要回复问题请先登录注册