cancel
Showing results for 
Search instead for 
Did you mean: 

QSPI flash not read in S25FL512 with STMH743

ykn
Senior

hi,

i want read read and write data from external QSPI flash S25FL512.

i posted code from below st link

https://www.st.com/content/st_com/en/support/learning/stm32-education/stm32-moocs/external_QSPI_loader.html

QSPI_READ and QSPI_write function execute with no HAL_ERROR.

but at debugging the read buffer showing garbage value.

can you help me out, below is the code.

int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* 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_QUADSPI_Init();
  /* USER CODE BEGIN 2 */
 
  uint8_t buffer_test[MEMORY_SECTOR_SIZE];
  uint8_t readbuf[100];
  uint32_t var = 0;
 
  if (CSP_QUADSPI_Init() != HAL_OK)
     {
   	  Error_Handler();
     }
 
  if (CSP_QSPI_Erase_Chip() != HAL_OK)
      {
    	  Error_Handler();
      }
 
 
      sprintf (buf, "%u", number);
      if (CSP_QSPI_WriteMemory(buf, 0, strlen (buf)) != HAL_OK)
      {
    	  Error_Handler();
      }
 
 
      if (CSP_QSPI_Read(readbuf, 0, 4) != HAL_OK)
      {
    	  Error_Handler();
      }
 
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
 
 
/* Includes ------------------------------------------------------------------*/
#include "main.h"
 
/* USER CODE BEGIN Includes */
 
/* USER CODE END Includes */
 
extern QSPI_HandleTypeDef hqspi;
 
/* USER CODE BEGIN Private defines */
 
uint8_t CSP_QUADSPI_Init(void);
uint8_t CSP_QSPI_EraseSector(uint32_t EraseStartAddress, uint32_t EraseEndAddress);
uint8_t CSP_QSPI_WriteMemory(uint8_t* buffer, uint32_t address, uint32_t buffer_size);
uint8_t CSP_QSPI_EnableMemoryMappedMode(void);
uint8_t CSP_QSPI_Erase_Chip (void);
 
/* USER CODE END Private defines */
 
void MX_QUADSPI_Init(void);
 
/* USER CODE BEGIN Prototypes */
 
/*MT25QL512 memory parameters*/
#define MEMORY_FLASH_SIZE               0x4000000 /* 512 MBits*/
#define MEMORY_SECTOR_SIZE              0x40000  /* 64kBytes */
#define MEMORY_PAGE_SIZE                0x200   /* 256 bytes */
 
 
/*MT25QL512 commands */
#define WRITE_ENABLE_CMD               0x06
#define READ_STATUS_REG_CMD            0x05
 
//#define ENTER_4_BYTE_ADD_CMD           0xB7
#define ENTER_4_BYTE_ADD_CMD           0x13
#define WRITE_VOL_CFG_REG_CMD          0x4A
#define SECTOR_ERASE_CMD               0xD8
 
#define CHIP_ERASE_CMD                 0x60
 
#define QUAD_IN_FAST_PROG_CMD          0x32
#define READ_CONFIGURATION_REG_CMD     0x35
#define QUAD_OUT_FAST_READ_CMD         0x6B
#define QUAD_INOUT_FAST_READ_CMD             0xBB
#define N25Q128A_DUMMY_CYCLES_READ_QUAD      10
#define DUMMY_CLOCK_CYCLES_READ_QUAD   8
#define RESET_ENABLE_CMD               0xF0
#define RESET_EXECUTE_CMD              0xFF
 
/*MT25QL512 timeouts*/
#define QUADSPI_MAX_ERASE_TIMEOUT 460000 /* 460s max */
 
/* USER CODE END Prototypes */

3 REPLIES 3
ykn
Senior

#include <string.h>

#define SECTORS_COUNT 100

uint8_t *writebuf = "Hello world from QSPI !";

uint8_t readbuf[100];

uint16_t number = 1234;

uint8_t buf[5];

Andreas Bolsch
Lead II

Unfortunately, this little code fragment does't tell very much. One observation:

//#define ENTER_4_BYTE_ADD_CMD 0xB7

#define ENTER_4_BYTE_ADD_CMD 0x13

is not going to work. 0x13 is NOT "Enter 4 byte address mode" but "Read with 4-byte address". 0xB7 is a configuration command whereas 0x13 a read command.

Regarding erase and program operations in you code: Where do you wait for completion of these operations by checking the WIP bit of the flash?

I'd suggest you start experimenting with "RDID" command 0x9F, as it doesn't care about 3/4-byte address mode and it always returns known data.

yes, it is difficult to understand.

so i have alternate module(IS25LP128), I think, I should get familiar with the datasheet.

read, write, erase function and checking the status register for erasing, page programming.

i have written some function and that working fine with checking the of RDID and RDSR r

/*
 * w25q128.c
 *
 *  Created on: 11-Jan-2022
 *      Author: 91844
 */
 
#include "w25q128.h"
#include "main.h" // STM32 HAL defines
#include <stdio.h> // printf()
unsigned char buff[50];
 
#define W25_CMD_READID        0x9F
#define W25_CMD_READDATA      0x03
#define W25_CMD_WriteEn       0x06
#define W25_CMD_WriteDis      0x04
#define W25_CMD_Status        0x05
#define W25_eraseSector       0x20
#define W25_CMD_WriteData     0x02
 
extern SPI_HandleTypeDef hspi3; // STM32 SPI instance
extern UART_HandleTypeDef huart1;
#define TIMEOUT          0xFFFF  // MS
#define W25_ID_BUF_SIZE  3    // bytes
 
/* W25Q128 chip select is active LOW */
#define W25_CS_ENABLE()   HAL_GPIO_WritePin(SPI3_NCS_GPIO_Port, SPI3_NCS_Pin, GPIO_PIN_RESET)
#define W25_CS_DISABLE()  HAL_GPIO_WritePin(SPI3_NCS_GPIO_Port, SPI3_NCS_Pin, GPIO_PIN_SET)
 
// Return 3 byte Manufacturer and device ID (requires 3 byte buffer)
uint8_t W25_ReadID(uint8_t *buf, int bufSize) {
	uint8_t retval;
  uint8_t idcmd = W25_CMD_READID;
  if(bufSize < W25_ID_BUF_SIZE)
    return HAL_ERROR; // buffer too small
  W25_CS_ENABLE(); // Drive Winbond chip select, /CS low
  HAL_SPI_Transmit(&hspi3, &idcmd , sizeof(idcmd ), TIMEOUT); // Send the ID command
  retval = HAL_SPI_Receive(&hspi3, buf, W25_ID_BUF_SIZE, TIMEOUT);
  W25_CS_DISABLE();
  sprintf(buff, "%s: retval %d, 0x%02X, 0x%02X, 0x%02X\r\n",__func__, retval, buf[0],buf[1],buf[2]);
  HAL_UART_Transmit (&huart1, buff, sizeof (buff), 10);
  return retval;
} // W25_R
 
uint8_t W25_ReadData(uint32_t address, uint8_t *Fbuf, int bufSize)
{
	uint8_t cmd = W25_CMD_READDATA;
	W25_CS_ENABLE(); // Drive Winbond chip select, /CS low
	HAL_SPI_Transmit(&hspi3, &cmd , sizeof(cmd ), TIMEOUT); // Send the Read command
	HAL_SPI_Transmit(&hspi3, ((address>16)&0xFF) , 1, TIMEOUT);
	HAL_SPI_Transmit(&hspi3, ((address>8)&0xFF) , 1, TIMEOUT);
	HAL_SPI_Transmit(&hspi3, ((address>0)&0xFF) , 1, TIMEOUT);
    HAL_SPI_Receive(&hspi3, Fbuf, bufSize, TIMEOUT);
	W25_CS_DISABLE();
	//HAL_UART_Transmit (&huart1, buff, sizeof (buff), 10);
	//return retval;
}
 
uint8_t W25_WriteEnable(void)
{   //int retval;
	uint8_t cmd = W25_CMD_WriteEn;
	W25_CS_ENABLE(); // Drive Winbond chip select, /CS low
	HAL_SPI_Transmit(&hspi3, &cmd , sizeof(cmd ), TIMEOUT); // Send write enable command
	W25_CS_DISABLE();
}
 
uint8_t W25_WriteDisable(void)
 
{   //int retval;
    uint8_t cmd = W25_CMD_WriteDis;
	W25_CS_ENABLE(); // Drive Winbond chip select, /CS low
	HAL_SPI_Transmit(&hspi3, &cmd , sizeof(cmd ), TIMEOUT); // Send write enable command
	W25_CS_DISABLE();
}
 
uint8_t W25_ReadStatusReg1(void)
{
	uint8_t retval;
	uint8_t cmd = W25_CMD_Status;
	W25_CS_ENABLE(); // Drive Winbond chip select, /CS low
	HAL_SPI_Transmit(&hspi3, &cmd , sizeof(cmd ), TIMEOUT); // Send write enable command
	retval = HAL_SPI_Receive(&hspi3, 0xFF, 1, TIMEOUT);
	W25_CS_DISABLE();
	return retval;
}
 
uint8_t W25_SectorErase(uint32_t address)
{
	uint8_t status;
	uint8_t cmd = W25_eraseSector;
	W25_WriteEnable();
	HAL_Delay(1);
	W25_CS_ENABLE(); // Drive Winbond chip select, /CS low
	HAL_SPI_Transmit(&hspi3, &cmd , sizeof(cmd ), TIMEOUT); // Send write enable command
	HAL_SPI_Transmit(&hspi3, ((address>16)&0xFF) , 1, TIMEOUT);
	HAL_SPI_Transmit(&hspi3, ((address>8)&0xFF) , 1, TIMEOUT);
	HAL_SPI_Transmit(&hspi3, ((address>0)&0xFF) , 1, TIMEOUT);
	W25_CS_DISABLE();
	//int retval;
	while(1)
	{
		status = W25_ReadStatusReg1();
		if((status & 0x01) == 0)
			break;
	}
	 W25_WriteDisable();
}
 
uint8_t W25_PageProgram(uint32_t address, uint8_t *Fbuf, int bufSize)
{
	uint8_t status;
	uint8_t cmd = W25_CMD_WriteData;
	W25_WriteEnable();
	HAL_Delay(1);
	W25_CS_ENABLE(); // Drive Winbond chip select, /CS low
	HAL_SPI_Transmit(&hspi3, &cmd , sizeof(cmd ), TIMEOUT); // Send write enable command
	HAL_SPI_Transmit(&hspi3, ((address>16)&0xFF) , 1, TIMEOUT);
	HAL_SPI_Transmit(&hspi3, ((address>8)&0xFF) , 1, TIMEOUT);
	HAL_SPI_Transmit(&hspi3, ((address>0)&0xFF) , 1, TIMEOUT);
	HAL_SPI_Transmit(&hspi3, Fbuf , bufSize, TIMEOUT);
	//while()
	//	HAL_SPI_Transmit(&hspi3, *Fbuf++ , 1, TIMEOUT);
	W25_CS_DISABLE();
	//int retval;
	while(1)
	  {
		status = W25_ReadStatusReg1();
		if((status & 0x01) == 0)
			break;
	  }
	W25_WriteDisable();
}
 
 
 

egister

but if use address 0x000000 then after on that address It showing only 0xFF.

except this address writing and reading is math.

can you tell where could i wromg.

thanking you.

 uint8_t idbuffer[W25_ID_BUF_SIZE];  // buffer for W25_ReadID()
  W25_ReadID(idbuffer,sizeof(idbuffer)); // Read the Manufacturer ID and device ID from the Winbond part
  W25_SectorErase(0x001FFF);
  W25_ReadData(0x001FFF, Rbuf, 64);
  //memset(buf,0x01,64);
  W25_PageProgram(0x001FFF,buf,sizeof(buf));
  W25_ReadData(0x001FFF, Rbuf, 64);