我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。
老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师:
简单,单纯,喜欢独处,独来独往,不易合同频过着接地气的生活,除了生存温饱问题之外,没有什么过多的欲望,表面看起来很高冷,内心热情,如果你身边有这样灵性的人,一定要好好珍惜他们眼中有神有光,干净,给人感觉很舒服,有超强的感知能力有形的无形的感知力很强,能感知人的内心变化喜欢独处,好静,清静,享受孤独,不打扰别人不喜欢被别人打扰,在自己人世界里做着自己喜欢的事。
时间不知不觉中,来到新的一年。2024结束,2025开始新的忙碌。成年人的我也不知道去哪里渡自己的灵魂,独自敲击一些文字算是对这段时间做一个记录。
一、背景信息
在介绍ECU BootLoader开发组成时,提到了Flash编程程序开发是Bootloader开发的重要一环,本文主要总结一下Flash编程相关的内容和注意点。
1、Flash模块
与其他底层控制驱动开发一样,Flash编程开发也依赖具体芯片的Flash模块,因此在Flash编程前需了解编程芯片Flash模块各寄存器的相关内容。
通常来说,对Flash模块寄存器的操作有模块配置、读写操作、中断处理等。例如MC9S12类芯片FCLKDIV寄存器用于时钟配置,FCCOBHI、FCCOB、FSTAT等寄存器用于读写操作控制, FERCNFG、FERSTAT等寄存器用于中断处理等。
Flash编程开发依赖于特定芯片的Flash模块。因此,在开发之前,必须深入了解目标芯片的Flash模块及其寄存器。这些寄存器通常用于模块配置、读写操作控制以及中断处理等。
寄存器操作
模块配置寄存器:如MC9S12类芯片的FCLKDIV寄存器,用于配置Flash模块的时钟。
读写操作控制寄存器:如FCCOBHI、FCCOB(Flash Command Code Buffer High/Low,Flash命令代码缓冲区高/低)和FSTAT(Flash Status,Flash状态)等,用于控制Flash的读写操作。
中断处理寄存器:如FERCNFG、FERSTAT(Flash Error Configuration/Status,Flash错误配置/状态)等,用于处理Flash操作中的中断。
2、Flash模块配置
Flash模块配置主要完成对Flash模块的时钟配置,一般按芯片用户手册定义的Flash模块时钟工作范围配置时钟分频相关值即可。
但需要注意的是有些芯片需要配置Flash等待周期相关的寄存器,一般在芯片用户手册里有Flash等待周期和时钟频率、电压范围的关系配置说明,相关配置必须符合要求,否则Flash读写操作可能会出错,甚至导致芯片运行死机。
Flash模块的配置主要涉及时钟配置和等待周期配置。
时钟配置
按照芯片用户手册中定义的Flash模块时钟工作范围,配置时钟分频相关值。这是确保Flash模块能够正常工作的基础。
等待周期配置
有些芯片需要配置Flash等待周期相关的寄存器。等待周期的配置与时钟频率和电压范围密切相关。在芯片用户手册中,通常会提供Flash等待周期与这些参数的配置说明。如果配置不当,Flash读写操作可能会出错,甚至导致芯片运行死机。
二、刷写数据
1、Flash数据读取
Flash数据读取一般直接通过地址就可以读取数据。
Flash数据读取操作相对简单,通常只需要通过指定的地址即可直接访问并读取存储在该地址的数据。这种直接访问的方式使得读取Flash数据变得高效且直接。然而,值得注意的是,尽管读取操作看似简单,但在实际应用中仍需考虑数据的完整性和一致性,特别是在多线程或多任务环境下,可能需要采取额外的同步措施来避免数据冲突。
2、Flash数据写入
对于有Flash保护机制的芯片需要先进行Flash解锁操作才可以写入数据,Flash解锁操作每个芯片都不太一样,需要按芯片用户手册操作进行。完成解锁后通过命令写入Flash数据的流程一般为:
-> 1、通过状态寄存器检查Flash状态是否为空闲状态;
-> 2、通过Flash命令操作控制寄存器写入对应命令值来激活Flash编程;
-> 3、通过地址寄存器和数据寄存器写入Flash数据或通过Flash地址直接写入数据,具体芯片操作方式会有差异,但是都需要注意写入的数据字节长度,一般有1、2、4、8等不同的字节长度配置;
-> 4、通过状态寄存器等待写入操作完成并通过状态标志位判断是否成功。
Flash解锁:
对于有Flash保护机制的芯片,在进行数据写入之前,必须先进行解锁操作。这一步骤是为了防止未经授权的写入操作对Flash内容造成破坏。解锁操作的具体流程因芯片而异,通常需要按照芯片用户手册中的指导进行。
检查Flash状态:
在写入数据之前,必须首先通过状态寄存器检查Flash是否处于空闲状态。如果Flash正在执行其他操作(如擦除或编程),则必须等待其完成后再进行写入。
激活Flash编程:
一旦确认Flash处于空闲状态,就可以通过操作控制寄存器来写入对应的命令值,从而激活Flash编程模式。这一步骤是写入数据前的必要准备。
写入数据:
在激活Flash编程模式后,就可以通过地址寄存器和数据寄存器将数据写入Flash。不同芯片在写入数据时的具体操作方式可能会有所不同,但通常都需要注意写入数据的字节长度。常见的字节长度配置包括1字节、2字节、4字节和8字节等。在写入数据时,必须确保数据的长度与芯片的要求相匹配,以避免写入错误。
等待写入完成并检查状态:
写入数据后,必须等待写入操作完成。这通常可以通过轮询状态寄存器来实现。一旦写入操作完成,就可以通过检查状态标志位来判断写入是否成功。如果写入失败,可能需要根据芯片用户手册中的指导进行相应的错误处理。
例如按word类型字节长度进行Flash数据写入的函数大致内容如下,虽然不同芯片寄存器会有差异,但流程差异不大。
byte FlashWriteWord(word address,word data)
{
if(当前Flash无操作)
{
关闭其他中断
ErrorFlag标志位 = 操作Mask; // 清零所有Error标志位
......// 配置相关寄存器,如有些芯片需先写入命令寄存器序列命令寄存器 = 写操作命令值; // 将写操作命令值写入对应的操作命令寄存器Flash地址寄存器 = address; // 将要进行Flash编程的地址写入对应地址寄存器Flash数据寄存器 = data; // 将要进行Flash编程的数据写入对应数据寄存器Status寄存器 = 操作Mask; // 清除Flash操作状态寄存器,有些芯片会同时触发写入操作while (!Status寄存器完成标志位); // 等待以上操作完成 打开其他中断return (FLASH_OK); // 写入操作成功完成
}
else
{return (FLASH_BUSY); // 当前Flash状态忙
}
}