cancel
Showing results for 
Search instead for 
Did you mean: 

How to setup STM32L031K6 to read W25Q32JV Flash memory

SGovi.1
Associate

I am a newbee to STM32 development and I am struck with not being able to communicate with flash at all.

int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 
  /* USER CODE BEGIN Init */
 
  HAL_Init();
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
 
  /* USER CODE BEGIN 2 */
 
	MX_GPIO_Init();
  MX_I2C1_Init();
  MX_LPUART1_UART_Init();
  MX_RTC_Init();
  MX_USART2_UART_Init();
  MX_SPI1_Init();
  MX_ADC_Init();
 
	InitFlash();
	/* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
 
  /** Configure the main internal regulator output voltage 
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Configure LSE Drive Capability 
  */
  HAL_PWR_EnableBkUpAccess();
  __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSE;
  RCC_OscInitStruct.LSEState = RCC_LSE_ON;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_4;
  RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != 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_DIV16;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2|RCC_PERIPHCLK_LPUART1
                              |RCC_PERIPHCLK_I2C1|RCC_PERIPHCLK_RTC;
  PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;
  PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK1;
  PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1;
  PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}
 
static void MX_SPI1_Init(void)
{
 
  /* USER CODE BEGIN SPI1_Init 0 */
 
  /* USER CODE END SPI1_Init 0 */
 
  /* USER CODE BEGIN SPI1_Init 1 */
 
  /* USER CODE END SPI1_Init 1 */
  /* SPI1 parameter configuration*/
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 7;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI1_Init 2 */
 
  /* USER CODE END SPI1_Init 2 */
 
}
 
/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
 
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
 
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1|GPIO_PIN_8, GPIO_PIN_RESET);
 
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1|GPIO_PIN_3, GPIO_PIN_RESET);
 
  /*Configure GPIO pins : PA1 PA8 */
  GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_8;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
  /*Configure GPIO pins : PB1 PB3 */
  GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_3;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
}
 
void InitFlash(void)
{
	for(int i = 0; i < 8; i++)
	{
		if(W25qxx_Init()==0)
		{
			printf("Fail to init Flash\r\n");
		}
		else
		{
    		        printf("Flash detected\r\n");
			break;
		}
	}
}
 

I would appreciate if someone can point out where I am going wrong.

Just in case if this could help in analyzing the problem.

0693W000003OtXAQA0.png0693W000003OtX5QAK.png0693W000003OtX0QAK.png0693W000003OtWvQAK.png

7 REPLIES 7

Missing actual code that sends SPI data, and function that's failing.

Check signalling with scope or logic analyzer. Check chip select.

Start be reading JEDEC ID from chip.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
SGovi.1
Associate

I use the HAL library. Here is the extract

//###################################################################################################################
uint8_t	W25qxx_Spi(uint8_t	Data)
{
	uint8_t	ret;
	HAL_SPI_TransmitReceive(&_W25QXX_SPI,&Data,&ret,1,10);	
	return ret;	
}
//###################################################################################################################
uint32_t W25qxx_ReadID(void)
{
  uint32_t Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;
  W25qxx_Slave_Select();
  W25qxx_Spi(SPI_FLASH_INS_RDJDID);           
  Temp0 = W25qxx_Spi(W25QXX_DUMMY_BYTE);
  Temp1 = W25qxx_Spi(W25QXX_DUMMY_BYTE);
  Temp2 = W25qxx_Spi(W25QXX_DUMMY_BYTE);
  W25qxx_Slave_DeSelect();
  Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;
  return Temp;
}
//###################################################################################################################
void W25qxx_ReadUniqID(void)
{
  W25qxx_Slave_Select();
  W25qxx_Spi(SPI_FLASH_INS_RDID);
	for(uint8_t	i=0;i<4;i++)
		W25qxx_Spi(W25QXX_DUMMY_BYTE);
	for(uint8_t	i=0;i<8;i++)
	w25qxx.UniqID[i] = W25qxx_Spi(W25QXX_DUMMY_BYTE);
  W25qxx_Slave_DeSelect();
}
//##################################################################################################################
void W25qxx_Slave_Select(void ){
	HAL_GPIO_WritePin(_W25QXX_CS_GPIO,_W25QXX_CS_PIN,GPIO_PIN_RESET);
}
//##################################################################################################################
void W25qxx_Slave_DeSelect(void){
	HAL_GPIO_WritePin(_W25QXX_CS_GPIO,_W25QXX_CS_PIN,GPIO_PIN_SET);
}
 
 
uint8_t	W25qxx_Init(void)
{
	w25qxx.Lock=1;	
	while(HAL_GetTick()<100)
		W25qxx_Delay(1);
	HAL_GPIO_WritePin(_W25QXX_CS_GPIO,_W25QXX_CS_PIN,GPIO_PIN_SET);
  W25qxx_Delay(100);	
	uint32_t	id;
	#if (_W25QXX_DEBUG==1)
	printf("Ex_Flash Init Begin...\r\n");
	#endif
	
	id=W25qxx_ReadID();
	
	#if (_W25QXX_DEBUG==1)
	printf("Ex_Flash ID:0x%X\r\n",id);
	#endif
	switch(id&0x0000FFFF)
	{
		case 0x401A:	// 	w25q512
			w25qxx.ID=W25Q512;
			w25qxx.BlockCount=1024;
			#if (_W25QXX_DEBUG==1)
			printf("Ex_Flash Chip: w25q512\r\n");
			#endif
		break;
		case 0x4019:	// 	w25q256
			w25qxx.ID=W25Q256;
			w25qxx.BlockCount=512;
			#if (_W25QXX_DEBUG==1)
			printf("Ex_Flash Chip: w25q256\r\n");
			#endif
		break;
		case 0x4018:	// 	w25q128
			w25qxx.ID=W25Q128;
			w25qxx.BlockCount=256;
			#if (_W25QXX_DEBUG==1)
			printf("Ex_Flash Chip: w25q128\r\n");
			#endif
		break;
		case 0x4017:	//	w25q64
			w25qxx.ID=W25Q64;
			w25qxx.BlockCount=128;
			#if (_W25QXX_DEBUG==1)
			printf("Ex_Flash Chip: w25q64\r\n");
			#endif
		break;
		case 0x4016:	//	w25q32
			w25qxx.ID=W25Q32;
			w25qxx.BlockCount=64;
			#if (_W25QXX_DEBUG==1)
			printf("Ex_Flash Chip: w25q32\r\n");
			#endif
		break;
		case 0x4015:	//	w25q16
			w25qxx.ID=W25Q16;
			w25qxx.BlockCount=32;
			#if (_W25QXX_DEBUG==1)
			printf("Ex_Flash Chip: w25q16\r\n");
			#endif
		break;
		case 0x4014:	//	w25q80
			w25qxx.ID=W25Q80;
			w25qxx.BlockCount=16;
			#if (_W25QXX_DEBUG==1)
			printf("Ex_Flash Chip: w25q80\r\n");
			#endif
		break;
		case 0x4013:	//	w25q40
			w25qxx.ID=W25Q40;
			w25qxx.BlockCount=8;
			#if (_W25QXX_DEBUG==1)
			printf("Ex_Flash Chip: w25q40\r\n");
			#endif
		break;
		case 0x4012:	//	w25q20
			w25qxx.ID=W25Q20;
			w25qxx.BlockCount=4;
			#if (_W25QXX_DEBUG==1)
			printf("Ex_Flash Chip: w25q20\r\n");
			#endif
		break;
		case 0x4011:	//	w25q10
			w25qxx.ID=W25Q10;
			w25qxx.BlockCount=2;
			#if (_W25QXX_DEBUG==1)
			printf("Ex_Flash Chip: w25q10\r\n");
			#endif
		break;
		
		case 0x6015:
			w25qxx.ID=W25Q16;
			w25qxx.BlockCount=32;
			#if (_W25QXX_DEBUG==1)
			printf("IS25 Chip: IS25LP016D\r\n");
			#endif
		break;
		
		case 0x7015:
			w25qxx.ID=W25Q16;
			w25qxx.BlockCount=32;
			#if (_W25QXX_DEBUG==1)
			printf("IS25 Chip: IS25LP016D\r\n");
		  #endif
		break;
		
		
		default:
				#if (_W25QXX_DEBUG==1)
				printf("Ex_Flash Unknown ID\r\n");
				#endif
			w25qxx.Lock=0;	
			return 0;
				
	}		
	w25qxx.PageSize=256;                                                  //256 bytes per programmable page
	w25qxx.SectorSize=0x1000;                                             //4K sector Size  
	w25qxx.SectorCount=w25qxx.BlockCount*16;                              //16 sector count per block
	w25qxx.PageCount=(w25qxx.SectorCount*w25qxx.SectorSize)/w25qxx.PageSize;  
	w25qxx.BlockSize=w25qxx.SectorSize*16;                                // 4K*16
	w25qxx.CapacityInKiloByte=(w25qxx.SectorCount*w25qxx.SectorSize)/1024;
	W25qxx_ReadUniqID();
	W25qxx_ReadStatusRegister(1);
	W25qxx_ReadStatusRegister(2);
	W25qxx_ReadStatusRegister(3);
	#if (_W25QXX_DEBUG==1)
	
	
	printf("----------------------------------------------\r\n");
	printf("Ex_Flash Page Size: %d Bytes\r\n",w25qxx.PageSize);
	printf("Ex_Flash Page Count: %d\r\n",w25qxx.PageCount);
	printf("Ex_Flash Sector Size: %d Bytes\r\n",w25qxx.SectorSize);
	printf("Ex_Flash Sector Count: %d\r\n",w25qxx.SectorCount);
	printf("Ex_Flash Block Size: %d Bytes\r\n",w25qxx.BlockSize);
	printf("Ex_Flash Block Count: %d\r\n",w25qxx.BlockCount);
	printf("Ex_Flash Capacity: %d KiloBytes\r\n",w25qxx.CapacityInKiloByte);
	printf("Ex_Flash Init Done\r\n");
	printf("----------------------------------------------\r\n");
	#endif
	w25qxx.Lock=0;	
	return 1;
}

 I get this output.

Ex_Flash Init Begin...

Ex_Flash ID:0xFFFFFF

Ex_Flash Unknown ID

Fail to init Flash

Mahendra
Associate II

Hi @SGovi.1​ 

did you solve the problem ?

Mahendra

As Clive said above:

>Check signalling with scope or logic analyzer. Check chip select.

> Start by reading JEDEC ID from chip.

Tell us about your hardware and what are your findings.

JW

I have the same issue on my STM32F407 board.

https://www.aliexpress.com/item/32978440523.html

I have only FF returns. The CS and WP pins work. HAL status is OK.

I played with hspi1.Init.BaudRatePrescaler, maybe speed problems, but no luck.

 hspi1.Instance = SPI1;

 hspi1.Init.Mode = SPI_MODE_MASTER;

 hspi1.Init.Direction = SPI_DIRECTION_2LINES;

 hspi1.Init.DataSize = SPI_DATASIZE_8BIT;

 hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;

 hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;

 hspi1.Init.NSS = SPI_NSS_SOFT;

 hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;

 hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;

 hspi1.Init.TIMode = SPI_TIMODE_DISABLE;

 hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;

 hspi1.Init.CRCPolynomial = 10;

Sample code:

 uint8_t rxData[8] = { };

 uint8_t txData[8] = { };

 HAL_StatusTypeDef status = 0;

 txData[0] = 0x9f;

 HAL_GPIO_WritePin(FL_CS_GPIO_Port, FL_CS_Pin, GPIO_PIN_RESET);

 HAL_Delay(1);

 status = HAL_SPI_Transmit(&hspi1, txData, 1, 1000);

 status = HAL_SPI_Receive(&hspi1, rxData, 3, 1000);

 HAL_Delay(1);

 HAL_GPIO_WritePin(FL_CS_GPIO_Port, FL_CS_Pin, GPIO_PIN_SET);

 HAL_Delay(10);

Focus on

Clocks

Pins

Peripherals

Use Transmit Receive function.

C​heck boards schematic and jumpers or solder bridges.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
LaurV
Associate II

Put a breakpoint there at line 59 and check what ID you get. If it sounds anything like "normal" (i.e. not 0x0 or FF everywhere) then check the datasheet of your chip to see what the ID means. This driver is over 6 years old, and there is a high probability that everything, in fact, _works_, but you have a newer memory whose ID is not in the switch/case list, and that's why you get unknown flash ID message. In fact, that switch/case list looks very short to me (maybe you cut it for posting purpose).