在HCS08 微控制器上 操作EEPROM 1
0赞
在微控制器应用的很多场合,EEPROM 被用来保存要求掉电仍然保持的数据,包括系统
配置数据、过程数据、测量或运算结果等。虽然HCS08 系列微控制器并不包含片上
EEPROM,然而它所拥有的高性能FLASH 存储器可以方便地实现数据存储功能。在本文
中,提供了 4 个封装好的函数来实现 EEPROM 的模拟功能,屏蔽了复杂的底层操作,可以
很方便地集成到应用程序中去。
HCS08微控制器片上 FLASH的性能
HCS08 的程序存储器为 0.25um工艺FLASH,以 512bytes为一个页组织。表1 给出了
HCS08 片上 FLASH 存储器的大部分特性。
特性 表示符号 最小值 典型值 最大值 单位
内部 FCLK频率 fFCLK 150 200 kHz
内部 FCLK周期 tFcyc 5 6.67 us
字节编程时间(随机地址) tprog 9 tFcyc
字节编程时间(突发模式) tburst 4 tFcyc
页擦除时间 tpage 4,000 tFcyc
全部擦除时间 tmass 20,000 tFcyc
字节编程电流 RIDDBP 4 mA
页擦除电流 RIDDPE 6 mA
编程/擦除寿命 10,000 100,000 次
数据保持时间 tD_ret 15 100 年
表 1:HCS08微控制器片上 FLASH 特性
更快的访问(读取,编程,擦除)速度
HCS08 微控制器片上 FLASH 存储器的编程和擦除操作都以 fFCLK 为基准时钟进行,它
的取值范围在150 kHz 到 200 kHz 之间。假如 fFCLK 被设置为200 kHz,则编程一个字节的时
间为:
9 × (1/200 kHz) = 45 us
使用突发模式编程,每编程一个字节的时间为:
4 × (1/200 kHz) = 20 us
而擦除一页的时间为:
4000 × (1/200 kHz) = 20 ms
全部擦除的时间为:
20000× (1/200 kHz) = 100 ms
更多擦写周期,100,000 次
在室温下,HCS08 片上 FLASH存储器的典型擦写次数为10 万次。在全温度范围内,最
小值为 1万次。另外可以采用数学办法来循环使用 FLASH存储器的一个页面,从而成倍扩
展FLASH 的擦写次数。
内建擦除和编程算法,全工作电压范围内可以工作
HCS08 微控制器的工作电压有两种,分别是1.8V~3.6V和 2.7V~5.5V。由于采用内部的
电荷泵来产生编程电压,绝大部分 HCS08 微控制器的FLASH 存储器都可以在整个工作电压
范围之内完成编程和擦除操作。
FLASH存储器的编程和擦除操作都有由内建的算法逻辑完成,用户程序只要向 FLASH
命令寄存器写入相应的命令即可调用这些算法逻辑。由于编程电压的打开、关闭以及其时序
都由内部算法完成,使得 FLASH 操作变得更加简单和安全。
灵活的 FLASH 块保护功能
灵活的 FLASH块保护功能使得 FLASH 可以按页被保护,被保护的页不会被误擦除或者
误编程。当应用程序中包含 FLASH编程和擦除代码的时候,这种安全性的考虑尤其重要。
以上特点使 EEPROM 的模拟非常方便和可靠。
FLASH控制和状态寄存器
HCS08 微控制器用于FLASH的寄存器一共 6 个。
FLASH Clock Divider Register (FCDIV, 地址 0x1820)
DIVLD: 分频系数写入标志
FCDIV是一个只写一次的寄存器,这一位用来表示自从最近一次复位后,FCDIV 是否已经被写过。复位清除该
位;向FCDIV 第一次写入数据设置该位。
0 – FCDIV从复位后还没有被写过,FLASH的擦除和编程操作被禁止;
1 – FCDIV从复位后已经被写过,FLASH 的擦除和编程操作被使能。
PRDIV8: FCLK预分频选择
0 – 输入到 FLASH Clock分频器的时钟源为总线频率;
1 – 输入到 FLASH Clock分频器的时钟源为总线频率的 1/8。
DIV: FCLK 的分频系数
FCLK可以用下面的公式计算:
FCLK = bus frequency ÷ (8exp( PRDIV8)×(DIV +1))
FLASH Options Register (FOPT和 NVOPT, 地址 0x1821 和 0xFFBF)
复位后,NVOPT 的内容被自动复制到 FOPT。其中的 4 个有效位用于设置 FLASH和
RAM 的安全机制。
KEYEN:后门密钥使能
0 – 后门密钥禁止;
1 – 后门密钥机制使能。如果固件程序向FLASH地址NVBACKKEY~NVBACKKEY7写正确的密钥,则安全机制
被暂时关闭,直到下一次复位。
FNORED:中断向量表重定位使能
0 – 正常中断向量表;
1 – 中断向量表被重新定位。
SEC[1:0]:安全机制选择
这两位用于选择 FLASH和RAM的安全机制。在所有4 种可能的取值中,只有 1:0 禁止安全机制,其它的3 种
取值都启用安全机制。
FLASH Configuration Register (FCNFG,地址 0x1823)
KEYACC:使能后门密钥比较
0 – 向地址 NVBACKKEY的写操作被作为编程或者擦除的开始;
1 – 向地址 NVBACKKEY的写操作被作为比较密钥。
FLASH Protection Register (FPROT和 NVPROT,地址 0x1824 和 0xFFBD)
FPS:FLASH保护选择
当 FPDIS为 0,FPS 的内容为 FLASH 的最后一个不受保护的单元的地址的高7 位。
FPDIS:FLASH保护禁止
0 – 由 FPS设定的地址以后的页面都被保护,无法进行编程和擦除操作;
1 – FLASH保护未打开。
FLASH Status Register (FSTAT,地址 0x1825)
FCBEF:FLASH命令缓冲器为空标志
0 – 命令缓冲器非空,此时不能执行新的命令;
1 – 命令缓冲器为空,可以执行新的突发编程命令。
FCCF:FLASH命令完成标志
0 – 命令执行中;
1 – 命令执行完成。
FPVIOL:FLASH保护冲突标志
0 – 无保护冲突;
1 – 试图编程或者擦除被保护的 FLASH位置。
FACCERR:FLASH 访问错误标志
0 – 无访问错误;
1 – FLASH访问错误。可能的原因有:FDIV 没有初始化之前写 FLASH,在 FCBEF 置位(命令缓冲空)前写
FLASH,在完成前一个命令前重复写一个 FLASH 地址,在完成前一个命令前重复写 FCMD,在写 FLASH地址
时写除FCMD 之外的其它 FLASH 控制寄存器,向 FCMD 写非法的命令编码,在向 FCMD 写命令之后试图访
问(读或写)除 FSTAT 之外的 FLASH控制寄存器,在编程或者擦除命令执行过程中进入休眠模式(命令终
止),在 MCU 被加密时通过背景调试命令写字节编程、突发编程或者页擦除命令,向 FCBEF写0 以取消未执
行完成的命令,等等。
FBLANK:FLASH为空(0xFF)标志
0 – 完成检查空命令后,此标志表示 FLASH单元非空;
1 – 完成检查空命令后,此标志表示 FLASH单元为空。
FLASH Command Register (FCMD,地址 0x1826)
FCMD寄存器用来接收 FLASH 操作命令。合法的命令定义如表 2 所列。
命令 FCMD
检查空 0x05
字节编程 0x20
突发模式字节编程 0x25
页擦除 0x40
全部擦除 0x41
表 2:FCMD命令定义
FLASH操作流程
在 5 种 FLASH操作命令中,全部擦除命令只有调试或者烧录工具才会用到。检查空命
令只在解除加密机制时才能用到。
突发模式字节编程省去了更新目标地址的操作流程,从而可以节省编程时间。在本文的
例程中,暂时没有使用突发模式。如果需要尽可能减少FLASH编程的时间以节约 CPU资
源,或者节省电流,则应采用突发编程模式。
图 1 描述了字节编程和页擦除操作的流程。
图 1:FLASH 字节编程和页擦除流程
需要注意的是,流程中描述的部分操作代码必须在RAM 中运行,因为FLASH 阵列被加
上编程电压后,从中取指是不安全的。在这个API 中,这些代码首先被复制到一个局部变量
的数组中,亦即栈中运行。当编程或擦除程序退出后,栈空间的内容被自动摧毁。下面3 个
静态函数仅供 API 内部使用:
static void flash_byte_prog(unsigned int _addr, unsigned char _data);
static void flash_page_erase(unsigned int _addr);
static unsigned char flash_byte_read(unsigned int _addr);
flash_byte_prog()向 FLASH 的指定地址写入一个字节的数据;flash_page_erase()擦除指定
的一页;而 flash_byte_read()读取 FLASH 指定地址的1 字节数据。
开始
FACCERR?
清除错误标志
向FLASH写入以
缓冲地址和数据
向FCMD写入命令
等待至少4个
总线周期
FCBEF置位,
启动命令
检查错误标志
FACCERR?
FVIOLP?
FCCF?
完成
1
0
错误退出 YES
N
EEPROM模拟的实现
在 API 中,使用了 FLASH的两个单独的页(共 1024 字节)来实现 EEPROM 的模拟。
应用程序必须定义需要的 EEPROM 的长度(以字节为单位)EEPROM_DATA_LEN。
EEPROM 数据被打包为一种简化的定长记录格式,每次写入操作时,首先根据标志
FLAG_CURRENT_PAGE 找出当前页,然后遍历当前页中的已有记录,直到找出下一个空记
录地址,向下一个空的地址写入标志FLAG_RECORD_USED来标志该 N+1 个单元被使用,
然后写入 N字节的用户数据。读取时,首先找出当前页,顺序遍历当前页中的记录的标志字
节,直到找到最后一个记录,然后读取它的数据空间。
图 2:定长记录格式的 EEPROM数据
写入时,如果当前页面剩余的空间不足写入一个新的记录,则新记录被写入另一页,并
且在该页的最后一个单元写入标志 FLAG_CURRENT_PAGE,标志该页为当前页。
图 2:重复使用一页中的空间
这样的实现模型交替使用 FALSH 的两页来保存 EEPROM 数据,并且在每一页中,都交
替使用几乎所有空间,在保证数据可靠性的同时,也有效地延长了 FLASH的擦写周期。此
时的擦写周期取决于 EEPROM 数据长度。
模拟 EEPROM的擦写周期 = ((512 - 1) ÷ (EEPROM_DATA_LEN + 1)) × 100,000 × 2次
HCS08_EEPROM_API函数说明
这个 API 提供给用户 5 个接口函数,可以方便地实现 EEPROM 的模拟,屏蔽了底层的
操作,并且适用于所有HCS08 系列微控制器。在使用这些函数之前,必须定义一些宏。
预定义
• EEPROM_DATA_LEN
0x55 N字节数据
0xAA 剩余的字节单元
0x55 N字节数据
0x55 N字节数据
0x55 N字节数据
……
每页X 个记录
FLAG_RECORD_USED = 0x55
FLAG_CURRENT_PAGE = 0xAA
EEPROM_DATA_LEN = N
PAGE_REUSE_TIMES = X
0x55 N字节数据
FLAG_RECORD_USED = 0x55
EEPROM_DATA_LEN = N
