STM32F417ZGT6 移植RL-FLASH FS

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

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 222,000评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,745评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,561评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,782评论 1 298
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,798评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,394评论 1 310
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,952评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,852评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,409评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,483评论 3 341
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,615评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,303评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,979评论 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,470评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,571评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,041评论 3 377
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,630评论 2 359