请选择 进入手机版 | 继续访问电脑版
查看: 11447|回复: 4

万能的Flash烧写程序—基于FLM文件实现

[复制链接]
  • TA的每日心情
    开心
    3 天前
  • 签到天数: 266 天

    [LV.8]以坛为家I

    3296

    主题

    6541

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    31904
    最后登录
    2024-3-28
    发表于 2021-4-15 10:10:35 | 显示全部楼层 |阅读模式
    万能的Flash烧写程序—基于FLM文件实现
    Flash作为一种非易失性(Non-Volatile)存储器,其最显著的特点在于掉电之后,其存储的内容不会丢失。还有一点需要注意的是,对于flash存储器件的数据访问往往都是以块为单位进行操作的,在这里,要对数据读取进行特殊说明,对于Nor Flash器件来说,是支持随机读取的,但Nand Flash器件是不支持的。
    由于flash访问的特殊性,一般我们需要设计一套Flash烧写算法,至少要包括flash初始化,read、write、erase这些操作。说到这儿,仿佛一切都还算美好,只需要有一套适配的烧写算法即可。


    但是,小编还是不得不泼一盆冷水。算法本身一般情况是无法复用的,每更换一个flash器件就要额外去编写一套新的算法,尽管有会者不难的属性加持,但适配所有的flash器件,工作量也可想而知。


    小编今天就为大家提供一个适配几乎任意flash型号的flash程序,之所以说是几乎,不是小编谦虚啊,是因为我们这次要借东风,而这个东风就是Keil的FLM文件。也就是说,只有FLM所支持的,我们才可以使用。

    FLM文件是什么?


    熟悉Keil的朋友们都知道,当我们要下载编译好的镜像到Flash时,首先要做的一步就是选择合适的Flash下载算法,而这个算法本身就是一个FLM文件:
    21.png


    所谓Flash下载算法,是负责擦除或是下载应用数据到flash的一个软件。而Keil往往会集成不少FLM文件以支持大多数的flash型号。


    当然,正如前文所述,这些算法也是根据不同型号的flash所编写的。只不过,前人们已经为我们种好了大树,我们可以直接在树下乘凉了。

    FLM文件结构


    那么FLM文件是怎么个构成呢?Keil为我们提供了新建FLM工程的步骤,有兴趣的朋友可以自行参考。


    当然,正是因为Keil规定了FLM文件的构成,它是一成不变的,我们才可以无忧无虑的对文件本身进行解析。


    Keil规定,一个FLM文件中一般要有以下函数:
    22.png
    其中最为重要的有5个,我们来逐一说明:


    1、int Init (unsigned long adr, unsigned long clk, unsigned long fnc);


    负责flash器件的初始化工作,其中:


    adr: 设备首地址
    clk:时钟频率(Hz)
    fnc:要执行的flash操作,包括,1:Erase,2:Program,3:Verify


    2、int EraseSector (unsigned long adr);
    擦除addr所指定地址处的整个sector


    3、int ProgramPage (unsigned long adr, unsigned long sz, unsigned char*buf);
    对flash进行烧写操作,其中:


    adr:待烧写地址
    sz:待烧写数据长度
    bug:待烧写数据


    4、int EraseChip (void); 擦除整块flash
    5、int UnInit (unsigned long fnc); Uninit flash, 并根据传入的fnc执行不同的flash后操作,fnc的定义同Init。
    下面让我们解析一下现有的FLM文件,以MIMXRT106x_QSPI_4KB_SEC.FLM为例:
    打开windows的命令行工具,输入readelf.py MIMXRT106x_QSPI_4KB_SEC.FLM-S:
    23.png
    没错,这些正是我们需要的,也正是对于Flash进行操作所应该有的基本函数。


    FLM文件解析与代码实现


    我们下一步要做的就是老生常谈的事儿了,我们要将这些函数从FLM文件中提取出来,此处略过具体实现,可以参考小编上传的代码。如此一来,我们就将所有用到的函数都打包成了一个整体,并记录各个函数所在的位置:
    24.png
    接下来,为了方便后续使用,定义对应的结构体变量:
    1. typedef struct {
    2.         int (*Init)(ulong adr, ulong clk, ulong fnc);
    3.         int (*UnInit)(ulong fnc);
    4.         int (*EraseSector)(ulong adr);
    5.         int (*ProgramPage)(ulong adr, ulong sz, uchar* buf);
    6.         int (*EraseChip)(void);
    7. } flash_ops_t;
    复制代码
    同时定义一个宏,以对变量进行初始化:
    1. #define INIT_FLASH_OPS(ops) \
    2.     flash_ops_t ops = {  \
    3.         .Init = CAST_VALUE_TO_FUNC(OPS_OFFSET + INIT_OFFSET, ops.Init), \
    4.         .UnInit = CAST_VALUE_TO_FUNC(OPS_OFFSET + UNINIT_OFFSET, ops.UnInit), \
    5.         .EraseSector = CAST_VALUE_TO_FUNC(OPS_OFFSET + ERASESECTOR_OFFSET, ops.EraseSector), \
    6.         .ProgramPage = CAST_VALUE_TO_FUNC(OPS_OFFSET + PROGRAMPAGE_OFFSET, ops.ProgramPage), \
    7.         .EraseChip = CAST_VALUE_TO_FUNC(OPS_OFFSET + ERASECHIP_OFFSET, ops.EraseChip),         \
    8.     };
    复制代码
    效果展示


    实际使用就很方便了,用户只需要调用一次INIT_FLASH_OPS(ops); 即可实现变量声明已经变量赋值,我们以ProgramPage函数进行展示,代码如下:


    #define FLASH_BASE_ADDR(0x60000000U)
    #define SECTOR_SIZE     (4096)
    #define PAGE_SIZE       (256)
    #define OP_NUM          (0U)


    首先对sector进行擦除:
    ops.EraseSector(FLASH_BASE_ADDR +OP_NUM * SECTOR_SIZE);
    25.png


    烧写flash为0x56
    1. char *pool = malloc(sizeof(char) * PAGE_SIZE);       
    2. memcpy(pool, (void*)FLASH_BASE_ADDR, PAGE_SIZE);
    3. memset(pool, 0x56, PAGE_SIZE);
    4. ops.ProgramPage(FLASH_BASE_ADDR + OP_NUM * PAGE_SIZE, PAGE_SIZE, (uchar*)pool);
    5. free(pool);
    复制代码
    26.png
    烧写成功!


    小编这次为大家带来了一种基于Keil的FLM文件进行Flash烧写的新思路,这样一来,在进行Flash操作时,我们可以不必重复造轮子,依靠Keil这颗大树,真的好乘凉。


    换句话说,实现了一种几乎万能的Flash下载器,Keil所能支持的Flash器件,我们都可以对其进行操作。本文代码请点击。



    签到签到
    回复

    使用道具 举报

  • TA的每日心情

    2016-10-20 11:32
  • 签到天数: 1 天

    [LV.1]初来乍到

    12

    主题

    108

    帖子

    0

    高级会员

    Rank: 4

    积分
    545
    最后登录
    2022-3-1
    发表于 2021-5-21 08:54:35 | 显示全部楼层
    大神啊,有没有完整代码啊,你这个最后的跳转没有链接啊
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2022-5-25 16:03
  • 签到天数: 11 天

    [LV.3]偶尔看看II

    8

    主题

    718

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    3395
    最后登录
    2024-3-5
    发表于 2021-5-21 14:24:12 | 显示全部楼层
    怎么提取函数?是什么工具
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2021-6-14 00:30
  • 签到天数: 10 天

    [LV.3]偶尔看看II

    1

    主题

    54

    帖子

    0

    注册会员

    Rank: 2

    积分
    108
    最后登录
    2021-6-14
    发表于 2021-5-29 17:50:08 | 显示全部楼层
    可以脱离原厂烧录软件进行烧录所有的比如ST PIC???谢谢
    开心
    回复 支持 反对

    使用道具 举报

  • TA的每日心情

    2021-9-10 13:05
  • 签到天数: 18 天

    [LV.4]偶尔看看III

    8

    主题

    61

    帖子

    0

    注册会员

    Rank: 2

    积分
    181
    最后登录
    2021-9-18
    发表于 2021-9-10 13:12:05 | 显示全部楼层
    又来膜拜大神了,那如果使用jlink烧写扩展的外部flash应该怎么做啊?
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-3-29 00:10 , Processed in 0.133070 second(s), 24 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表