STM32CbueMX之NAND FLASH

前言:

关于NAND FLASH,外面好多例程都是关于时序的计算都是一笔带过。

只会告诉你a=2,但是不会告诉你为什么=2,而不是3.

所以找了挺多资料看,希望文章对你有帮助吧。

ECC我没研究。

 

Nand flash

Nand-flash存储器是flash存储器的一种,其内部采用非线性宏单元模式,为固态大容量内存的实现提供了廉价有效的解决方案。Nand-flash存储器具有容量较大,改写速度快等优点,适用于大量数据的存储,因而在业界得到了越来越广泛的应用,如嵌入式产品中包括数码相机、MP3随身听记忆卡、体积小巧的U盘等。

 

硬件 :MT29F4G08+ F429

STM32CbueMX之NAND FLASH_第1张图片

STM32CbueMX之NAND FLASH_第2张图片

 

发送命令周期时序图:

STM32CbueMX之NAND FLASH_第3张图片

 

STM32CbueMX之NAND FLASH_第4张图片

 

STM32CbueMX之NAND FLASH_第5张图片

 

STM32 FMC NAND寄存器

STM32CbueMX之NAND FLASH_第6张图片

STM32CbueMX之NAND FLASH_第7张图片

 

(MEMxSET + 1) + MEMxHOLD  控制NWE/NOE的高电平时间,

(MEMxWAIT + 1)  控制NWE/NOE的低电平时间,

MEMxHIZ 控制写入时数据线高阻态时间。

 

 

 

计算时序过程:

配置STM32CubeMX之前需要先把MEMxSET、MEMxWAIT、MEMxHOLD 和 MEMxHIZ算出来。

先看一下《AN4761 Application note Using STM32L476/486 FSMC peripheral to drive external memories》手册的4 Interfacing an 8-bit NAND Flash memory章节(手册可以在https://www.stmcu.org.cn/搜索AN4761找到)

得到下面时序计算不等式:

STM32CbueMX之NAND FLASH_第8张图片

 

结合我们上面硬件芯片时序表格,代入不等式,未知数大等于0且向上取整:

tHCLK = 1s / 180MHz = 5.5ns

(SET + 1) x tHCLK ≥ max (tCS, tCLS, tALS, tCLR, tAR) - tWP

(SET + 1) x 5.5 >= max (15, 10, 10, 10, 10) - 10 

(SET + 1) x 5.5 >= 15 - 10 

SET >= 0  即可让不等式成立;

不等式(SET + 1) x 5.5 >= 5 ,SET >= 0 虽然不等式成立;

但是5.5ns仅仅比5ns大了0.5ns,考虑到走线等等因素,建议SET >= 1;(向上加 1)

 

(HIZ) x tHCLK ≥ max (tCS, tALS, tCLS) + (tWP - tDS)

(HIZ) x 5.5 ≥ max (15, 10, 10) + (10 - 7)

(HIZ) x 5.5 >= 15 + 3

HIZ >= 4  即可让不等式成立;

 

(HOLD) x tHCLK ≥ max (tCH, tCLH, tALH)

(HOLD) x tHCLK ≥ max (5, 5, 5)

(HOLD) x tHCLK ≥ 5

HOLD >= 1 即可让不等式成立;

不等式HOLD x 5.5 >= 5 ,HOLD >= 1 虽然不等式成立;

但是5.5ns仅仅比5ns大了0.5ns,考虑到走线等等因素,建议HOLD >= 2;(向上加 1)

 

 

WAIT 计算比较麻烦:必须满足下面几条不等式:

(WAIT + 1) x tHCLK ≥ max (tWP, tRP)

(WAIT + 1)× tHCLK ≥ (tREA + tsu(D-NOE))

WAIT ≥ (tREA + tsu(D-NOE)) /tHCLK - 1

tsu(D-NOE) = 9 ns(来自如《DS9405 STM32F427xx STM32F429xx datasheets》)

最后的计算结果:WAIT  >= 4 即可让不等式成立;

 

 

最后一步验证一下:

((WAIT + 1) + (HOLD) + (SET + 1)) x tHCLK ≥ max (tWC/RC)

((4+ 1) + (2) + (1+ 1)) x 5.5 ≥ 20

成立!

 

得到下面结果:

MEMxSET = 1

MEMxWAIT = 4

MEMxHOLD  = 2

MEMxHIZ = 4

 

 

STM32MXCUBEMX配置:

 

NAND FLASH使用的是AHB时钟,180MHz,1 HCLK = 5.5ns

STM32CbueMX之NAND FLASH_第9张图片

STM32CbueMX之NAND FLASH_第10张图片

 

STM32CbueMX之NAND FLASH_第11张图片

 

ECC computation  使能ECC纠正

ECC page size        选PAGE大小,芯片的page大小是2048

CLE low to RE low delay in HCLK cycles  = 1

ALE low to RE low delay in HCLK cycles = 1

 

由下图手册得知:t_clr = (TCLR + SET + 2) × THCLK ;其中 TCLR 是我们软件CLE low to RE low delay in HCLK cycles的设置值,而SET手册也有写 “注意: 根据寻址空间,SET 为 MEMSET 或 ATTSET”。芯片手册tCLR = 10ns

THCLK = 1 / 180MHz = 5.5ns。由于MEMSET = 1;故TAR >= 0即可。

那为什么软件配置是CLE low to RE low delay in HCLK cycles  = 1 呢,

看下面手册 TAR = 0,实际上是1个tHCKL。而软件配置问的是几个tHCKL,

那么配置写1个tHCKL,生成代码的时候会变成0。

 

ALE low to RE low delay in HCLK cycles计算过程如上。

STM32CbueMX之NAND FLASH_第12张图片

 

Common space setup time = MEMxSET = 2 tHCLK;

STM32CubeMX 的Common space setup time的单位是tHCLK;从下面手册图可以看到 

MEMxSET = 0的时候就是1个tHCLK;由于上面我们已经算出来MEMxSET 取 1,即2tHCLK。

图片来源于《STM32F4xx中文参考手册-扩展章节.pdf》

STM32CbueMX之NAND FLASH_第13张图片

Common space wait time = MEMxWAIT = 4 tHCLK

STM32CbueMX之NAND FLASH_第14张图片

Common space hold time = MEMxHOLD  = 2 tHCLK(这个参数  不  需要MEMxHOLD  往上加1

STM32CbueMX之NAND FLASH_第15张图片

Common space Hi-Z time = MEMxHIZ = 4 tHCLK

STM32CbueMX之NAND FLASH_第16张图片

 

下面4个参数和上面4个参数设置过程类似。

Attribute space setup time = MEMxSET = 1 tHCLK

Attribute space wait time = MEMxWAIT = 4 tHCLK

Attribute space hold time = MEMxHOLD  = 2 tHCLK

Attribute space Hi-Z time = MEMxHIZ = 4 tHCLK

 

STM32CbueMX之NAND FLASH_第17张图片

看图配置

Page size = 2048 bytes

Spare area size = 64 bytes

Block size = 64 pages

Block number = 2048 blocks

Plane number = 2 planes

Plane size = 4096 blocks

Extra command enable  = Disabled

 

 

生成代码。

 

main.c

int main(void)
{
    /* USER CODE BEGIN 1 */
    uint32_t i = 0;
    NAND_IDTypeDef id;
    NAND_AddressTypeDef temp;
    /* USER CODE END 1 */


    /* MCU Configuration--------------------------------------------------------*/

    /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    HAL_Init();

    /* USER CODE BEGIN Init */

    /* USER CODE END Init */

    /* Configure the system clock */
    SystemClock_Config();

    /* USER CODE BEGIN SysInit */

    /* USER CODE END SysInit */

    /* Initialize all configured peripherals */
    MX_GPIO_Init();
    MX_USART1_UART_Init();
    MX_FMC_Init();
    /* USER CODE BEGIN 2 */
    HAL_Delay(100);
    printf("sudaroot\r\n");
    HAL_NAND_Reset(&hnand1);
    HAL_NAND_Read_ID(&hnand1, &id);
    printf("HAL_id = 0x%X\r\n", *((unsigned int *)&id));

    for(i = 0; i < NAND_PAGE_SIZE; i++)
    {
        buf[i] = 0xFA;
    }

    temp.Plane = 0;
    temp.Block = 0;
    temp.Page = 0;
    printf("HAL_NAND_Erase_Block = %d\r\n", HAL_NAND_Erase_Block(&hnand1, &temp));
    printf("HAL_NAND_Write_Page_8b = %d\r\n", HAL_NAND_Write_Page_8b(&hnand1, &temp, buf, 1));
    memset(buf, 0, NAND_PAGE_SIZE);
    printf("HAL_NAND_Read_Page_8b = %d\r\n", HAL_NAND_Read_Page_8b(&hnand1, &temp, buf, 1));

    for(i = 0; i < NAND_PAGE_SIZE; i++)
    {
        if((i % 5) == 0)  printf("\r\n");
        printf("buf[%04d] = 0x%02X ", i, buf[i]);        
    }

    printf("\r\n");
    /* USER CODE END 2 */

    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while (1)
    {
        /* USER CODE END WHILE */

        /* USER CODE BEGIN 3 */
        HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
        HAL_Delay(100);
    }

    /* USER CODE END 3 */
}

 

现象:

STM32CbueMX之NAND FLASH_第18张图片

 

 

 

 

 

20200715:更新main函数的测试代码

int main(void)
{
    uint32_t i = 0;
    NAND_IDTypeDef id;
    NAND_AddressTypeDef temp;
    temp.Plane = 0;
    temp.Block = 0;
    temp.Page = 0;

    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_USART1_UART_Init();
    MX_FMC_Init();


    HAL_Delay(100);
    printf("sudaroot\r\n");
    
     // 1、复位NAND芯片,读取芯片ID
    HAL_NAND_Reset(&hnand1);
    HAL_NAND_Read_ID(&hnand1, &id);
    printf("1.HAL_id = 0x%X\r\n", *((unsigned int *)&id));
    
    // 2、擦除第0页所在的第0块的数据,并打印HAL_NAND_Erase_Block函数执行结果
    printf("3.HAL_NAND_Erase_Block = %d\r\n", HAL_NAND_Erase_Block(&hnand1, &temp));
    
    // 3、读取在芯片第0页的数据,并打印HAL_NAND_Read_Page_8b函数执行结果
    memset(buf, 0, NAND_PAGE_SIZE);
    printf("2.HAL_NAND_Read_Page_8b = %d\r\n", HAL_NAND_Read_Page_8b(&hnand1, &temp, buf, 1));
    for(i = 0; i < NAND_PAGE_SIZE; i++)
    {
        if((i % 5) == 0)  printf("\r\n");
        printf("buf[%04d] = 0x%02X ", i, buf[i]);
    }
    printf("\r\n");
    
    // 4、初始化数据,把新的数据写入芯片第0页,并打印HAL_NAND_Write_Page_8b函数执行结果
    for(i = 0; i < NAND_PAGE_SIZE; i++)
    {
        buf[i] = i & 0x00FF;
    }
    printf("4.HAL_NAND_Write_Page_8b = %d\r\n", HAL_NAND_Write_Page_8b(&hnand1, &temp, buf, 1));
    
    // 5、重新读取芯片第0页数据,并打印HAL_NAND_Read_Page_8b函数执行结果
    memset(buf, 0, NAND_PAGE_SIZE);
    printf("5.HAL_NAND_Read_Page_8b = %d\r\n", HAL_NAND_Read_Page_8b(&hnand1, &temp, buf, 1));
    for(i = 0; i < NAND_PAGE_SIZE; i++)
    {
        if((i % 5) == 0)  printf("\r\n");
        printf("buf[%04d] = 0x%02X ", i, buf[i]);
    }
    printf("\r\n");

    while (1)
    {
        HAL_Delay(100);
    }
}

现象:

1、读取芯片ID.证明时序配置正常。

2、擦除第0页所在的第0块的数据,并打印HAL_NAND_Erase_Block函数执行结果(0表示成功)

3、读取在芯片第0页的数据,并打印HAL_NAND_Read_Page_8b函数执行结果(此时数据全是0xFF)

4、初始化数据0x00~0xFF循环,把新的数据写入芯片第0页,并打印HAL_NAND_Write_Page_8b函数执行结果

5、重新读取芯片第0页数据,并打印HAL_NAND_Read_Page_8b函数执行结果,数据0x00~0xFF循环,正确。

STM32CbueMX之NAND FLASH_第19张图片

 

 

 

全篇完。

 

本人是一个嵌入式未入门小白,博客仅仅代表我个人主观见解方便记录成长笔记。 若有与大神大大见解有冲突,我坚信大神大大见解是对的,我的是错的。 若无法下载源码,可私聊私发。 感谢~!

你可能感兴趣的:(STM32)