做个网站费用多少合适,可以免费开店的平台,网站怎么做跳转页面,高碑店网站建设价格引言 本篇文章将介绍flash算法文件#xff0c;阐述从jlink如何下载镜像文件写入到内部的falsh。
一、XIP 在谈flash下载算法文件时#xff0c;先说明XIP是什么。 芯片的启动方式有很多种#xff1a;可以从RAM中启动、内部的flash、外部的flash等等#xff08;还有从sd卡、…引言 本篇文章将介绍flash算法文件阐述从jlink如何下载镜像文件写入到内部的falsh。
一、XIP 在谈flash下载算法文件时先说明XIP是什么。 芯片的启动方式有很多种可以从RAM中启动、内部的flash、外部的flash等等还有从sd卡、emmc、nor flash、nand flash等这里我们只考虑内部的flash的情况。 我们都知道flash只是一块ROMflash有两种类型分为nor flash、nand flash一般32位处理器里面使用的是nor flash作为ROM存放镜像文件。 在专业课计算机组成原理或者操作系统中有提到CPU从内存RAM中读取、运行程序。但在stm32这种微处理器上一般都是直接从内部的flash启动。这牵扯到一个技术叫做XIPeXecute In Place 即芯片内执行。其含义就是CPU直接从存储器读取指令将指令送给译码器和执行器等部件使用。 有了XIP就不必将代码读取到RAM中可以直接在flash运行。好处即是程序代码无需占用内存减少内存的要求。XIP是复杂性和速度的权衡而这就意味着XIP通常仅用于BIOS或RAM极度短缺(MCU的情况就是如此)的情况。 要实现XIP必须要有如下几个条件 1. 存储器必须提供与内存相似的接口给CPU。 2. 该接口必须提供足够快的读取操作并具有随机访问模式。 3. 如有文件系统则需要提供合适的映射功能 4. 程序链接时需要知道存储器的地址或地址与位置无关。 5. 程序不能修改已加载映像中的数据。 因为nor flash和EEPROM通常能满足上述要求所以其可以XIP。 而nand flash因为有地址数据命令共用IO口的问题cpu发送来地址之后还要nand flahs控制器再处理一下才能得到数据因此不适合不是不能XIP只是不适合。nor flash的访问和RAM类似提供地址就可以得到数据。因此一般处理器内部都是使用nor flash作为XIP的方案而且nor flash读取速度比nand flash要快很多。 当bin文件经过JLink、SW-DP接口经过AHB-DP将数据传到AHB总线上之后已经具备可以写入到falsh里面的条件了。这里随便找了一个芯片内部图作为例子。 从上图中可以看到FLASH上面有Controller接口、XIP接口、EEPROM仿真接口。Controller接口就是我们在平常使用程序往flash写入数据的控制部分一般流程是先解锁flash写保护、写入数据、上锁写保护。这个例子应该很容易想起来的不懂的可以搜索一下stm32往内部flash写入数据。就可以得到相关信息了。这里我们写入bin文件到flash同样通过Controller接口。 SWD接口将数据传到AHB-DP、到总线之后就会在控制信号的指引下控制Controller然后将bin文件写入到flash写入完成、校验之后就可以reset启动芯片了使用XIP技术从flash某个地址启动常用的stm32一般是0x08000000。 知道了往哪里写之后也大概了解了数据写入的流程那么该如何写这里就要用到了flash下载算法了。
二、FLM文件 FLM文件是keil进行代码下载时的必须文件该文件主要包含被下载芯片的存储器的相关信息芯片型号、存储器页大小等和存储器写入算法。FLM文件本质上也是一种ELFExecutable and Linkable Format文件ELF文件的具体格式我们放到后面介绍。 上图中就是FLM文件他指导jlink如何下载镜像文件。镜像文件本质上就是一堆二进制我们都知道keil会生成axf文件、hex、bin文件镜像文件其实就是bin文件下载到flash里面的内容就是bin文件的内容。算法的名字叫做NEW_DEVICE.FLM路径在keil的安装目录里面ARM\PACK\ARM\CMSIS\4.5.0\Device\ARM\Flash。 在C:\Keil_v5\ARM\Flash_Template默认安装的情况下下面会有一个keil工程这个工程就是keil官方提供给我们制作flash下载算法的。
打开之后很简单就两个文件 FlashDev.c就只有一个struct FlashDevice类型的结构体上图是一个例子具体定义在FlashOS.H中。
struct FlashSectors {unsigned long szSector; // Sector Size in Bytesunsigned long AddrSector; // Address of Sector
};
struct FlashDevice {unsigned short Vers; // Version Number and Architecturechar DevName[128]; // Device Name and Descriptionunsigned short DevType; // Device Type: ONCHIP, EXT8BIT, EXT16BIT, ...unsigned long DevAdr; // Default Device Start Addressunsigned long szDev; // Total Size of Deviceunsigned long szPage; // Programming Page Sizeunsigned long Res; // Reserved for future Extensionunsigned char valEmpty; // Content of Erased Memoryunsigned long toProg; // Time Out of Program Page Functionunsigned long toErase; // Time Out of Erase Sector Functionstruct FlashSectors sectors[SECTOR_NUM];
};
从上面的结构体中我们可以知道我们的flash地址、大小、扇区大小等信息这些都会在下载bin文件的时候用到。
在FlashDev.c中我们可以看到16行表示flash设备的类型有如下几种情况。
#define UNKNOWN 0 // Unknown
#define ONCHIP 1 // On-chip Flash Memory
#define EXT8BIT 2 // External Flash Device on 8-bit Bus
#define EXT16BIT 3 // External Flash Device on 16-bit Bus
#define EXT32BIT 4 // External Flash Device on 32-bit Bus
#define EXTSPI 5 // External Flash Device on SPI
17--23就是指flash的参数有多大每页多少字节等等。 FlashPrg.c里面就只是一些函数的接口具体有哪些函数接口在下面。
// Flash Programming Functions (Called by FlashOS)
extern int Init (unsigned long adr, // Initialize Flashunsigned long clk,unsigned long fnc);
extern int UnInit (unsigned long fnc); // De-initialize Flash
extern int BlankCheck (unsigned long adr, // Blank Checkunsigned long sz,unsigned char pat);
extern int EraseChip (void); // Erase complete Device
extern int EraseSector (unsigned long adr); // Erase Sector Function
extern int ProgramPage (unsigned long adr, // Program Page Functionunsigned long sz,unsigned char *buf);
extern unsigned long Verify (unsigned long adr, // Verify Functionunsigned long sz,unsigned char *buf);
其实就是对flash的操作以前搞过spi flash就是w25qxx系列对上面的回调函数很好理解。 直接将keil官方提供的例子进行编译如下图。 其他的跟keil生成程序一样画横线的log是在编译结束之后将axf拷贝位flx文件从这里可以看出 flm文件其实就是axf文件看看二者的文件大小均为10500Byte。 axf文件是什么是在bin文件的基础山添加了地址信息和调试信息的文件。使用记事本打开确实有调试信息。 能生成axf文件说明有sct分散加载文件指导整个工程生成axf我们在keil配置里面找到之后发现只有一个叫做Target.lin的文件打开之后看到 跟平常见到的sct文件不太一样。 其实本质上并无差别无非就是指定code中的各种属性RO、RW、ZI放到某些位置。
三、操作flash接口 现在来看看FlashPrg.c里面的函数接口。 int Init (unsigned long adr, unsigned long clk, unsigned long fnc) 功能用于初始化Flash adr参数表示设备基地址Base Address clk参数表示时钟频率 adr参数表示功能码1 - 擦除, 2 - 程序, 3 -验证 int ProgramPage (unsigned long adr, unsigned long sz,unsigned char *buf); 功能将代码写入到flash中。 adr参数表示flash起始地址 sz参数表示写入数据的大小 buf参数表示缓存区 这里强调一点falsh是以块为单位组织的在FlashDev里面也有指定大小为szPage。主机系统往flash写入数据的时候会确保不会出现跨块写入数据就是一块一块的写入。在前面的内容中 T5324 000:563.106 Data: 88 08 00 20 D5 01 00 10 8B 0A 00 10 65 0A 00 10 ... T5324 000:563.126 CPU_WriteMem(512 bytes 0x20000670) 写入是以512B大小的内容往flash写入。其他的函数都比较好理解就不细讲了。
回过头来再看jlink下载日志写入flash的部分已删掉 T5324 000:386.354 JLINK_WriteMem(0xE0001000, 0x1C Bytes, ...) T5324 000:386.358 Data: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... T5324 000:386.372 CPU_WriteMem(28 bytes 0xE0001000) T5324 000:390.509 JLINK_WriteMem(0x20000000, 0x670 Bytes, ...) T5324 000:390.517 Data: 00 BE 0A E0 0D 78 2D 06 68 40 08 24 40 00 00 D3 ... T5324 000:390.720 CPU_WriteMem(1648 bytes 0x20000000) T5324 000:527.583 JLINK_WriteMem(0x20000000, 0x670 Bytes, ...) T5324 000:527.598 Data: 00 BE 0A E0 0D 78 2D 06 68 40 08 24 40 00 00 D3 ... T5324 000:527.622 CPU_WriteMem(1648 bytes 0x20000000) ..... T1A34 000:768.192 JLINK_WriteMem(0x20000000, 0x670 Bytes, ...) T1A34 000:768.209 Data: 00 BE 0A E0 0D 78 2D 06 68 40 08 24 40 00 00 D3 ... T1A34 000:768.232 CPU_WriteMem(1648 bytes 0x20000000) T1A34 000:884.512 JLINK_WriteMem(0x20000000, 0x2 Bytes, ...) T1A34 000:884.533 Data: FE E7 T1A34 000:884.552 CPU_WriteMem(2 bytes 0x20000000) 以下的部分内容有些是猜测根据自己的实践和网上的内容进行合理猜测。 T5324 000:386.354跟DWT通信开始写入flash算法也就时一段短的程序。
T5324 000:390.509将flash写入算法的内容写入到RAM中地址在这里设置。 之后通过jlink按照块512B大小发送程序的镜像文件内容和bin文件一样由flash写入算法接受数据将镜像文件写入到flash中。最后完成校验、复位等工作还有一些工作就不展开了跟本文内容不是很紧密jlink就可以断开了。 这部内容简单的总结下就是jlink先和M3内核沟通然后将flash下载算法传输到到RAM中再发送bin文件到RAM中由flash下载算法将RAM中的bin文件前面接受到的写入到内部的flash。最后进行校验复位若有等扫尾工作。 到这里也明白了下载bin文件到flah中的过程其实是由我们指定的flm文件这个flm文件一般由芯片厂商提供keil只是将这个接口具体的下载bin的过程开放出去了各个芯片厂家适配他们自己的芯片。
四、芯片启动过程 bin下载的过程基本上已经讲完了如果还有内容的话以后再更。最后谈一谈芯片如何启动。再说明芯片启动之前我们先看看芯片的地址空间。 上面时M3内核定义的地址空间使用一般芯片厂商会根据自己的需要在划分的区域里面实现自己的地址划分。博主这里不想找了就简单的画一个我需要讲解的部分作为说明素材 玩过stm32的同学应该知道stm32有两个boot引脚boot0、boot1二者配合起来选择从哪里启动boot[0:1] 均为0的时候从内部flash启动也就是从地址0x0800 0000其他的情况从RAM或者外部flash启动现在各位同学应该知道如果从外部flash启动该如何做了0^0。 在配置boot0/1为低电平时芯片从0x0800 0000地址出读取两个字一个sp一个pc然后配置中断向量表、进入复位中断就是startup_stm32xxxx.s的内容。但按理说pc、sp一开始的值应该为0那如何跳到0x0800 0000进而读取那里的bin文件呢问题就在Boot里面 看上图Boot是一段代码由厂商烧录。芯片在启动的时候pc值为0运行Boot程序Boot程序会去检测boot0/1引脚进而决定是从内部flash还是ram或者其他的地方启动其实就是一个地址的区别内部flash启动就是0x0800 0000ram就是0x2000 0000之后跳转到0x0800 0000boot0/1为低电平下面才是startup_stm32xxxx.s的内容。