美文网首页我爱编程
STM32F417ZGT6 移植RL-FLASH FS

STM32F417ZGT6 移植RL-FLASH FS

作者: annge | 来源:发表于2018-02-15 16:31 被阅读0次

    一般学习中使用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);
    
    }
    
    

    相关文章

      网友评论

        本文标题:STM32F417ZGT6 移植RL-FLASH FS

        本文链接:https://www.haomeiwen.com/subject/htkutftx.html