主页 > 互联网 > 内容页

世界简讯:开放NAND闪存接口ONFI介绍

2023-06-21 10:00:45 来源:嵌入式Lee

本文转自公众号,欢迎关注

开放NAND闪存接口ONFI介绍 (qq.com)

一.前言

ONFI即 Open NAND Flash Interface,开放NAND闪存接口.是一个由100多家制造、设计或启用NAND闪存的公司组成的行业工作组,主要是Intel和镁光。致力于简化NAND闪存集成到消费电子产品、计算平台和任何其他需要固态大容量存储的应用程序中。为NAND闪存定义标准化的组件级接口规范以及连接器和模块外形规格。使用开放接口标准加强了来自不同供应商的NAND设备的兼容性和互操作性。这增加了标准器件的供应基础,缩短了设计时间并加快了上市时间。


【资料图】

从软件的角度,主要是读取符合ONFI标准的参数,比如容量等信息,用以做驱动代码的兼容性设计。这部分信息一般放置在指定的参数PAGE中,描述芯片组织、功能、时序和其他行为参数的数据结构。

以下基于GD5F1GQ5xExxG详细介绍ONFI的参数页。

二.读取参数页

参考《GD5F1GQ5xExxG DATASHEET》的8.11 ReadParameter Page (P27)

参数PAGE至少有三份参数副本存储在设备中,读PAGE到Cache(13h) 之后,从Cache读(03H/0BH)命令可用于读指定的数据,可以一次只读一份,如果校验错误再偏移读下一份。

操作过程如下:

1.配置B0寄存器的OTP_EN位为1

2.然后回读确认B0寄存器的OTP_EN位置1

3.使用(13h)指令加载地址24’h000004的PAGE到Cache中

4.读C0寄存器,等待OIP为0表示操作完

5.使用(03H/0BH)命令从Cache中读出指定数据。

如下是使用逻辑分析仪抓取的一次完整的操作

(1)先读B0寄存器,设置OTP_EN位为1(bit6), 然后回读确认OTP_EN置位

(2)使用(13h)指令加载地址24’h000004的PAGE到Cache中,第一次读C0寄存器为0x01即OIP=1还未完成,然后后面继续读OIP变为了0表示完成。

(3)03H指令读取整个PAGE的数据,可以看到256字节就重复了。

可以看到256字节重复了8遍,刚好2KB,最后还有128B的Spare区域

三.参数页数据结构

Byte

O/M

Description

3.3V/1.8V

实际值(数据小端模式)

0-3

M

Parameter page signatureByte 0: 4FH, “O”Byte 1: 4EH, “N”Byte 2: 46H, “F”Byte 3: 49H, “I”

4FH4EH46H49H

“ONFI”

4-5

M

Revision number0-15 Reserved (0)

00H00H

6-7

M

Features supported0-15 Reserved (0)

00H00H

8-9

M

Reserved (0)

00H00H

10-31

Reserved (0)

00H…00H

Manufacturer Information block

32-43

M

Device manufacturer (12 ASCII characters)“GIGADEVICE ”

47H49H47H41H44H45H56H49H43H45H20H20H

“GIGADEVICE ”

44-63

M

Device model (20 ASCII characters)

“GD5F1GQ5U”x4 2.7v ~ 3.6v

“GD5F1GQ5R”x4 1.7v ~ 2.0v

47H44H35H46H31H47H51H35H55H/52H20H20H20H20H20H20H

20H

20H

20H

20H

20H

“GD5F1GQ5R”

64

M

JEDEC manufacturer ID“C8”

C8H

C8

65-66

O

Date code

00H00H

67-79

Reserved

00H00H00H

Memory organization block

80-83

M

Number of data bytes per page

00H08H00H00H

PAGE数据大小

0x00000800=2KB

84-85

M

Number of spare bytes per page

80H00H

PAGE的SPARE区域大小0x0080=128字节

86-89

M

Number of data bytes per partial page

00H02H00H00H

分页大小0x0200=512字节

即一个PAGE分为4个小页

90-91

M

Number of spare bytes per partial page

20H00H

每个分页SPARE区域大小0x0020=32字节

92-95

M

Number of pages per block

40H00H00H00H

每个块的PAGE数0x00000040=64块

96-99

M

Number of blocks per logical unit (LUN)

00H04H00H00H

每个逻辑单元的块数0x00000400=1024个

100

M

Number of logical units (LUNs)

01H

逻辑单元数1

101

M

Reserved

00H

102

M

Number of bits per cell

01H

每个存储单元的位数1,即SLC

103-104

M

Bad blocks maximum

14H00H

最大坏块数20

105-106

M

Block endurance

01H05H

耐久性0x0501 (指的什么待查)

107

M

Guaranteed valid blocks at beginning of target

01H

保证存储开始的该块数在生命周期是有效的

108-109

M

Block endurance for guaranteed valid blocks

00H00H

保证有效区块的耐久性

110

M

Number of programs per page

04H

每页有4个可编程小页

111

M

Partial programming attributes5-7 Reserved4 1 = partial page layout is partial page data followed by partial page spare1-3 Reserved0 1 = partial page programming has constraints

00H

部分页面编程无约束

小页连续放一起,SPARE区域连续放一起。

112

M

Number of bits ECC correctability

00H

113

M

Number of interleaved address bits4-7 Reserved (0)0-3 Number of interleaved address bits

00H

114

O

Interleaved operation attributes4-7 Reserved (0)3 Address restrictions for program cache2 1 = program cache supported1 1 = no block address restrictions0 Overlapped / concurrent interleaving support

00H

115-127

Reserved

00H…00H

Electrical parameters block

128

M

I/O capacitance

08H

129-130

M

IO clock support

00H00H

131-132

O

Reserved (0)

00H00H

133-134

M

tPROG Maximum page program time (us)

58H02H

135-136

M

tBERS Maximum block erase time (us)

10H27H

137-138

M

tR Maximum page read time (us)

3CH00H

139-140

M

Reserved

00H00H

141-163

Reserved

00H

Vendor block

164-165

M

Vendor specificRevision number

00H

166-253

Vendor specific

00H

254-255

M

Integrity CRC

Set on test

0x3E80

Redundant parameter pages

256-511

M

Value of bytes 0-255

512-767

M

Value of bytes 0-255

768+

O

Additional redundant parameter pages

校验值如下

Device Model

ORGANIZATION

VCC RANGE

CRC value B254/B255

“GD5F1GQ5UxxG”

X4

2.7v ~ 3.6v

58H/F3H

“GD5F1GQ5RxxG”

X4

1.7v ~ 2.0v

80H/3EH

其中1.“O”代表可选,“M”代表强制

完整性CRC(循环冗余检查)字段用于验证参数页面的内容是否已正确传输到主机。有关详细信息,请参阅ONFI 1.0规范。CRC应使用以下16位生成器多项式计算:G(X)=X^16+X^15+X^2+1,此十六进制多项式可表示为8005h

CRC值应在计算开始前用4F4Eh的值进行初始化。在计算出最终CRC值之后,没有对其应用XOR。不存在数据字节或CRC计算值的反转。

四.关键代码

读参数页的主要流程,相关底层接口这里不再贴出

int nand_read_param_page(uint8_t* buffer, uint16_t start, uint16_t len){    int res = 0;    /*  设置OTP_EN =  1 */     res = nand_set_otp(NAND_B_OPT_ACCESS,NAND_REG_RETRY);    if(res == 0)    {        /* 加载数据到Cache */        res = nand_read_page_to_cache(NAND_PARAM_PAGE_ADDR,NAND_PAGE_TO_CACHE_RETRY);        if(res == 0)        {            /* 从Cache读数据 */            res = nand_read_from_cache(start,  len, buffer);            if(res == 0)            {                /* 成功 */            }            else            {                res = -3;            }        }        else        {            return -2;        }    }    else    {        res = -1;    }    /* 切回正常模式 */    nand_set_otp(NAND_B_OPT_NORMAL,NAND_REG_RETRY);    return res;}
五.uCFS的NAND FTL中使用ONFI

fs_dev_nand_part_onfi.c

fs_dev_nand_part_onfi.h

函数FS_NAND_PartONFI_ParamPageParse根据参数页解释参数到FS_NAND_PART_DATA结构体

/***********************************************************************************************************                                   FS_NAND_PartONFI_ParamPageParse()** Description : Parse the ONFI parameter page.** Argument(s) : p_part_data     Pointer to a NAND part data object.*               -----------     Argument validated by caller.**               p_err           Pointer to variable that will receive return the error code from this function :*               -----           Argument validated by caller.**                                   FS_ERR_DEV_NAND_ONFI_INVALID_PARAM_PAGE     Invalid parameter page.*                                   FS_ERR_DEV_NAND_ONFI_VER_NOT_SUPPORTED      ONFI version not supported.*                                   FS_ERR_NONE                                 Parameter page parsed successfully.** Return(s)   : none.** Note(s)     : none.**********************************************************************************************************/static  void  FS_NAND_PartONFI_ParamPageParse (FS_NAND_PART_DATA  *p_part_data,                                               FS_ERR             *p_err){    CPU_BOOLEAN  is_ver_supported;    CPU_BOOLEAN  has_ext_pp;    CPU_BOOLEAN  is_bus_16;    CPU_BOOLEAN  is_invalid;    CPU_INT08U   value;    CPU_INT08U   multiplier;    CPU_INT08U   lun_nbr;    CPU_INT16U   version;    CPU_INT32U   pg_size;    CPU_INT32U   max_size;    CPU_INT32U   nb_pg_per_blk;    CPU_INT32U   blk_cnt;    CPU_INT64U   max_blk_erase;    CPU_DATA     ix;   *p_err = FS_ERR_NONE;                                                                /* -------------- REV INFO AND FEATURES --------------- */                                                                /* Validate ONFI version.                               */    MEM_VAL_COPY_GET_INT16U_LITTLE(&version, &FS_NAND_PartONFI_ParamPg[4]);    is_invalid = DEF_BIT_IS_SET(version, DEF_BIT_00);    if (is_invalid == DEF_YES) {       *p_err = FS_ERR_DEV_INVALID;        return;    }    ix = 0;    is_ver_supported = DEF_NO;    while ((is_ver_supported != DEF_YES) &&           (ix < FS_NAND_PART_ONFI_V_QTY)){        is_ver_supported = DEF_BIT_IS_SET(version, FS_NAND_PartONFI_SupportedVersions[ix]);        ix++;    }    if (is_ver_supported == DEF_YES) {        version = FS_NAND_PartONFI_SupportedVersions[ix - 1u];    } else {        FS_TRACE_DBG(("FS_NAND_PartONFI_ParamPageParse(): ONFI version not supported by this driver.rn"));       *p_err = FS_ERR_DEV_INVALID;        return;    }                                                                /* Identify features.                                   */    has_ext_pp = DEF_BIT_IS_SET(FS_NAND_PartONFI_ParamPg[6], FS_NAND_PART_ONFI_FEATURE_EX_PP);    is_bus_16  = DEF_BIT_IS_SET(FS_NAND_PartONFI_ParamPg[6], FS_NAND_PART_ONFI_FEATURE_BUS_16);    if (is_bus_16 == DEF_YES) {        p_part_data->BusWidth = 16u;    } else {        p_part_data->BusWidth =  8u;    }                                                                /* Extended parameter page length.                      */    if (has_ext_pp == DEF_YES) {        FS_NAND_PartONFI_ExtParamPageLen  = FS_NAND_PartONFI_ParamPg[12];        FS_NAND_PartONFI_ExtParamPageLen |= (CPU_INT16U)((CPU_INT16U)FS_NAND_PartONFI_ParamPg[13] << DEF_INT_08_NBR_BITS);        FS_NAND_PartONFI_ExtParamPageLen *= 16u;    }                                                                /* Number of parameter pages.                           */    if (version >= FS_NAND_PART_ONFI_V21) {        FS_NAND_PartONFI_ParamPageCnt = FS_NAND_PartONFI_ParamPg[14];    } else {        FS_NAND_PartONFI_ParamPageCnt = 3u;    }                                                                /* ----------- IDENTIFY MEMORY ORGANIZATION ----------- */                                                                /* Page size.                                           */    MEM_VAL_COPY_GET_INT32U_LITTLE(&pg_size, &FS_NAND_PartONFI_ParamPg[80]);    max_size = (FS_NAND_PG_SIZE) -1;    if (pg_size > max_size) {        FS_TRACE_DBG(("FS_NAND_PartONFI_ParamPageParse(): Page size does not fit in container type FS_NAND_PG_SIZE.rn"));       *p_err = FS_ERR_DEV_INCOMPATIBLE_LOW_PARAMS;        return;    }    p_part_data->PgSize = pg_size;                                                                /* Spare size.                                          */    MEM_VAL_COPY_GET_INT16U_LITTLE(&(p_part_data->SpareSize), &FS_NAND_PartONFI_ParamPg[84]);                                                                /* Nb of pages per blk.                                 */    MEM_VAL_COPY_GET_INT32U_LITTLE(&nb_pg_per_blk, &FS_NAND_PartONFI_ParamPg[92]);    max_size  = (FS_NAND_PG_PER_BLK_QTY) -1;    if (nb_pg_per_blk > max_size) {        FS_TRACE_DBG(("FS_NAND_PartONFI_ParamPageParse(): Nb of pages per blk does not fit in container type FS_NAND_PG_PER_BLK_QTY.rn"));       *p_err = FS_ERR_DEV_INCOMPATIBLE_LOW_PARAMS;        return;    }    p_part_data->PgPerBlk = nb_pg_per_blk;                                                                /* Nb of block per logical unit.                        */    MEM_VAL_COPY_GET_INT32U_LITTLE(&blk_cnt, &FS_NAND_PartONFI_ParamPg[96]);    max_size = (FS_NAND_BLK_QTY) - 1;    if (blk_cnt > max_size) {        FS_TRACE_DBG(("FS_NAND_PartONFI_ParamPageParse(): Blk cnt does not fit in container type FS_NAND_BLK_QTY.rn"));       *p_err = FS_ERR_DEV_INCOMPATIBLE_LOW_PARAMS;        return;    }                                                                /* Nb of logical units.                                 */    lun_nbr = FS_NAND_PartONFI_ParamPg[100];    p_part_data->BlkCnt = blk_cnt * lun_nbr;                                                                /* Max nb of bad blocks per logical unit.               */    MEM_VAL_COPY_GET_INT16U_LITTLE(&(p_part_data->MaxBadBlkCnt), &FS_NAND_PartONFI_ParamPg[103]);    p_part_data->MaxBadBlkCnt *= lun_nbr;                                                                /* Max programming operations per block.                */    value          = FS_NAND_PartONFI_ParamPg[105];    multiplier     = FS_NAND_PartONFI_ParamPg[106];    if (multiplier > 9u) {        FS_TRACE_DBG(("FS_NAND_PartONFI_ParamPageParse: Max blk erase count larger than supported.rn"));       *p_err = FS_ERR_DEV_INCOMPATIBLE_LOW_PARAMS;        return;    }    max_blk_erase     = value * FS_NAND_PartONFI_PowerOf10[multiplier];    max_size          = (CPU_INT32U) - 1;    if (max_blk_erase > max_size) {        FS_TRACE_DBG(("FS_NAND_PartONFI_ParamPageParse(): Max blk erase cnt does not fit in container type CPU_INT32U.rn"));       *p_err = FS_ERR_DEV_INCOMPATIBLE_LOW_PARAMS;        return;    }    p_part_data->MaxBlkErase = max_blk_erase;                                                                /* Max nb of partial page programming.                  */    p_part_data->NbrPgmPerPg = FS_NAND_PartONFI_ParamPg[110];                                                                /* ECC correction needed.                               */    p_part_data->ECC_NbrCorrBits = FS_NAND_PartONFI_ParamPg[112];    if (p_part_data->ECC_NbrCorrBits == 0xFFu) {        p_part_data->ECC_CodewordSize = 0u;        if (has_ext_pp == DEF_FALSE) {            FS_TRACE_DBG(("FS_NAND_PartONFI_ParamPageParse(): ECC located in extended param pg, but dev does not have one.rn"));           *p_err = FS_ERR_DEV_INVALID;            return;        } else {           *p_err = FS_ERR_DEV_NAND_ONFI_EXT_PARAM_PAGE;        }    } else {        p_part_data->ECC_CodewordSize = 528u;    }                                                                /* Factory defect mark type.                            */    if (version >= FS_NAND_PART_ONFI_V21) {        p_part_data->DefectMarkType = DEFECT_SPARE_L_1_PG_1_OR_N_ALL_0;    } else {                                                                /* #### NAND drv not compatible with "any loc".         */        p_part_data->DefectMarkType = DEFECT_SPARE_L_1_PG_1_OR_N_ALL_0;    }}
六.参考

https://www.onfi.org/specifications

最新版本是5.1

审核编辑黄宇

标签:

上一篇:汉高力促“新基建、新能源”行业革新与可持续发展-天天热讯
下一篇:最后一页