目录
实验平台
硬件:银杏科技GT7000双核心开发板-ARM-STM32H743XIH6,银杏科技iToolXE仿真器
软件:最新版本STM32CubeH7固件库,STM32CubeMX v6.10.0,开发板环境MDK v5.35,TCP&UDP测试工具,串口工具putty
网盘资料包:链接: https://pan.baidu.com/s/1Y3nwaY4SMxfoUsdqPm2R3w?pwd=inba 提取码: inba
IAP(SD卡存储介质)
在上一章节我们介绍了IAP相关知识,并且利用UART串口传输APP文件,本章我们采用SD卡来传输APP文件。
SD卡相关知识可以参考文章STM32H743-ARM例程13-SDIO
STM32CubeMX生成工程
我们参考前面章节STM32H743-结合CubeMX新建HAL库MDK工程,打开CubeMX软件,重复步骤不再展示,我们来看配置SDMMC部分如下图所示:
配置SDMMC1

配置FATFS

实验代码
本章实验包含两个程序,APP和bootloader,APP程序可以参考STM32H743-ARM例程34-BootROM,把启动地址修改为0x8040000
c
#define FLASH_ADDRESS (uint32_t)0x8040000
bootloader程序:
1. 主函数
c
int main(void)
{
/* USER CODE BEGIN 1 */
int cnt;
int k;
unsigned char buffer[6144];
unsigned char * p;
unsigned long int ncounter = 0;
unsigned int counter;
/* Enable the CPU Cache */
CPU_CACHE_Enable();
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_SPI5_Init();
MX_USART6_UART_Init();
MX_SDMMC1_SD_Init();
MX_FATFS_Init();
/* USER CODE BEGIN 2 */
uart6.initialize(115200);
uart6.printf("\x0c");
uart6.printf("\033[1;32;40m");
uart6.printf("Hello,I am GT7000\r\n");
LED_ON;
/* USER CODE END 2 */
if(ARM_KEY4_STATE == KEY_UP){ //按键松开状态直接跳向应用程序
goto start;
}
//SD卡初始化
if(BSP_SD_Init() != MSD_OK){
led_trade();
}
res = f_mount(&fatfs,"0:",1);
//判断是否成功
if(res != RES_OK){
led_trade();
}else{
uart6.printf("f_mount is ok!\r\n");
}
res = f_open(&fil,"0:/app.bin",FA_READ); //打开app.bin文件
//判断文件打开是否成功
if(res != RES_OK){
led_trade();
}else{
uart6.printf("f_open is ok!\r\n");
}
res = f_lseek(&fil,0); //将指针移动到第一个位置
//指针是否移动成功
if(res != RES_OK){
led_trade();
uart6.printf("f_lseek is error!\r\n");
}else{
uart6.printf("f_lseek is ok!\r\n");
}
//获取文件信息
f_stat("0:/app.bin",&finfo);
while(ncounter < finfo.fsize)
{
//读取6144Byte数据
res = f_read(&fil,buffer,6144,&counter); //读文件
if(res != RES_OK){
uart6.printf("Read APP error!\r\n");
led_trade();
}
uart6.printf("%d\r\n",counter);
p =(unsigned char*)buffer;
uart6.printf("Read APP ...!\r\n");
iap_write_appbin(APPLICATION_ADDRESS,p ,6144);
ncounter +=6144;
}
uart6.printf("Load APP finish!\r\n");
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
start:
if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x24000000){
//跳转至用户程序
JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
JumpToApplication = (pFunction) JumpAddress;
//初始化用户程序的堆栈指针
__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
//跳转至应用程序
JumpToApplication();
}
else{
led_trade();
}
/* USER CODE END 3 */
}
2. iap_write_appbin函数
c
void iap_write_appbin(uint32_t appxaddr,uint8_t *appbuf,uint32_t appsize)
{
uint32_t t;
uint16_t i=0;
uint32_t temp;
uint32_t fwaddr=appxaddr;//当前写入的地址
uint8_t *dfu=appbuf;
for(t=0;t<appsize;t+=4)
{
temp=(uint32_t)dfu[3]<<24;
temp|=(uint32_t)dfu[2]<<16;
temp|=(uint32_t)dfu[1]<<8;
temp|=(uint32_t)dfu[0];
dfu+=4;//偏移4个字节
iapbuf[i++]=temp;
if(i==FLASH_SECTOR)
{
i=0;
STMFLASH_Write(fwaddr,iapbuf,FLASH_SECTOR);
fwaddr+=FLASH_SECTOR*4;//偏移2048 512*4=2048
}
}
if(i)STMFLASH_Write(fwaddr,iapbuf,i);//将最后的一些内容字节写进去.
}
实验现象
我们将app.bin 文件拷贝到SD卡中,运行程序,按下 ARM-KEY 将烧写 Bootloader(IAP)程序烧写程序到GT7000上,通过读取SD卡中的app.bin文件,重新上电 ARM-LED 灯闪烁,即 ARM 更新升级成功。