cancel
Showing results for 
Search instead for 
Did you mean: 

Interfacing Nucleo F767ZI Board with W25Q256JV using QSPI

NajeebUllahKhan
Associate II

Hi Everyone,

I interfaced Nucleo F767ZI with W25Q256JV using SPI and everything was working fine. But due to time and speed requirements, now I have to shift it to QSPI. I have used example code of STM Document named "QSPI_F769_discovery_flashloader" and developed a code for QSPI. But whenever I try to run the code and write/read the memory, nothing happens. I started to run code in debug on STMCube IDE and found that when try to send command to enable write and read status register, the register value doesn't change to write enable (0x02).

Always fail here and Error LED turns ON.

if (HAL_QSPI_AutoPolling(&hqspi, &sCommand, &sConfig, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
return QSPI_ERROR;
}

The Write Enable function is here.

uint8_t QSPI_WriteEnable(void) {

QSPI_CommandTypeDef sCommand;

QSPI_AutoPollingTypeDef sConfig;



memset(&sCommand, 0, sizeof(sCommand));

memset(&sConfig, 0, sizeof(sConfig));



/* Enable write operations ------------------------------------------ */

sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;

sCommand.Instruction = WRITE_ENABLE_CMD;

sCommand.AddressMode = QSPI_ADDRESS_NONE;

sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;

sCommand.DataMode = QSPI_DATA_NONE;

sCommand.DummyCycles = 0;

sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;

sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;

sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;



if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)

!= HAL_OK) {

return QSPI_ERROR;

}



/* Configure automatic polling mode to wait for write enabling ---- */

sConfig.Match = 0x02;

sConfig.Mask = 0x02;

sConfig.MatchMode = QSPI_MATCH_MODE_AND;

sConfig.StatusBytesSize = 1;

sConfig.Interval = 0x10;

sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE;

sCommand.Instruction = READ_STATUS_REG_CMD;

sCommand.DataMode = QSPI_DATA_1_LINE;



if (HAL_QSPI_AutoPolling(&hqspi, &sCommand, &sConfig,

HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {

HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);

return QSPI_ERROR;

}

return QSPI_OK;

}

Below is my attached qspi.h and qspi.c files and CubeMX configuration.

Capture.PNG

Kindly help me, what is the problem and if possible provide me a .c .h file for QSPI it's urgent.

Looking forward to suitable response, thanks in advance.

12 REPLIES 12

I tend to use PB6 rather than PB10 on NUCLEO-144 platforms, but should work, not sure if there are other nodes/stubs on that, or one vs the other.

>16MB would typically need to use the 4-byte (32-bit) addressing mode, rather than 3-byte (24-bit)

So W25Q256 code might not work on W25Q128 parts.

Could try this as an External Loader in STM32 Cube Programmer to test/check implementation

https://github.com/cturvey/stm32extldr/blob/main/h7_w25q256/CLIVEONE-W25Q256_STM32H7XX-PB2-PB10-PD11-PD12-PE2-PD13.stldr

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

Hi @Tesla DeLorean @JJhin.1 @mƎALLEm 

Sorry for the late response, the code you provided worked for W25Q256 and STM32F7 Nucleo. Thanks,

Now I have a custom designed PCB board where I have used STM32L56 and W25Q256 along with other components. First, I was using SPI for interfacing but it was taking so much time when writing/reading MBs file. So I have to opt for QSPI now. L5 doesn't have specific QSPI, but using OSPI we can configure it as Quad SPI.

So, my questions are

1) what is difference between QSPI and OSPI as QSPI (command and working mechanism)

2) will this code work for OSPI as QSPI

3) if you have any test code for OSPI as QSPI, I can test and will modify it according to my needs

Looking forward to your response

Below are my configurations, code files with changes accordingly.

void testQSPI(){
OSPI_RegularCmdTypeDef s_command = {0};
/*uint8_t pData[3];
uint8_t wData[0x100];
uint8_t rData[0x100];*/
uint8_t pData[3];
uint8_t wData[0x100];
uint8_t rData[0x100];
memset(pData, 0x00, sizeof(pData));
memset(wData, 0x00, sizeof(wData));
memset(wData, 0x00, sizeof(wData));
uint32_t i;
printf("***************QuadSPi Example*******************************\r\n");
BSP_QSPI_Init();

BSP_QSPI_Erase_Chip();

/*##-2-Read Device ID Test ###########################################*/
/* Read Manufacture/Device ID */
s_command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
s_command.Instruction = READ_ID_CMD;
s_command.AddressMode = HAL_OSPI_ADDRESS_1_LINE;
s_command.AddressSize = HAL_OSPI_ADDRESS_24_BITS;
s_command.Address = 0x000000;
s_command.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
s_command.DataMode = HAL_OSPI_DATA_1_LINE;
s_command.DummyCycles = 0;
s_command.NbData = 2;
s_command.DQSMode = HAL_OSPI_DQS_DISABLE;
// s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
s_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;

if (HAL_OSPI_Command(&hospi1, &s_command, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
if (HAL_OSPI_Receive(&hospi1, pData, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
printf("SPI I/0 Read Device ID : 0x%2X 0x%2X\r\n",pData[0],pData[1]);


/* Read Manufacture/Device ID Dual I/O*/
s_command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
s_command.Instruction = DUAL_READ_ID_CMD;
s_command.AddressMode = HAL_OSPI_ADDRESS_2_LINES;
s_command.AddressSize = HAL_OSPI_ADDRESS_24_BITS;
s_command.Address = 0x000000;
s_command.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_2_LINES;
s_command.AlternateBytesSize= HAL_OSPI_ALTERNATE_BYTES_8_BITS;
s_command.AlternateBytes = 0;
s_command.DataMode = HAL_OSPI_DATA_2_LINES;
s_command.DummyCycles = 0;
s_command.NbData = 2;
s_command.DQSMode = HAL_OSPI_DQS_DISABLE;
// s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
s_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;

if (HAL_OSPI_Command(&hospi1, &s_command, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
if (HAL_OSPI_Receive(&hospi1, pData, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
printf("Dual I/O Read Device ID : 0x%2X 0x%2X\r\n",pData[0],pData[1]);

/* Read Manufacture/Device ID Quad I/O*/
s_command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
s_command.Instruction = QUAD_READ_ID_CMD;
s_command.AddressMode = HAL_OSPI_ADDRESS_4_LINES;
s_command.AddressSize = HAL_OSPI_ADDRESS_24_BITS;
s_command.Address = 0x000000;
s_command.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_4_LINES;
s_command.AlternateBytesSize= HAL_OSPI_ALTERNATE_BYTES_8_BITS;
s_command.AlternateBytes = 0x00;
s_command.DataMode = HAL_OSPI_DATA_4_LINES;
s_command.DummyCycles = 4;
s_command.NbData = 2;
s_command.DQSMode = HAL_OSPI_DQS_DISABLE;
// s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
s_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;

if (HAL_OSPI_Command(&hospi1, &s_command, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
if (HAL_OSPI_Receive(&hospi1, pData, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
printf("Quad I/O Read Device ID : 0x%2X 0x%2X\r\n",pData[0],pData[1]);

/* Read JEDEC ID */
s_command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
s_command.Instruction = READ_JEDEC_ID_CMD;
s_command.AddressMode = HAL_OSPI_ADDRESS_NONE;
s_command.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
s_command.DataMode = HAL_OSPI_DATA_1_LINE;
s_command.DummyCycles = 0;
s_command.NbData = 3;
s_command.DQSMode = HAL_OSPI_DQS_DISABLE;
// s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
s_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;

if (HAL_OSPI_Command(&hospi1, &s_command, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
if (HAL_OSPI_Receive(&hospi1, pData, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
printf("Read JEDEC ID : 0x%2X 0x%2X 0x%2X\r\n\r\n",pData[0],pData[1],pData[2]);

/*##-3-QSPI Erase/Write/Read Test ###########################################*/
/* fill buffer */
for(i =0;i<0x100;i ++)
{
wData[i] = i*2;
rData[i] = 0;
}

if(BSP_QSPI_Erase_Block(0) == QSPI_OK)
printf(" QSPI Erase Block ok\r\n");
else
Error_Handler();

if(BSP_QSPI_Write(wData,0x00,0x100)== QSPI_OK)
printf(" QSPI Write ok\r\n");
else
Error_Handler();

if(BSP_QSPI_Read(rData,0x00,0x100)== QSPI_OK)
printf(" QSPI Read ok\r\n\r\n");
else
Error_Handler();

printf("QSPI Read Data : \r\n");
for(i =0;i<0x100;i++)
printf("0x%02X ",rData[i]);
printf("\r\n\r\n");

for(i =0;i<0x100;i++)
if(rData[i] != wData[i])printf("0x%02X 0x%02X ",wData[i],rData[i]);
printf("\r\n\r\n");
/* check date */
if(memcmp(wData,rData,0x100) == 0 )
printf(" W25Q128FV QuadSPI Test OK\r\n");
else
printf(" W25Q128FV QuadSPI Test False\r\n");

}

 

Capture 1.PNG

Capture 2.PNG  

Hello @NajeebUllahKhan ,

On next time please use </> button to share a code. See this post. I'm updating your post.

Thank you for your understanding.

 

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.