《AVR105 高效持久保存参数到 Flash》由会员分享,可在线阅读,更多相关《AVR105 高效持久保存参数到 Flash(15页珍藏版)》请在金锄头文库上搜索。
1、.AVR105:高效持久保存参数到Flash翻译:邵子扬2006年8月31日http:/1 特点l 快速存储参数l 高持久性存储350K次写循环l 高效参数存储l 任意参数大小l 参数冗余存储l 可选写入验证l 电源失效后优化恢复2 介绍3 嵌入式系统在复位或掉电后依赖于保存的参数。在一些系统这个静态的参数用于初始化系统,在另外一些应用下用于记录系统的历史数据或累计数据。EEPROM存储器可以用于这个目的,但是当一次要保存多个字节时就难以匹配Flash存储器的速度。Flash存储器对于大量参数更有效率的原因是可以使用页编程,减少了编程时间。这样在存储多个字节时对于Flash每个字节的编程时间就
2、比EEPROM少。作为快速存储法的直接结果就是电源消耗可以减少,因为更多的时间可以进入休眠模式。这篇应用笔记说明了使用AVR的自编程特性来高效参数保存的方法。利用整个Flash页和类似于环形缓冲区的方法,Flash页的每个存储器单元的写入次数不像只使用一个单元那么频繁,这增加了存储器的使用次数,保证存储区不会被“耗尽”。存储器的使用次数与参数大小和分配页面大小成正比。理论3.1 AVR单片机的megaAVR系列有个特性叫做“自编程”,这个特点使得AVR可以再次编程内部的Flash存储器。所有AVR单片机的程序存储器都可以用于存储常数,现在也可以存储参数,因为能够在运行时修改Flash存储器的内
3、容。使用Flash存储器存储参数不像使用EEPROM接口那样简单,自编程的目的主要是为了用于固件程序升级,但是其灵活性也允许用于更新Flash中的参数。这一小节说明了Flash存储器关于使用内部存储器保存参数的基本资料。Read-While-WriteFlashFlash存储器可以用SPM指令再次编程。SPM指令只能从Boot区运行,从应用程序区执行SPM指令将没有任何效果。应用程序区的范围是从地址0x0000直到Boot区的起始地址(如图1)。Boot区可以选择4个不同的大小,它由熔丝位来决定。Boot大小与使用的AVR单片机型号有关。图1.ATmega128的应用程序区和Boot区存储器映
4、射3.2 Boot区总是在No-Read-While-Write(NRWW)区,应用程序区包括了Read-While-Write(RWW)区以及NRWW区的一部分。当Boot区的大小选择为最大时,它占用了整个的NRWW区,这时应用程序区就只包含了RWW区。NRWW和RWW是固定的,不受Boot区大小的影响。参考芯片的数据手册获得更详细的资料(注:也可以参考AVR109自编程,这篇应用笔记已经翻译过了)。NRWW和RWW区的不同在于当擦除或写入RWW区时,AVR单片机可以继续执行位于NRWW区的程序代码。反过来则不行的:AVR内核在修改NRWW区时被暂停。概括的讲,位于Boot区的代码可以在程序
5、区编程时执行,这里假设被程序区修改的页面在RWW中。因此,Flash参数更新的代码必须位于Boot区,而Flash参数必须在程序区的RWW部分。这要求在写入参数时不能禁止中断。擦除和编程Flash单元3.3 Flash存储器由独立的位单元组成,Flash单元基于浮动门晶体管工艺:一个电荷“捕捉”晶体管门电路决定Flash单元读取的逻辑电平。Flash的工作方式可以简单的描述为:当“擦除”一个单元时,对门进行充电,单元读取为逻辑1。“编程”Flash等于对门电路放电,使逻辑变为0。只能编程(放电)一个已经擦除过(充电)的单元。Flash以页的形式组织,当使用自编程擦除和编程时也是以页方式进行的。
6、注意位可以单独编程,因为位编程就是放电,没有被编程的位仍然保持电荷,任何没有被编程的位可以在以后进行编程。如果在编程一个字节前不先进行擦除,其结果就是旧参数和新参数的与。例如写参数0x01到一个Flash字节需要先擦除该字节(8个Flash单元),使其变为0xFF。写入参数时,7个高位(Flash单元)被放电。如果Flash没有被预先擦除,结果很可能是不正确的:假设原来的参数是0xFE,并且要编程的新参数为0x01,编程的结果将是0x00,因为LSB不能从0变为1。Flash编程次数实际上一个参数(1)可以存储多次到一个Flash页,Flash单元保证可以承受10,000次擦除/写入循环。就是
7、说,每个单元可以擦除并编程10,000次。因此,如果一个参数可以在一个页面的不同位置写入10次,那么总次数可以认为是100,000次。注意:3.4 这里的“参数”既可以是一个单独的参数,也可以是一组参数。“参数”可以看做一系列任意大小的数据。写入时间当写入EEPROM时,一次写入一个字节,使用Flash就不是这样因为可以用页编程方式,这对于多个字节参数存储时是一个优势。参数越多,每个字节编程的时间越短。写入一个long(4字节)类型的参数到Flash大约是4ms(不包括擦除时间,耗时基本相同),平均一个字节1ms。作为比较,写入相同参数到EEPROM(1)大约是32ms,这里包括了EEPROM
8、的擦除时间,但比较是公平的,因为Flash只在所有单元都被用完后才擦除。以ATmega128为例:页大小是256字节,可以存储一个long类型的变量256/4=64次。擦除时间平均到64次写入中,就是4ms除以64,就已经非常小了。结论是多个参数的存储使用Flash在写入时间上更有效率更多时间可以进入休眠模式,节约电能。注:3.4.1 这里以ATmega128为例,具体的EEPROM编程时间与芯片有关请参考芯片的数据手册。Flash写访问限制3.5 Flash和EEPROM共享擦除和编程模块,结果就是EEPROM和Flash不能同时写入(或擦除)。这也意味着在使用自编程来修改程序存储器时,需要
9、先检测是否正在进行EEPROM写入。如果是EEPROM正在写入,必须等待EEPROM写完成。反过来也一样,EEPROM也需要等Flash写入完成。Flash数据保存时间可编程存储器中数据正确保存的时间称为数据保存时间(或数据保持能力)。存储器不能无限保存数据的原因是存储器单元存在泄露,这意味着单元中存储的电荷会逐渐减弱,直到不再表现出应有的逻辑电平。擦除或编程单元都会朝向不确定状态。如果超过了数据保存时间,其内容将变得不再可靠。3.5.1 擦除和写入减少数据保存时间3.6 当擦除和写入Flash单元时,是有损伤的,而读取操作不会影响数据保存时间。随着擦除/写入周期次数的增加,Flash单元的泄
10、露也随之增加。结果就是电荷快速减弱,数据很快变得无效换句话说,数据保存时间就会减少。如果擦除/写入周期次数超过10K次,数据保存时间就会低于预期的20年。和参数保存到Flash相关联,知道Flash页是相互独立的非常重要;如果一个Flash页用于保存参数,这个页将会减少数据保存时间,而Flash其余部分,用于保存代码,不会受到参数页的影响而减少数据保存时间。掉电考虑3.7 一个必须考虑的问题是任何嵌入式系统都可能遇到电源失效,这也是使用非易失存储器保存参数的原因:这样可以在电源正常后恢复参数。有许多方法来验证参数被正确写入,首选是根据时间和代码空间来验证。一个安全方法是使用很少的存储器空间和时
11、间,保存写完成标志到一个静态存储器位置,这个标志可以用于在电源恢复后判断上次写入是否正常完成,如果没有就需要采取适当的操作。考虑关于避免类似于EEPROM错误那样的Flash故障(参考AVR数据手册关于避免EEPROM错误部分)。为了避免Flash因为电源失效引起的写入故障,在使用自编程时推荐总是允许低压检测功能。使用自编程详细关于自编程的内容可以在器件的数据手册中找到,以及在应用笔记“AVR109:自编程”中。注意到Flash写操作不会被外部复位或Brown-out复位中止是很重要的。只有上电复位才会中止Flash写操作,其结果就是写操作将尽可能长的执行,即使供电电压低于要求的最低低压。这不
12、会引起数据损坏这个特点增加了Flash页写入/擦除完成的可能。4 执行Flash参数存储的例子使用了IAREWAVR2.27b编译器。它也能用于其他编译器,但是可能需要一些修改,因为例子代码中使用了一些IAR内部函数。例子的目的是创建可以快速存储多字节参数的驱动以及获得参数长久保存。存储的持久性与参数的大小和Flash页大小有关,在例子中存储一个7字节的结构体参数到ATmega128。页大小是256字节,一页可以保存35个参数,包括了写入完成标志。那么存储的次数可以按如下方式计算:总次数=单元次数*个数=10,000*35=350,000一般情况下数据保存次数要大于最低保存次数,可以预计比最低
13、次数增加10倍即数百万次参数更新。此外,放置参数到存储器的RWW区可以使电源消耗达到最小。因为在更新参数时代码可以在NRWW区继续运行,节约了时间。代码使得中断可以继续操作以及在RWW区中断驱动代码能继续执行。4.1 选项为了获得更可靠的存储方法,需要“允许”使用写完成标志。如果使用了此标志,参数写入和参数位置标志(也就是写完成标志)将分为两个写操作,这样可以通过写完成标志判断参数被正确存储。不过,和用一个操作就储存它们相比分别存储参数和写完成标志将花费两倍的时间。为了增加安全性,在擦除参数页时参数临时存储到EEPROM。这是为了防止在擦除操作和写操作之间电源失效造成丢失参数。如果发生了电源失
14、效,参数可以从EEPROM中恢复并编程到参数页中。这些功能由FlashStorageDriver.c控制,默认情况下是允许的。4.2 需求例子使用了ATmega128,因此适合于同样内存大小的芯片。如果用在其它型号上,命令链接文件和FlashStorageDriver.c文件中芯片的参数需要被修改。4.3 固件说明驱动由3个函数组成:它们在下面用流程图(图2、3、4)说明。4.3.1 FlashStorageInit4.3.2 Flash存储器的初始化就是检查Flash存储器的状态。如果参数存储在临时EEPROM(根据EEPROM备份有效标志),参数将被恢复并复制到Flash存储器。否则Fla
15、sh缓冲区最后使用的位置将从索引标志中进行识别。图2.Flash存储初始化FlashStorageWrite参数存储程序先检查EEPROM是否正在访问。如果是,程序就禁止EEPROM中断并等待访问结束。如果参数页被填满,参数首先存储到EEPROM,然后擦除参数页。当EEPROM保存参数时,设置EEPROM备份有效标志。一旦擦除结束,参数写入到参数页并清除EEPROM备份有效标志。写入参数到参数页后,相应的参数索引位也被清除,这个方法可以在初始化时判断参数是否有效。最后,EEPROM中断被恢复到初始状态。除了上面列表外,存储器的RWW区访问控制使得在函数返回时可以允许存储器读取。图3.Flash存储写入过程4.3.3 FlashStorageRead应用程序不能直接读取Flash中参数,因为程序不知道参数的当前位置,因此用一个专门的函数用来读取参数。函数首先判断是否可以读取参数(SPM指令没有执行),然后读取并返回参数。5 图4.Flash存储读过程参考文献列表1. AVR带有自编程功能的芯片数据手册,在Atmel网站上。应用笔记“AVR109自编程”,在Atmel网站上。(全文完).8