1.4 Cubemx_NandFlash_STM32F4\H7


写这篇文章的时候,我已经花了三天搞这个东西了。期间遇到两个问题,搞了好久才解决:
1、生成的代码全速跑,弹框提示 Could not stop Coretx-M device!Please check the JTAG cable。
2、ID可以读出,但是数据写进去与读出来不一致,出现错位。
上面问题我网上搜索了很久,很多人遇到的问题,但是只是提,没人答。

先介绍两颗芯片

1. 硬件描述

1.1 MT29F4G08

在这里插入图片描述
由图可知:MT29F4G08 由 2 个 plane 组成,每个 plane 有 2048 个 block,每个 block 由 64 个 page 组成,每个 page 有 2K+64 字节(2112 字节)的存储容量。所以,MT29F4G08 的总容 量为:2 * 2048 * 64*(2K+64)= 553648128 字节(512MB)。其中,plane、block、page 等的个数根据 NAND FLASH 型号的不同,会有所区别,大家注意查看对应 NAND FLASH 芯片的数据
手册。
2plane =2 * 2048block=2 * 2048 * 64page
1page=2K+64Byte 2K: 数据区data area, 64Byte:备用区spare area。

NAND FLASH 的 page 由 2 部分组成:数据存储区(data area)和备用区域(spare area),
对 MT29F4G08 来说,数据存储区大小为 2K 字节,备用区域大小为 64 字节。我们存储的有效 数据,一般都是存储在数据存储区(data area)。备用区域(spare area),一般用来存放 ECC(Error Checking and Correcting)校验值,可利用这个区域,来实现 NAND FLASH 坏块管理和磨损均衡。

1.2 H27(U_S)4G8_6F2D

H27(U_S)4G8_6F2Dseries is a 512Mx8bit with spare 16Mx8 bit capacity.
数据区:512M8bit
备用去:16M
8bit

  • X8: (2K + 64) bytes x 64 pages x 4096 blocks
  • X16: (1k+32) words x 64 pages x 2048 blocks

PAGE SIZE

  • X8: (2048 + 64 spare) bytes
  • X16:(1024 + 32spare) Words
Multiplane Architecture
Array is split into two independent planes.
Parallel operations on both planes are available, having
program and erase time.

从上面两颗芯片对比,你可以发现,结构、引脚、存储方法、内存大小等等和MT29F4G08是一模一样的,不一样可能就是里面某些性能参数。

1.3 芯片引脚描述

开发板NANDFALSH芯片:H27U4G8F2ETR-BI
4Gbit Nandflash
在这里插入图片描述
在这里插入图片描述
上图是常见的Nand Flash所拥有的引脚(Pin)所对应的功能,简单翻译如下:

1、I/O0 ~ I/O7:I/O0 ~ I/O7:用于输入地址/数据/命令,输出数据。
2、CLE:Command Latch Enable,命令锁存使能,在输入命令之前,要先在模式寄存器中,设置CLE使能。
3、ALE:Address Latch Enable,地址锁存使能,在输入地址之前,要先在模式寄存器中,设置ALE使能
4、CE#:Chip Enable,芯片使能,在操作Nand Flash之前,要先选中此芯片,才能操作。
5、RE#:Read Enable,读使能,在读取数据之前,要先使CE#有效。
6、WE#:Write Enable,写使能,在写取数据之前,要先使WE#有效。
7、WP#:Write Protect,写保护
8、R/B#:Ready/Busy Output,就绪/忙,主要用于在发送完编程/擦除命令后,检测这些操作是否完成,忙,表示编程/擦除操作仍在进行中,就绪表示操作完成.
9、Vcc:Power,电源
10、Vss:Ground,接地
11、N.C:Non-Connection,未定义,未连接
(字母上面带横杠说明引脚是低电平有效,为书写方便,在字母后面加“#”表示)

1.4 STM32 nandflash原理图

在这里插入图片描述

根据STM32F7中文参考手册如下:
在这里插入图片描述
存储芯片与单片机的关系
在这里插入图片描述
如下编程操作和读操作的时序。首先先拉低NCE片选,只有选中芯片才能让他工作。

Nand Flash是通过 ALE/CLE 来区分数据线上的数据是命令(CLE有效),地址(ALE有效)还是数据(CLE/ALE都无效)。通过NWE/NRE来区分数据线上的数据是写操作(NWE有效)还是读操作(NRE有效)。

1.5 FMC存储区域

FMC的存储区域外部储存分配图如图。其中Nand Flash为储存区域3,4x64MB。起始地址为0x8000 0000。
在这里插入图片描述

1.6 时序图

一下时H27U4G8F2E芯片资料上的截图:

1.6.1 Table 28: AC Timing Characteristics

在这里插入图片描述

1.6.2 Figure 5: Command Latch Cycle

在这里插入图片描述

1.6.3 Figure 6: Address Latch Cycle

在这里插入图片描述

1.6.4 Figure 7: Input Data Latch Cycle

在这里插入图片描述

1.6.5 Figure 8: Sequential Out Cycle after Read

在这里插入图片描述
在这里插入图片描述

1.6.6 Figure 10: Status / EDC Read Cycle

在这里插入图片描述
在这里插入图片描述

1.6.7 Figure 12: Read Operation (Read One Page)

在这里插入图片描述
在这里插入图片描述

1.6.8 Figure 14: Random Data Output

在这里插入图片描述

1.6.9 Figure 15: Page Program Operation

在这里插入图片描述

1.6.10 Figure 16: Random Data In

在这里插入图片描述

1.6.11 Figure 19: Block Erase Operation (Erase One Block)

在这里插入图片描述

1.6.12 Figure 20: Multiple plane page program

在这里插入图片描述

1.6.13 Figure 27: ID Read

在这里插入图片描述

1.6.14 Figure 29: Reset operation timing

在这里插入图片描述

1.6.15 …

还有其他很大时序图,请参考芯片手册

1.7 时序图解析

在这里插入图片描述
从上面图中命令序列:
命令1# + Col.Addr1 + Col.Addr2 + Row.Addr1 + Row.Addr2 + Row.Addr3 +命令2#

Col:列地址(等价于页里具体地址)
Row:行地址(等价于总页地址)

NAND FLASH 的地址分为三类:
块地址(Block Address)、页地址(Page Address)和列地址(Column Address)。以 MT29F4G08 为例,这三个地址,通过 5 个周期发送,如表 46.1.1.2所示:

在这里插入图片描述
表中,CA0~CA11 为列地址(Column Address),用于在一个 Page 内部寻址,MT29F4G08的一个 Page 大小为 2112 字节,需要 12 个地址线寻址;PA0~PA5 为页地址(Page Address),用于在一个 Block 内部寻址,MT29F4G08 一个 Block 大小为 64 个 Page,需要 6 个地址线寻址;BA6~BA17 为块地址(Block Address),用于块寻址,MT29F4G08 总共有 4096 个Block,需要12 根地址线寻址。

整个寻址过程,分 5 次发送(5 个周期),首先发送列地址,在发送页地址和块地址。这里提醒一下:块地址和页地址,其实是可以写在一起的,由一个参数传递即可,所以表中的 BA并不是由 BA0 开始的,大家可以理解为这个地址(PA+BA)为整个 NAND FLASH 的 Page 地址。在完成寻址以后,数据线 I/O0~ I/O7 来传输数据了。

举例:
在这里插入图片描述
该指令用于读取 NAND 的一个 Page(包括 spare 区数据,但不能跨页读),该指令时序如上图由图可知,READ PAGE 的命令分两次发送,首先发送 00H 命令,然后发送 5 次地址
(Block&Page&Column 地址),指定读取的地址,随后发送 30H 命令,在等待 RDY 后,即可读取 PAGE 里面的数据。注意:不能跨页读,所以最多一次读取一个 PAGE 的数据(包括 spare
区)。

1.8 命令列表

在这里插入图片描述
在这里插入图片描述

2. HAL库解析

2.1 NAND_DeviceConfigTypeDef

typedef struct
{
   
  uint32_t        PageSize;              /*!< NAND memory page (without spare area) size measured in bytes
                                              for 8 bits adressing or words for 16 bits addressing             */

  uint32_t        SpareAreaSize;         /*!< NAND memory spare area size measured in bytes
                                              for 8 bits adressing or words for 16 bits addressing             */

  uint32_t        BlockSize;             /*!< NAND memory block size measured in number of pages               */

  uint32_t        BlockNbr;              /*!< NAND memory number of total blocks                               */

  uint32_t        PlaneNbr;              /*!< NAND memory number of planes                                     */

  uint32_t        PlaneSize;             /*!< NAND memory zone size measured in number of blocks               */

  FunctionalState ExtraCommandEnable;    /*!< NAND extra command needed for Page reading mode. This
                                              parameter is mandatory for some NAND parts after the read
                                              command (NAND_CMD_AREA_TRUE1) and before DATA reading sequence.
                                              Example: Toshiba THTH58BYG3S0HBAI6.
                                              This parameter could be ENABLE or DISABLE
                                              Please check the Read Mode sequnece in the NAND device datasheet */
} NAND_DeviceConfigTypeDef;
芯片:H27U4G8F2ETR-BI
容量:(2K+64Byte)* 64 * 2048 * 2 =512M Byte

1、PageSize:   1页里出去备用区数据大小 :2048Byte。
2、SpareAreaSize:  1页备用区数据大小:64Byte。
3、BlockSize:  NAND内存块大小(以页数为单位):64page
4、BlockNbr:  设备内存总块数:4096 block
5、PlaneNbr:  设备 plane数:2 plane
6、PlaneSize:  1plane多少Block(以块数为单位): 2048 block

2.2 库函数

HAL_StatusTypeDef  HAL_NAND_Read_Page_8b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumPageToRead);
HAL_StatusTypeDef  HAL_NAND_Write_Page_8b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumPageToWrite);
HAL_StatusTypeDef  HAL_NAND_Read_SpareArea_8b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaToRead);
HAL_StatusTypeDef  HAL_NAND_Write_SpareArea_8b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, uint32_t NumSpareAreaTowrite);

HAL_StatusTypeDef  HAL_NAND_Read_Page_16b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint16_t *pBuffer, uint32_t NumPageToRead);
HAL_StatusTypeDef  HAL_NAND_Write_Page_16b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint16_t *pBuffer, uint32_t NumPageToWrite);
HAL_StatusTypeDef  HAL_NAND_Read_SpareArea_16b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint16_t *pBuffer, uint32_t NumSpareAreaToRead);
HAL_StatusTypeDef  HAL_NAND_Write_SpareArea_16b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint16_t *pBuffer, uint32_t NumSpareAreaTowrite);

HAL_StatusTypeDef  HAL_NAND_Erase_Block(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress);

函数中第二个地址参数详解:

NAND_AddressTypeDef temp;//地址句柄
temp.Plane = 1;   //(第几个plane 0-1)
temp.Block = 2047;//(第几个block 0-2047)
temp.Page = 63;		//(第几个papge 0-63)

了解了这之后,基本上可以开始搞代码了

3 STM32F429 cubemx的配置

在这里插入图片描述
在这里插入图片描述

特别注意了:
当space timing in HCLK cycles那四个时间参数配置错了(上下是一样的),就会出现写读出来的数据移位,不一致的情况。至于怎么计算来的,我也不太懂。具体可以参考:仅供参考,不一定对。

仅供参考
我测出来可用的数据如下:至于什么关系,我也没搞多么清楚
这里面的值是生成代码里面static void MX_FMC_Init(void)函数
在这里插入图片描述

  /* ComSpaceTiming */
  ComSpaceTiming.SetupTime = 4;
  ComSpaceTiming.WaitSetupTime = 4;
  ComSpaceTiming.HoldSetupTime = 4;
  ComSpaceTiming.HiZSetupTime = 3;
  /* AttSpaceTiming */
  AttSpaceTiming.SetupTime = 4;
  AttSpaceTiming.WaitSetupTime = 4;
  AttSpaceTiming.HoldSetupTime = 4;
  AttSpaceTiming.HiZSetupTime = 3;

NAND 属性信息根据自己NANDFlash来填写,我的是
NAND=2plane =22048block=22048*64page
1page=2K+64Byte
2K: 数据区data area,
64Byte:备用区spare area。

Page size:2048      //一页多少字节数,不包含备用区
Spare area size:64 //一页备用区多少字节
Block size:64           //一个bock有多少page
Block number:4096   //Device 多少个block
Plane number:2      //Device 多少plane
Plane size:2048      //1plane多少block

在这里插入图片描述
在这里插入图片描述
这里也需要特别注意:FMC_NWAT是就绪/忙碌信号,低电平为忙碌,高电平为准备就绪。如果配置的时候不拉高,会弹框提示:Could not stop Coretx-M device!Please check the JTAG cable。程序卡死再读ID那个地方。
至于为什么会出现,那是因为R/B脚是低电平,NANDFLASH 没有准备就绪。所以读ID就死掉。经过测试发现它整个过程并没有对R/B脚操作,它一直默认为就就绪态,就是一直是高电平。所以配置的时候必须要高电平。
经过测试还发现,当执行HAL_NAND_Reset(&hnand1);复位函数时,R/B有0.2uS拉低的一个动作。
配置好后直接生成代码就可以了:
下面附上测试代码:

  /* USER CODE BEGIN 2 */
	bsp_init();
	NAND_FLASH_TEST();

  /* USER CODE END 2 */

在这里插入图片描述
结果就会出现,读出与写入一致.

4 驱动代码

测试代码:
bsp_nandflash.c

#include "bsp_nandflash.h"
#include "pub_delay.h"
#include <stdio.h>
#include <string.h>
//#include "malloc.h"

//NAND_HandleTypeDef NAND_Handler;    //NAND FLASH句柄
nand_attriute nand_dev;             //nand重要参数结构体

extern NAND_HandleTypeDef hnand1;
#define NAND_Handler hnand1
#define FMC_Bank3 FMC_Bank3_R

//初始化NAND FLASH
u8 NAND_Init(void)
{
    
	NAND_IDTypeDef id;
	NAND_MPU_Config(); 
		
	HAL_NAND_Reset(&NAND_Handler);
	nand_dev.id=NAND_ReadID();
	
	//HAL_NAND_Read_ID(&NAND_Handler, &id);

	printf("NAND ID:%#x\r\n",nand_dev.id);
	NAND_ModeSet(4);			        //设置为MODE4,高速模式 
	if(nand_dev.id==MT29F16G08ABABA)    //NAND为MT29F16G08ABABA
	{
   
			nand_dev.page_totalsize=4320;       
			nand_dev.page_mainsize=4096;       
			nand_dev.page_sparesize=224;
			nand_dev.block_pagenum=128;
			nand_dev.plane_blocknum=2048;
			nand_dev.block_totalnum=4096;    
	}
	else if(nand_dev.id==MT29F4G08ABADA)//NAND为MT29F4G08ABADA  H27U4GBF
	{
   
			nand_dev.page_totalsize=2112;
			nand_dev.page_mainsize=2048;
			nand_dev.page_sparesize=64;
			nand_dev.block_pagenum=64;
			nand_dev.plane_blocknum=2048;
			nand_dev.block_totalnum=4096; 
	}
	else
		return 1;	//错误,返回
   return 0;
}



//配置MPU的region
void NAND_MPU_Config(void)
{
   
	MPU_Region_InitTypeDef MPU_Initure;
	
	HAL_MPU_Disable();							//配置MPU之前先关闭MPU,配置完成以后在使能MPU
	
	//配置RAM为region1,大小为256MB,此区域可读写
	MPU_Initure.Enable=MPU_REGION_ENABLE;			//使能region
	MPU_Initure.Number=NAND_REGION_NUMBER;			//设置region,NAND使用的region0
	MPU_Initure.BaseAddress=NAND_ADDRESS_START;		//region基地址
	MPU_Initure.Size=NAND_REGION_SIZE;				//region大小
	MPU_Initure.SubRegionDisable=0X00;
	MPU_Initure.TypeExtField=MPU_TEX_LEVEL0;
	MPU_Initure.AccessPermission=MPU_REGION_FULL_ACCESS;	//此region可读写
	MPU_Initure.DisableExec=MPU_INSTRUCTION_ACCESS_ENABLE;	//允许读取此区域中的指令
	MPU_Initure.IsShareable=MPU_ACCESS_NOT_SHAREABLE;
	MPU_Initure.IsCacheable=MPU_ACCESS_NOT_CACHEABLE;
	MPU_Initure.IsBufferable=MPU_ACCESS_BUFFERABLE;
	HAL_MPU_ConfigRegion(&MPU_Initure);
	
	HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);			//开启MPU
}

//读取NAND FLASH的ID
//返回值:0,成功;
//    其他,失败
u8 NAND_ModeSet(u8 mode)
{
      
	*(vu8*)(NAND_ADDRESS|NAND_CMD)=NAND_FEATURE;//发送设置特性命令
	*(vu8*)(NAND_ADDRESS|NAND_ADDR)=0X01
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32F4是意法半导体公司推出的一款32位ARM Cortex-M4处理器核心的微控制器系列,具有丰富的外设和强大的性能。NAND Flash是一种常见的非易失性存储器,具有较大的存储容量和高速读写特性。本文将介绍如何使用STM32F4驱动NAND Flash。 首先,STM32F4的GPIO外设可以用来配置引脚的输入输出状态。我们可以通过设置GPIO引脚为输出模式,控制NAND Flash的片选、写使能、读使能等信号。另外,STM32F4还提供了寄存器控制的SPI和FSMC接口,可以用来和NAND Flash进行通信。 其次,STM32Cube软件平台可以为STM32F4系列提供丰富的驱动库。在使用NAND Flash时,我们可以借助STM32Cube的外设库函数,方便地对NAND Flash进行初始化、读写操作。可以通过调用库函数来配置FSMC接口的时序参数,以及设置NAND Flash的特性和模式等。此外,还可以使用DMA控制器来提高数据读写效率。 最后,针对具体的NAND Flash型号,我们需要查阅其数据手册来了解其特性和命令集。通过合理配置STM32F4的寄存器参数,将数据传输到NAND Flash的相应寄存器,然后读取返回的数据,完成对NAND Flash的读写操作。 综上所述,通过合理配置STM32F4的GPIO和FSMC接口,并结合STM32Cube库函数和DMA控制器,我们可以实现对NAND Flash的驱动。这样可以充分发挥STM32F4的性能优势,实现高速、可靠的数据存储和读取,满足各种应用的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值