STM32F767 Nucleo 接入NAND

/ 0评 / 0

 
其实是为了测试我这个新买的好杜邦新.
接入的NAND是K91FG080U0E,包含1024 Blocks,每个Block包含 64 Pages,每个Page包含2K Bytes数据空间 + 64 Bytes冗余空间,总大小=1024 Blocks x 64 Pages x (2K+ 64) B = (1024 + 32) MBits = 1G Bits.
先用Cube生成工程,把CPU时钟设置成216MHz这个应该不用多说了.

然后把USART3绑定在PD9,PD8.

然后引脚排列真的乱啊,在芯片上是相邻的引脚,却不一定排针上相邻.

 
所以也不用想着走线是否等长,没有这么一回事.引脚有这么几个.

  1. I/O0 ~ I/O7:用于输入地址/数据/命令/输出数据,接线无难度.
  2. CLE:命令锁存使能,在输入命令之前,要先在模式寄存器中,设置CLE使能,接FMC_CLE引脚.
  3. ALE:地址锁存使能,在输入地址之前,要先在模式寄存器中,设置ALE使能,接FMC_ALE引脚.
  4. CE#:芯片使能,在操作Nand Flash之前,要先选中此芯片,才能操作,接FMC_NCE引脚.
  5. RE#:读使能,在读取数据之前,要先使RE#有效,接FMC_NOE引脚.
  6. WE#:写使能,在写取数据之前,要先使WE#有效,接FMC_NWE引脚.
  7. R/B#:就绪/忙,主要用于在发送完编程/擦除命令后,检测这些操作是否完成,忙,表示编程/擦除操作仍在进行中,就绪表示操作完成.接FMC_NWAIT引脚.

然后配置好速度,因为不等长的,所以速度估计比手册要慢一些,我的测试程序如下.
用低格方式鉴别Flash,很好的是我这Flash竟然没坏块.

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f7xx_hal.h"
/* USER CODE BEGIN Includes */
#include <string.h>
/* USER CODE END Includes */
/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart3;
NAND_HandleTypeDef hnand1;
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
NAND_IDTypeDef NAND_ID;
NAND_AddressTypeDef WriteReadAddr;
#define NAND_PAGE_SIZE             ((uint16_t)0x0800) /* 2 * 1024 bytes per page w/o Spare Area */
#define NAND_BLOCK_SIZE            ((uint16_t)0x0040) /* 64 pages per block */
#define NAND_ZONE_SIZE             ((uint16_t)0x0400) /* 1024 Block per zone */
#define NAND_SPARE_AREA_SIZE       ((uint16_t)0x0040) /* last 64 bytes as spare area */
#define NAND_MAX_ZONE              ((uint16_t)0x0001) /* 1 zones of 1024 block */
static uint8_t TxBuffer [NAND_PAGE_SIZE];
static uint8_t RxBuffer [NAND_PAGE_SIZE];
uint16_t i, j;
uint16_t block = 0, page = 0;
uint16_t status;
uint8_t bad = 0;
uint8_t bad_t[1024] = {0x00};
uint16_t bad_cnt = 0;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void Error_Handler(void);
static void MX_GPIO_Init(void);
static void MX_FMC_Init(void);
static void MX_USART3_UART_Init(void);
/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
int fputc(int ch, FILE *f)
{
    /* Place your implementation of fputc here */
    /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
    HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 0xFFFF);
    return ch;
}
/* USER CODE END 0 */
int main(void)
{
    /* USER CODE BEGIN 1 */
    HAL_StatusTypeDef res;
    /* USER CODE END 1 */
    /* MCU Configuration----------------------------------------------------------*/
    /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    HAL_Init();
    /* Configure the system clock */
    SystemClock_Config();
    /* Initialize all configured peripherals */
    MX_GPIO_Init();
    MX_FMC_Init();
    MX_USART3_UART_Init();
    /* USER CODE BEGIN 2 */
    printf("
 NandFlash Example 

");
    //	HAL_NAND_Reset(&hnand1);
    /* Read the NAND memory ID */
    res = HAL_NAND_Read_ID(&hnand1, &NAND_ID);
    printf("
 NandID %d 

", res);
    printf("Nand Flash ID = 0x%02X,0x%02X,0x%02X,0x%02X  ", NAND_ID.Maker_Id, NAND_ID.Device_Id,
           NAND_ID.Third_Id, NAND_ID.Fourth_Id );
    /* NAND memory address to write to */
    WriteReadAddr.Plane = 0x00;
    WriteReadAddr.Block = 0x00;
    WriteReadAddr.Page = 0x00;
    /* Fill the buffer to send */
    for (i = 0; i < NAND_ZONE_SIZE; i++ )
    {
        WriteReadAddr.Block = i;
        res = HAL_NAND_Erase_Block(&hnand1, &WriteReadAddr);
    }
    /* Erase the NAND first Block */
    HAL_Delay(100);
    WriteReadAddr.Plane = 0x00;
    WriteReadAddr.Block = 0x00;
    WriteReadAddr.Page = 0x00;
    while(1)
    {
        printf("check 0xff now
");
        for (i = 0; i < NAND_ZONE_SIZE; i++ )
        {
            WriteReadAddr.Block = i;
            res = HAL_NAND_Erase_Block(&hnand1, &WriteReadAddr);
        }
        for(block = 0; block < 1024; block++)
        {
            bad = 0;
            for(page = 0; page < 64; page++)
            {
                WriteReadAddr.Block = block;
                WriteReadAddr.Page = page;
                /* Read data from FMC NAND memory */
                HAL_NAND_Read_Page(&hnand1, &WriteReadAddr, RxBuffer, 1);
                for(j = 0; j < 2048; j++)
                {
                    if(RxBuffer[j] != 0xFF)
                    {
                        /*
                        if(RxBuffer[j] != 0x00)
                        	if(RxBuffer[j] != 0x30)
                        		if(RxBuffer[j] != 0x55)
                        				if(RxBuffer[j] != 0xAA)
                        	printf("0x%02X 
",RxBuffer[j]);
                        */
                        bad = 1;
                    }
                }
            }
            if(bad)
            {
                bad_t[block] = 0x01;
                printf("bad blk = %d
", block);
                bad_cnt++;
            }
            else
            {
                bad_t[block] = 0x00;
            }
        }
        printf("check 0xaa now
");
        for (i = 0; i < NAND_ZONE_SIZE; i++ )
        {
            WriteReadAddr.Block = i;
            res = HAL_NAND_Erase_Block(&hnand1, &WriteReadAddr);
        }
        for(block = 0; block < 1024; block++)
        {
            bad = 0;
            if(bad_t[block] == 0x00)
            {
                for(page = 0; page < 64; page++)
                {
                    WriteReadAddr.Block = block;
                    WriteReadAddr.Page = page;
                    for (i = 0; i < NAND_PAGE_SIZE; i++ )
                    {
                        TxBuffer[i] = 0xAA;
                    }
                    HAL_NAND_Write_Page(&hnand1, &WriteReadAddr, TxBuffer, 1);
                    HAL_Delay(1);
                    /* Read data from FMC NAND memory */
                    HAL_NAND_Read_Page(&hnand1, &WriteReadAddr, RxBuffer, 1);
                    for(j = 0; j < 2048; j++)
                    {
                        if(RxBuffer[j] != 0xAA)
                        {
                            //printf("0x%02X 
",TxBuffer[j]);
                            bad = 1;
                        }
                    }
                }
                if(bad)
                {
                    bad_t[block] = 0x01;
                    printf("bad blk = %d
", block);
                    bad_cnt++;
                }
                else
                {
                    bad_t[block] = 0x00;
                }
            }
        }
        printf("check 0xaa now
");
        for (i = 0; i < NAND_ZONE_SIZE; i++ )
        {
            WriteReadAddr.Block = i;
            res = HAL_NAND_Erase_Block(&hnand1, &WriteReadAddr);
        }
        for(block = 0; block < 1024; block++)
        {
            bad = 0;
            if(bad_t[block] == 0x00)
            {
                for(page = 0; page < 64; page++)
                {
                    WriteReadAddr.Block = block;
                    WriteReadAddr.Page = page;
                    for (i = 0; i < NAND_PAGE_SIZE; i++ )
                    {
                        TxBuffer[i] = 0x55;
                    }
                    HAL_NAND_Write_Page(&hnand1, &WriteReadAddr, TxBuffer, 1);
                    HAL_Delay(1);
                    /* Read data from FMC NAND memory */
                    HAL_NAND_Read_Page(&hnand1, &WriteReadAddr, RxBuffer, 1);
                    for(j = 0; j < 2048; j++)
                    {
                        if(RxBuffer[j] != 0x55)
                        {
                            //printf("0x%02X 
",TxBuffer[j]);
                            bad = 1;
                        }
                    }
                }
                if(bad)
                {
                    bad_t[block] = 0x01;
                    printf("bad blk = %d
", block);
                    bad_cnt++;
                }
                else
                {
                    bad_t[block] = 0x00;
                }
            }
        }
        printf("check 0x00 now
");
        for (i = 0; i < NAND_ZONE_SIZE; i++ )
        {
            WriteReadAddr.Block = i;
            res = HAL_NAND_Erase_Block(&hnand1, &WriteReadAddr);
        }
        for(block = 0; block < 1024; block++)
        {
            bad = 0;
            if(bad_t[block] == 0x00)
            {
                for(page = 0; page < 64; page++)
                {
                    WriteReadAddr.Block = block;
                    WriteReadAddr.Page = page;
                    for (i = 0; i < NAND_PAGE_SIZE; i++ )
                    {
                        TxBuffer[i] = 0x00;
                    }
                    HAL_NAND_Write_Page(&hnand1, &WriteReadAddr, TxBuffer, 1);
                    HAL_Delay(1);
                    /* Read data from FMC NAND memory */
                    HAL_NAND_Read_Page(&hnand1, &WriteReadAddr, RxBuffer, 1);
                    for(j = 0; j < 2048; j++)
                    {
                        if(RxBuffer[j] != 0x00)
                        {
                            bad = 1;
                        }
                    }
                }
                if(bad)
                {
                    bad_t[block] = 0x01;
                    printf("bad blk = %d
", block);
                    bad_cnt++;
                }
                else
                {
                    bad_t[block] = 0x00;
                }
            }
        }
        printf("bad cnt = %d
", bad_cnt);
        while(1)
        {
        }
    }
    /* USER CODE END 2 */
}
/** System Clock Configuration
*/
void SystemClock_Config(void)
{
    RCC_OscInitTypeDef RCC_OscInitStruct;
    RCC_ClkInitTypeDef RCC_ClkInitStruct;
    RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
    /**Configure the main internal regulator output voltage
    */
    __HAL_RCC_PWR_CLK_ENABLE();
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
    /**Initializes the CPU, AHB and APB busses clocks
    */
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    RCC_OscInitStruct.HSICalibrationValue = 16;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
    RCC_OscInitStruct.PLL.PLLM = 8;
    RCC_OscInitStruct.PLL.PLLN = 216;
    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    RCC_OscInitStruct.PLL.PLLQ = 2;
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    {
        Error_Handler();
    }
    /**Activate the Over-Drive mode
    */
    if (HAL_PWREx_EnableOverDrive() != HAL_OK)
    {
        Error_Handler();
    }
    /**Initializes the CPU, AHB and APB busses clocks
    */
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
                                  | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK)
    {
        Error_Handler();
    }
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART3;
    PeriphClkInitStruct.Usart3ClockSelection = RCC_USART3CLKSOURCE_PCLK1;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    {
        Error_Handler();
    }
    /**Configure the Systick interrupt time
    */
    HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000);
    /**Configure the Systick
    */
    HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
    /* SysTick_IRQn interrupt configuration */
    HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
/* USART3 init function */
static void MX_USART3_UART_Init(void)
{
    huart3.Instance = USART3;
    huart3.Init.BaudRate = 115200;
    huart3.Init.WordLength = UART_WORDLENGTH_7B;
    huart3.Init.StopBits = UART_STOPBITS_1;
    huart3.Init.Parity = UART_PARITY_NONE;
    huart3.Init.Mode = UART_MODE_TX_RX;
    huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart3.Init.OverSampling = UART_OVERSAMPLING_16;
    huart3.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
    huart3.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
    if (HAL_UART_Init(&huart3) != HAL_OK)
    {
        Error_Handler();
    }
}
/* FMC initialization function */
static void MX_FMC_Init(void)
{
    FMC_NAND_PCC_TimingTypeDef ComSpaceTiming;
    /** Perform the NAND1 memory initialization sequence
    */
    hnand1.Instance = FMC_NAND_DEVICE;
    /* hnand1.Init */
    hnand1.Init.NandBank = FMC_NAND_BANK3;
    hnand1.Init.Waitfeature = FMC_NAND_WAIT_FEATURE_ENABLE;
    hnand1.Init.MemoryDataWidth = FMC_NAND_MEM_BUS_WIDTH_8;
    hnand1.Init.EccComputation = FMC_NAND_ECC_ENABLE;
    hnand1.Init.ECCPageSize = FMC_NAND_ECC_PAGE_SIZE_512BYTE;
    hnand1.Init.TCLRSetupTime = 0;
    hnand1.Init.TARSetupTime = 0;
    /* hnand1.Config */
    hnand1.Config.PageSize = 2048;
    hnand1.Config.SpareAreaSize = 64;
    hnand1.Config.BlockSize = 64;
    hnand1.Config.BlockNbr = 64;
    hnand1.Config.PlaneNbr = 1;
    hnand1.Config.PlaneSize = 1024;
    hnand1.Config.ExtraCommandEnable = DISABLE;
    /* ComSpaceTiming */
    ComSpaceTiming.SetupTime = 10;
    ComSpaceTiming.WaitSetupTime = 4;
    ComSpaceTiming.HoldSetupTime = 4;
    ComSpaceTiming.HiZSetupTime = 10;
    if (HAL_NAND_Init(&hnand1, &ComSpaceTiming, &ComSpaceTiming) != HAL_OK)
    {
        Error_Handler();
    }
}
/** Pinout Configuration
*/
static void MX_GPIO_Init(void)
{
    /* GPIO Ports Clock Enable */
    __HAL_RCC_GPIOE_CLK_ENABLE();
    __HAL_RCC_GPIOD_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
  * @brief  This function is executed in case of error occurrence.
  * @param  None
  * @retval None
  */
void Error_Handler(void)
{
    /* USER CODE BEGIN Error_Handler */
    /* User can add his own implementation to report the HAL error return state */
    while(1)
    {
    }
    /* USER CODE END Error_Handler */
}
#ifdef USE_FULL_ASSERT
/**
   * @brief Reports the name of the source file and the source line number
   * where the assert_param error has occurred.
   * @param file: pointer to the source file name
   * @param line: assert_param error line source number
   * @retval None
   */
void assert_failed(uint8_t *file, uint32_t line)
{
    /* USER CODE BEGIN 6 */
    /* User can add his own implementation to report the file name and line number,
      ex: printf("Wrong parameters value: file %s on line %d
", file, line) */
    /* USER CODE END 6 */
}
#endif
/**
  * @}
  */
/**
  * @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

 

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注