942 views|3 replies

410

Posts

3

Resources
The OP
 

【CW32L052 Review】 spi flash read and write test [Copy link]

 This post was last edited by TL-LED on 2023-7-22 06:39

This article tests the SPI flash read and write test based on the board's routines, and the serial port prints the test content.

1. Hardware Circuit

1.1、SPI FLASH on the board

The chip used is W25Q64, connected to the PC00~PC03 pins of the MCU.

1.2、PC00~PC03 pin mapping

1.3. w25q64 instructions

2. Procedure

2.1, fun_flash.c

#include "main.h"

#define  BufferSize                     (ARRAY_SZ(TxBuffer) - 1)
#define  FLASH_WriteAddress             0x00000
#define  FLASH_ReadAddress              FLASH_WriteAddress
#define  FLASH_SectorToEraseAddress     FLASH_WriteAddress

typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus;

//SPI TEST
uint8_t TxBuffer[] = "cw32l052 board write and read spi flash test!";
uint8_t RxBuffer[BufferSize];

uint8_t DeviceID = 0;
uint16_t ManufactDeviceID = 0;
int32_t JedecID = 0;
uint8_t UniqueID[8];

uint8_t status1;
uint8_t status2;
volatile TestStatus TransferStatus = FAILED; 



void  init_spi_flash(void)
{
	SPI_InitTypeDef  SPI_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
	
 /************************GPIO Configuration***********************/
  RCC_AHBPeriphClk_Enable(FLASH_SPI_SCK_GPIO_CLK | FLASH_SPI_MISO_GPIO_CLK | FLASH_SPI_MOSI_GPIO_CLK | FLASH_SPI_CS_GPIO_CLK, ENABLE);
  FLASH_SPI_APBClkENx(FLASH_SPI_CLK, ENABLE);

  //SPI SCK MOSI MISO ′ó
  FLASH_SPI_AF_SCK;
  FLASH_SPI_AF_MISO;  
  FLASH_SPI_AF_MOSI;     

  //CS
  GPIO_InitStructure.Pins = FLASH_SPI_CS_GPIO_PIN;
  GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_Init(FLASH_SPI_CS_GPIO_PORT, &GPIO_InitStructure);

  //SCK   
  GPIO_InitStructure.Pins = FLASH_SPI_SCK_GPIO_PIN;
  GPIO_Init(FLASH_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);

  //MOSI
  GPIO_InitStructure.Pins = FLASH_SPI_MOSI_GPIO_PIN;
  GPIO_Init(FLASH_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);

  //MISO
  GPIO_InitStructure.Pins = FLASH_SPI_MISO_GPIO_PIN;
  GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
  GPIO_Init(FLASH_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);

  //à-CS
  FLASH_SPI_CS_HIGH();

  /************************SPI Configuration***********************/
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;    // è1¤
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                         // ÷ú£ê
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                     // êyY3¤èa8bit
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;                           // ê±óDμa
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;                          // μút±2éù
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                             // DoóéSSI′÷
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;    // 2¨ìêaPCLKμ8·μ
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                    // ×óDD§ MSB ê·¢ú°
  SPI_InitStructure.SPI_Speed = SPI_Speed_Low;                          // μíùSPI
  
  SPI_Init(FLASH_SPIx, &SPI_InitStructure);
  SPI_Cmd(FLASH_SPIx, ENABLE); 
}

/**
 * [url=home.php?mod=space&uid=159083]@brief[/url] í¨1ySPIáèò×úμêyY
 * 
 * [url=home.php?mod=space&uid=784970]@return[/url] uint8_t :óêμμêyY
 */
uint8_t SPI_FLASH_ReadByte(void)
{
  return (SPI_FLASH_SendByte(FLASH_DUMMY_BYTE));
}

/**
 * @brief í¨1ySPI·¢íò×úμêyY£2¢·μóêμμò×úêyY
 * 
 * @param byte :′y·¢íμêyY
 * @return uint8_t :óêμμêyY
 */
uint8_t SPI_FLASH_SendByte(uint8_t byte)
{
  while(SPI_GetFlagStatus(FLASH_SPIx, SPI_FLAG_TXE) == RESET);

  SPI_SendData(FLASH_SPIx, byte);

  while(SPI_GetFlagStatus(FLASH_SPIx, SPI_FLAG_RXNE) == RESET);

  return SPI_ReceiveData(FLASH_SPIx);
}

/**
 * @brief í¨1ySPI·¢íá×úμêyY£2¢·μóêμμá×úêyY
 * 
 * @param HalfWord :′y·¢íμêyY
 * @return uint16_t :óêμμêyY
 */
uint16_t SPI_FLASH_SendHalfWord(uint16_t HalfWord)
{
  while(SPI_GetFlagStatus(FLASH_SPIx, SPI_FLAG_TXE) == RESET);

  SPI_SendData(FLASH_SPIx, HalfWord);

  while(SPI_GetFlagStatus(FLASH_SPIx, SPI_FLAG_RXNE) == RESET);
	
  return SPI_ReceiveData(FLASH_SPIx);
}

/**
 * @brief òFLASH·¢í D′ê1ü á
 * 
 */
void SPI_FLASH_WriteEnable(void)
{
  FLASH_SPI_CS_LOW();

  //·¢í D′ê1ü á
  SPI_FLASH_SendByte(FLASH_CMD_WriteEnable);

  FLASH_SPI_CS_HIGH();
}

 /**
  * @brief μè′y2á3yò±à3ìíê3é
  * 
  */
void SPI_FLASH_WaitForWriteEnd(void)
{
  uint8_t flashstatus = 0;

  FLASH_SPI_CS_LOW();

  // ·¢í á×′ì′÷1 á
  SPI_FLASH_SendByte(FLASH_CMD_ReadStatusReg1);

  do
  {
    //áFLASH×′ì′÷
    flashstatus = SPI_FLASH_ReadByte();	 
  }while((flashstatus & FLASH_WIP_FLAG) == SET);  //yúD′è£ìD-·

  FLASH_SPI_CS_HIGH();
}

/**
 * @brief á×′ì′÷1
 * 
 * @return uint8_t 
 */
uint8_t SPI_FLASH_ReadStatusReg1(void)
{
  uint8_t flashstatus = 0;

  FLASH_SPI_CS_LOW();

  // ·¢í á×′ì′÷1 á
  SPI_FLASH_SendByte(FLASH_CMD_ReadStatusReg1);

  flashstatus = SPI_FLASH_ReadByte();	

  FLASH_SPI_CS_HIGH(); 

  return flashstatus;
}

/**
 * @brief á×′ì′÷2
 * 
 * @return uint8_t 
 */
uint8_t SPI_FLASH_ReadStatusReg2(void)
{
  uint8_t flashstatus = 0;

  FLASH_SPI_CS_LOW();

  // ·¢í á×′ì′÷2 á
  SPI_FLASH_SendByte(FLASH_CMD_ReadStatusReg2);

  flashstatus = SPI_FLASH_ReadByte();	

  FLASH_SPI_CS_HIGH(); 

  return flashstatus;
}

/**
 * @brief D′×′ì′÷1
 * 
 * @param status 
 */
void SPI_FLASH_WriteStatusReg1(uint8_t status)
{
  //·¢í D′ê1ü á
  SPI_FLASH_WriteEnable();

  FLASH_SPI_CS_LOW();

  // ·¢í D′×′ì′÷1 á
  SPI_FLASH_SendByte(FLASH_CMD_WriteStatusReg1);

  //·¢í ×′ì′÷1 éè¨μ
  SPI_FLASH_SendByte(status);

  FLASH_SPI_CS_HIGH(); 

  //μè′yD′èíê3é
  SPI_FLASH_WaitForWriteEnd();
}

/**
 * @brief D′×′ì′÷2
 * 
 * @param status 
 */
void SPI_FLASH_WriteStatusReg2(uint8_t status)
{
  //·¢í D′ê1ü á
  SPI_FLASH_WriteEnable();

  FLASH_SPI_CS_LOW();

  // ·¢í D′×′ì′÷2 á
  SPI_FLASH_SendByte(FLASH_CMD_WriteStatusReg2);

  //·¢í ×′ì′÷2 éè¨μ
  SPI_FLASH_SendByte(status);

  FLASH_SPI_CS_HIGH(); 

  //μè′yD′èíê3é
  SPI_FLASH_WaitForWriteEnd();
}

/**
 * @brief éè2á3y 4KB
 * 
 * @param SectorAddr :′y2á3yμéèμ·
 */
void SPI_FLASH_SectorErase(uint32_t SectorAddr)
{
  //·¢í D′ê1ü á
  SPI_FLASH_WriteEnable();
  //μè′yD′èíê3é
  // SPI_FLASH_WaitForWriteEnd();

  FLASH_SPI_CS_LOW();

  //·¢í éè2á3y á
  SPI_FLASH_SendByte(FLASH_CMD_SectorErase);

  //·¢í ′y2á3yéèμ·
  SPI_FLASH_SendByte((SectorAddr & 0xFF0000) >> 16);
  SPI_FLASH_SendByte((SectorAddr & 0xFF00) >> 8);
  SPI_FLASH_SendByte(SectorAddr & 0xFF);

  FLASH_SPI_CS_HIGH();

  //μè′y2á3yíê3é
  SPI_FLASH_WaitForWriteEnd();
}

/**
 * @brief é2á3y 64KB
 * 
 * @param BlockAddr :′y2á3yμéμ·
 */
void SPI_FLASH_BlockErase(uint32_t BlockAddr)
{
  //·¢í D′ê1ü á
  SPI_FLASH_WriteEnable();
  //μè′yD′èíê3é
  // SPI_FLASH_WaitForWriteEnd();

  FLASH_SPI_CS_LOW();

  //·¢í é2á3y á
  SPI_FLASH_SendByte(FLASH_CMD_BlockErase);

  //·¢í ′y2á3yéμ·
  SPI_FLASH_SendByte((BlockAddr & 0xFF0000) >> 16);
  SPI_FLASH_SendByte((BlockAddr & 0xFF00) >> 8);
  SPI_FLASH_SendByte(BlockAddr & 0xFF);

  FLASH_SPI_CS_HIGH();

  //μè′y2á3yíê3é
  SPI_FLASH_WaitForWriteEnd();
}

/**
 * @brief 2á3y
 * 
 */
void SPI_FLASH_ChipErase(void)
{
  //·¢í D′ê1ü á
  SPI_FLASH_WriteEnable();

  FLASH_SPI_CS_LOW();

  //·¢í 2á3y á
  SPI_FLASH_SendByte(FLASH_CMD_ChipErase);

  FLASH_SPI_CS_HIGH();

  //μè′y2á3yíê3é
  SPI_FLASH_WaitForWriteEnd();
}

/**
 * @brief ò3D′èêyY
 * 
 * @param pBuffer :′yD′èêyYμ
 * @param WriteAddr :D′èμ·
 * @param NumByteToWrite :D′èêyY3¤è
 * @note
 *    -Dèòaè2á3y
 *    -NumByteToWrite <= SPI_FLASH_PerWritePageSize
 */
void SPI_FLASH_PageWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
  //·¢í D′ê1ü á
  SPI_FLASH_WriteEnable();

  FLASH_SPI_CS_LOW();

  //·¢í ò3D′è á
  SPI_FLASH_SendByte(FLASH_CMD_PageProgram);

  //·¢í D′μ·
  SPI_FLASH_SendByte((WriteAddr & 0xFF0000) >> 16);
  SPI_FLASH_SendByte((WriteAddr & 0xFF00) >> 8);
  SPI_FLASH_SendByte(WriteAddr & 0xFF);

  //D′èêyY
  while(NumByteToWrite--)
  {
    SPI_FLASH_SendByte(*pBuffer);
    pBuffer++;
  }

  FLASH_SPI_CS_HIGH();

  //μè′yD′èíê3é
  SPI_FLASH_WaitForWriteEnd();
}

/**
 * @brief D′è2¨áêyY
 * 
 * @param pBuffer :′yD′èêyYμ
 * @param WriteAddr :D′èμ·
 * @param NumByteToWrite :D′èêyY3¤è
 * @note
 *    -Dèòaè2á3y
 */
void SPI_FLASH_BufferWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
  uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;
	
  Addr = WriteAddr % SPI_FLASH_PageSize;
  count = SPI_FLASH_PageSize - Addr;
  NumOfPage =  NumByteToWrite / SPI_FLASH_PageSize;
  NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;
	
  if(Addr == 0) /* WriteAddr o°′ò3 */
  {
    if(NumOfPage == 0) /* NumByteToWrite < SPI_FLASH_PageSize */ 
    {
      SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
    }
    else /* NumByteToWrite >= SPI_FLASH_PageSize */
    { 
      while(NumOfPage--)
      {
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);
        WriteAddr +=  SPI_FLASH_PageSize;
        pBuffer += SPI_FLASH_PageSize;
      }

      if(NumOfSingle != 0)
      {
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);
      }
    }
  }
  else /* WriteAddr ó SPI_FLASH_PageSize 2  */
  {
    if(NumOfPage == 0) /* NumByteToWrite < SPI_FLASH_PageSize */
    {
      if(NumOfSingle > count) /*!< (NumByteToWrite + WriteAddr) > SPI_FLASH_PageSize */
      {
        temp = NumOfSingle - count;
        
        //D′íêμ±°ò3
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);
        WriteAddr +=  count;
        pBuffer += count;

        //D′ê£óàêyY
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, temp);
      }
      else
      {
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
      }
    }
    else /* NumByteToWrite >= SPI_FLASH_PageSize */
    {
      NumByteToWrite -= count;
      NumOfPage =  NumByteToWrite / SPI_FLASH_PageSize;
      NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;
			
      //èD′íêμ±°ò3£òoóμ·
      SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);
      WriteAddr +=  count;
      pBuffer += count;

      //WriteAddr o°′ò3
      while(NumOfPage--)
      {
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);
        WriteAddr +=  SPI_FLASH_PageSize;
        pBuffer += SPI_FLASH_PageSize;
      }

      if(NumOfSingle != 0)
      {
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);
      }
    }
  }
}

/**
 * @brief áêyY
 * 
 * @param pBuffer :′′¢á3êyYμ
 * @param ReadAddr :áèμ·
 * @param NumByteToRead :áèêyY3¤è
 */
void SPI_FLASH_BufferRead(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead)
{
  FLASH_SPI_CS_LOW();

  //·¢í áêyY á
  SPI_FLASH_SendByte(FLASH_CMD_ReadData);

  //·¢í áμ·
  SPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
  SPI_FLASH_SendByte((ReadAddr& 0xFF00) >> 8);
  SPI_FLASH_SendByte(ReadAddr & 0xFF);
	
  //áêyY
  while(NumByteToRead--)
  {
    *pBuffer = SPI_FLASH_ReadByte();
    pBuffer++;
  }

  FLASH_SPI_CS_HIGH();
}

/**
 * @brief ˉáèêyY×úDòáD
 * 
 * @param ReadAddr :áèμ·
 */
void SPI_FLASH_StartReadSequence(uint32_t ReadAddr)
{
  FLASH_SPI_CS_LOW();

  //·¢í áêyY á
  SPI_FLASH_SendByte(FLASH_CMD_ReadData);

  //·¢í áμ·
  SPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
  SPI_FLASH_SendByte((ReadAddr& 0xFF00) >> 8);
  SPI_FLASH_SendByte(ReadAddr & 0xFF);
}

/**
 * @brief áèDevice ID
 * 
 * @return uint8_t :Device ID
 */
uint8_t SPI_FLASH_DeviceID(void)
{
  uint8_t Temp = 0;

  FLASH_SPI_CS_LOW();

  //·¢í áDevice ID á
  SPI_FLASH_SendByte(FLASH_CMD_DeviceID);

  SPI_FLASH_SendByte(FLASH_DUMMY_BYTE);
  SPI_FLASH_SendByte(FLASH_DUMMY_BYTE);
  SPI_FLASH_SendByte(FLASH_DUMMY_BYTE);
  
  //áêyY
  Temp = SPI_FLASH_ReadByte();

  FLASH_SPI_CS_HIGH();

  return Temp;
}

/**
 * @brief áèManufacturer / Device ID
 * 
 * @return uint16_t :Manufacturer / Device ID
 */
uint16_t SPI_FLASH_ManufactDeviceID(void)
{
  uint16_t Temp = 0, Temp0 = 0, Temp1 = 0;

  FLASH_SPI_CS_LOW();

  //·¢í áManufacturer / Device ID á
  SPI_FLASH_SendByte(FLASH_CMD_ManufactDeviceID);

  SPI_FLASH_SendByte(0x00);
  SPI_FLASH_SendByte(0x00);
  SPI_FLASH_SendByte(0x00);

  //áêyY
  Temp0 = SPI_FLASH_ReadByte();
  Temp1 = SPI_FLASH_ReadByte();

  FLASH_SPI_CS_HIGH();

  Temp = (Temp0 << 8) | Temp1;

  return Temp;
}

/**
 * @brief áèJEDEC ID
 * 
 * @return uint32_t :JEDEC ID
 */
uint32_t SPI_FLASH_JedecID(void)
{
  uint32_t Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;

  FLASH_SPI_CS_LOW();

  //·¢í áJEDEC ID á
  SPI_FLASH_SendByte(FLASH_CMD_JedecID);

  //áêyY
  Temp0 = SPI_FLASH_ReadByte();
  Temp1 = SPI_FLASH_ReadByte();
  Temp2 = SPI_FLASH_ReadByte();

  FLASH_SPI_CS_HIGH();

  Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;

  return Temp;
}

/**
 * @brief áèUnique ID (64bit)
 * 
 * @param pBuffer :′·UIDμBuffer
 */
void SPI_FLASH_UniqueID(uint8_t* pBuffer)
{
  uint8_t NumByteToRead = 8;

  FLASH_SPI_CS_LOW();

  //·¢í áUnique ID á
  SPI_FLASH_SendByte(FLASH_CMD_UniqueID);

  SPI_FLASH_SendByte(FLASH_DUMMY_BYTE);
  SPI_FLASH_SendByte(FLASH_DUMMY_BYTE);
  SPI_FLASH_SendByte(FLASH_DUMMY_BYTE);
  SPI_FLASH_SendByte(FLASH_DUMMY_BYTE);

  //áêyY
  while(NumByteToRead--)
  {
    *pBuffer = SPI_FLASH_ReadByte();
    pBuffer++;
  }

  FLASH_SPI_CS_HIGH();
}

/**
 * @brief èμμ£ê
 * 
 */
void SPI_FLASH_PowerDown(void)   
{ 
  FLASH_SPI_CS_LOW();

  //·¢í μμ á
  SPI_FLASH_SendByte(FLASH_CMD_PowerDown);

  FLASH_SPI_CS_HIGH();
}   

/**
 * @brief D
 * 
 */
void SPI_FLASH_WAKEUP(void)   
{
  FLASH_SPI_CS_LOW();

  //·¢í Release Power-down or High Performance Mode á
  SPI_FLASH_SendByte(FLASH_CMD_ReleasePowerDown);

  FLASH_SPI_CS_HIGH();
} 

TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength)
{
  while(BufferLength--)
  {
    if(*pBuffer1 != *pBuffer2)
    {
      return FAILED;
    }
    
    pBuffer1++;
    pBuffer2++;
  }

  return PASSED;  
}

void SPI_FLASH_Test(void)
{
	printf("SPI_FLASH Test Start\r\n");
	
	DeviceID = SPI_FLASH_DeviceID();
  ManufactDeviceID = SPI_FLASH_ManufactDeviceID();
  JedecID = SPI_FLASH_JedecID();	
  SPI_FLASH_UniqueID(UniqueID);

  printf("\r\nDeviceID = 0x%X\r\nManufactDeviceID = 0x%X\r\nJedecID = 0x%X\r\n", DeviceID, ManufactDeviceID, JedecID);	
//  printf("\r\nUniqueID = 0x ");
//  for(uint8_t i = 0;i<8;i++)
//  {
//    printf("%X ", UniqueID[i]);
//  }

  /* á×′ì′÷ */
  status1 = SPI_FLASH_ReadStatusReg1();
  status2 = SPI_FLASH_ReadStatusReg2();
//  printf("\r\nstatus1 = 0x%X\r\nstatus2 = 0x%X\r\n", status1, status2);

  // /* D′×′ì′÷ */
  // SPI_FLASH_WriteStatusReg1(0x00);
  // SPI_FLASH_WriteStatusReg2(0x00);
  // status1 = SPI_FLASH_ReadStatusReg1();
  // status2 = SPI_FLASH_ReadStatusReg2();
  // printf("\r\nstatus1 = 0x%X\r\nstatus2 = 0x%X\r\n", status1, status2);
   /* Check JEDEC ID */
	if(JedecID == sJedecID)
	{	
		//2á3yéè 4KB
		SPI_FLASH_SectorErase(FLASH_SectorToEraseAddress);	 	 

		//D′êyY
		SPI_FLASH_BufferWrite(TxBuffer, FLASH_WriteAddress, BufferSize);		
		printf("D′èμêyYa£o%s\r\n", TxBuffer);

		//áêyY
		SPI_FLASH_BufferRead(RxBuffer, FLASH_ReadAddress, BufferSize);
		printf("á3μêyYa£o%s\r\n", RxBuffer);

		//ì2éD′èμêyYóá3μêyYê·ò
		TransferStatus = Buffercmp(TxBuffer, RxBuffer, BufferSize);

		if(TransferStatus == PASSED)
		{ 
			printf("SPI_FLASH Test OK\r\n");
		}
		else
		{        
			printf("\r\nSPI_FLASH Test Error:Read and Write Data is not same\r\n");
			while(1);
		}
		
		//2á3yéè 4KB
		SPI_FLASH_SectorErase(FLASH_SectorToEraseAddress);

		//áêyY
		SPI_FLASH_BufferRead(RxBuffer, FLASH_ReadAddress, BufferSize);

		for(uint8_t j = 0; j < BufferSize; j++)
		{
			if(RxBuffer[j] != 0xFF)
			{
				printf("\r\nSPI_FLASH Test Error:FLASH Erase fail\r\n");
				while(1);
			}
		}
	}
	else// (FlashID £= sFLASH_ID)
	{ 
		printf("\r\nSPI_FLASH Test Error:Read JEDEC ID Error\r\n");
		while(1);
	}	
		
}

2.2, fun_flash.h

#ifndef __FUN_FLASH_H
#define __FUN_FLASH_H

#ifdef __cplusplus
 extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "cw32l052.h"
//#include "cw32l052_rcc.h"
//#include "cw32l052_gpio.h"
//#include "cw32l052_spi.h"

/******************************************************************************
 * type definitions ('typedef')
 ******************************************************************************/

/******************************************************************************
 * pre-processor symbols/macros ('#define')
 ******************************************************************************/
 //Manufacturer and Device Identification (W25Q64)
#define sDeviceID                         0x16
#define sManufactDeviceID                 0xEF16
#define sJedecID                          0x5E4017

/* SPI FLASH supported commands */
#define FLASH_CMD_WriteEnable		      0x06 
#define FLASH_CMD_WriteDisable		      0x04 
#define FLASH_CMD_ReadStatusReg1		  0x05 
#define FLASH_CMD_ReadStatusReg2		  0x35 
#define FLASH_CMD_WriteStatusReg1		  0x01 
#define FLASH_CMD_WriteStatusReg2		  0x31
#define FLASH_CMD_ReadData			      0x03 
#define FLASH_CMD_FastReadData		      0x0B 
#define FLASH_CMD_FastReadDual		      0x3B 
#define FLASH_CMD_PageProgram		      0x02 
#define FLASH_CMD_SectorErase		      0x20 
#define FLASH_CMD_BlockErase			  0xD8 
#define FLASH_CMD_ChipErase			      0xC7 
#define FLASH_CMD_PowerDown			      0xB9 
#define FLASH_CMD_ReleasePowerDown	      0xAB 
#define FLASH_CMD_DeviceID			      0xAB 
#define FLASH_CMD_ManufactDeviceID   	  0x90 
#define FLASH_CMD_JedecID		          0x9F
#define FLASH_CMD_UniqueID		          0x4B

/* Write In Progress (WIP) flag */
#define FLASH_WIP_FLAG                    0x01

#define FLASH_DUMMY_BYTE                  0xFF

#define SPI_FLASH_PageSize                256
#define SPI_FLASH_PerWritePageSize        256

//SPIx
#define FLASH_SPIx                        CW_SPI1
#define FLASH_SPI_CLK                     RCC_APB2_PERIPH_SPI1
#define FLASH_SPI_APBClkENx               RCC_APBPeriphClk_Enable2

//SPIx GPIO
#define FLASH_SPI_SCK_GPIO_CLK            RCC_AHB_PERIPH_GPIOE
#define FLASH_SPI_SCK_GPIO_PORT           CW_GPIOC 
#define FLASH_SPI_SCK_GPIO_PIN            GPIO_PIN_1

#define FLASH_SPI_MISO_GPIO_CLK           RCC_AHB_PERIPH_GPIOE
#define FLASH_SPI_MISO_GPIO_PORT          CW_GPIOC
#define FLASH_SPI_MISO_GPIO_PIN           GPIO_PIN_2

#define FLASH_SPI_MOSI_GPIO_CLK           RCC_AHB_PERIPH_GPIOE
#define FLASH_SPI_MOSI_GPIO_PORT          CW_GPIOC
#define FLASH_SPI_MOSI_GPIO_PIN           GPIO_PIN_3

#define FLASH_SPI_CS_GPIO_CLK             RCC_AHB_PERIPH_GPIOE
#define FLASH_SPI_CS_GPIO_PORT            CW_GPIOC 
#define FLASH_SPI_CS_GPIO_PIN             GPIO_PIN_0

//GPIO AF
#define FLASH_SPI_AF_SCK                  PC01_AFx_SPI1SCK()
#define FLASH_SPI_AF_MISO                 PC02_AFx_SPI1MISO()
#define FLASH_SPI_AF_MOSI                 PC03_AFx_SPI1MOSI()

//CS LOW or HIGH
#define FLASH_SPI_CS_LOW()     		      PC00_SETLOW()
#define FLASH_SPI_CS_HIGH()    		      PC00_SETHIGH()


 /******************************************************************************
 * Global variable definitions (declared in header file with 'extern')
 ******************************************************************************/
 
 
 /******************************************************************************
 * Global function prototypes 
 ******************************************************************************/

/* SPI FLASH 3êˉ*/
void init_spi_flash(void);

/* Low layer functions */
uint8_t SPI_FLASH_ReadByte(void);
uint8_t SPI_FLASH_SendByte(uint8_t byte);
uint16_t SPI_FLASH_SendHalfWord(uint16_t HalfWord);
void SPI_FLASH_WriteEnable(void);
void SPI_FLASH_WaitForWriteEnd(void);

/* áD′×′ì′÷ */
uint8_t SPI_FLASH_ReadStatusReg1(void);
uint8_t SPI_FLASH_ReadStatusReg2(void);
void SPI_FLASH_WriteStatusReg1(uint8_t status);
void SPI_FLASH_WriteStatusReg2(uint8_t status);

/* High layer functions */
void SPI_FLASH_SectorErase(uint32_t SectorAddr);
void SPI_FLASH_BlockErase(uint32_t BlockAddr);
void SPI_FLASH_ChipErase(void);

void SPI_FLASH_PageWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);
void SPI_FLASH_BufferWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);
void SPI_FLASH_BufferRead(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead);
void SPI_FLASH_StartReadSequence(uint32_t ReadAddr);

uint8_t SPI_FLASH_DeviceID(void);
uint16_t SPI_FLASH_ManufactDeviceID(void);
uint32_t SPI_FLASH_JedecID(void);
void SPI_FLASH_UniqueID(uint8_t* pBuffer);
void SPI_FLASH_PowerDown(void);
void SPI_FLASH_WAKEUP(void);

void SPI_FLASH_Test(void);

#ifdef __cplusplus
}
#endif
#endif 

2.3, main.c

#include "main.h"

void Delay(uint16_t nCount);

void rcc_config(void)
{
	uint8_t res = 0U;
	RCC_AHBPeriphClk_Enable(RCC_AHB_PERIPH_FLASH, ENABLE);
	RCC_LSI_Enable( );                                                   //开启外部高速时钟LSI
	res = RCC_SysClk_Switch( RCC_SYSCLKSRC_LSI );                        //切换系统时钟到LSI
	if( res == 0x00 )                                                    //系统时钟切换成功
	{
			RCC_HSI_Disable();                                               //切换时钟到PLL后关闭源时钟HSI
			FirmwareDelay( 400 );   //about 100mS
	}
	
	RCC_HSI_Enable( RCC_HSIOSC_DIV1 );                                   //开启内部高速时钟HSI = HSIOSC / 2
	FLASH_SetLatency(FLASH_Latency_3); 
	res = RCC_SysClk_Switch( RCC_SYSCLKSRC_HSI );                        //切换系统时钟到HSI
	if( res == 0x00 )                                                    //系统时钟切换成功
	{
			RCC_LSI_Disable();                                               //切换时钟到HSI后关闭LSI时钟
			FirmwareDelay( 275000 );  //about 100mS
	}
	
	RCC_HCLKPRS_Config(RCC_HCLK_DIV1);
	
	RCC_HCLK_OUT();                           //通过PA04观察HCLK频率
}

int32_t main(void)
{
		GPIO_InitTypeDef GPIO_InitStruct = {0};
		rcc_config();
		init_uart();
		init_led();
		init_spi_flash();
	
    InitTick( 48000000 );                  //初始化SysTick
		SPI_FLASH_Test();
    while (1)
    {
				led2_tog();
				SysTickDelay(100);
				//printf("CW32L052 UART Printf Test!\r\n");
    }
}

/**
 * @brief 循环延时
 *
 * @param nCount
 */
void Delay(__IO uint16_t nCount)
{
    /* Decrement nCount value */
    while (nCount != 0)
    {
        nCount--;
    }
}

/******************************************************************************
 * EOF (not truncated)
 ******************************************************************************/
#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,
       tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
       /* USER CODE END 6 */
}
#endif

3. Program running

Download the program, and the serial port output content of the development board is as follows:

This post is from Domestic Chip Exchange

Latest reply

Thanks for sharing, looking forward to the follow-up!   Details Published on 2023-7-24 20:21
 
 

623

Posts

0

Resources
2
 

Did you try to erase it?

The official erasure time is in the millisecond level. Is it that long during your test?

This post is from Domestic Chip Exchange

Comments

I tried it. This was tested according to the routine on the official website without any modification.  Details Published on 2023-7-22 16:44
 
 
 

410

Posts

3

Resources
3
 
jobszheng5 posted on 2023-7-22 11:16 OP, have you tried the erase operation? The official erase time is in the millisecond level. Did you take that long when testing?

I tried it. This was tested according to the routine on the official website without any modification.

This post is from Domestic Chip Exchange
 
 
 

7422

Posts

2

Resources
4
 

Thanks for sharing, looking forward to the follow-up!

This post is from Domestic Chip Exchange
Personal signature

默认摸鱼,再摸鱼。2022、9、28

 
 
 

Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list