FEE作用:对底层存储的数据进行抽象,无论是存储在芯片内部的Flash,EEPROM,亦或是外挂的存储单元,上层都可以对其进行统一封装管理。
对于TC297来说,FEE驱动是对其DFlash模块的部分区域(DF_EEPROM)进行模拟EEPROM,共768KBytes空间。
对于AUTOSAR来说,只能通过FEE/FLS驱动进行访问DF_EEPROM区域。
访问流程如下图所示:
- 为了在其中一个FEE扇区被擦除的同时对另一个FEE扇区执行读取或写入操作,首先暂停正在进行的擦除操作,然后执行读/写操作,最后再恢复擦除操作。所以提供了 Fls_17_Pmu_SuspendErase和Fls_17_Pmu_ResumeErase两个API,同时在FLS模块配置的时候,还会配置延迟的时间。
- FEE模块没有中断,但是如果FLS模块设置了中断,那么当FLS驱动的JOB完成时,FEE模块的回调函数Fee_JobEndNotification和Fee_JobErrorNotification将会被FLS驱动的ISR(中断服务程序)调用。
TC297的双扇区存储
- TC297 Sector划分
TC297并没有遵循Autosar 关于FEE与FLS地址之间的映射关系。而是使用双扇区算法:将768KBytes的DF_EEPROM空间分为两个扇区(sector),每一个sector 384KBytes。如下图所示:
-
Sector组成:
一个sector包含两种类型的page,分别是data page,state page。data page用于存储数据,state page用于存储FEE Sector的状态(i.e. Valid/Erased). -
双扇区算法存储过程:
1、FEE会先获取两个Sector的状态,假设Sector1状态为“Actived“, Sector2状态为“Not Actived”;
2、先往Sector1存数据;
3、当Sector1存满后,把Sector1中的各个Block的最新数据copy到Sector2,同时将Sector2状态置为“Actived”;
4、将Sector1里的数据全部擦除,同时将Sector1的状态置为“Not Actived”;
5、新到的数据就依次存到Sector2;
6、当Sector2存满后,再将Sector2中各个Block的最新数据copy到Sector1;同时将Sector1状态置为“Actived”;
7、擦除Sector2里的数据,同时将Sector2的状态置为“Not Actived”;
8、如此循环往复;
-----------------------------------------------分----割----线------------------------------------------------
Garbage Collection
英飞凌将两个扇区之间的数据copy称为garbage collection (GC),过程如下:
1、将所需的数据从filled sector copy到new sector;
2、将new sector的state page状态改为”VALID“;(此步骤标志着Copy过程完成);
3、擦除filled sector;
4、验证是否擦除干净(wordlines),同时将filled sector中的state page状态置为”ERASED“(此步骤标志着擦除过程结束)。
-
InitGC步骤:
1、确定active sector和GC的恢复点;
2、如果需要,修复/重写脏状态页;
3、如果需要,擦除和/或准备DFLASH;
4、恢复GC(如果需要); -
遍历active sector;
1、找到data block的最新状态信息;
2、对data block进行数据一致性校验;
3、对data block中的数据进行copy;
4、data block中的数据以及数据copy都被存到指向缓存区域的表里面;
这一过程称做“缓存更新”或者“缓存建立”;
上述步骤完成后,才能进行read/write/invalid操作;
触发GC的条件:用户的write/invalid请求超出了当前sector的存储边界;
对于wordline的操作规则:
- 在同一个wordline里,如果空闲的page能够满足当前请求的block所需要的page数量,则从wordline里面的一个新的page开始写这个block;
- 如果空闲的page不够,从新的wordline去写。
Unconfigured blocks:
存在与DF_EEPROM中,但未被FEE block配置的block集合。
FEE驱动校验data block时,是按照wordline为单位进行校验;
当需要写新的block时,会先把这个wordline中之前block都copy到RAM中,然后才执行写新block的操作。
如果校验失败,FEE会从下一个新的wordline开始先写校验失败的block,然后再写新的block。
如果校验再次失败,则会报错,FEE驱动将会进入FAIL 状态,此时需要用户重新reset控制器,以便重新初始化FEE驱动模块;
关于GC的disbale/enable特征:
在ECU做after run的时候,往往需要往Flash里面存数据,此时如果启用了GC功能,那么有可能会出现两种情况:1、控制器延迟下电;2、GC执行失败;因此,通常情况下,会在after run之前将GC start disable掉,这样保证ECU正常下电;
-
这就涉及到何时开始进行Sector之间的copy(GC);
AutoSar中有一个FeeThresholdValue可供配置,表示距离FEE sector末端的字节空间。阈值空间有下列3部分组成:
1、所有配置为immediate block的空间大小之和;
2、最大的immediate blokc的空间大小;
3、512 bytes (1个wordline的大小); -
一个page可以存储7个data bytes。需要额外2个page(16bytes)来存储FEE 内部的management block data.
eg:如果一个block的大小为28bytes。那么需要占用的存储空间为:4+2 = 6 pages = 48 bytes。
如果一个block的大小为30bytes,那么需要占用的存储空间为:5+2 pages = 7 pages = 56 bytes。
假设目前有如下4个block:
Block 1 – Normal block of size 50 bytes
Block 2 – Normal block of size 60 bytes
Block 3 – Immediate block of size 28 bytes
Block 4 – Immediate block of size 30 bytes
那么需要考虑的只有imme block:
Block 3 ,需要48 bytes
Block 4 ,需要56bytes
因此最小的阈值空间为:48+56+56+512=672 bytes.
几个疑问:
1、为何要再加一个最大的block的空间大小?
答: 因为如果恰巧一个wordline中的剩余空间比最大的blockpage数小,则这个wordline中剩余的page都浪费掉了,需要从下一个新的wordline开始写;
2、为何要增加一个wordline(512kbytes)?
答:因为FEE在写新的block之前,会将这个wordline中之前所有的block都copy到RAM中进行校验,如果校验不通过,则会从一个新的wordline开始写校验不过的block。
-
调用Fee_17_DisableGcStart API可以将GC disable掉。
1、如果disable掉GC,那么immediate属性的write/invalid操作会继续执行,直至将当前sector空间填满;后面的write/invalid请求会被pending,直到重新恢复GC;
2、如果disable掉GC,normal属性的write/invalid请求会被pending,直到GC恢复。
3、假如用户想立刻写入数据,则需要先调用Fee_Cancel,然后将write的属性置为immediate. -
触发GC的条件:
1、调用Fee_17_EnableGcStart;
2、ECU重新上电后,初始化FEE driver,GC-Start会默认enable;并且会在第一次write/invalid请求后被触发。
FEE模块write 请求:
-
FEE的一些非法状态:
1、两个state page的状态一样,比如都是valid; 此时可以通过全部擦除DF_EEPROM来解决该问题;
2、FEE检测到DF_EEPROM全为0x00; 如果此时的配置为:FeeVirginFlashIllegalState = True;
FeeEraseAllEnable = False;
3、GC过程中,由于硬件错误导致erase/copy(write,read)错误;比如不能执行EraseAll操作等;
4、GC copy过程中,数据校验错误> 1 failure per block;
5、write操作过程中,之前的block校验出现错误 > 1 failure;
6、底层FLS驱动调用Fee_17_IllegalStateNotification;
FEE出现上述非法状态时,建议重启ECU; -
Write请求中断;
1、如果block写了一半发生了reset,则会记录在data block的missing marker page中,然后这个写了一半的block被会全部忽略掉,该block的信息以上一次完整的状态信息为准。