加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

AMI EFI Flash emodule

发布时间:2020-12-15 06:17:20 所属栏目:百科 来源:网络整理
导读:我可爱的多多还没满三个月时,公司就把我招回来干活了。为了能准时下班陪多多,我在上班的前两天拼命的debug呀,终于把M2MTC那个串口的问题解决了。接下来就很闲,闲的发慌的时候就胡思乱想,有一分钟想到了以前phoenix EFI下读写SPI flash的问题,于是决定

我可爱的多多还没满三个月时,公司就把我招回来干活了。为了能准时下班陪多多,我在上班的前两天拼命的debug呀,终于把M2MTC那个串口的问题解决了。接下来就很闲,闲的发慌的时候就胡思乱想,有一分钟想到了以前phoenix EFI下读写SPI flash的问题,于是决定也来研究一下AMI的flash模块。

?

u? 第一只程序—FlashInit

BOOLEAN found = FALSE;

???for(i=0; !found && FlashList[i]; i++)

??? {

???????found=FlashList[i](pBlockAddress,&FlashAPI);

}

FlashList的定义为:IDENTIFY*FlashList[] = {FLASH_LIST NULL};

FlashList是一个指针数组,它在flash.mak里有定义/D"FLASH_LIST=$(FlashList)",这个数组的每一个指针都指向一个函数。由于不同厂家的flash part都可能有不同的opcode,所以每一家的flash part都有一个identify函数,在我们这个案子里,一共支持了4种flash part,我们可以在build生成的token.mak里找到FlashList的实际值。

FlashList = IdentifySst_25VF,

????????????????? IdentifyStm_25PExx,

??????????????? ? IdentifyAtmel_26DF,

????????????? ??? IdentifySst_25LF,

所以FlashList[0]= IdentifySst_25VF

???????FlashList[1]= IdentifyStm_25Pexx

???????FlashList[2]= IdentifyAtmel_26DF

?????? FlashList[3]= IdentifySst_25LF

?????? FlashList[4]=NULL

如果FlashList[0]返回值为true,就表明flash part型号已经找到,否则继续调用FlashList[1],依此类推,直到FlashList[i]全部执行完都没有找到flash part,就可以向全世界公告本机台不支持你这颗flash芯片了。

?

u? 第二只程序—CommonSpiReadId

其实所有的Identify函数都差不多,只是opcode不同而已,这里我们以IdentifySst_25VF为例来研究。这只程序调用到的第一个函数为

CommonSpiReadId( &Sst_25VF,&MfgDevId );

注意Sst_25VF的定义为:

// Flash Part Data Structures

FLASH_INFOSst_25VF =

{? // Write Byte

? {SPI_SST25LF_COMMAND_WRITE,??? SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS},

? // Read Data

? {SPI_SST25LF_COMMAND_READ,???? SPI_OPCODE_TYPE_READ_WITH_ADDRESS},

? // Erase 4k Sector

? {SPI_SST25LF_COMMAND_ERASE,???SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS},

? // Read Device Status Reg

? {SPI_SST25LF_COMMAND_READ_STATUS,SPI_OPCODE_TYPE_READ_NO_ADDRESS},

? // Read device ID

? {SPI_SST25VF_COMMAND_READ_ID,? SPI_OPCODE_TYPE_READ_WITH_ADDRESS},

? // Write Status Register

? {SPI_SST25LF_COMMAND_WRITE_S,??SPI_OPCODE_TYPE_WRITE_NO_ADDRESS},

? // Write Status Enable

? {SPI_SST25LF_COMMAND_WRITE_S_EN,

? // Write Enable

{SPI_SST25LF_COMMAND_WRITE_ENABLE,SPI_OPCODE_TYPE_WRITE_NO_ADDRESS},

? 1,????????????????????????????????? // Page Size

? SECTOR_SIZE_4KB

};

CommonSpiReadId这只程序所做的事情如下:

(1)??????InitializeSpiEnvironment(FlashInfo);??

?????????????? //FlashInfo就是Sst_25VF, SPI BAR=RCBA+0x3020

????????????? 把Sst_25VF里相应的值填到SPI BAR 那边的opcode menu和opcode type里去。

????????????? 注意:write status enable和write enable这两个opcode是填到opcode prefix那边,和其他的read,read ID等命令区别开,以防止flash芯片被恶意擦写。

(2)??????SPI Address填0,然后往SPIcontrol寄存器下命令,opcode index要按照(1)里面SPI_SST25VF_COMMAND_READ_ID所在位置来设置。

(3)??????ID读回来后,根据ID就能判断flash芯片的容量了。使用一个结构体mExFlashPart来记录下容量,ID,还有opcode等信息,

?

?

u? 第三个重点—FLASH_PART FlashAPI

(1)第一只程序FlashInit跑完后,会返回一个类型为FLASH_PART的FlashAPI。

typedef struct _FLASH_PART {

???FLASH_READ_COMMAND?????????????FlashReadCommand;

???FLASH_ERASE_COMMAND????????????FlashEraseCommand;

???FLASH_PROGRAM_COMMAND??????????FlashProgramCommand;

???FLASH_IS_ERASE_COMPLETED???????FlashIsEraseCompleted;

???FLASH_IS_PROGRAM_COMPLETED?????FlashIsProgramCompleted;

???FLASH_BLOCK_WRITE_ENABLE???????FlashBlockWriteEnable;

???FLASH_BLOCK_WRITE_DISABLE??????FlashBlockWriteDisable;

???FLASH_DEVICE_WRITE_ENABLE??????FlashDeviceWriteEnable;

???FLASH_DEVICE_WRITE_DISABLE?? ???FlashDeviceWriteDisable;

???FLASH_VIRTUAL_FIXUP????????????FlashVirtualFixup;

???UINT32?????????????????????????FlashProgramSize;

???UINT32?????????????????????????FlashSectorSize;

???UINT8??????????????????????????*FlashPartNumber;???

} FLASH_PART;

?

(2)上面那个FlashAPI是啥时候被初始化的呢,原来第二只程序IdentifySst_25VF读完ID后,会给FlashAPI赋值,

*FlashStruct = &mCommonSpiFlash;

FLASH_PART mCommonSpiFlash ={

???CommonSpiReadCommand,

???CommonSpiEraseCommand,

???CommonSpiProgramCommand,

???CommonSpiIsEraseCompleted,

??? CommonSpiIsProgramCompleted,

???CommonSpiBlockWriteEnable,

???CommonSpiBlockWriteDisable,

???CommonSpiDeviceWriteEnable,

???CommonSpiDeviceWriteDisable,

???CommonSpiDeviceVirtualFixup,

???1,????????????????????? // defaultvalue,should be changed in Init function

???SECTOR_SIZE_4KB

};

所以实际上FlashAPI -> FlashReadCommand = CommonSpiReadCommand; 等等。。

各位,请注意这里的Common,所谓Common就是通用了,我之所以能通用,是因为CommonSpiReadId里的InitializeSpiEnvironment已经把opcode填好了。不同的flash芯片最大的差异就在于opcode的不同,真希望有一天,这个世界可以和谐到所有的opcode都统一。

?

所以以后的读写擦除程序,你想单干的都必须先做FlashInit。

(1)??????CommonSpiReadCommand

????????????? 很简单,使用SPI_SST25LF_COMMAND_READ命令,一次读一个byte回来,想要多长的数据就读多少次了。

(2)??????CommonSpiEraseCommand

????????????? FlashPart擦除是以一个sector为单位的,大多数sector都是4KB的,也有些是8KB或者64KB。

???????????? 说到sector,我一直在想,它和block到底谁是老大,他们的实际关系如下:

?????????????????????????? 1 Flash = n x FV (Flash Volume)

?????????????????????????? 1 FV = n x Block

?????????????????????????? 1 Block = n x Sector

?????????????????????????? 1 page = n x Sector

??????????????? 擦之前先读一下,如果值已经是全FF,就不必再擦了。

(3)??????CommonSpiProgramCommand

?????????????? 有些flash芯片只支持一次写一个byte,有些可以一次写256个byte。

??????????????下一次命令写一点,写完为止。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读