银杏科技有限公司旗下技术文档发布平台 |
技术支持电话 | 0379-69926675-801 |
技术支持邮件 | Gingko@vip.163.com |
版本 | 日期 | 作者 | 修改内容 |
V1.0 | 2020-07-11 | gingko | 初次建立 |
实验三十四:U_DISK_IAP_ARM实验——更新升级STM32
一、 实验目的与意义
了解STM32的IAP结构。
了解STM32的IAP特征。
掌握STM32的IAP的使用方法。
掌握USB HOST MSC卡的使用方法。
掌握FATFS的使用方法。
掌握STM32 HAL库中FATFS和USB HOST属性的配置方法。
掌握KEIL MDK 集成开发环境使用方法。
二、 实验设备及平台
-
-
Micro USB线缆。
SD卡。
Keil MDK 开发平台。
STM32CubeMX开发平台。
装有WIN XP(及更高版本)系统的计算机。
三、 实验原理
1、U盘简介
U盘,全称USB闪存盘,英文名“USBflashdisk”。它是一种使用USB接口的无需物理驱动器的微型高容量移动存储产品,通过USB接口与主机连接,实现即插即用,是最常用的移动存储设备之一。
STM32F767的USB_OTG_HS支持U盘,并且ST官方提供了USB HOST大容量存储设备(MSC)例程,本实验,我们就要移植该例程到iCore4双核心板上,以通过STM32F767的USB HOST接口,读写U盘或SD卡读卡器等设备。
2、USB_OTG主要特性
主要特性可分为三类:通用特性、主机模式特性和从机模式特性。
a)通用特性
OTG_FS/OTG_HS 接口的通用特性如下:
经USB-IF认证,符合通用串行总线规范第2.0版
OTGHS支持3个PHY接口
片上全速PHY
连接外部全速PHY的I2C接口
连接外部高速PHY的ULPI接口
模块内嵌的PHY还完全支持定义在标准规范OTG补充第1.3版中的OTG协议
可通过软件配置为以下角色:
支持FS/HSSOF和LSKeep-alive令牌
SOF脉冲可通过PAD输出
SOF脉冲从内部连接到定时器(TIMx)
可配置的帧周期
可配置的帧结束中断
OTG HS内嵌DMA,并可软件配置AHB的批量传输类型。
具有省电功能,例如在USB挂起期间停止系统、关闭数字模块时钟、对PHY和DFIFO电源加以管理
具有采用高级FIFO控制的1.25K[FS]/4K[HS]字节专用RAM:
b)主机模式特性
OTG_FS/OTG_HS接口在主机模式下具有以下主要特性和要求:
c)从机模式特性
OTG_FS/OTG_HS接口在从机模式下具有以下主要特性:
1个双向控制端点0
5[FS]/7[HS]个IN端点(EP),可配置为支持批量传输、中断传输或同步传输
具有5[FS]/7[HS]个OUT端点,可配置为支持批量、中断或同步传输
管理一个共享RxFIFO和一个Tx-OUTFIFO,以高效使用USB数据RAM
管理多达6[FS]/8[HS]个专用Tx-INFIFO(分别用于每个使能的INEP),降低应用程序负荷
支持软断开功能。
3、高速OTG模块框图
4、IAP简介
IAP是In Application Programming的首字母缩写,IAP是用户自己的程序在运行过程中对User Flash的部分区域进行烧写,目的是为了在产品发布后可以方便地通过预留的通信口对产品中的固件程序进行更新升级。
通常在用户需要实现IAP功能时,即用户程序运行中作自身的更新操作,需要在设计固件程序时编写两个项目代码,第一个项目程序不执行正常的功能操作,而只是通过某种通信管道(如USB、USART)接收程序或数据,执行对第二部分代码的更新;第二个项目代码才是真正的功能代码。这两部分项目代码都同时烧录在User Flash中,当芯片上电后,首先是第一个项目代码开始运行,它作如下操作:
(1)检查是否需要对第二部分代码进行更新
(2)如果不需要更新则转到4)
(3)执行更新操作
(4)跳转到第二部分代码执行
第一部分代码必须通过其它手段,如JTAG或ISP烧入;第二部分代码可以使用第一部分代码IAP功能烧入,也可以和第一部分代码一道烧入,以后需要程序更新是再通过第一部分IAP代码更新。
对于STM32来说,因为它的中断向量表位于程序存储器的最低地址区,为了使第一部分代码能够正确地响应中断,通常会安排第一部分代码处于Flash的开始区域,而第二部分代码紧随其后。
在第二部分代码开始执行时,首先需要把CPU的中断向量表映像到自己的向量表,然后再执行其他的操作。
如果IAP程序被破坏,产品必须返厂才能重新烧写程序,这是很麻烦并且非常耗费时间和金钱的。针对这样的需求,STM32在对Flash区域实行读保护的同时,自动地对用户Flash区的开始4页设置为写保护,这样可以有效地保证IAP程序(第一部分代码)区域不会被意外地破坏。
5、FATFS文件系统简介
6、FATFS的特点
7、FATFS模块的层次结构图
最顶层是应用层,使用者无需理会FATFS的内部结构和复杂的FAT协议,只需要调用FATFS模块提供给用户的一系列应用接口函数,如f_open,f_read,f_write和f_close等,就可以像在PC上读/写文件那样简单。
中间层FATFS模块,实现了FAT文件读/写协议。FATFS模块提供的是ff.c和ff.h。除非有必要,使用者一般不用修改,使用时将头文件直接包含进去即可。
需要我们编写移植代码的是FATFS模块提供的底层接口,它包括存储媒介读/写接口(diskI/O)和供给文件创建修改时间的实时时钟。
8、原理图
四、实验程序
1、主函数
int main(void)
{
/* MCU配置 */
/* 重置所有外设, 初始化Flash接口和Systick. */
HAL_Init();
/* 系统时钟配置 */
SystemClock_Config();
/* 初始化所有已配置的外设 */
MX_GPIO_Init();
MX_USB_HOST_Init();
MX_FATFS_Init();
if(ARM_KEY_STATE == KEY_UP)
goto start;
while (1)
{
MX_USB_HOST_Process();
}
start:
//测试用户代码是否从APPLICATION_ADDRESS被编程
if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000){
//跳转至用户程序
JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
Jump_To_Application = (pFunction) JumpAddress;
//初始化用户程序的堆栈指针
__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
//跳转至应用程序
Jump_To_Application();
}else{
led_trade();
}
}
2、USB HOST初始化
void MX_USB_HOST_Init(void)
{
/* 初始化主机库,添加支持的类并启动该库*/
USBH_Init(&hUsbHostHS, USBH_UserProcess, HOST_HS);
USBH_RegisterClass(&hUsbHostHS, USBH_MSC_CLASS);
USBH_Start(&hUsbHostHS);
}
/*初始化HOST 内核 */
USBH_StatusTypeDef USBH_Init(USBH_HandleTypeDef *phost, void (*pUsrFunc)(USBH_HandleTypeDef *phost, uint8_t ), uint8_t id)
{
/* 检查USB主机句柄是否有效 */
if(phost == NULL)
{
USBH_ErrLog("Invalid Host handle");
return USBH_FAIL;
}
/* 设置 DRiver ID */
phost->id = id;
/* 取消连结类*/
phost->pActiveClass = NULL;
phost->ClassNumber = 0;
/* 恢复默认状态并准备EP0 */
DeInitStateMachine(phost);
/* 分配用户进程 */
if(pUsrFunc != NULL)
{
phost->pUser = pUsrFunc;
}
#if (USBH_USE_OS == 1)
/* 创建USB主机队列 */
osMessageQDef(USBH_Queue, 10, uint16_t);
phost->os_event = osMessageCreate (osMessageQ(USBH_Queue), NULL);
/*创建USB HOST任务 */
#if defined (USBH_PROCESS_STACK_SIZE)
osThreadDef(USBH_Thread, USBH_Process_OS, USBH_PROCESS_PRIO, 0, USBH_PROCESS_STACK_SIZE);
#else
osThreadDef(USBH_Thread, USBH_Process_OS, USBH_PROCESS_PRIO, 0, 8 * configMINIMAL_STACK_SIZE);
#endif
phost->thread = osThreadCreate (osThread(USBH_Thread), phost);
#endif
/*初始化底层驱动 */
USBH_LL_Init(phost);
return USBH_OK;
}
/*启动USB Host内核*/
USBH_StatusTypeDef USBH_Start (USBH_HandleTypeDef *phost)
{
/* 启动底层驱动 */
USBH_LL_Start(phost);
/* 在端口上激活VBUS */
USBH_LL_DriverVBUS (phost, TRUE);
return USBH_OK;
}
3、USB HOST处理函数
void MX_USB_HOST_Process(void)
{
/* USB主机后台任务 */
USBH_Process(&hUsbHostHS);
}
/*用户回调定义 */
static void USBH_UserProcess (USBH_HandleTypeDef *phost, uint8_t id)
{
int k;
int cnt;
unsigned int counter;
unsigned long int ncounter = 0;
unsigned char buffer[1024];
FIL fil;
static FRESULT res;
unsigned long int *p;
switch(id)
{
case HOST_USER_SELECT_CONFIGURATION:
break;
case HOST_USER_DISCONNECTION:
Appli_state = APPLICATION_DISCONNECT;
break;
case HOST_USER_CLASS_ACTIVE:
Appli_state = APPLICATION_READY;
LED_BLUE_ON;
//解锁内存,擦除扇区
HAL_FLASH_Unlock();
for(cnt = FLASH_SECTOR_2;cnt < FLASH_SECTOR_11;cnt ++){
FLASH_Erase_Sector(cnt,OB_BOR_LEVEL3);
}
LED_BLUE_OFF;
LED_RED_ON;
//f_mount
res = f_mount(&fatfs,"0:",1); //给磁盘分配盘符
if(res != RES_OK){
LED_RED_OFF;
led_trade();
}
//f_open
res = f_open(&fil,"0:/app.bin",FA_READ); //打开app.bin文件
if(res != RES_OK){
LED_RED_OFF;
led_trade();
}
//f_lseek
res = f_lseek(&fil,0); //将指针移动到第一个位置
if(res != RES_OK){
LED_RED_OFF;
led_trade();
}
//写Flash
while(ncounter < fil.fsize)
{
res = f_read(&fil,buffer,1024,&counter); //读文件
if(res != RES_OK){
LED_RED_OFF;
led_trade();
}
p = (unsigned long int *)buffer;
for(k = 0; k < counter / 4; k++)
{
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,APPLICATION_ADDRESS + ncounter,*(p + k));
ncounter += 4;
}
}
HAL_FLASH_Lock();
//ARM更新升级成功,绿色LED灯点亮
LED_BLUE_OFF;
LED_RED_OFF;
LED_GREEN_ON;
break;
case HOST_USER_CONNECTION:
Appli_state = APPLICATION_START;
break;
default:
break;
}
}
五、 实验步骤
把仿真器与iCore4的SWD调试口相连(直接相连或者通过转接器相连);
将跳线冒插在USB UART;
把iCore4(USB UART)通过Micro USB线与计算机相连,为iCore4供电;
打开Keil MDK开发环境,并打开APP实验工程,编译连接后,将Objects文件夹下的app.hex文件拷贝至hex_to_bin文件夹下,将其转化成app.bin文件(方法:将app.hex拉至HEX2BIN应用程序),将app.bin文件拷贝至U盘中;
把USB OTG通过Micro USB线与U盘相连,来读取U盘中的升级文件;
打开Keil MDK 开发环境,并打开IAP实验工程;
按下ARM-KEY将烧写Bootloader程序到 iCore4上;
也可以进入Debug模式,单步运行或设置断点验证程序逻辑。
六、 实验现象