cancel
Showing results for 
Search instead for 
Did you mean: 

nucleo-f767ZI QSPI direct read/write is not working

mr_phyadav
Associate II

Hello @Amel NASRI ,

I am using nucleo-f767ZI board. I have custom LCD board which use NV3041A QSPI interface.
I am trying to read manufacture ID from NV3041A on QSPI interface.
My code is as below

static void MX_QUADSPI_Init(void)
{

  /* USER CODE BEGIN QUADSPI_Init 0 */

  /* USER CODE END QUADSPI_Init 0 */

  /* USER CODE BEGIN QUADSPI_Init 1 */

  /* USER CODE END QUADSPI_Init 1 */
  /* QUADSPI parameter configuration*/
  hqspi.Instance = QUADSPI;
  hqspi.Init.ClockPrescaler = 4;
  hqspi.Init.FifoThreshold = 1;
  hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE;
  hqspi.Init.FlashSize = 1;
  hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE;
  hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;
  hqspi.Init.FlashID = QSPI_FLASH_ID_1;
  hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
  if (HAL_QSPI_Init(&hqspi) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN QUADSPI_Init 2 */

  /* USER CODE END QUADSPI_Init 2 */

}

void NV3041A_ReadData(uint8_t command, uint32_t address, uint8_t *data, uint32_t len)
{
	QSPI_CommandTypeDef sCommand;
	HAL_StatusTypeDef status;
	// Configure the command phase for reading
	sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
	sCommand.Instruction       = command;                 // Your NV3041A read command
	sCommand.AddressMode       = QSPI_ADDRESS_1_LINE;
	sCommand.AddressSize       = QSPI_ADDRESS_24_BITS;
	sCommand.Address           = address;
	sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
	sCommand.DataMode          = QSPI_DATA_1_LINE;
	sCommand.DummyCycles       = 0;
	sCommand.NbData            = len;
	sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
	sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_HALF_CLK_DELAY;
	sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
	status = HAL_QSPI_Command(&hqspi, &sCommand, HAL_QSPI_TIMEOUT_DEFAULT_VALUE);
	if(status == HAL_OK)
	{

		status = HAL_QSPI_Receive(&hqspi, data, HAL_QSPI_TIMEOUT_DEFAULT_VALUE);
		if(status != HAL_OK)
		{
			while(1);
		}
	}

}
/**
* @brief QSPI MSP Initialization
* This function configures the hardware resources used in this example
* @param hqspi: QSPI handle pointer
* @retval None
*/
void HAL_QSPI_MspInit(QSPI_HandleTypeDef* hqspi)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(hqspi->Instance==QUADSPI)
  {
  /* USER CODE BEGIN QUADSPI_MspInit 0 */

  /* USER CODE END QUADSPI_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_QSPI_CLK_ENABLE();

    __HAL_RCC_GPIOE_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOD_CLK_ENABLE();
    /**QUADSPI GPIO Configuration
    PE2     ------> QUADSPI_BK1_IO2
    PB2     ------> QUADSPI_CLK
    PD11     ------> QUADSPI_BK1_IO0
    PD12     ------> QUADSPI_BK1_IO1
    PD13     ------> QUADSPI_BK1_IO3
    PB6     ------> QUADSPI_BK1_NCS
    */
    GPIO_InitStruct.Pin = GPIO_PIN_2;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_2;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /* USER CODE BEGIN QUADSPI_MspInit 1 */

  /* USER CODE END QUADSPI_MspInit 1 */
  }

}
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 */
  static uint8_t device_id[3]; // Buffer to store the read data
  NV3041A_ReadData(0x03, (0xda<<8), device_id, sizeof(device_id));

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

 
I probe logic analyzer of QSPI-data-0, data 1, clock and chip select line. I could not see any data being transmitted at end of "HAL_QSPI_Receive" API.

After debugging through register on my end I can see status register(QUADSPI_SR) is set to 0x01, which is being set by below code in  HAL_QSPI_Receive API
/* Start the transfer by re-writing the address in AR register */
WRITE_REG(hqspi->Instance->AR, addr_reg);


When I change sCommand.AddressMode = QSPI_ADDRESS_NONE; I am able to see data without address (0xda) on QSPI line.

Can you please help me regarding this?
Let me know if any further information is required on my end.

5 REPLIES 5
KDJEM.1
ST Employee

Hello @mr_phyadav and welcome to the community;

 

The QUADSPI_SR is set to 0x01 when an invalid address is being accessed in indirect mode. 

Why are you using 0xda<<8?

NV3041A_ReadData(0x03, (0xda<<8), device_id, sizeof(device_id));

Are you shifting the address by 8 bits? 

Could you please share the device datasheet?

Thank you.

Kaouthar

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

I am able to resolve issue by changing flash size to 23, which was previously 1 as I was not using flash.

 

After changing flash size i am able to see data on qspi line.

 

One behaviour I have seen, I am not sure whether it is correct or not.

I am sending qspi data with following cmd config

Instruction = 0x32 , one line

Address = 0x002c00 , 24 bit, one line

Data = {1,0,0,0,0,0,0,0} , 8 byte, 4 lines

 

On logic analyzer I m seeing following data on line 0

0x32

0x00

0x2c

0x00

0x40

0x00

 

Is this correct behaviour?

Let me know if more details required on my end.

Datasheet: https://www.google.com/url?sa=t&source=web&rct=j&opi=89978449&url=https://admin.osptek.com/uploads/NV_3041_A_Datasheet_V1_2_20221011_686486a221.pdf&ved=2ahUKEwiSgYT-xpmOAxXQr1YBHS8EKJQQFnoECCAQAQ&usg=AOvVaw2yCuzCAIqsJ-HH4pc-zQGu

 

 

Hello @mr_phyadav 

The logic analyzer show 0x40 on line 0 during data phase when switching to quad mode, this suggest that the data is being split across the 4 lines.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om
Hi thanks for update, can you please guide how to interpret the data is
correct?

Since QSPI sends 4 bits per clock cycle, the byte is split into two parts :

taking the example of 0X01 to be sent :

  • First cycle (higher bits): bits 7 to 4 → 0000b [D3 D2 D1 D0]
  • Second cycle (lower bits): bits 3 to 0 → 0001b [D3 D2 D1 D0]

The output on D0 line in this case should be 01b

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om