MDK程序下载 ---- FLM文件
MDK编程算法
用过MDK下载程序的小伙伴可能都知道,在下载程序之前需要都在Debug设置的Flash Download子选项卡选择编程算法。大多数时候,
我们只要安装了芯片包之后,就可以直接得到对应的编程算法,并不需要我们去修改它。但是,当你是一个芯片包的开发者,或者你有独特
的下载需求(比如在你的程序里加入一些校验信息),这个时候你就需要去了解它了!
编程算法呢,说白就其实也就是一段程序,主要功能就是擦除相应的内存块,并将我们的程序写入到相应的内存区域上去。
在你点击下载按钮的时候,这段程序会被先下载到RAM上(RAM for Algorithm上的设置),然后才会通过它,将你的程序写入到
指定的内存区域内。
实现一个自己的编程算法
怎么去实现一个自己的编程算法?首先我们找到自己的MDK的安装路径,进入到ARM\Flash文件夹下(例如:D:\Keil_v5\ARM\Flash)。
这里有个编程算法的工程模板,复制这个工程到你的工程文件夹下,重命名你自己的想要的名字。
打开工程,里面主要有两个文件 FlashPrg.c 和 FlashDev.c:
FlashDev.c主要实现了一个设备相关的结构体(根据自己的Flash情况去实现)
比如STM32L051实现如下:
FlashPrg.c实现了几个Flash编程相关的函数:
根据自己的需要去实现,STM32L051实现如下:
1 /* ----------------------------------------------------------------------------- 2 * Copyright (c) 2014 ARM Ltd. 3 * 4 * This software is provided 'as-is', without any express or implied warranty. 5 * In no event will the authors be held liable for any damages arising from 6 * the use of this software. Permission is granted to anyone to use this 7 * software for any purpose, including commercial applications, and to alter 8 * it and redistribute it freely, subject to the following restrictions: 9 * 10 * 1. The origin of this software must not be misrepresented; you must not 11 * claim that you wrote the original software. If you use this software in 12 * a product, an acknowledgment in the product documentation would be 13 * appreciated but is not required. 14 * 15 * 2. Altered source versions must be plainly marked as such, and must not be 16 * misrepresented as being the original software. 17 * 18 * 3. This notice may not be removed or altered from any source distribution. 19 * 20 * 21 * $Date: 18. November 2014 22 * $Revision: V1.00 23 * 24 * Project: Flash Programming Functions for ST STM32L0xx Flash 25 * --------------------------------------------------------------------------- */ 26 27 /* History: 28 * Version 1.00 29 * Initial release 30 */ 31 32 #include "FlashOS.H" // FlashOS Structures 33 34 typedef volatile unsigned char vu8; 35 typedef volatile unsigned long vu32; 36 typedef volatile unsigned short vu16; 37 38 #define M8(adr) (*((vu8 *) (adr))) 39 #define M16(adr) (*((vu16 *) (adr))) 40 #define M32(adr) (*((vu32 *) (adr))) 41 42 // Peripheral Memory Map 43 #define IWDG_BASE 0x40003000 44 #define FLASH_BASE 0x40022000 45 46 #define IWDG ((IWDG_TypeDef *) IWDG_BASE) 47 #define FLASH ((FLASH_TypeDef*) FLASH_BASE) 48 49 #define FLASH_MEMORY 50 51 // Independent WATCHDOG 52 typedef struct { 53 vu32 KR; // offset 0x000 Key register (IWDG_KR) 54 vu32 PR; // offset 0x004 Prescaler register (IWDG_PR) 55 vu32 RLR; // offset 0x008 Reload register (IWDG_RLR) 56 vu32 SR; // offset 0x00C Status register (IWDG_SR) 57 } IWDG_TypeDef; 58 59 // Flash Registers 60 typedef struct { 61 vu32 ACR; // offset 0x000 Flash access control register (FLASH_ACR) 62 vu32 PECR; // offset 0x004 Flash program erase control register (FLASH_PECR) 63 vu32 PDKEYR; // offset 0x008 Flash power down key register (FLASH_PDKEYR) 64 vu32 PEKEYR; // offset 0x00C Flash program erase key register (FLASH_PEKEYR) 65 vu32 PRGKEYR; // offset 0x010 Flash program memory key register (FLASH_PRGKEYR) 66 vu32 OPTKEYR; // offset 0x014 Flash option key register (FLASH_OPTKEYR) 67 vu32 SR; // offset 0x018 Flash status register (FLASH_SR) 68 vu32 OPTR; // offset 0x01C Option byte register (FLASH_OBR) 69 vu32 WRPRT; // offset 0x020 Flash write protection register (FLASH_WRPR) 70 } FLASH_TypeDef; 71 72 73 // Flash Keys 74 #define FLASH_PEKEY1 (0x89ABCDEFul) 75 #define FLASH_PEKEY2 (0x02030405ul) 76 #define FLASH_PRGKEY1 (0x8C9DAEBFul) 77 #define FLASH_PRGKEY2 (0x13141516ul) 78 #define FLASH_OPTKEY1 (0xFBEAD9C8ul) 79 #define FLASH_OPTKEY2 (0x24252627ul) 80 81 // Flash program erase control register (FLASH_PECR) definitions 82 #define FLASH_PELOCK (0x00000001ul) // FLASH_PECR and data memory lock 83 #define FLASH_PRGLOCK (0x00000002ul) // Program memory lock 84 #define FLASH_OPTLOCK (0x00000004ul) // Option bytes block lock 85 #define FLASH_PROG (0x00000008ul) // Program memory selection 86 #define FLASH_DATA (0x00000010ul) // Data memory selection 87 #define FLASH_OPT (0x00000020ul) // Option Bytes memory selection 88 #define FLASH_FIX (0x00000100ul) // Fixed time data write for Byte, Half Word and Word programming 89 #define FLASH_ERASE (0x00000200ul) // Page or Double Word erase mode 90 #define FLASH_FPRG (0x00000400ul) // Half Page/Double Word programming mode 91 #define FLASH_GBHF_ER (0x00000800ul) // Global Half Erase mode 92 93 // Flash status register (FLASH_SR) definitions 94 #define FLASH_BSY (0x00000001ul) // Write/erase operations in progress 95 #define FLASH_EOP (0x00000002ul) // End of operation 96 #define FLASH_ENDHV (0x00000004ul) // End of high voltage 97 #define FLASH_WRPERR (0x00000100ul) // Write protected error 98 #define FLASH_PGAERR (0x00000200ul) // Programming alignment error 99 #define FLASH_SIZERR (0x00000400ul) // Size error 100 #define FLASH_OPTVERR (0x00000800ul) // Option validity error 101 102 #define FLASH_ERRs (FLASH_PGAERR | FLASH_WRPERR | FLASH_SIZERR | FLASH_OPTVERR) 103 104 // Option byte register (FLASH_OBR) definitions 105 #define FLASH_IWDG_SW (0x00100000ul) // Software IWDG or Hardware IWDG selected 106 107 /* 108 * Initialize Flash Programming Functions 109 * Parameter: adr: Device Base Address 110 * clk: Clock Frequency (Hz) 111 * fnc: Function Code (1 - Erase, 2 - Program, 3 - Verify) 112 * Return Value: 0 - OK, 1 - Failed 113 */ 114 115 #ifdef FLASH_MEMORY 116 int Init (unsigned long adr, unsigned long clk, unsigned long fnc) { 117 118 FLASH->SR |= FLASH_ERRs; // clear error flags 119 120 // Unlock PECR Register 121 FLASH->PEKEYR = FLASH_PEKEY1; 122 FLASH->PEKEYR = FLASH_PEKEY2; 123 124 // Unlock Program Matrix 125 FLASH->PRGKEYR = FLASH_PRGKEY1; 126 FLASH->PRGKEYR = FLASH_PRGKEY2; 127 128 129 return (0); 130 } 131 #endif // FLASH_MEMORY 132 133 /* 134 * De-Initialize Flash Programming Functions 135 * Parameter: fnc: Function Code (1 - Erase, 2 - Program, 3 - Verify) 136 * Return Value: 0 - OK, 1 - Failed 137 */ 138 139 #ifdef FLASH_MEMORY 140 int UnInit (unsigned long fnc) { 141 142 switch (fnc) { 143 case 1: 144 case 2: 145 // Lock PECR register and program matrix 146 FLASH->PECR |= FLASH_PRGLOCK; // Program memory lock 147 FLASH->PECR |= FLASH_PELOCK; // FLASH_PECR and data memory lock 148 break; 149 } 150 151 return (0); 152 } 153 #endif // FLASH_MEMORY 154 155 /* 156 * Erase Sector in Flash Memory 157 * Parameter: adr: Sector Address 158 * Return Value: 0 - OK, 1 - Failed 159 */ 160 161 #ifdef FLASH_MEMORY 162 int EraseSector (unsigned long adr) { 163 164 FLASH->PECR |= FLASH_ERASE; // Page or Double Word Erase enabled 165 FLASH->PECR |= FLASH_PROG; // Program memory selected 166 167 M32(adr) = 0x00000000; // write '0' to the first address to erase page 168 169 while (FLASH->SR & FLASH_BSY) { 170 IWDG->KR = 0xAAAA; // Reload IWDG 171 } 172 173 FLASH->PECR &= ~FLASH_ERASE; // Page or Double Word Erase disabled 174 FLASH->PECR &= ~FLASH_PROG; // Program memory deselected 175 176 return (0); // Done 177 } 178 #endif // FLASH_MEMORY 179 180 /* 181 * Program Page in Flash Memory 182 * Parameter: adr: Page Start Address 183 * sz: Page Size 184 * buf: Page Data 185 * Return Value: 0 - OK, 1 - Failed 186 */ 187 188 #ifdef FLASH_MEMORY 189 int ProgramPage (unsigned long adr, unsigned long sz, unsigned char *buf) { 190 unsigned long cnt; 191 unsigned long i; 192 193 sz = (sz + 63) & ~63; // adjust programming size 194 195 for (i = 0; i < (sz / 64); i++) { 196 FLASH->PECR |= FLASH_FPRG; // Half Page programming mode enabled 197 FLASH->PECR |= FLASH_PROG; // Program memory selected 198 199 cnt = 64; 200 while (cnt ) { 201 M32(adr) = *((unsigned long *)buf); // Program Word 202 adr += 4; 203 buf += 4; 204 cnt -= 4; 205 } 206 207 while (FLASH->SR & FLASH_BSY) { 208 IWDG->KR = 0xAAAA; // Reload IWDG 209 } 210 211 if (FLASH->SR & (FLASH_ERRs)) { // Check for Errors 212 FLASH->SR |= FLASH_ERRs; // clear error flags 213 return (1); // Failed 214 } 215 216 FLASH->PECR &= ~FLASH_FPRG; // Half Page programming mode disabled 217 FLASH->PECR &= ~FLASH_PROG; // Program memory deselected 218 } 219 220 return (0); // Done 221 } 222 #endif // FLASH_MEMORY
从上面我们就可以看出了,下载程序的时候就是调用了上面的几个函数,跟我们自己写Flash没有太大的区别。那么程序都编程完成之后,
怎么生成FLM文件呢?我们先编译工程,完成之后你去看你的工程输出目录,这个时候你就已经可以找到FLM后缀的文件了,这个就是你自己
的编程算法,把它复制到 ' MDK安装路径 '\ARM\Flash下面就可以了,在选项卡里选择你自己的编程算法就可以使用了。
结束
到这里,你已经可以自己实现一个编程算法了。但是细心的小伙伴可能会发现,这个过程下来其实和我们自己的项目工程没有什么区别,
但是为什么我们自己的工程就生成不了FLM文件呢?哈哈,小伙伴可以自己看一看编译的日志,有没有类似下面的日志
原来.FLM文件跟.axf文件是一样的,就是改了一下文件后缀。具体.axf文件又是什么呢?哈哈, 我就不说了,感兴趣的小伙伴们可以自己去了解一下!