我爱编程

STM32F417ZGT6 移植RL-FLASH FS

2018-02-15  本文已影响0人  annge

一般学习中使用FatFS可能多一点,使用上差别不是太大,但是FatFs没有,磨损均衡,坏块,ECC等管理,作为学习移植文件系统,问题不大,但在用到实际项目上去的话,这是肯定不行的,FLASH在产生坏块后,文件系统会受到破坏导致数据的丢失和产品的不稳定,RL-FlashFs是专门针对Flash芯片的文件系统,类似的还有国外一个开源的SPI-ffs,是专门针对小型化SPI FLASH的一种文件系统。

平台配置

FLASH:W29N1GV 128MB SLC NAND

控制器:STM32F417ZGT6

接口:STM32的FSMC接口

软件平台:MDK4.74(选4.74的原因是5版本以后的RL-FlashFs变成了一个pack,依赖于RTX,因为现在使用了QPN框架,暂时不想用RTX就不去掉这个依赖了)

CubeMx配置:

image

根据自己FLASH的数据手册来进行配置吧

其余的部分大可参照安富莱的教程,记录一下自己遇到的坑,其他朋友也可以参考一下

1.配置时不使用STM32的硬件ECC。

2.读取时的页大小 = Page Size + Spare area Size(我这边是2048 + 64 = 2112)

3.ST官方的库里面的读取函数都是整页读取的,移植时要自己写字节读取函数

以下是移植用到的API


uint8_t FSMC_NAND_Write_Page(uint8_t *_pBuffer, uint32_t _ulPageNo, uint16_t _usAddrInPage, uint16_t _usByteCount)

{

  __IO uint32_t index = 0U;

  uint32_t tickstart = 0U;

  /* Process Locked */

  __HAL_LOCK(&hnand1); 

  /* Check the NAND controller state */

  if(hnand1.State == HAL_NAND_STATE_BUSY)

  {

    return HAL_BUSY;

  }

  hnand1.State = HAL_NAND_STATE_BUSY;

/* Send write page command sequence */

*(__IO uint8_t *)((uint32_t)(NAND_DEVICE1 | CMD_AREA)) = NAND_CMD_AREA_A;

*(__IO uint8_t *)((uint32_t)(NAND_DEVICE1 | CMD_AREA)) = NAND_CMD_WRITE0;

/* (hnand->Config.PageSize) > 512 */

{

//(((hnand1.Config.BlockSize)*(hnand1.Config.BlockNbr)) <= 65535U)

// 1024 Blocks = 1024 * 64 pages * 2K Bytes

{

*(__IO uint8_t *)((uint32_t)(NAND_DEVICE1 | ADDR_AREA)) = ADDR_1ST_CYCLE(_usAddrInPage);

*(__IO uint8_t *)((uint32_t)(NAND_DEVICE1 | ADDR_AREA)) = ADDR_2ND_CYCLE(_usAddrInPage);

*(__IO uint8_t *)((uint32_t)(NAND_DEVICE1 | ADDR_AREA)) = ADDR_1ST_CYCLE(_ulPageNo);

*(__IO uint8_t *)((uint32_t)(NAND_DEVICE1 | ADDR_AREA)) = ADDR_2ND_CYCLE(_ulPageNo);

}

}

  for(uint16_t i = 0; i < 40; i++);

/* Write data to memory */

for(; index < _usByteCount; index++)

{

*(__IO uint8_t *)NAND_DEVICE1 = *(uint8_t *)_pBuffer++;

}

for(uint16_t i = 0; i < 40; i++);

*(__IO uint8_t *)((uint32_t)(NAND_DEVICE1 | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;

/* Read status until NAND is ready */

while(HAL_NAND_Read_Status(&hnand1) != NAND_READY)

{

/* Get tick */

tickstart = HAL_GetTick();

if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT)

{

return ERR_NAND_HW_TOUT;

}

}

uint32_t status = HAL_NAND_Read_Status(&hnand1);

  /* Update the NAND controller state */

  hnand1.State = HAL_NAND_STATE_READY;

  /* Process unlocked */

  __HAL_UNLOCK(&hnand1);

  if(status == NAND_READY)

{

return RTV_NOERR;

}

else if(status == NAND_ERROR)

{

return ERR_NAND_PROG;

}

return RTV_NOERR;

}

uint8_t FSMC_NAND_Read_Page(uint8_t *_pBuffer, uint32_t _ulPageNo, uint16_t _usAddrInPage, uint16_t _usByteCount)

{

  __IO uint32_t index = 0U;

  uint32_t tickstart = 0U;

  /* Process Locked */

  __HAL_LOCK(&hnand1); 

  /* Check the NAND controller state */

  if(hnand1.State == HAL_NAND_STATE_BUSY)

  {

    return HAL_BUSY;

  }

  hnand1.State = HAL_NAND_STATE_BUSY;

/* Send write page command sequence */

*(__IO uint8_t *)((uint32_t)(NAND_DEVICE1 | CMD_AREA)) = NAND_CMD_AREA_A;

/* (hnand->Config.PageSize) > 512 */

{

//(((hnand1.Config.BlockSize)*(hnand1.Config.BlockNbr)) <= 65535U)

// 1024 Blocks = 1024 * 64 pages * 2K Bytes

{

*(__IO uint8_t *)((uint32_t)(NAND_DEVICE1 | ADDR_AREA)) = ADDR_1ST_CYCLE(_usAddrInPage); //Ò³ÄÚµØÖ·µÍ8

*(__IO uint8_t *)((uint32_t)(NAND_DEVICE1 | ADDR_AREA)) = ADDR_2ND_CYCLE(_usAddrInPage); //Ò³ÄÚµØÖ·¸ß8

*(__IO uint8_t *)((uint32_t)(NAND_DEVICE1 | ADDR_AREA)) = ADDR_1ST_CYCLE(_ulPageNo);    //Ò³µØÖ·¸ß8

*(__IO uint8_t *)((uint32_t)(NAND_DEVICE1 | ADDR_AREA)) = ADDR_2ND_CYCLE(_ulPageNo);    //Ò³µØÖ·µÍ8

}

}

*(__IO uint8_t *)((uint32_t)(NAND_DEVICE1 | CMD_AREA))  = NAND_CMD_AREA_TRUE1;

  for(uint16_t i = 0; i < 40; i++);

/* Read status until NAND is ready */

while(HAL_NAND_Read_Status(&hnand1) != NAND_READY)

{

/* Get tick */

tickstart = HAL_GetTick();

if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT)

{

return ERR_NAND_HW_TOUT;

}

}

/* Go back to read mode */

*(__IO uint8_t *)((uint32_t)(NAND_DEVICE1 | CMD_AREA)) = ((uint8_t)0x00);

__DSB();

/* ¶ÁÊý¾Ýµ½»º³åÇøpBuffer */

for(index = 0; index < _usByteCount; index++)

{

*(uint8_t *)_pBuffer++ = *(uint8_t *)(NAND_DEVICE1); 

}

hnand1.State = HAL_NAND_STATE_READY;

__HAL_UNLOCK(&hnand1);

return RTV_NOERR;

}

uint8_t NAND_IsBadBlock(uint32_t _ulBlockNo)

{

uint8_t ucFlag;

/* Èç¹ûNAND Flash³ö³§Ç°ÒѾ­±êעΪ»µ¿éÁË£¬Ôò¾ÍÈÏΪÊÇ»µ¿é */

FSMC_NAND_Read_Page(&ucFlag, _ulBlockNo * NAND_BLOCK_SIZE, NAND_PAGE_SIZE + BBM_OFFSET, 1);

if (ucFlag != 0xFF)

{

return 1;

}

FSMC_NAND_Read_Page(&ucFlag, _ulBlockNo * NAND_BLOCK_SIZE + 1, NAND_PAGE_SIZE + BBM_OFFSET, 1);

if (ucFlag != 0xFF)

{

return 1;

}

return 0; /* ÊǺÿé */

}

uint8_t FSMC_NAND_EraseBlock(uint32_t _ulBlockNo)

{

  uint32_t tickstart = 0U;

  /* Process Locked */

  __HAL_LOCK(&hnand1);

  /* Check the NAND controller state */

  if(hnand1.State == HAL_NAND_STATE_BUSY)

  {

    return HAL_BUSY;

  }

  /* Update the NAND controller state */

  hnand1.State = HAL_NAND_STATE_BUSY; 

  /* Send Erase block command sequence */

  *(__IO uint8_t *)((uint32_t)(NAND_DEVICE1 | CMD_AREA)) = NAND_CMD_ERASE0;

_ulBlockNo <<= 6;

  *(__IO uint8_t *)((uint32_t)(NAND_DEVICE1 | ADDR_AREA)) = ADDR_1ST_CYCLE(_ulBlockNo);

  *(__IO uint8_t *)((uint32_t)(NAND_DEVICE1 | ADDR_AREA)) = ADDR_2ND_CYCLE(_ulBlockNo >> 8);   

  *(__IO uint8_t *)((uint32_t)(NAND_DEVICE1 | CMD_AREA)) = NAND_CMD_ERASE1;

  /* Update the NAND controller state */

  hnand1.State = HAL_NAND_STATE_READY;

  /* Get tick */

  tickstart = HAL_GetTick();

  /* Read status until NAND is ready */

  while(HAL_NAND_Read_Status(&hnand1) != NAND_READY)

  {

    if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT)

    {

      /* Process unlocked */

      __HAL_UNLOCK(&hnand1);   

      return ERR_NAND_HW_TOUT;

    }

  }   

uint32_t status = HAL_NAND_Read_Status(&hnand1);

  /* Process unlocked */

  __HAL_UNLOCK(&hnand1);   

  if(status == NAND_READY)

{

return RTV_NOERR;

}

else if(status == NAND_ERROR)

{

return ERR_NAND_PROG;

}

return RTV_NOERR;

}

uint8_t NAND_Format(void)

{

for(uint16_t i = 0; i < 1024; i++)

{

FSMC_NAND_EraseBlock(i);

}

return NAND_OK;

}

void NAND_Init(void)

{

MX_FSMC_Init();

HAL_NAND_Reset(&hnand1);

}

void NAND_UnInit(void)

{

HAL_NAND_MspDeInit(&hnand1);

}

上一篇下一篇

猜你喜欢

热点阅读