0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

恩智浦经典LPC系列MCU内部Flash IAP驱动介绍

痞子衡嵌入式 来源:痞子衡嵌入式 2023-03-30 09:19 次阅读

LPC 系列 MCU 是恩智浦公司于 2003 年开始推出的非常具有代表性的产品,距今已经有近 20 年的生命。按时间线演进来说,其主要分为三代:

- 元老:基于 ARM7/9 内核的 LPC2000/3000 系列
- 中坚:基于 Cortex-M0/0+/3/4 内核的 LPC800/1100/1200/1300/1500/1700/1800/4000/4300/54000
- 新锐:基于 Cortex-M33 内核的 LPC5500 系列。

其中坚产品即是痞子衡今天要重点聊的经典 MCU,从其第一颗 LPC1800 到至今仍有新型号出来的 LPC800,仍然深受广大开发者喜爱。今天痞子衡想讨论的是内部 Flash 驱动这个对嵌入式软件开发者来说既冷门又不冷门的话题

Note:本文内容主要以 LPC845 这个型号为例,未必完全适用其它经典 LPC 型号,具体需要查看相应手册。

一、关于MCU内部Flash的基本概念

痞子衡先解释下为什么内部 Flash 驱动这个话题既冷门又不冷门。说它冷门是因为大部分嵌入式软件开发工程师写的应用代码里很少包含 Flash 操作功能(除非应用需要 OTA 升级或者断电保存参数),因此对 Flash 模块的关注度不如其它外设模块。说它不冷门则是在 IDE 中调试或者编程器做量产又离不开 Flash 操作,所以避不可免地关注 Flash 擦写算法、性能、寿命、效率等。

话说回来,Flash 外设一般由两部分组成:Flash 控制器 + Flash Memory 介质,其 Memory 介质部分从原理上属于并行 NOR Flash,MCU 上电 Flash 外设总是使能的,可以通过 AHB 总线直接读取其映射空间内任意 Flash 地址处的数据/指令,所以其最主要的作用就是存储可执行代码。

如果应用程序需要做 OTA 升级,则需要借助 Flash 控制器完成擦除和写入操作。这里就有一些概念性的东西出现了,比如 Flash 擦除正常是按 Block/Sector 为单元(不排除有些支持按 Page 擦除),并且擦除操作是将 Block/Sector 里全部 bit 从 0 恢复为 1。而 Flash 写入则是按 PUnit 为最小单元的(可能是 1/2/4/8 bytes),一次性最多写入一个 Page 的数据(这里指一次完整命令执行等待过程)。擦除和写入操作都不是立刻就完成的,需要等待 Memory 介质更新完成(读 Flash 控制器相应状态位寄存器)。

LPC845 内部 Flash 一共 64KB,划分为 64 个 Sector,每个 Sector 大小为 1KB。每个 Sector 包含 16 个 Page,每个 Page 大小为 64Bytes。支持按 Sector/Page 擦除,IAP 仅支持按 Page 写入(但是控制器底层最小写入单元是 4bytes),不支持 RWW 特性。

    64KB          N/A            N/A           1KB          64Bytes       4Bytes
Flash Memory > Flash Bank >= Flash Block > Flash Sector > Flash Page >= Flash PUnit >= Flash Byte
                   |              |             |              |             |
                RWW单元        擦除单元        擦除单元      最大写入单元    最小写入单元

关于 Flash 擦写操作,还有一个重要概念叫 Read-While-Write(简称 RWW),因为默认代码是执行在 Flash 里,如果我们这个时候还做 Flash 擦写操作,就会让同一个 Flash 处于又做擦写处理同时也要响应 AHB 总线来的读指令请求,大部分 Flash 是无法支持这个特性的,因此常见的操作是将触发 Flash 擦写命令以及读 Flash 状态的代码重定向到 RAM 里去执行。而 LPC 上不一样的 Flash IAP 驱动设计正是为了解决这个 RWW 限制的。

二、一般Flash驱动设计

在讲 LPC Flash IAP 特色驱动之前,我们先来看看一般 MCU 上 Flash 驱动设计,就以恩智浦 Kinetis MK60DN512Z 系列为例。它的 Flash 外设是 FTFL (详见参考手册里 Chapter 28 Flash Memory Module (FTFL) 章节),Flash 大小为 512KB,分为两个 256KB Block (这里就相当于Bank),支持 RWW 特性(以 Block 为单元)。每个 Block 包含 128 个 Sector,每个 Sector 大小为 2KB。它其实没有明确的 Page 概念(但是最大写入单元是专用 4KB FLEXRAM 的一半,可以理解为 Page 大小就是 2KB),支持的最小写入单元是 4bytes。

   512KB         256KB          256KB          2KB            2KB         4Bytes
Flash Memory > Flash Bank >= Flash Block > Flash Sector >= Flash Page > Flash PUnit >= Flash Byte
                   |              |             |              |             |
                RWW单元        擦除单元        擦除单元      最大写入单元    最小写入单元

在官方驱动 SDK_2_2_0_TWR-K60D100MdevicesMK60D10driversfsl_flash.c 里我们重点关注如下 5 个基本函数,这些函数都是直接操作 FTFL 外设寄存器来完成相应 Flash 擦写功能的。其中 flash_command_sequence() 内部函数设计是核心,每一个 API 基本都会调用它,这里面有一个关于解决 RWW 限制的黑科技设计,后面痞子衡会写文章专门介绍。

//一般初始化函数,主要是软件层面初始化
status_tFLASH_Init(flash_config_t*config);
//为了解决RWW限制而特殊设计的命令触发执行函数
status_tFLASH_PrepareExecuteInRamFunctions(flash_config_t*config);
staticstatus_tflash_command_sequence(flash_config_t*config)
//擦除函数,长度不限(需要按Sector对齐),key参数是为了降低误擦除风险
status_tFLASH_Erase(flash_config_t*config,uint32_tstart,uint32_tlengthInBytes,uint32_tkey);
//写入函数,长度不限(仅最小写入单元对齐限制),函数内部自动结合Page和PUnit写入命令做处理
status_tFLASH_Program(flash_config_t*config,uint32_tstart,uint32_t*src,uint32_tlengthInBytes);

三、LPC Flash IAP驱动设计原理

终于来到本文核心 - LPC Flash IAP 驱动了。按照我们一般经验,首先是翻看 LPC845 用户手册寻找 Flash 外设,但是很遗憾,用户手册里并没有 Flash 外设详细介绍,取而代之的是 Chapter 5: LPC84x ISP and IAP 章节。因为 LPC 全系列都包含 BootROM(映射地址为 0x0F00_0000 - 0x0F00_3FFF),而 BootROM 代码里包含了 Flash 擦写驱动,因此官方直接推荐用户调用 ROM 里的 Flash 驱动 API 来完成操作,而不是按照传统方式提供直接操作 Flash 外设寄存器的 SDK 源码。

BootROM 提供的 API 不止 Flash IAP 一个,可以在 Boot Process 章节里如下图里找到全部 API。这里我们可以看到 Flash IAP 函数的统一入口地址是 0x0F001FF1,这在 SDK 里 LPC845_features.h 文件里有如下专门宏:

/*@briefPointertoROMIAPentryfunctions*/
#defineFSL_FEATURE_SYSCON_IAP_ENTRY_LOCATION(0x0F001FF1)
04988e6a-ce98-11ed-bfe3-dac502259ad0.png

有了 IAP 入口地址,调用起来就简单了,芯片用户手册里直接给了参考 C 代码,可以看到 API 设计上将全部支持的 13 个函数集中在一起了,复用了输入参数列表 command_param 和输出结果列表 status_result。痞子衡之前写过一篇 《二代 Kinetis 上的 Flash IAP 设计》,那个 API 接口设计更偏向现代嵌入式软件开发者的习惯,而 LPC Flash IAP 接口设计是 2008 年推出来的,那时候看是超前时代。

unsignedintcommand_param[5];
unsignedintstatus_result[5];

typedefvoid(*IAP)(unsignedint[],unsignedint[]);
#defineIAP_LOCATION*(volatileunsignedint*)(0x0F001FF1)
IAPiap_entry=(IAP)IAP_LOCATION;

iap_entry(command_param,status_result);
04b45f14-ce98-11ed-bfe3-dac502259ad0.png

四、LPC Flash IAP驱动快速上手

最后看一下官方驱动 SDK_2_13_0_LPCXpresso845MAXdevicesLPC845driversfsl_iap.c ,这相当于将 Flash IAP 做了二次封装,我们重点关注如下 6 个基本函数。其中 iap_entry() 最终调用的是 ROM 中代码,直接执行在 ROM 区域,不会和 Flash 访问冲突,天然没有 RWW 限制问题。

擦除函数 IAP_ErasePage()/IAP_EraseSector() 没什么好说的,就是这个写入函数 IAP_CopyRamToFlash() 命名有点绕,不符合一般习惯,然后需要特别注意的是写入长度 numOfBytes 必须是 Page 倍数,且不能超过一个 Sector 大小(但是实测可以横跨两个 Sector 一次性写入多个 Page 数据,所以这仅仅是软件代码人为规定,不是 Flash 控制器限制)。

最后还有一个注意点就是擦写操作都是所谓的 two step process,就是需要先调用一下 IAP_PrepareSectorForWrite() 函数才行,这个设计其实是为了降低程序跑飞出现误擦写的风险。

//一般初始化函数,主要是配置Flash访问时间
voidIAP_ConfigAccessFlashTime(uint32_taccessTime);
//进入ROMIAP的入口函数
staticinlinevoidiap_entry(uint32_t*cmd_param,uint32_t*status_result);
//擦除和写入前准备函数
status_tIAP_PrepareSectorForWrite(uint32_tstartSector,uint32_tendSector);
//擦除函数,按Page/Sector为单位
status_tIAP_ErasePage(uint32_tstartPage,uint32_tendPage,uint32_tsystemCoreClock);
status_tIAP_EraseSector(uint32_tstartSector,uint32_tendSector,uint32_tsystemCoreClock);
//写入函数,长度最大限定为一个Sector
status_tIAP_CopyRamToFlash(uint32_tdstAddr,uint32_t*srcAddr,uint32_tnumOfBytes,uint32_tsystemCoreClock);






审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 控制器
    +关注

    关注

    112

    文章

    15239

    浏览量

    171225
  • 寄存器
    +关注

    关注

    30

    文章

    5037

    浏览量

    117764
  • OTA
    OTA
    +关注

    关注

    7

    文章

    526

    浏览量

    34599
  • NOR flash
    +关注

    关注

    2

    文章

    84

    浏览量

    22864
  • MCU芯片
    +关注

    关注

    3

    文章

    222

    浏览量

    11147

原文标题:为什么说内部Flash驱动是个既冷门又不冷门的话题 | LPC Flash IAP

文章出处:【微信号:pzh_mcu,微信公众号:痞子衡嵌入式】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    NXP LPC1100L系列ARM

    11E00和LPC11U00系列)可通过片内引导装载程序软件来实现在系统编程(ISP)和在应用编程(IAP)可选择通过CAN(仅LPC11C00系列
    发表于 02-20 11:10

    NXP LPC800系列微控制器

    LPC800系列MCU是采用ARM®CortexTM M0+内核的32位低功耗微处理器,运行频率高达30MHz。LPC800采用低引脚封装,最高支持16KB片内
    发表于 02-20 11:22

    NXP LPC1700系列ARM

    单元。 LPC1700系列ARM增加了一个专用的Flash存储器加速模块,使得在Flash中运行代码能够达到较理想的性能。LPC1700
    发表于 02-20 11:24

    NXP LPC3000系列ARM9

    概述LPC3000系列ARM采用了带有矢量浮点协处理器的ARM926EJ-S CPU内核,与数据处理能力大幅提升;工作频率可高达266MHz,这为USB、以太网、LCD控制器等外设同时运行提供了
    发表于 02-20 11:30

    大中华区LPC微控制器技术应用研讨会即将开始

    智能电表、数据采集、PC及游戏设备控制周边等应用的解决方案  ● MCU完整的嵌入式开发生态系统:工具、软件、硬件、文档、技术支持和销售服务等  ● LPC嵌入式应用及方案开发实
    发表于 05-12 14:19

    NXP ARM7 ARM9 Cortex-M0 M3 M4 内核芯片汇总

    产品是业界性能最佳的Cortex-M3 MCU系列产品,其运行速度达到180 MHz,提供较大片内存储和专用外设,包括高速USB、SPI Flash接口和状态配置定时器。
    发表于 10-13 17:12

    用于USB TypeC & Pd 的负载开关介绍

    `从以下几方面详细介绍目前针对USBPD提供的负载开关产品:1. 负载开关产品的规格2.
    发表于 06-03 15:21

    8位MCU P89LPC982 Demo板

    [size=0.83em]8位MCU P89LPC982 Demo板.jpg(72.79 KB, 下载次数: 0)下载附件[color=rgb(153, 153, 153
    发表于 06-12 14:11

    LPC微控制器产品族谱

    。Kinetis与LPC系出同门,双剑合璧,有助于在竞争激烈的MCU战场,开疆扩土,大显神威。本文介绍
    发表于 06-13 11:34

    2018半导体大中华区合作伙伴技术交流会(苏州)

    `半导体在众多半导体产品市场长期位于领先的位置,半导体具有非常丰富的通用MICR产品系列,从
    发表于 06-20 17:26

    i.MX RTxxx系列MCU的特性

      大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是i.MX RTxxx系列MCU的基本特性。  
    发表于 11-04 07:08

    eIQ® Neutron神经处理单元

    的Kinetis MCULPC系列以及最近的MCX产品系列,到我们的i.MX RT跨界MCU和i.MX应用处理器,我们服务的每一个市场领域
    发表于 02-17 13:51

    LPC2200_flash内部Flash和外部Flash分散加载

    LPC2200_flash内部Flash和外部Flash分散加载示例。
    发表于 05-20 16:08 16次下载

    基于NXP LPC系列ARM IAP使用注意事项

    基于NXP LPC系列ARM IAP使用注意事项
    发表于 10-09 10:31 5次下载
    基于NXP <b class='flag-5'>LPC</b><b class='flag-5'>系列</b>ARM <b class='flag-5'>IAP</b>使用注意事项

    HT8 MCU IAP应用须知

    部分 HOLTEK Flash MCU 提供了 IAP 功能,IAP (In-Application Programming) 是在线应用 编程,它可以使用
    发表于 06-26 15:19 1次下载
    HT8 <b class='flag-5'>MCU</b> <b class='flag-5'>IAP</b>应用须知