cancel
Showing results for 
Search instead for 
Did you mean: 

Problem with QSPI in STM32F7

Pilous Droip
Senior
Posted on February 06, 2018 at 12:56

Hello.

I have a problem with QSPI. I try everything, but program doesn't work.

I split my program to some parts.

qspi_gpio_ini(); /* Init GPIO pins */

qspi_dma_init(); /* Init DMA */

qspi_init(); /* Init QSPI */

qspi_config(); /* Config QSPI */

QSPI_Cmd(ENABLE); /* Enable QSPI */

QSPI_WriteEnable();   /* Enable Write*/

https://paste.ofcode.org/3aqqGSDyMuwZCzxrCRXMTHK

. This is work fine.

https://paste.ofcode.org/Cpv7tmQ7aGGVMWJ6x3zYWR

. Init DMA and I don't know, if this part working. But it has time.

https://paste.ofcode.org/hvCyJQ2EjHTHJMLTAvDEgm

/**

* Set register:

*

* CR->PRESCALER = 0x04

* CR->SSHIFT = 0x01

* DCR->FSIZE = 0x17

*/

void qspi_init(void)

{

/* Initialize QSPI ------------------------------------------------------ */

LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_QSPI);

QSPI_StructInit(&QSPI_InitStructure);

QSPI_InitStructure.QSPI_SShift = QSPI_SShift_HalfCycleShift; //By default, the QUADSPI samples data 1/2 of a CLK cycle after the data is driven by the Flash memory

QSPI_InitStructure.QSPI_Prescaler = 11; //Number = (216MHz / Freq)-1 (Freq = 50MHz)

QSPI_InitStructure.QSPI_CKMode = QSPI_CKMode_Mode0; //By default, nCS is high, deselecting the external Flash memory

QSPI_InitStructure.QSPI_CSHTime = QSPI_CSHTime_1Cycle; //Chip select high time

QSPI_InitStructure.QSPI_FSize = 23; //Number = 16MB is = (2^24) where 24-1 is Number

QSPI_InitStructure.QSPI_FSelect = QSPI_FSelect_1; //Flash memory selection

QSPI_InitStructure.QSPI_DFlash = QSPI_DFlash_Disable; //Dual Flash mode disable

QSPI_Init(&QSPI_InitStructure);

QSPI_SetFIFOThreshold(0);

}

https://paste.ofcode.org/MKZAn5RxfHt8ngMU5QZvYk

/**

* Set registers:

* CCR->ADSIZE = 0x02

* CCR->DHHC = 0x01

* CCR->IMODE = 0x01

*/

void qspi_config(void)

{

/* Command default config */

QSPI_ComConfig_StructInit(&QSPI_ComConfig_InitStructure);

QSPI_ComConfig_InitStructure.QSPI_ComConfig_FMode = QSPI_ComConfig_FMode_Indirect_Write; //QUADSPI is in indirect write mode, where bytes are sent to the Flash memory during the data phase

QSPI_ComConfig_InitStructure.QSPI_ComConfig_SIOOMode = QSPI_ComConfig_SIOOMode_Disable; //Send instruction only-once

QSPI_ComConfig_InitStructure.QSPI_ComConfig_ABSize = QSPI_ComConfig_ABSize_8bit; //number of alternate bytes

QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADSize = QSPI_ComConfig_ADSize_24bit; //max. addressable memory (2^24)

/* this set is from DM00224583.pdf, page 409, picture 63 */

QSPI_ComConfig_InitStructure.QSPI_ComConfig_IMode = QSPI_ComConfig_IMode_1Line; //instruction phase is skipped

QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADMode = QSPI_ComConfig_ADMode_NoAddress; //address phase is skipped

QSPI_ComConfig_InitStructure.QSPI_ComConfig_ABMode = QSPI_ComConfig_ABMode_NoAlternateByte; //alternate-bytes phase is skipped

QSPI_ComConfig_InitStructure.QSPI_ComConfig_DummyCycles = 0; //Set dummy cycle

QSPI_ComConfig_StructInit(&QSPI_ComConfig_InitStructure);

QSPI_Cmd(ENABLE);

/* QSPI_ITConfig(QSPI_IT_SM , ENABLE);

NVIC_SetPriority(QUADSPI_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));

NVIC_EnableIRQ(QUADSPI_IRQn);*/

}

And here is my problem. When I call QSPI_WriteEnable(), program stop and wait on QSPI_FLAG_SM. But I don know, why.

https://paste.ofcode.org/356zahT4pM2K7f4wKeHT5JW

void QSPI_WriteEnable(void)

{

/* Command Config for Write Enable */

QSPI_ComConfig_InitStructure.QSPI_ComConfig_DHHC = QSPI_ComConfig_DHHC_Disable;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_DDRMode = QSPI_ComConfig_DDRMode_Disable;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_FMode = QSPI_ComConfig_FMode_Indirect_Write;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_SIOOMode = QSPI_ComConfig_SIOOMode_Disable;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_ABSize = QSPI_ComConfig_ABSize_8bit;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADSize = QSPI_ComConfig_ADSize_24bit;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_DMode = QSPI_ComConfig_DMode_NoData;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADMode = QSPI_ComConfig_ADMode_NoAddress;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_ABMode = QSPI_ComConfig_ABMode_NoAlternateByte;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_IMode = QSPI_ComConfig_IMode_1Line;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_Ins = WRITE_ENABLE_CMD ;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_DummyCycles = 0;

QSPI_ComConfig_Init(&QSPI_ComConfig_InitStructure);

QSPI_ITConfig(QSPI_IT_SM, ENABLE);

/* Switch to Autopolling mode for the end of the Command */

while(QSPI_GetFlagStatus(QSPI_FLAG_BUSY) != RESET){};

QSPI_AutoPollingMode_Config(0x02, 0x02, QSPI_PMM_AND);

QSPI_SetDataLength(0x01);

QSPI_AutoPollingMode_SetInterval(0x10);

QSPI_AutoPollingModeStopCmd(ENABLE);

QSPI_SetDataLength(0x00);

QSPI_ComConfig_InitStructure.QSPI_ComConfig_FMode = QSPI_ComConfig_FMode_Auto_Polling;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADMode = QSPI_ComConfig_ADMode_NoAddress;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_DMode = QSPI_ComConfig_DMode_1Line;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_Ins = READ_STATUS_REG_CMD;

QSPI_ComConfig_Init(&QSPI_ComConfig_InitStructure);

//QSPI_ClearFlag(QSPI_FLAG_SM | QSPI_FLAG_TE | QSPI_FLAG_FT | QSPI_FLAG_TO | QSPI_FLAG_TC);

while(QSPI_GetFlagStatus(QSPI_FLAG_SM) == RESET){};

QSPI_ClearFlag(QSPI_FLAG_SM);

QSPI_ClearFlag(QSPI_FLAG_TC);

while(QSPI_GetFlagStatus(QSPI_FLAG_BUSY) != RESET){};

asm('NOP');

}

In attach files are my use library for QSPI and scope views on signals.

Setting:

  1. STM32F767ZI
  2. Clock: 216MHz
  3. Clock QSPI: 18MHz
  4. Mode: single-SPI mode
  5. Memory connect:
  • PB10 - CS flash
  • PF8 - IO0 (SI)
  • PF9 - IO1 (SO)
  • PF10 - SCK

6. Connect memory:

http://www.issi.com/WW/pdf/IS25LP032-064-128.pdf

Any idea what's wrong? I tried to set up registers but the result was the same.

#nucleo-f767zi #qspi-flash
3 REPLIES 3
Pilous Droip
Senior
Posted on February 07, 2018 at 09:56

And now, I send 0x06 write enable and read status register 0x05, where 0x06 is sent only once. 

You can see on the picture:

  • purple - send data to slave (0x05)
  • blue - receive byte from slave

But autopolling doesn't match:

QSPI_AutoPollingMode_Config(0x02, 0x02, QSPI_PMM_AND);

0690X00000609dgQAA.png

I I don't know, what is true? blue or orange? Because, receive datas have 9bits....

And I'm waiting on this line:

while(QSPI_GetFlagStatus(QSPI_FLAG_SM) == RESET){};

0690X00000604LqQAI.jpg
Pilous Droip
Senior
Posted on February 08, 2018 at 09:10

Hello.

My problem was in connection cable. I moved my receive pin on 1 position.

🙂

 

🙂

 

🙂

 

>:(

And here is my solution, only for Enable Write with memory: is25lp064

This solution is without HAL function.

But you must use the files from my 1. topic.

Init GPIO:

void qspi_gpio_ini(void)

{

LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOF);

LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOB);

/* MISO - input datas */

LL_GPIO_SetPinMode( GPIOF, LL_GPIO_PIN_8, LL_GPIO_MODE_ALTERNATE);

LL_GPIO_SetAFPin_8_15( GPIOF, LL_GPIO_PIN_8, LL_GPIO_AF_10);

/* MOSI - output datas */

LL_GPIO_SetPinMode( GPIOF, LL_GPIO_PIN_9, LL_GPIO_MODE_ALTERNATE);

LL_GPIO_SetAFPin_8_15( GPIOF, LL_GPIO_PIN_9, LL_GPIO_AF_10);

/* SCK pin */

LL_GPIO_SetPinMode( GPIOF, LL_GPIO_PIN_10, LL_GPIO_MODE_ALTERNATE);

LL_GPIO_SetPinPull( GPIOF, LL_GPIO_PIN_10, LL_GPIO_PULL_NO);

LL_GPIO_SetAFPin_8_15( GPIOF, LL_GPIO_PIN_10, LL_GPIO_AF_9);

/* CS pin */

LL_GPIO_SetPinMode( GPIOB, LL_GPIO_PIN_10, LL_GPIO_MODE_ALTERNATE);

//LL_GPIO_SetPinOutputType( GPIOB, LL_GPIO_PIN_10, LL_GPIO_OUTPUT_PUSHPULL);

//LL_GPIO_SetPinPull( GPIOB, LL_GPIO_PIN_10, LL_GPIO_PULL_UP);

//LL_GPIO_SetPinSpeed( GPIOB, LL_GPIO_PIN_10, LL_GPIO_SPEED_FREQ_VERY_HIGH);

LL_GPIO_SetAFPin_8_15( GPIOB, LL_GPIO_PIN_10, LL_GPIO_AF_9);

}

Init QSPI:

/**

* Set register:

*

* CR->PRESCALER = 0x04

* CR->SSHIFT = 0x01

* DCR->FSIZE = 0x17

*/

void qspi_init(void)

{

/* Initialize QSPI ------------------------------------------------------ */

LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_QSPI);

QSPI_StructInit(&QSPI_InitStructure);

QSPI_InitStructure.QSPI_SShift = QSPI_SShift_NoShift; //By default, the QUADSPI samples data 1/2 of a CLK cycle after the data is driven by the Flash memory

QSPI_InitStructure.QSPI_Prescaler = 11; //Number = (216MHz / Freq)-1 (Freq = 50MHz)

QSPI_InitStructure.QSPI_CKMode = QSPI_CKMode_Mode0; //By default, nCS is high, deselecting the external Flash memory

QSPI_InitStructure.QSPI_CSHTime = QSPI_CSHTime_1Cycle; //Chip select high time

QSPI_InitStructure.QSPI_FSize = 23; //Number = 16MB is = (2^24) where 24-1 is Number

QSPI_InitStructure.QSPI_FSelect = QSPI_FSelect_1; //Flash memory selection

QSPI_InitStructure.QSPI_DFlash = QSPI_DFlash_Disable; //Dual Flash mode disable

QSPI_Init(&QSPI_InitStructure);

QSPI_SetFIFOThreshold(1);

}

Config QSPI:

/**

* Set registers:

* CCR->ADSIZE = 0x02

* CCR->DHHC = 0x01

* CCR->IMODE = 0x01

*/

void qspi_config(void)

{

/* Command default config */

QSPI_ComConfig_StructInit(&QSPI_ComConfig_InitStructure);

QSPI_ComConfig_InitStructure.QSPI_ComConfig_FMode = QSPI_ComConfig_FMode_Indirect_Write; //QUADSPI is in indirect write mode, where bytes are sent to the Flash memory during the data phase

QSPI_ComConfig_InitStructure.QSPI_ComConfig_SIOOMode = QSPI_ComConfig_SIOOMode_Disable; //Send instruction only-once

QSPI_ComConfig_InitStructure.QSPI_ComConfig_ABSize = QSPI_ComConfig_ABSize_8bit; //number of alternate bytes

QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADSize = QSPI_ComConfig_ADSize_24bit; //max. addressable memory (2^24)

/* this set is from DM00224583.pdf, page 409, picture 63 */

QSPI_ComConfig_InitStructure.QSPI_ComConfig_IMode = QSPI_ComConfig_IMode_1Line; //instruction phase is skipped

QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADMode = QSPI_ComConfig_ADMode_NoAddress; //address phase is skipped

QSPI_ComConfig_InitStructure.QSPI_ComConfig_ABMode = QSPI_ComConfig_ABMode_NoAlternateByte; //alternate-bytes phase is skipped

QSPI_ComConfig_InitStructure.QSPI_ComConfig_DummyCycles = 0; //Set dummy cycle

QSPI_ComConfig_StructInit(&QSPI_ComConfig_InitStructure);

QSPI_Cmd(ENABLE);

}

Enable Write to memory:

static void QSPI_WriteEnable(void)

{

/* Send 0x06 */

QSPI_ComConfig_InitStructure.QSPI_ComConfig_DHHC = QSPI_ComConfig_DHHC_Disable;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_DDRMode = QSPI_ComConfig_DDRMode_Disable;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_SIOOMode = QSPI_ComConfig_SIOOMode_Disable;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_ABSize = QSPI_ComConfig_ABSize_8bit;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADSize = QSPI_ComConfig_ADSize_24bit;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_DMode = QSPI_ComConfig_DMode_NoData;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADMode = QSPI_ComConfig_ADMode_NoAddress;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_ABMode = QSPI_ComConfig_ABMode_NoAlternateByte;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_IMode = QSPI_ComConfig_IMode_1Line;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_FMode = QSPI_ComConfig_FMode_Indirect_Write;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_Ins = WRITE_ENABLE_CMD ;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_DummyCycles = 0;

QSPI_ComConfig_Init(&QSPI_ComConfig_InitStructure);

/* Send 0x05 and receive 1 byte */

while(QSPI_GetFlagStatus(QSPI_FLAG_BUSY) != RESET)

{}

QSPI_AutoPollingMode_SetInterval(0x10);//Number of CLK cycles between to read during automatic polling phases.

QSPI_AutoPollingMode_Config(0x02, 0x02, QSPI_PMM_AND); //set compare mode for autopolling

QSPI_AutoPollingModeStopCmd(ENABLE); //enable autopolling

QSPI_SetDataLength(0x00); //data lenght is 0

QSPI_ComConfig_InitStructure.QSPI_ComConfig_FMode = QSPI_ComConfig_FMode_Auto_Polling;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_ADMode = QSPI_ComConfig_ADMode_NoAddress;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_DMode = QSPI_ComConfig_DMode_1Line;

QSPI_ComConfig_InitStructure.QSPI_ComConfig_Ins = READ_STATUS_REG_CMD;

QSPI_ComConfig_Init(&QSPI_ComConfig_InitStructure);

QSPI_ClearFlag(QSPI_FLAG_SM);

/* wait on recive 0x02 (WEL bit) from memory */

while(QSPI_GetFlagStatus(QSPI_FLAG_SM) == RESET){};

QSPI_ClearFlag(QSPI_FLAG_SM);

QSPI_ClearFlag(QSPI_FLAG_TC);

while(QSPI_GetFlagStatus(QSPI_FLAG_BUSY) != RESET){};

}
Matthew Staben
Associate II
Posted on February 09, 2018 at 17:24

When implementing QSPI (using HAL) on our custom STM32F769II platform, I dealt with a host of problems with the QSPI part until all waveforms were correctly established; any ringing or inexactness otherwise led to a foray into the HAL implementation always ultimately demonstrating that the STM micro itself was rejecting interaction with the QSPI part.  

We've had some difficulty with HAL, but overall, it's led to a satisfactory conclusion.  The only existing exception at this time is that HAL as-is does not operate USB-Host in its RTOS implementation - only the non-RTOS version.

HAL FTW!