本文主要是介绍STM32CbueMX之NAND FLASH,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
前言:
关于NAND FLASH,外面好多例程都是关于时序的计算都是一笔带过。
只会告诉你a=2,但是不会告诉你为什么=2,而不是3.
所以找了挺多资料看,希望文章对你有帮助吧。
ECC我没研究。
本文代码链接:FSMCNAND.rar-其它代码类资源-CSDN下载
Nand flash
Nand-flash存储器是flash存储器的一种,其内部采用非线性宏单元模式,为固态大容量内存的实现提供了廉价有效的解决方案。Nand-flash存储器具有容量较大,改写速度快等优点,适用于大量数据的存储,因而在业界得到了越来越广泛的应用,如嵌入式产品中包括数码相机、MP3随身听记忆卡、体积小巧的U盘等。
硬件 :MT29F4G08+ F429
发送命令周期时序图:
STM32 FMC NAND寄存器
(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章节(手册可以在意法半导体STM32/STM8技术社区 - 提供最新的ST资讯和技术交流搜索AN4761找到)
得到下面时序计算不等式:
结合我们上面硬件芯片时序表格,代入不等式,未知数大等于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
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计算过程如上。
Common space setup time = MEMxSET = 2 tHCLK;
STM32CubeMX 的Common space setup time的单位是tHCLK;从下面手册图可以看到
MEMxSET = 0的时候就是1个tHCLK;由于上面我们已经算出来MEMxSET 取 1,即2tHCLK。
图片来源于《STM32F4xx中文参考手册-扩展章节.pdf》
Common space wait time = MEMxWAIT = 4 tHCLK
Common space hold time = MEMxHOLD = 2 tHCLK(这个参数 不 需要MEMxHOLD 往上加1)
Common space Hi-Z time = MEMxHIZ = 4 tHCLK
下面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
看图配置
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 */
}
现象:
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芯片,读取芯片IDHAL_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循环,正确。
全篇完。
本人是一个嵌入式未入门小白,博客仅仅代表我个人主观见解,记录成长笔记。
笔记是以最简单的方式,只展示最核心的原理。
若有与 大神大大 见解有歧义,我绝对坚信 大神大大 见解是对的,我的是错的。
若无积分等无法下载源码,可加入QQ群657407920下载交流经验。感谢~!
这篇关于STM32CbueMX之NAND FLASH的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!