keil下载程序具体过程4:flash下载算法

news2025/1/14 18:42:15

引言

        本篇文章将介绍flash算法文件,阐述从jlink如何下载镜像文件写入到内部的falsh。

一、XIP

        在谈flash下载算法文件时,先说明XIP是什么。

        芯片的启动方式有很多种:可以从RAM中启动、内部的flash、外部的flash等等(还有从sd卡、emmc、nor flash、nand flash等),这里我们只考虑内部的flash的情况。
        我们都知道flash只是一块ROM,flash有两种类型,分为nor flash、nand flash,一般32位处理器里面使用的是nor flash作为ROM,存放镜像文件。

        在专业课(计算机组成原理或者操作系统)中,有提到,CPU从内存(RAM)中读取、运行程序。但在stm32这种微处理器上,一般都是直接从内部的flash启动。这牵扯到一个技术,叫做XIP(eXecute 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文件本质上也是一种ELF(Executable 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 Bytes
    unsigned long AddrSector; // Address of Sector
};
struct FlashDevice {
    unsigned short Vers; // Version Number and Architecture
    char DevName[128]; // Device Name and Description
    unsigned short DevType; // Device Type: ONCHIP, EXT8BIT, EXT16BIT, ...
    unsigned long DevAdr; // Default Device Start Address
    unsigned long szDev; // Total Size of Device
    unsigned long szPage; // Programming Page Size
    unsigned long Res; // Reserved for future Extension
    unsigned char valEmpty; // Content of Erased Memory
    unsigned long toProg; // Time Out of Program Page Function
    unsigned long toErase; // Time Out of Erase Sector Function
    struct 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 Flash
                    unsigned long clk,
                    unsigned long fnc);
extern int UnInit (unsigned long fnc); // De-initialize Flash
extern int BlankCheck (unsigned long adr, // Blank Check
                        unsigned 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 Function
                        unsigned long sz,
                        unsigned char *buf);
extern unsigned long Verify (unsigned long adr, // Verify Function
                                unsigned 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  0000,ram就是0x2000 0000),之后跳转到0x0800  0000(boot0/1为低电平),下面才是startup_stm32xxxx.s的内容。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/869675.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CSDN博客批量查询质量分https://yma16.inscode.cc/请求超时问题(设置postman超时时间)(接口提供者设置了nginx超时时间)

文章目录 查询链接问题请求超时原因解决谷歌浏览器超时问题办法(失败了)谷歌浏览器不支持设置请求超时时间(谷歌浏览器到底有没限制请求超时?貌似没有限制?)看能否脱离浏览器请求,我们查看关键代…

基于C++实现了最小反馈弧集问题的三种近似算法(GreedyFAS、SortFAS、PageRankFAS)

该项目是一个基于链式前向星存图、boost(boost::hash、asio线程池)以及emhash7/8的非官方实现,实现了最小反馈弧集问题的三种近似算法。该问题是在有向图中找到最小的反馈弧集,其中反馈弧集是指一组弧,使得从这些反馈弧…

环境与分支的详细介绍及其关联(开发、测试、预发布、生产)

文章目录 前言一、开发环境(dev)二、测试环境(test)三、预发布环境(pre)四、生产环境(pro)五、环境与分支的关系总结 前言 在现代软件开发中,前端项目的开发和部署往往需…

【wiki】电竞助手掉落提醒 EsportsHelper「Webhook」「钉钉」「饭碗警告」「企业微信」「Discord」

介绍 本项目链接 Github电竞助手链接 github上项目电竞助手(EsportsHelper)的掉落提醒配置教程,当有掉宝的时候会发送你信息提示. 至于这个脚本是怎么使用的简单说一下,就是通过自动观看英雄联盟直播 从而获取奖励(仅限直营服),有兴趣的可以去github上看readme,非常详细,支持…

广联达 Linkworks办公OA SQL注入+后台文件上传漏洞复现(HW0day)

0x01 产品简介 广联达Linkworks办公OA(Office Automation)是一款综合办公自动化解决方案,旨在提高组织内部的工作效率和协作能力。它提供了一系列功能和工具,帮助企业管理和处理日常办公任务、流程和文档。 0x02 漏洞概述 由于 广…

hackNos靶机

靶机训练1 - hackNos: Os-hackNos 靶机平台 Vulnhub 是一个提供各种漏洞环境的靶场平台,供安全爱好者学习使用,大部分环境是做好的虚拟机镜像文件,镜像预先设计了多种漏洞,需要使用VMware或者VirtualBox运行。每个镜像会有破解的目…

【CSS学习笔记】

学习内容 1.css是什么 2.CSS怎么用(快速入门) 3.CSS选择器(重点 难点) 4.美化页面(文字、阴影、超链接、列表、渐变…) 5.盒子模型 6.浮动 7.定位 8.网页动画(特效) 1.什么是CSS C…

Reinforcement Learning with Code 【Chapter 10. Actor Critic】

Reinforcement Learning with Code 【Chapter 10. Actor Critic】 This note records how the author begin to learn RL. Both theoretical understanding and code practice are presented. Many material are referenced such as ZhaoShiyu’s Mathematical Foundation of …

Blazor简单教程(2):布局

文章目录 前言布局自定义布局默认布局 前言 我们现在主流的页面都是单页面Layout布局,即一个页面有侧边栏,抬头,下边栏,中间主题。 BootstrapBlazor UI, Blazor Server 模式配置 布局 自定义布局 注入LayoutCompon…

微服务06-分布式事务解决方案Seata

1、Seata 概述 Seata事务管理中有三个重要的角色: TC (Transaction Coordinator) - **事务协调者:**维护全局和分支事务的状态,协调全局事务提交或回滚。 TM (Transaction Manager) - **事务管理器:**定义全局事务的范围、开始全局事务、提交或回滚全局事务。 RM (Resourc…

软考笔记 信息管理师 高级

文章目录 介绍考试内容与时间教材 预习课程一些例子课本结构考试内容 1 信息与信息化1.1 信息与信息化1.1.1 信息1.1.2 信息系统1.1.3 信息化 1.2 现代化基础设施1.2.1 新型基础建设1.2.2 工业互联网1.2.3 车联网: 1.3 现代化创新发展1.3.1 农业农村现代化1.3.2 两化…

常见的路由协议之RIP协议与OSPF协议

目录 RIP OSPF 洪泛和广播的区别 路由协议是用于在网络中确定最佳路径的一组规则。它们主要用于在路由器之间交换路由信息,以便找到从源到目标的最佳路径。 常见的路由协议: RIP (Routing Information Protocol):RIP 是一种基于距离向量算…

cookie是什么?

cookie是什么? Cookie实际上是一小段的文本信息。 http协议本身是无状态的。无状态是指Web浏览器与Web服务器之间不需要建立持久的连接,这意味着当一个客户端向服务器端发出请求,然后Web服务器返回响应(Response)&…

用友移动管理系统 任意文件上传漏洞复现(HW0day)

0x01 产品简介 用友移动系统管理是用友公司推出的一款移动办公解决方案,旨在帮助企业实现移动办公、提高管理效率和员工工作灵活性。它提供了一系列功能和工具,方便用户在移动设备上管理和处理企业的系统和业务。 0x02 漏洞概述 用友移动管理系统 uploa…

Kubesphere中DevOps流水线无法部署/部署失败

摘要 总算能让devops运行以后,流水线却卡在了deploy这一步。碰到了两个比较大的问题,一个是无法使用k8sp自带的kubeconfig认证去部署;一个是部署好了以后但是没有办法解析镜像名。 版本信息 k8s:v1.21.5 k8sp:v3.3.…

GO学习之 微框架(Gin)

GO系列 1、GO学习之Hello World 2、GO学习之入门语法 3、GO学习之切片操作 4、GO学习之 Map 操作 5、GO学习之 结构体 操作 6、GO学习之 通道(Channel) 7、GO学习之 多线程(goroutine) 8、GO学习之 函数(Function) 9、GO学习之 接口(Interface) 10、GO学习之 网络通信(Net/Htt…

kafka高吞吐量分享

消息队列kafka基本介绍基本概念整体架构 高吞吐量实现分区分段顺序写磁盘零拷贝技术DMA(Direct Memory Access)传统传输零拷贝传输 批量发送 消息队列 解耦合 耦合的状态表示当你实现某个功能的时候,是直接接入当前接口,而利用消…

20230812在WIN10下使用python3将SRT格式的字幕转换为SSA格式

20230812在WIN10下使用python3将SRT格式的字幕转换为SSA格式 2023/8/12 20:58 本文的SSA格式以【Batch Subtitles Converter(批量字幕转换) v1.23】的格式为准! 1、 缘起:网上找到的各种各样的字幕转换软件/小工具都不是让自己完全满意! 【都…

2023年中国智慧公安行业发展现况及发展趋势分析:数据化建设的覆盖范围不断扩大[图]

智慧公安基于互联网、物联网、云计算、智能引擎、视频技术、数据挖掘、知识管理为技术支撑,公安信息化为核心,通过互联互通、物联化、智能方式促进公安系统各功能模块的高度集成、协同作战实现警务信息化“强度整合、高度共享、深度应用”警察发展的新概…

goland插件推荐Rider UI Theme Pack

推荐一个goland配色插件Rider UI Theme Pack,里面自带visual assist配色,配色截图如下: 直接在plugins里面进行搜索或者在插件home page下载后进行安装均可。 总算找到一统vscode 和goland二者优势的插件了。