|
本帖最后由 magicoctoier 于 2018-3-10 16:59 编辑
参考“基于RL-FlashFS的F429驱动NAND Flash”的移植,但是移植卡在关于NAND Flash的底层参数配置上,直接读写NAND正常,但是加上RL-FlashFS后显示如下:
操作NAND Flash.............
正在进行低级格式化中....
低级格式化完成....
挂载文件系统失败 (2:卷错误,挂载失败,对于FAT文件系统意味着无效的MBR,启动记录或者非FAT格式)
挂载失败,需要进行FAT32格式化
正在进行FAT32格式?
??...
格式化成功
------------------------------------------------------------------
Volume访问错误
NAND Flash剩余容量 = 0字节
卸载文件系统成功
总容量 = 510.132.224字节
总扇区数 = 996352
读扇区大小 = 512字节
写扇区大小 = 512字节
卸载成功
------------------------------------------------------------------
操作NAND Flash.............
挂载文件系统失败 (2:卷错误,挂载失败,对于FAT文件系统意味着无效的MBR,启动记录或者非FAT格式)
卸载文件系统成功
------------------------------------------------------------------
应该是底层关于NAND 的移植有问题?
使用的HAL库,NAND FLASH是MT29F4G08ABADA(512MB)需要修改那些地方呢?
1、
2、NAND_STM32F4xx.c中的几个读写NAND的函数。如下:
3、其他还有吗?
/* 定义NAND Flash的物理地址。这个是由硬件决定的 */
#define Bank2_NAND_ADDR NAND_DEVICE1 //在stm32f4xx_hal_nand.h中声明((uint32_t)0x70000000)
#define Bank3_NAND_ADDR NAND_DEVICE2 //在stm32f4xx_hal_nand.h中声明((uint32_t)0x80000000)
#define Bank_NAND_ADDR Bank3_NAND_ADDR
/* 定义操作NAND Flash用到3个宏 */
#define NAND_CMD_AREA *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA)
#define NAND_ADDR_AREA *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA)
#define NAND_DATA_AREA *(__IO uint8_t *)(Bank_NAND_ADDR | DATA_AREA)
/* */
static uint32_t FSMC_NAND_GetStatus(void);
/* */
NAND_HandleTypeDef NAND_Handler; /* NAND FLASH句柄 */
/*
*********************************************************************************************************
* 函 数 名: FSMC_NAND_Init
* 功能说明: 配置FSMC和GPIO用于NAND Flash接口。这个函数必须在读写nand flash前被调用一次。
* 形 参: 无
* 返 回 值: 无
* 说 明:此函数会调用HAL_NAND_MspInit(),在BSP-Nand.c中。
*********************************************************************************************************
*/
static void FSMC_NAND_Init(void)
{
FMC_NAND_PCC_TimingTypeDef ComSpaceTiming, AttSpaceTiming;
NAND_Handler.Instance = FMC_NAND_DEVICE;
NAND_Handler.Init.NandBank = FMC_NAND_BANK3; /* NAND挂在BANK3上 */
NAND_Handler.Init.Waitfeature = FMC_NAND_PCC_WAIT_FEATURE_DISABLE; /* 关闭等待特性 */
NAND_Handler.Init.MemoryDataWidth = FMC_NAND_PCC_MEM_BUS_WIDTH_8; /* 8位数据宽度 */
NAND_Handler.Init.EccComputation = FMC_NAND_ECC_DISABLE; /* 不使用ECC */
NAND_Handler.Init.ECCPageSize = FMC_NAND_ECC_PAGE_SIZE_2048BYTE; /* ECC页大小为2k */
NAND_Handler.Init.TCLRSetupTime = 0; /* 设置TCLR(tCLR=CLE到RE的延时)=(TCLR+TSET+2)*THCLK,THCLK=1/180M=5.5ns */
NAND_Handler.Init.TARSetupTime = 1; /* 设置TAR(tAR=ALE到RE的延时)=(TAR+TSET+2)*THCLK,THCLK=1/180M=5.5n。 */
ComSpaceTiming.SetupTime = 2; /* 建立时间 */
ComSpaceTiming.WaitSetupTime = 3; /* 等待时间 */
ComSpaceTiming.HoldSetupTime = 2; /* 保持时间 */
ComSpaceTiming.HiZSetupTime = 1; /* 高阻态时间 */
AttSpaceTiming.SetupTime = 2; /* 建立时间 */
AttSpaceTiming.WaitSetupTime = 3; /* 等待时间 */
AttSpaceTiming.HoldSetupTime = 2; /* 保持时间 */
AttSpaceTiming.HiZSetupTime = 1; /* 高阻态时间 */
HAL_NAND_Init(&NAND_Handler,&ComSpaceTiming,&AttSpaceTiming);
}
/*
*********************************************************************************************************
* 函 数 名: FSMC_NAND_Reset
* 功能说明: 复位NAND Flash
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static uint8_t FSMC_NAND_Reset(void)
{
NAND_CMD_AREA = NAND_CMD_RESET;
/* 检查操作状态 */
if (FSMC_NAND_GetStatus() == NAND_READY){
return NAND_OK;
}
return NAND_FAIL;
}
/*
*********************************************************************************************************
* 函 数 名: FSMC_NAND_ReadStatus
* 功能说明: 使用Read statuc 命令读NAND Flash内部状态
* 形 参: - Address: 被擦除的快内任意地址
* 返 回 值: NAND操作状态,有如下几种值:
* - NAND_BUSY: 内部正忙
* - NAND_READY: 内部空闲,可以进行下步操作
* - NAND_ERROR: 先前的命令执行失败
*********************************************************************************************************
*/
static uint8_t FSMC_NAND_ReadStatus(void)
{
uint8_t ucData;
uint8_t ucStatus = NAND_BUSY;
/* 读状态操作 */
NAND_CMD_AREA = NAND_CMD_STATUS;
ucData = *(__IO uint8_t *)(Bank_NAND_ADDR);
if((ucData & NAND_ERROR) == NAND_ERROR){
ucStatus = NAND_ERROR;
}else if((ucData & NAND_READY) == NAND_READY){
ucStatus = NAND_READY;
}else{
ucStatus = NAND_BUSY;
}
return (ucStatus);
}
/*
*********************************************************************************************************
* 函 数 名: FSMC_NAND_GetStatus
* 功能说明: 获取NAND Flash操作状态
* 形 参: - Address: 被擦除的快内任意地址
* 返 回 值: NAND操作状态,有如下几种值:
* - NAND_TIMEOUT_ERROR : 超时错误
* - NAND_READY : 操作成功
* - NAND_ERROR: 先前的命令执行失败
*********************************************************************************************************
*/
static uint32_t FSMC_NAND_GetStatus(void)
{
uint32_t ulTimeout = 0x10000;
uint32_t ucStatus = NAND_READY;
ucStatus = FSMC_NAND_ReadStatus();
/* 等待NAND操作结束,超时后会退出 */
while ((ucStatus != NAND_READY) &&( ulTimeout != 0x00)){
ucStatus = FSMC_NAND_ReadStatus();
if(ucStatus == NAND_ERROR){
/* 返回操作状态 */
return (ucStatus);
}
ulTimeout--;
}
if(ulTimeout == 0x00){
ucStatus = 0x80; //NAND_TIMEOUT_ERROR;
}
/* 返回操作状态 */
return (ucStatus);
}
/*
*********************************************************************************************************
* 函 数 名: NAND_ReadID
* 功能说明: 读NAND Flash的ID。ID存储到形参指定的结构体变量中。
* 形 参: 无
* 返 回 值: 32bit的NAND Flash ID
*********************************************************************************************************
*/
uint32_t NAND_ReadID(void)
{
uint32_t data = 0;
/* 发送命令 Command to the command area */
NAND_CMD_AREA = 0x90;
NAND_ADDR_AREA = 0x00;
/* 顺序读取NAND Flash的ID */
data = *(__IO uint32_t *)(Bank_NAND_ADDR | DATA_AREA);
data = ((data << 24) & 0xFF000000) |
((data << 8 ) & 0x00FF0000) |
((data >> 8 ) & 0x0000FF00) |
((data >> 24) & 0x000000FF) ;
return data;
}
/*
*********************************************************************************************************
* 函 数 名: FSMC_NAND_WritePage
* 功能说明: 写一组数据至NandFlash指定页面的指定位置,写入的数据长度不大于一页的大小。
* 形 参: - _pBuffer : 指向包含待写数据的缓冲区.
* - _ulPageNo : 页号,所有的页统一编码,范围为:0 - 65535.
* - _usAddrInPage : 页内地址,范围为:0-2111.
* - _usByteCount : 写入的字节个数.
* 返 回 值: 执行结果:
* RTV_NOERR - 页写入成功
* ERR_NAND_PROG - 页写入失败
* ERR_NAND_HW_TOUT - 超时
*********************************************************************************************************
*/
uint8_t FSMC_NAND_WritePage(uint8_t *_pBuffer, uint32_t _ulPageNo, uint16_t _usAddrInPage, uint16_t _usByteCount)
{
uint32_t i;
uint8_t ucStatus;
/* 发送页写命令 */
NAND_CMD_AREA = NAND_CMD_WRITE0;
/* 发送页内地址 , 对于 HY27UF081G2A
Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
第1字节: A7 A6 A5 A4 A3 A2 A1 A0 (_usPageAddr 的bit7 - bit0)
第2字节: 0 0 0 0 A11 A10 A9 A8 (_usPageAddr 的bit11 - bit8, 高4bit必须是0)
第3字节: A19 A18 A17 A16 A15 A14 A13 A12
第4字节: A27 A26 A25 A24 A23 A22 A21 A20
H27U4G8F2DTR (512MB)
Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
第1字节: A7 A6 A5 A4 A3 A2 A1 A0 (_usPageAddr 的bit7 - bit0)
第2字节: 0 0 0 0 A11 A10 A9 A8 (_usPageAddr 的bit11 - bit8, 高4bit必须是0)
第3字节: A19 A18 A17 A16 A15 A14 A13 A12
第4字节: A27 A26 A25 A24 A23 A22 A21 A20
第5字节: 0 0 0 0 A31 A30 A29 A28
MT29F4G08ABADA(512MB)
Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
第1字节: CA7 CA6 CA5 CA4 CA3 CA2 CA1 CA0 CA0~11`:列地址,一个page内的寻址。一个page=2112字节,所以要12个寻址。
第2字节: 0 0 0 0 CA11 CA10 CA9 CA8
第3字节: BA7 BA6 PA5 PA4 PA3 PA2 PA1 PA0 PA0~5 :页地址,一个Block内的寻址。64个page,所以要6个寻址。
第4字节: BA15 BA14 BA13 BA12 BA11 BA10 BA9 BA8 BA6~17 :块地址,全部Block的寻址。总共4096个块,所以要12个寻址。
第5字节: 0 0 0 0 0 0 BA17 BA16
*/
NAND_ADDR_AREA = _usAddrInPage;
NAND_ADDR_AREA = _usAddrInPage >> 8;
NAND_ADDR_AREA = _ulPageNo;
NAND_ADDR_AREA = (_ulPageNo & 0xFF00) >> 8;
#if NAND_ADDR_5 == 1
NAND_ADDR_AREA = (_ulPageNo & 0xFF0000) >> 16;
#endif
/* tADL = 100ns, Address to Data Loading */
for (i = 0; i < 20; i++); /* 需要大于 100ns */
/* 写数据 */
for(i = 0; i < _usByteCount; i++){
NAND_DATA_AREA = _pBuffer;
}
NAND_CMD_AREA = NAND_CMD_WRITE_TRUE1;
/* WE High to Busy , 100ns */
for (i = 0; i < 20; i++); /* 需要大于 100ns */
#if ENABLE_TIMEOUT
for (i = TIMEOUT_COUNT; i; i--) {
if (GPIOD->IDR & (1 << 6)){
break;
}
}
/* 返回超时 */
if(i == 0){
return (ERR_NAND_HW_TOUT);
}
#else
while((GPIOD->IDR & (1 << 6)) == 0);
#endif
/* 返回状态 */
ucStatus = FSMC_NAND_GetStatus();
if(ucStatus == NAND_READY) {
ucStatus = RTV_NOERR;
}else if(ucStatus == NAND_ERROR){
ucStatus = ERR_NAND_PROG;
}else if(ucStatus == 0x80){ //NAND_TIMEOUT_ERROR
ucStatus = ERR_NAND_HW_TOUT;
}
return (ucStatus);
}
/*
*********************************************************************************************************
* 函 数 名: FSMC_NAND_ReadPage
* 功能说明: 从NandFlash指定页面的指定位置读一组数据,读出的数据长度不大于一页的大小。
* 形 参: - _pBuffer: 指向包含待写数据的缓冲区
* - _ulPageNo: 页号,所有的页统一编码,范围为:0 - 65535
* - _usAddrInPage : 页内地址,范围为:0-2111
* - _usByteCount: 字节个数, (最大 2048 + 64)
* 返 回 值: 执行结果:
* RTV_NOERR - 页读取成功
* ERR_NAND_HW_TOUT - 超时
*********************************************************************************************************
*/
uint8_t FSMC_NAND_ReadPage(uint8_t *_pBuffer, uint32_t _ulPageNo, uint16_t _usAddrInPage, uint16_t _usByteCount)
{
uint32_t i;
/* 发送页面读命令 */
NAND_CMD_AREA = NAND_CMD_AREA_A;
/* 发送页内地址 , 对于 HY27UF081G2A (128MB)
Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
第1字节: A7 A6 A5 A4 A3 A2 A1 A0 (_usPageAddr 的bit7 - bit0)
第2字节: 0 0 0 0 A11 A10 A9 A8 (_usPageAddr 的bit11 - bit8, 高4bit必须是0)
第3字节: A19 A18 A17 A16 A15 A14 A13 A12
第4字节: A27 A26 A25 A24 A23 A22 A21 A20
H27U4G8F2DTR (512MB)
Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
第1字节: A7 A6 A5 A4 A3 A2 A1 A0 (_usPageAddr 的bit7 - bit0)
第2字节: 0 0 0 0 A11 A10 A9 A8 (_usPageAddr 的bit11 - bit8, 高4bit必须是0)
第3字节: A19 A18 A17 A16 A15 A14 A13 A12
第4字节: A27 A26 A25 A24 A23 A22 A21 A20
第5字节: A28 A29 A30 A31 0 0 0 0
MT29F4G08ABADA(512MB)
Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
第1字节: CA7 CA6 CA5 CA4 CA3 CA2 CA1 CA0 (_usPageAddr 的bit7 - bit0)
第2字节: 0 0 0 0 CA11 CA10 CA9 CA8 (_usPageAddr 的bit11 - bit8, 高4bit必须是0)
第3字节: BA7 BA6 BA5 BA4 BA3 BA2 BA1 BA0
第4字节: BA15 BA14 BA13 BA12 BA11 BA10 BA9 BA8
第5字节: 0 0 0 0 0 0 BA17 BA16
*/
NAND_ADDR_AREA = _usAddrInPage;
NAND_ADDR_AREA = _usAddrInPage >> 8;
NAND_ADDR_AREA = _ulPageNo;
NAND_ADDR_AREA = (_ulPageNo & 0xFF00) >> 8;
#if NAND_ADDR_5 == 1
NAND_ADDR_AREA = (_ulPageNo & 0xFF0000) >> 16;
#endif
NAND_CMD_AREA = NAND_CMD_AREA_TRUE1;
/* 必须等待,否则读出数据异常, 此处应该判断超时 */
for (i = 0; i < 20; i++);
#if ENABLE_TIMEOUT
for (i = TIMEOUT_COUNT; i; i--) {
if (GPIOD->IDR & (1 << 6)){
break;
}
}
/* 返回超时 */
if(i == 0){
return (ERR_NAND_HW_TOUT);
}
#else
while((GPIOD->IDR & (1 << 6)) == 0);
#endif
/* 读数据到缓冲区pBuffer */
for(i = 0; i < _usByteCount; i++){
_pBuffer = NAND_DATA_AREA;
}
return RTV_NOERR;
}
/*
*********************************************************************************************************
* 函 数 名: FSMC_NAND_EraseBlock
* 功能说明: 擦除NAND Flash一个块(block)
* 形 参: - _ulBlockNo: 块号,范围为:0 - 1023, 0-4095
* 返 回 值: NAND操作状态,有如下几种值:
* RTV_NOERR - 擦除成功
* ERR_NAND_ERASE - 擦除失败
* ERR_NAND_HW_TOUT - 超时
*********************************************************************************************************
*/
uint8_t FSMC_NAND_EraseBlock(uint32_t _ulBlockNo)
{
uint8_t ucStatus;
/* HY27UF081G2A (128MB)
Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
第1字节: A7 A6 A5 A4 A3 A2 A1 A0 (_usPageAddr 的bit7 - bit0)
第2字节: 0 0 0 0 A11 A10 A9 A8 (_usPageAddr 的bit11 - bit8, 高4bit必须是0)
第3字节: A19 A18 A17 A16 A15 A14 A13 A12 A18以上是块号
第4字节: A27 A26 A25 A24 A23 A22 A21 A20
H27U4G8F2DTR (512MB)
Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
第1字节: A7 A6 A5 A4 A3 A2 A1 A0 (_usPageAddr 的bit7 - bit0)
第2字节: 0 0 0 0 A11 A10 A9 A8 (_usPageAddr 的bit11 - bit8, 高4bit必须是0)
第3字节: A19 A18 A17 A16 A15 A14 A13 A12 A18以上是块号
第4字节: A27 A26 A25 A24 A23 A22 A21 A20
第5字节: A28 A29 A30 A31 0 0 0 0
MT29F4G08ABADA(512MB)
Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
第1字节: CA7 CA6 CA5 CA4 CA3 CA2 CA1 CA0 (_usPageAddr 的bit7 - bit0)
第2字节: 0 0 0 0 CA11 CA10 CA9 CA8 (_usPageAddr 的bit11 - bit8, 高4bit必须是0)
第3字节: BA7 BA6 BA5 BA4 BA3 BA2 BA1 BA0 A18以上是块号
第4字节: BA15 BA14 BA13 BA12 BA11 BA10 BA9 BA8
第5字节: 0 0 0 0 0 BA18 BA17 BA16
*/
/* 发送擦除命令 */
NAND_CMD_AREA = NAND_CMD_ERASE0;
_ulBlockNo <<= 6; /* 块号转换为页编号 */
#if NAND_ADDR_5 == 0 /* 128MB的 */
NAND_ADDR_AREA = _ulBlockNo;
NAND_ADDR_AREA = _ulBlockNo >> 8;
#else /* 512MB的 */
NAND_ADDR_AREA = _ulBlockNo;
NAND_ADDR_AREA = _ulBlockNo >> 8;
NAND_ADDR_AREA = _ulBlockNo >> 16;
#endif
NAND_CMD_AREA = NAND_CMD_ERASE1;
/* 返回状态 */
ucStatus = FSMC_NAND_GetStatus();
if(ucStatus == NAND_READY) {
ucStatus = RTV_NOERR;
}else if(ucStatus == NAND_ERROR){
ucStatus = ERR_NAND_PROG;
}else if(ucStatus == 0x80){ //NAND_TIMEOUT_ERROR
ucStatus = ERR_NAND_HW_TOUT;
}
return (ucStatus);
}
/*
*********************************************************************************************************
* 函 数 名: NAND_IsBadBlock
* 功能说明: 根据坏块标记检测NAND Flash指定的块是否坏块
* 形 参: _ulBlockNo :块号 0 - 1023 (对于128M字节,2K Page的NAND Flash,有1024个块)
* 返 回 值: 0 :该块可用; 1 :该块是坏块
*********************************************************************************************************
*/
uint8_t NAND_IsBadBlock(uint32_t _ulBlockNo)
{
uint8_t ucFlag;
/* 如果NAND Flash出厂前已经标注为坏块了,则就认为是坏块 */
FSMC_NAND_ReadPage(&ucFlag, _ulBlockNo * NAND_BLOCK_SIZE, NAND_PAGE_SIZE + BBM_OFFSET, 1);
if (ucFlag != 0xFF){
return 1;
}
FSMC_NAND_ReadPage(&ucFlag, _ulBlockNo * NAND_BLOCK_SIZE + 1, NAND_PAGE_SIZE + BBM_OFFSET, 1);
if (ucFlag != 0xFF){
return 1;
}
return 0; /* 是好块 */
}
/*
*********************************************************************************************************
* 函 数 名: NAND_Format
* 功能说明: NAND Flash格式化,擦除所有的数据,重建LUT
* 形 参: 无
* 返 回 值: NAND_OK : 成功; NAND_Fail :失败(一般是坏块数量过多导致)
*********************************************************************************************************
*/
uint8_t NAND_Format(void)
{
#if 0
uint16_t i;
uint16_t usGoodBlockCount;
/* 擦除每个块 */
usGoodBlockCount = 0;
for (i = 0; i < NAND_BLOCK_COUNT; i++){
/* 如果是好块,则擦除 */
if (!NAND_IsBadBlock(i)){
FSMC_NAND_EraseBlock(i);
usGoodBlockCount++;
}
}
/* 如果好块的数量少于100,则NAND Flash报废 */
if (usGoodBlockCount < 100){
return NAND_FAIL;
}
return NAND_OK;
#else
uint16_t i;
for (i = 0; i < NAND_BLOCK_COUNT; i++){
FSMC_NAND_EraseBlock(i);
}
return NAND_OK;
#endif
}
/*
*********************************************************************************************************
* 函 数 名: NAND_Init
* 功能说明: 初始化NAND Flash接口
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void NAND_Init(void)
{
FSMC_NAND_Init(); /* 配置FSMC和GPIO用于NAND Flash接口 */
FSMC_NAND_Reset(); /* 通过复位命令复位NAND Flash到读状态 */
}
/*
*********************************************************************************************************
* 函 数 名: NAND_UnInit
* 功能说明: 卸载NAND Flash
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void NAND_UnInit(void)
{
//FMC_NANDDeInit(FMC_NAND_BANK3);
HAL_NAND_DeInit(&NAND_Handler);
/* FSMC NAND Bank 禁能 */
//FMC_NANDCmd(FMC_NAND_BANK3, DISABLE);
__FMC_NAND_DISABLE(NAND_Handler.Instance, NAND_Handler.Init.NandBank);
}
|
|