/* ********************************************************************************************************* * * 模块名称 : NAND Flash 驱动模块 * 文件名称 : bsp_nand.h * 版 本 : V1.1 * 说 明 : 头文件 * * Copyright (C), 2014-2015, 安富莱电子 www.armfly.com * ********************************************************************************************************* */ #ifndef __BSP_NAND_H #define __BSP_NAND_H #include "stm32f2xx.h" typedef struct { uint8_t Maker_ID; uint8_t Device_ID; uint8_t Third_ID; uint8_t Fourth_ID; }NAND_IDTypeDef; typedef struct { uint16_t Zone; uint16_t Block; uint16_t Page; } NAND_ADDRESS_T; #define NAND_TYPE S34ML02G100TF /* 定义有效的 NAND ID HY27UF081G2A = 0xAD 0xF1 0x80 0x1D K9F1G08U0A = 0xEC 0xF1 0x80 0x15 K9F1G08U0B = 0xEC 0xF1 0x00 0x95 H27U4G8F2DTR = 0xAD DC 90 95 */ /* NAND Flash 型号 */ #define HY27UF081G2A 0xADF1801D #define K9F1G08U0A 0xECF18015 #define K9F1G08U0B 0xECF10095 #define H27U1G8F2BTR 0xADF1001D /* STM32-V4 缺省 */ #define H27U4G8F2DTR 0xADDC9095 #define S34ML02G100TF 0x01DA9095 #define NAND_UNKNOW 0xFFFFFFFF /* Exported constants --------------------------------------------------------*/ /* NAND Area definition for STM3210E-EVAL Board RevD */ #define CMD_AREA (uint32_t)(1<<16) /* A16 = CLE high */ #define ADDR_AREA (uint32_t)(1<<17) /* A17 = ALE high */ #define DATA_AREA ((uint32_t)0x00000000) /* FSMC NAND memory command */ #define NAND_CMD_AREA_A ((uint8_t)0x00) #define NAND_CMD_AREA_B ((uint8_t)0x01) #define NAND_CMD_AREA_C ((uint8_t)0x50) #define NAND_CMD_AREA_TRUE1 ((uint8_t)0x30) #define NAND_CMD_WRITE0 ((uint8_t)0x80) #define NAND_CMD_WRITE_TRUE1 ((uint8_t)0x10) #define NAND_CMD_ERASE0 ((uint8_t)0x60) #define NAND_CMD_ERASE1 ((uint8_t)0xD0) #define NAND_CMD_READID ((uint8_t)0x90) #define NAND_CMD_LOCK_STATUS ((uint8_t)0x7A) #define NAND_CMD_RESET ((uint8_t)0xFF) /* NAND memory status */ #define NAND_BUSY ((uint8_t)0x00) #define NAND_ERROR ((uint8_t)0x01) #define NAND_READY ((uint8_t)0x40) #define NAND_TIMEOUT_ERROR ((uint8_t)0x80) #if NAND_TYPE==S34ML02G100TF #define NAND_PAGE_SIZE ((uint16_t)0x0800) /* 2 * 1024 bytes per page w/o Spare Area */ #define NAND_BLOCK_SIZE ((uint16_t)0x0040) /* 64 pages per block */ #define NAND_ZONE_SIZE ((uint16_t)0x0400) /* 1024 Block per zone */ #define NAND_SPARE_AREA_SIZE ((uint16_t)0x0040) /* last 64 bytes as spare area */ #define NAND_MAX_ZONE ((uint16_t)0x0002) /* 2 zones of 1024 block */ #define NAND_ADDR_5 1 /* 0表示只用发送4个字节的地址,1表示5个 */ /* 命令代码定义 */ #define NAND_CMD_COPYBACK_A ((uint8_t)0x00) /* PAGE COPY-BACK 命令序列 */ #define NAND_CMD_COPYBACK_B ((uint8_t)0x35) #define NAND_CMD_COPYBACK_C ((uint8_t)0x85) #define NAND_CMD_COPYBACK_D ((uint8_t)0x10) #define NAND_CMD_STATUS ((uint8_t)0x70) /* 读NAND Flash的状态字 */ #define MAX_PHY_BLOCKS_PER_ZONE 1024 /* 每个区最大物理块号 */ #define MAX_LOG_BLOCKS_PER_ZONE 1000 /* 每个区最大逻辑块号 */ #define NAND_BLOCK_COUNT 1024 /* 块个数 */ #define NAND_PAGE_TOTAL_SIZE (NAND_PAGE_SIZE + NAND_SPARE_AREA_SIZE) /* 页面总大小 */ #elif NAND_TYPE == HY27UF081G2A #define NAND_PAGE_SIZE ((uint16_t)0x0800) /* 2 * 1024 bytes per page w/o Spare Area */ #define NAND_BLOCK_SIZE ((uint16_t)0x0040) /* 64 pages per block */ #define NAND_ZONE_SIZE ((uint16_t)0x0400) /* 1024 Block per zone */ #define NAND_SPARE_AREA_SIZE ((uint16_t)0x0040) /* last 64 bytes as spare area */ #define NAND_MAX_ZONE ((uint16_t)0x0001) /* 1 zones of 1024 block */ #define NAND_ADDR_5 0 /* 0表示只用发送4个字节的地址,1表示5个 */ /* 命令代码定义 */ #define NAND_CMD_COPYBACK_A ((uint8_t)0x00) /* PAGE COPY-BACK 命令序列 */ #define NAND_CMD_COPYBACK_B ((uint8_t)0x35) #define NAND_CMD_COPYBACK_C ((uint8_t)0x85) #define NAND_CMD_COPYBACK_D ((uint8_t)0x10) #define NAND_CMD_STATUS ((uint8_t)0x70) /* 读NAND Flash的状态字 */ #define MAX_PHY_BLOCKS_PER_ZONE 1024 /* 每个区最大物理块号 */ #define MAX_LOG_BLOCKS_PER_ZONE 1000 /* 每个区最大逻辑块号 */ #define NAND_BLOCK_COUNT 1024 /* 块个数 */ #define NAND_PAGE_TOTAL_SIZE (NAND_PAGE_SIZE + NAND_SPARE_AREA_SIZE) /* 页面总大小 */ #elif NAND_TYPE == H27U4G8F2DTR #define NAND_PAGE_SIZE ((uint16_t)0x0800) /* 2 * 1024 bytes per page w/o Spare Area */ #define NAND_BLOCK_SIZE ((uint16_t)0x0040) /* 64 pages per block */ #define NAND_ZONE_SIZE ((uint16_t)0x1000) /* 4096 Block per zone */ #define NAND_SPARE_AREA_SIZE ((uint16_t)0x0040) /* last 64 bytes as spare area */ #define NAND_MAX_ZONE ((uint16_t)0x0001) /* 1 zones of 4096 block */ #define NAND_ADDR_5 1 /* 1表示只发送4个字节的地址,1表示5个 */ /* 命令代码定义 */ #define NAND_CMD_COPYBACK_A ((uint8_t)0x00) /* PAGE COPY-BACK 命令序列 */ #define NAND_CMD_COPYBACK_B ((uint8_t)0x35) #define NAND_CMD_COPYBACK_C ((uint8_t)0x85) #define NAND_CMD_COPYBACK_D ((uint8_t)0x10) #define NAND_CMD_STATUS ((uint8_t)0x70) /* 读NAND Flash的状态字 */ #define MAX_PHY_BLOCKS_PER_ZONE 4096 /* 每个区最大物理块号 */ #define MAX_LOG_BLOCKS_PER_ZONE 4000 /* 每个区最大逻辑块号 */ #define NAND_BLOCK_COUNT 4096 /* 块个数 */ #define NAND_PAGE_TOTAL_SIZE (NAND_PAGE_SIZE + NAND_SPARE_AREA_SIZE) /* 页面总大小 */ #else #define NAND_PAGE_SIZE ((uint16_t)0x0200) /* 512 bytes per page w/o Spare Area */ #define NAND_BLOCK_SIZE ((uint16_t)0x0020) /* 32x512 bytes pages per block */ #define NAND_ZONE_SIZE ((uint16_t)0x0400) /* 1024 Block per zone */ #define NAND_SPARE_AREA_SIZE ((uint16_t)0x0010) /* last 16 bytes as spare area */ #define NAND_MAX_ZONE ((uint16_t)0x0004) /* 4 zones of 1024 block */ #endif #define NAND_BAD_BLOCK_FLAG 0x00 /* 块内第1个page备用区的第1个字节写入非0xFF数据表示坏块 */ #define NAND_USED_BLOCK_FLAG 0xF0 /* 块内第1个page备用区的第2个字节写入非0xFF数据表示已使用的块 */ #define BI_OFFSET 0 /* 块内第1个page备用区的第1个字节是坏块标志 */ #define USED_OFFSET 1 /* 块内第1个page备用区的第1个字节是已用标志 */ #define LBN0_OFFSET 2 /* 块内第1个page备用区的第3个字节表示逻辑块号低8bit */ #define LBN1_OFFSET 3 /* 块内第1个page备用区的第4个字节表示逻辑块号高8bit */ #define VALID_SPARE_SIZE 4 /* 实际使用的备用区大小,用于函数内部声明数据缓冲区大小 */ /* FSMC NAND memory address computation */ #define ADDR_1st_CYCLE(ADDR) (uint8_t)((ADDR)& 0xFF) /* 1st addressing cycle */ #define ADDR_2nd_CYCLE(ADDR) (uint8_t)(((ADDR)& 0xFF00) >> 8) /* 2nd addressing cycle */ #define ADDR_3rd_CYCLE(ADDR) (uint8_t)(((ADDR)& 0xFF0000) >> 16) /* 3rd addressing cycle */ #define ADDR_4th_CYCLE(ADDR) (uint8_t)(((ADDR)& 0xFF000000) >> 24) /* 4th addressing cycle */ /* Exported macro ------------------------------------------------------------*/ /* Exported functions ------------------------------------------------------- */ #define NAND_OK 0 #define NAND_FAIL 1 #define FREE_BLOCK (1 << 12 ) #define BAD_BLOCK (1 << 13 ) #define VALID_BLOCK (1 << 14 ) #define USED_BLOCK (1 << 15 ) /* LUT[]的格式: uint16_t usGoodBlockFirst; // 第1个好块 uint16_t usDataBlockCount; // 可用于数据存储的块个数, 从第2个好块开始 uint16_t usBakBlockStart; // 备份块起始块号 uint32_t usPhyBlockNo[ulDataBlockCount]; // 物理块号数组。低字节在前,高字节在后。 */ #define DATA_BLOCK_PERCENT 98 /* 数据块占总有效块数的百分比 */ #define LUT_FIRST_GOOD_BLOCK 0 /* LUT[] 第1个单元用于存储第1个有效块号 */ #define LUT_DATA_BLOCK_COUNT 1 /* LUT[] 第2个单元用于存储第有效块号个数 */ #define LUT_BAK_BLOCK_START 2 /* LUT[] 第3个单元用于备份区起始块号 */ #define LUT_GOOD_BLOCK_START 3 /* LUT[] 第4个单元用于数据区起始块号 */ /* Private Structures---------------------------------------------------------*/ typedef struct __SPARE_AREA { uint16_t LogicalIndex; uint16_t DataStatus; uint16_t BlockStatus; } SPARE_AREA; typedef enum { WRITE_IDLE = 0, POST_WRITE, PRE_WRITE, WRITE_CLEANUP, WRITE_ONGOING }WRITE_STATE; typedef enum { OLD_BLOCK = 0, UNUSED_BLOCK }BLOCK_STATE; /* ONFI 结构 (for H27U4G8F2DTR) page 26 */ /* 必须添加__packed关键字表示结构体成员间紧密排列 */ __packed typedef struct { uint8_t Sign[4]; /* = "ONFI" */ uint16_t Revision; /* Bit1 = 1 表示支持 ONFI Ver 1.0 */ uint16_t Features; /* */ uint16_t OptionalCommands; uint8_t Rsv1[22]; /* Manufacturer information block */ uint8_t Manufacturer[12]; /* 制造商 */ uint8_t Model[20]; /* 型号 */ uint8_t JEDEC_ID; /* AD */ uint16_t DateCode; uint8_t Rsv2[13]; /* Memory organization block */ uint32_t PageDataSize; uint16_t PageSpareSize; uint32_t PartialPageDataSize; uint16_t PartialPageSpareSize; uint32_t BlockSize; uint32_t LogicalUnitSize; uint8_t LogicalUnitNumber; uint8_t AddressCycles; uint8_t CellBits; uint16_t BadBlockMax; uint16_t BlockEndurance; uint8_t ValidBlocksBegin; /* 最前面保证有效的块个数 */ uint16_t BlockEndurance2; /* Block endurance for guaranteed valid blocks */ uint8_t ProgramsPerPage; /* Number of programs per page */ uint8_t PartialProgram; uint8_t ECCcorrectBits; uint8_t InterleavedAddrBits; /* 交错的地址位 */ uint8_t InterleavedOperaton; uint8_t Rsv3[13]; /* Electrical parameters block */ uint8_t PinCapactance; uint16_t TimingMode; uint16_t ProgramCacheTimingMode; uint16_t PageProgTime; uint16_t BlockEraseTime; uint16_t PageReadTime; uint16_t ChangeColumnSetupTime; uint8_t Rsv4[23]; /* Vendor block */ uint16_t VendorRevision; uint8_t VendorSpecific[88]; uint16_t IntegritaCRC; }PARAM_PAGE_T; /* Private macro --------------------------------------------------------------*/ //#define WEAR_LEVELLING_SUPPORT 磨损平衡支持 #define WEAR_DEPTH 10 /* 磨损深度 */ #define PAGE_TO_WRITE (Transfer_Length/512) #define BAD_BALOK_TEST_CYCLE 3 /* 判别坏块算法的重复擦写次数 */ /* NAND 块统计 */ typedef struct { uint32_t ChipID; char ChipName[16]; uint32_t Bad; uint32_t Free; uint32_t Used; }NAND_BLOCK_INFO_T; /* Private variables ----------------------------------------------------------*/ /* Private function prototypes ------------------------------------------------*/ /* exported functions ---------------------------------------------------------*/ uint8_t NAND_Init(void); uint8_t NAND_Write(uint32_t _ulMemAddr, uint32_t *_pWriteBuf, uint16_t _usSize); uint8_t NAND_Read(uint32_t _ulMemAddr, uint32_t *_pReadBuf, uint16_t _usSize); uint8_t NAND_Format(void); void NAND_DispBadBlockInfo(void); uint8_t NAND_ScanBlock(uint32_t _ulPageNo); uint32_t NAND_FormatCapacity(void); uint32_t NAND_ReadID(void); void NAND_DispPhyPageData(uint32_t _uiPhyPageNo); void NAND_DispLogicPageData(uint32_t _uiLogicPageNo); uint8_t NAND_WriteMultiSectors(uint8_t *_pBuf, uint32_t _SectorNo, uint16_t _SectorSize, uint32_t _SectorCount); uint8_t NAND_ReadMultiSectors(uint8_t *_pBuf, uint32_t _SectorNo, uint16_t _SectorSize, uint32_t _SectorCount); void NAND_ReadONFI(uint8_t *_pBuf); void NAND_ReadParamPage(PARAM_PAGE_T *_pData); void NAND_DispParamPage(void); void NAND_ScanAllBadBlock(void); uint8_t NAND_GetBlockInfo(NAND_BLOCK_INFO_T *_pInfo); void NAND_MarkBadBlock(uint32_t _ulBlockNo); #endif /* __FSMC_NAND_H */ /***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/