47.1 初学者重要提示
SPI Flash的相关知识点可以看第31章和32章。
SPI Flash下载算法文件直接采用HAL库制作,方便大家自己修改。
47.2 MDK下载算法基础知识
Flash编程算法是一种用于擦除应用程序或将应用程序下载到Flash的程序代码。MDK本身支持的各种器件都自带下载算法,存放在MDK各种器件的软件包里面,以STM32F4为例,算法存放在KeilSTM32F4xx_DFP2.15.0CMSISFlash(软件包版本不同,数值2.15.0不同),但不支持的需要我们自己制作,本章教程为此而生。
47.2.1 程序能够通过下载算法下载到芯片的核心思想
认识到这点很重要:通过MDK创建一批与地址信息无关的函数,实现的功能主要有初始化,擦除,编程,读取,校验等,然后MDK调试下载阶段,会将算法文件加载到芯片的内部RAM里面(加载地址可以通过MDK设置),然后MDK通过与这个算法文件的交互,实现程序下载,调试阶段数据读取等操作。
47.2.2 算法程序中擦除操作执行流程
擦除操作大致流程:
加载算法到芯片RAM。
执行初始化函数Init。
执行擦除操作,根据用户的MDK配置,这里可以选择整个芯片擦除或者扇区擦除。
执行Uinit函数。
操作完毕。
47.2.3 算法程序中编程操作执行流程
编程操作大致流程:
针对MDK生成的axf可执行文件做Init初始化,这个axf文件是指的大家自己创建应用程序生成的。
查看Flash算法是否在FLM文件。如果没有在,操作失败。如果在:
加载算法到RAM。
执行Init函数。
加载用户到RAM缓冲。
执行Program Page页编程函数。
执行Uninit函数。
操作完毕。
47.2.4 算法程序中校验操作执行流程
校验操作大致流程:
校验要用到MDK生成的axf可执行文件。校验就是axf文件中下载到芯片的程序和实际下载的程序读出来做比较。
查看Flash算法是否在FLM文件。如果没有在,操作失败。如果在:
加载算法到RAM。
执行Init函数。
查看校验算法是否存在
如果有,加载应用程序到RAM并执行校验。
如果没有,计算CRC,将芯片中读取出来的数据和RAM中加载应用计算输出的CRC值做比较。
执行Uninit函数。
替换BKPT(BreakPoint断点指令)为 B. 死循环指令。
执行RecoverySupportStop,恢复支持停止。
执行DebugCoreStop,调试内核停止。
运行应用:
执行失败。
执行成功,再执行硬件复位。
操作完毕,停止调试端口。
47.3 创建MDK下载算法通用流程
下面是MDK给的一种大致操作流程,不限制必须采用这种方法,自己创建也可以的。
47.3.1 第1步,使用MDK提供好的程序模板
位于路径:KeilARMPackARMCMSISversionDevice_Template_Flash。
效果如下:
47.3.2 第2步,修改工程名
MDK提供的工程模板原始名字是NewDevice.uvprojx,大家可以根据自己的需要做修改。比如修改为MyDevice.uvprojx。
47.3.3 第3步,修改使用的器件
在MDK的Option选项里面设置使用的器件。
47.3.4 第4步,修改输出算法文件的名字
这个名字是方便用户查看的,比如设置为stm32h7,那么输出的算法文件就是stm32h7.flm。
注:MDK这里设置的名字与下面位置识别出来的算法名无关:
这个名字是在FlashDev.c里面定义的。
47.3.5 第5步,修改编程算法文件FlashPrg.c
模板工程里面仅提供了接口函数,内容需要用户自己填。
/*
Mandatory Flash Programming Functions (Called by FlashOS):
int Init (unsigned long adr, // Initialize Flash
unsigned long clk,
unsigned long fnc);
int UnInit (unsigned long fnc); // De-initialize Flash
int EraseSector (unsigned long adr); // Erase Sector Function
int ProgramPage (unsigned long adr, // Program Page Function
unsigned long sz,
unsigned char *buf);
Optional Flash Programming Functions (Called by FlashOS):
int BlankCheck (unsigned long adr, // Blank Check
unsigned long sz,
unsigned char pat);
int EraseChip (void); // Erase complete Device
unsigned long Verify (unsigned long adr, // Verify Function
unsigned long sz,
unsigned char *buf);
- BlanckCheck is necessary if Flash space is not mapped into CPU memory space
- Verify is necessary if Flash space is not mapped into CPU memory space
- if EraseChip is not provided than EraseSector for all sectors is called
*/
/*
* Initialize Flash Programming Functions
* Parameter: adr: Device Base Address
* clk: Clock Frequency (Hz)
* fnc: Function Code (1 - Erase, 2 - Program, 3 - Verify)
* Return Value: 0 - OK, 1 - Failed
*/
int Init (unsigned long adr, unsigned long clk, unsigned long fnc) {
/* Add your Code */
return (0); // Finished without Errors
}
/*
* De-Initialize Flash Programming Functions
* Parameter: fnc: Function Code (1 - Erase, 2 - Program, 3 - Verify)
* Return Value: 0 - OK, 1 - Failed
*/
int UnInit (unsigned long fnc) {
/* Add your Code */
return (0); // Finished without Errors
}
/*
* Erase complete Flash Memory
* Return Value: 0 - OK, 1 - Failed
*/
int EraseChip (void) {
/* Add your Code */
return (0); // Finished without Errors
}
/*
* Erase Sector in Flash Memory
* Parameter: adr: Sector Address
* Return Value: 0 - OK, 1 - Failed
*/
int EraseSector (unsigned long adr) {
/* Add your Code */
return (0); // Finished without Errors
}
/*
* Program Page in Flash Memory
* Parameter: adr: Page Start Address
* sz: Page Size
* buf: Page Data
* Return Value: 0 - OK, 1 - Failed
*/
int ProgramPage (unsigned long adr, unsigned long sz, unsigned char *buf) {
/* Add your Code */
return (0); // Finished without Errors
}
47.3.6 第6步,修改配置文件FlashDev.c
模板工程里面提供简单的配置说明:
struct FlashDevice const FlashDevice = {
FLASH_DRV_VERS, // Driver Version, do not modify!
"New Device 256kB Flash", // Device Name
ONCHIP, // Device Type
0x00000000, // Device Start Address
0x00040000, // Device Size in Bytes (256kB)
1024, // Programming Page Size
0, // Reserved, must be 0
0xFF, // Initial Content of Erased Memory
100, // Program Page Timeout 100 mSec
3000, // Erase Sector Timeout 3000 mSec
// Specify Size and Address of Sectors
0x002000, 0x000000, // Sector Size 8kB (8 Sectors)
0x010000, 0x010000, // Sector Size 64kB (2 Sectors)
0x002000, 0x030000, // Sector Size 8kB (8 Sectors)
SECTOR_END
};
注:名字New Device 256kB Flash就是我们第4步所说的。MDK的Option选项里面会识别出这个名字。
47.3.7 第7步,保证生成的算法文件中RO和RW段的独立性,即与地址无关
C和汇编的配置都勾选上:
汇编:
如果程序的所有只读段都与位置无关,则该程序为只读位置无关(ROPI, Read-only position independence)。ROPI段通常是位置无关代码(PIC,position-independent code),但可以是只读数据,也可以是PIC和只读数据的组合。选择“ ROPI”选项,可以避免用户不得不将代码加载到内存中的特定位置。这对于以下例程特别有用:
(1)加载以响应运行事件。
(2)在不同情况下使用其他例程的不同组合加载到内存中。
(3)在执行期间映射到不同的地址。
使用Read-Write position independence同理,表示的可读可写数据段。
47.3.8 第8步,将程序可执行文件axf修改为flm格式
通过下面的命令就可以将生成的axf可执行文件修改为flm。
47.3.9 第9步,分散加载设置
我们这里的分散加载文件直接使用MDK模板工程里提供好的即可,无需任何修改。
分散加载文件中的内容如下:
; Linker Control File (scatter-loading)
;
PRG 0 PI ; Programming Functions
{
PrgCode +0 ; Code
{
* (+RO)
}
PrgData +0 ; Data
{
* (+RW,+ZI)
}
}
DSCR +0 ; Device Description
{
DevDscr +0
{
FlashDev.o
}
}
--diag_suppress L6305用于屏蔽L6503类型警告信息。
特别注意,设置了分散加载后,此处的配置就不再起作用了:
47.4 SPI Flash的MDK下载算法制作
下面将QSPI Flash算法制作过程中的几个关键点为大家做个说明。
47.4.1 第1步,制作前重要提示
这两点非常重要:
程序里面不要开启任何中断,全部查询方式。
HAL库里面各种时间基准相关的API全部处理掉。简单省事些,我们这里是直接注释,采用死等即可。无需做超时等待,因为超时后,已经意味着操作失败了,跟死等没有区别。
47.4.2 第2步,准备一个工程模板
推荐大家直接使用我们本章工程准备好的模板即可,如果大家自己制作,注意一点,请使用当前最新的HAL库。
47.4.3 第3步,修改HAL库
大家可以更新需要修改以下三个文件(当前配套程序未做修改):
47.4.4 第4步,时钟初始化
我们已经用不到滴答定时器了,直接在bsp.c文件里面对滴答初始化函数做重定向:
/*
*********************************************************************************************************
上一篇:第48章 STM32F429的内部Flash和SPI Flash都使用MDK下载
下一篇:第46章 STM32F429的DMA2D应用之刷色块,位图和Alpha混合
推荐阅读最新更新时间:2024-11-10 10:11
推荐帖子
- 集成电路库存
- 本帖最后由jameswangsynnex于2015-3-319:58编辑联系孙先生13537741609QQ510490216GM5221ET-TVE0310A-QTVP5146PFP74LVC14ADphilipsTS5V330DBQR(E330)tiAP1506-50anachip24LC16BmicrochipMSP3415G-B8-V3CD4052BMSOP16TITDA98
- martinshune 移动便携
- 【瑞米派 Remi-Pi】网络及usb功能实测
- ##一、网络性能实测###1.双路千兆以太网####测试方案-**设备**:PC机、以太网线、`iperf3`工具。-**步骤**:***1.***使用`iperf3`作为服务器端(一端瑞米派RemiPi),另一端作为客户端。***2.***分别通过两个以太网接口进行双向数据传输测试。-**结果**:两个网口平均上传速度均可达到710Mbps,下载速度700Mbps,展现了稳定的千兆级性能。###2.双频Wi-Fi(2.4GHz/5GHz)
- fangkaixin 工控电子
- 【Espier FPGA VHDL学习帖】第17帖按键消抖.doc
- 【EspierFPGAVHDL学习帖】第17帖按键消抖按键消抖程序的思路都是来源于特权同学的按键消抖,特权同学采用的是VHDL改编了他的程序。20ms就会读取键值,把这个键值放到寄存器low_sw的值锁存到low_swwireled_ctrl=low_sw_r&(~low_sw);这是特权同学Key_an是检测第一次按下,同时也是cnt计数,本开发板用的大概为4
- 常见泽1 FPGA/CPLD
- NXP LPC1768宝马开发板 第一章GPIO实验
- 第一章NXPLPC1768——GPIO开发环境:集成开发环境μVision4IDE版本4.60.0.0主机系统:MicrosoftWindowsXP开发平台:旺宝NXPLPC1768开发板1.1GPIO简介1.2硬件描述1.3程序说明1.4实验现象1、GPIO:GPIO(Genera
- 旺宝电子 NXP MCU
- 好东西要分享 51单片机 交通灯 含源程序
- 基于51单片机设计的交通灯含源程序,适合初学者学习使用!好东西要分享51单片机交通灯含源程序请问一下我想把东西时间改成39南北方向改成34怎么改啊
- zhaichun136 51单片机
- 【DigiKey创意大赛】便携生命探测仪06+各模块整合联调
- 上一帖介绍了如何获取心电数据并解析协议,最终显示在电脑上,实现了心电采集功能。本帖介绍如何把所有模块整合到一起,实现预期的作品功能。一、预期功能做一个便携生命探测仪,在发生危险时,能帮助救援人员方便找到遇险者。此方案主要采用热敏式图像传感器MLX90640ESF-BAB-000-TU检测人体红外信号,采用BME680气体,湿度,压力,温度传感器评估板记录环境信息,配合一个带屏幕的评估板,显示热成像图片。再额外添加一个心电采集模块,当发现遇险者后,能立即给遇险者采集心电图和心率并在
- sipower DigiKey得捷技术专区
设计资源 培训 开发板 精华推荐
- ADR3530 微功耗、高精度电压基准的典型应用
- EVALPRAHVOPAMP-1RZ,评估采用 SOIC 封装的 ADA4700-1ARDZ 高压运算放大器的通用精度
- NCP133AMX100TCGEVB:NCP133 XDFN-4 评估板 1V0
- LT3755IUD-2 50W 白色汽车 LED 前照灯驱动器的典型应用电路
- m.2 ESP32-S3 WROOM 模块
- LTM8049IY ±12VOUT 2.7 至 20 VIN、双路 SEPIC 或反相 DC/DC 转换器的典型应用电路
- LT3089IR 高效可调电源的典型应用电路
- ADR292GRUZ-REEL7 4.096V便携式设备稳压器典型应用电路
- DI-176 - 20W空调电源
- 具有宽范围 VDD 输入的 LTC2945HUD 宽范围电源监视器的典型应用