赞
踩
上一篇文章中我们介绍了如何将固件下载到SPI FLASH中。这一篇我们在上一篇的基础上实现:把存储在外部flash的代码拷贝到外部SRAM中执行。
MCU的内部flash和内部sram都不是特别大,在一些大型的应用中,会出现flash和ram不够的情况。这样我们就可以把应用程序存储在外部flash中,然后拷贝到外部sram中执行。
我这里说的外部flash指的是SPI FLASH。对于STM32F407单片机没有QSPI接口,也就不能在外部flash中执行代码了;对与STM32H7,F7这类单片机有QSPI接口,代码也不是必须复制到SRAM中执行,也可以通过QSPI的内存映射功能,在外部flash中执行。
程序分为两部分:一部分是BOOT程序,一部分是应用程序。
MCU上电先执行内部flash的代码(其实也只能先执行内部flash的代码,因为外部flash和sram的接口需要初始化,无法直接从这些器件中直接取指令,执行)也就是BOOT程序。BOOT程序的功能:初始化外部flash接口和外部sram接口,然后把外部flash的代码拷贝到外部sram中,跳转到SRAM中取指令,执行代码。
应用程序没什么特别的,只需应用程序的工程编写合适的分散加载文件(链接脚本)。
加载地址:就是程序的存储地址。
链接地址:就是程序执行的地址。
这两个地址可以是一样的(比如BOOT程序,程序在内部flash中存储,在内部flash中执行),也可以是不一样的(比如在外部flash中存储,在外部sram中执行)。
uint8_t read_buf[1024]; uint8_t *p = (uint8_t *)0x68000000;//外部SRAM的基地址 int main(void) { u8 key; u16 i=0; u16 id = 0; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2 delay_init(168); //初始化延时函数 uart_init(115200); //初始化串口波特率为115200 LED_Init(); //初始化LED KEY_Init(); //按键初始化 W25QXX_Init(); //初始化外部flash接口 id = W25QXX_ReadID(); printf("boot start...\r\n"); printf("flash chip id = %04x\r\n",id); FSMC_SRAM_Init();//初始化外部SRAM接口 for(int i=0;i<50;i++) { W25QXX_Read(read_buf,i*1024,1024);//从外部flash拷贝1K数据到read_buf memcpy(p,read_buf,1024);//从read_buf拷贝1K数据到外部SRAM p+=1024; } //跳转 jump2app = (IapFun)*(vu32*)(0x68000000 + 4); /* 初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址) */ MSR_MSP(*(vu32*)0x68000000); jump2app(); //跳转到APP while(1); }
思路中和注释已经解释的很清楚,这里就不再赘述。
应用程序的代码没有任何区别,需要自己编写链接脚本。
LR_IROM1 0x68000000 0x00100000 { ; load region size_region
ER_IROM1 0x68000000 0x00100000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
.ANY (+XO)
}
RW_IRAM1 0x20000000 0x00020000 { ; RW data
.ANY (+RW +ZI)
}
}
LR_IROM1 0x68000000 0x00100000
中的0x68000000是加载地址,0x00100000
是加载域的地址。
ER_IROM1 0x68000000 0x00100000
中的0x68000000是链接地址,0x00100000
是执行域的地址。
链接脚本大家要根据自己的实际工程项目灵活调整。
前边讲到加载地址就是程序的存储地址,链接地址是程序的执行地址。那外部flash存储代码外部sram执行代码,这明显的就是加载地址和链接地址不一样啊,为什么分散加载文件写的却是一样?
解释:其实加载地址和链接地址那是看站在哪个角度去看。站在应用程序的角度,应用程序并没有拷贝代码,CPU执行应用程序第一条指令的时候,应用程序就已经处于外部SRAM了,所以加载地址就等于链接地址了。至于拷贝代码那是BOOT程序去做的,和应用程序没有任何关系。
要实现外部FLASH存储代码内部SRAM执行代码,主要工作有两个,其一是制作下载算法文件,其二是调整应用程序的链接脚本。对于链接脚本中的一些知识需要理解,只有理解了,才能灵活的应用。
需要工程源码的请发私信。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。