首页 > 其他分享 >痞子衡嵌入式:恩智浦经典LPC系列MCU内部Flash IAP驱动入门

痞子衡嵌入式:恩智浦经典LPC系列MCU内部Flash IAP驱动入门

时间:2023-04-18 19:02:40浏览次数:46  
标签:Sector 恩智浦 Flash 写入 uint32 擦除 MCU IAP


  大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是恩智浦经典LPC系列MCU内部Flash IAP驱动

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

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

三、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 文件里有如下专门宏:

/* @brief Pointer to ROM IAP entry functions */
#define FSL_FEATURE_SYSCON_IAP_ENTRY_LOCATION (0x0F001FF1)

痞子衡嵌入式:恩智浦经典LPC系列MCU内部Flash IAP驱动入门_Memory

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

unsigned int command_param[5];
unsigned int status_result[5];

typedef void (*IAP)(unsigned int [],unsigned int[]);
#define IAP_LOCATION *(volatile unsigned int *)(0x0F001FF1)
IAP iap_entry=(IAP) IAP_LOCATION;

iap_entry (command_param,status_result);

痞子衡嵌入式:恩智浦经典LPC系列MCU内部Flash IAP驱动入门_Memory_02

四、LPC Flash IAP驱动快速上手

  最后看一下官方驱动 \SDK_2_13_0_LPCXpresso845MAX\devices\LPC845\drivers\fsl_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 访问时间
void IAP_ConfigAccessFlashTime(uint32_t accessTime);
// 进入 ROM IAP 的入口函数
static inline void iap_entry(uint32_t *cmd_param, uint32_t *status_result);
// 擦除和写入前准备函数
status_t IAP_PrepareSectorForWrite(uint32_t startSector, uint32_t endSector);
// 擦除函数,按 Page/Sector 为单位
status_t IAP_ErasePage(uint32_t startPage, uint32_t endPage, uint32_t systemCoreClock);
status_t IAP_EraseSector(uint32_t startSector, uint32_t endSector, uint32_t systemCoreClock);
// 写入函数,长度最大限定为一个 Sector
status_t IAP_CopyRamToFlash(uint32_t dstAddr, uint32_t *srcAddr, uint32_t numOfBytes, uint32_t systemCoreClock);

  至此,恩智浦经典LPC系列MCU内部Flash IAP驱动入门痞子衡便介绍完毕了,掌声在哪里~~~

欢迎订阅

微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。

痞子衡嵌入式:恩智浦经典LPC系列MCU内部Flash IAP驱动入门_API_03

  最后欢迎关注痞子衡个人微信公众号【痞子衡嵌入式】,一个专注嵌入式技术的公众号,跟着痞子衡一起玩转嵌入式。


痞子衡嵌入式:恩智浦经典LPC系列MCU内部Flash IAP驱动入门_LPC_04

痞子衡嵌入式:恩智浦经典LPC系列MCU内部Flash IAP驱动入门_LPC_05

痞子衡嵌入式:恩智浦经典LPC系列MCU内部Flash IAP驱动入门_API_06


  衡杰(痞子衡),目前就职于某知名外企半导体公司MCU系统部门,担任嵌入式系统应用工程师。

  关于专栏文章有任何疑问请直接在博客下面留言,痞子衡会及时回复免费(划重点)答疑。




标签:Sector,恩智浦,Flash,写入,uint32,擦除,MCU,IAP
From: https://blog.51cto.com/henjay724/6203990

相关文章

  • 关于将常量数组或某一函数单独或一起放在FLASH某一位置
    第一种情况:将数组或某一函数单独放在FLASH某个位置,具体配置如下图。.text1:{.=ALIGN(4);*(.text1)*(.text1.*).=ALIGN(4);}>FLASH1AT>FLASH1__attribute__((section(".text1")))voidCPUDelay(volatileuint32_t......
  • 停用flash的rtmfp 【禁止flash的udp上传】
    以XP为例,找到C:\WINDOWS\system32\Macromed\Flash\mms.cfg。当然你也可以直接搜索mms.cfg 在里面添加这段红色字体。  RTMFPP2PDisable=1  意味关闭flash的rtmfp。如果没有,可以手动添加。也可以新建bat文件,复制以下代码。1.echoon2.pause3.echoRTMFPP2PDisable=......
  • access violation at address isflash.dll
    右击“我的电脑”。单击“属性”。 在“系统属性”中单击“高级”。 在“性能”中单击“设置”。 在“性能选项”中单击“数据执行保护”。 单击“添加”。选择要运行的程序。 OK。就这么简单。 ......
  • 使用flash id查看SSD颗粒
    参考常见SSD固态硬盘不拆盘判断颗粒的办法_固态硬盘_什么值得买读懂固态硬盘中的“黑话”-简易百科先需要知道自己的主控是什么,常见的是这些Phison=群联SMI=慧荣Marvel=美满电子(马牌主控)Maxio=联芸Yeestor(SiliconGo)utility=得一微我一般的猜测顺序......
  • CPU, mpu mcu soc 的区别
      从它们的名字上看以及 从网上的资料上看,我觉得他们没有任何的区别。都是指的处理单元。但是在实际使用中,人们形成了约定俗称的叫法。比如: mcu :指的是单片机,芯片包含了ramflash以及外设接口。mpu:指的是cortexA系列,包含了cpu,以及外设接口,但是......
  • 高通总裁来中国公关了,不知道能否加速恩智浦收购案获批?
    据路透北京称,高通(Qualcomm)将于本周在北京和中国反垄断监管部门会谈,力争440亿美元收购恩智浦半导体(NXPSemiconductors)的计划获得通过。对高通来说,这次收购如若成功,有助于高通在无人驾驶及人工智能领域快速发展。之前,4月16日,美国芯片制造商高通公司向中国商务部重新提交申请,以批......
  • js:浏览器跨域ajax变通实现 -- flash + js + crossdomain.xml
    使用此方式能很好解决这个问题,因为考虑了php中转形式的双倍时间和莫须有的访问,不是很愿意用,除非不得已,现在找到flash的实现方法,对于能自按的服务器来说这是不错的解决方案,只需要担心的是有人不愿意安装flash控件,且能解决script方式的不能post不足,除非浏览器已经统一支持跨......
  • 关于纯净Flash无法打开4399游戏解决办法
    纯净Flash安装完成后,进行此操作:在设置->默认浏览器里面找IE兼容。把“让InternetExplorer在MicrosoftEdge中打开网站”调成“始终”->把“允许在InternetExplorer模式下重新加载网站(IE模式)”调成“允许”再重启网页。一、打开设置1、找到设置【操作】在浏览器右......
  • VisionMobile:Flash的死亡-8年前埋下的祸根
    说明:文章并非全文逐句翻译,为了加快速度,进行了概括,详细可阅读ThedeathofFlash–8yearsinthemaking。2011年11月,Adobe宣布停止为移动浏览器开发FlashPlayer。一时坊间众说纷纭,文章认为移动Flash的失败是因为Adobe无法跟随iphone脚步,但种子多年前已埋下。HTML5didnotki......
  • 基于AHB_BUS的eFlash控制器的Datasheet
    eFlash控制器的Datasheet硬件和软件交互的文档,提供Datasheet1.eFlash控制器功能列表eFlash存储控制器一局软件要求完成写擦操作,其提供系统boot时的命令数据,并在main区(存储器分为Main和Infrarea)存放各个IP模块工作所需要的命令数据.一般情况下,系统只对其进行读操作,除非......