EmbDev.net

Forum: µC & Digital Electronics QSPI - STM32F7


Author: Petr K. (buzzer_klaun)
Posted on:
Attached files:

Rate this post
0 useful
not useful
Hello friends.

I have a small problem with my QSPI on STM32F7. I connect memory on this 
pins.

PB10 - CS flash
PF8 - IO0 (SI)
PF9 - IO1 (SO)
PF10 - SCK

And I call in main:
int main(void)
{
/* init NVICcm */
LL_Init();
/* init system clock */
SystemClock_Config();

qspi_init();
QSPI_Cmd(ENABLE);
QSPI_WriteEnable();
while (1){
blink_led();
LL_mDelay(200);}

And qspi_init() is OK, but the function QSPI_WriteEnable isn't work. It 
is wait on this line:
while(QSPI_GetFlagStatus(QSPI_FLAG_SM) == RESET){}

Any idea, what is wrong?
void qspi_init(void)
{
  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOF);
  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOB);
  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);
  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);

  LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_QSPI);
  /* Initialize QSPI ------------------------------------------------------ */
  QSPI_StructInit(&QSPI_InitStructure);
  QSPI_InitStructure.QSPI_SShift    = QSPI_SShift_HalfCycleShift;
  QSPI_InitStructure.QSPI_Prescaler = 4;  //Number = (216MHz / Fpoz)-1     (nyni Fpoz = 50MHz)
  QSPI_InitStructure.QSPI_CKMode    = QSPI_CKMode_Mode0;
  QSPI_InitStructure.QSPI_CSHTime   = QSPI_CSHTime_1Cycle;
  QSPI_InitStructure.QSPI_FSize     = 23;  //Number = 16MB is = (2^24) where 24-1 is Number
  QSPI_InitStructure.QSPI_FSelect   = QSPI_FSelect_1;
  QSPI_InitStructure.QSPI_DFlash    = QSPI_DFlash_Disable;
  QSPI_Init(&QSPI_InitStructure);
  QSPI_SetFIFOThreshold(0);

  /* Command default config */
  QSPI_ComConfig_StructInit(&QSPI_ComConfig_InitStructure);
  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_DummyCycles = 0;
  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_DHHC        = QSPI_ComConfig_DHHC_Enable;
  QSPI_ComConfig_InitStructure.QSPI_ComConfig_DDRMode     = QSPI_ComConfig_DDRMode_Disable;

  QSPI_ITConfig(QSPI_IT_SM | QSPI_IT_TO, ENABLE);

  NVIC_SetPriority(QUADSPI_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
  NVIC_EnableIRQ(QUADSPI_IRQn);
  QSPI_Cmd(ENABLE);
}

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);

    /* Switch to Autopolling mode for the end of the Command */
    while(QSPI_GetFlagStatus(QSPI_FLAG_BUSY) != RESET)
    {}
    QSPI_SetDataLength(0x01);
    QSPI_AutoPollingMode_SetInterval(0x10);
    QSPI_AutoPollingMode_Config(0x02, 0x02, QSPI_PMM_AND);
    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);

    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");
}

: Moved by Moderator
Author: Bülent C. (mirki)
Posted on:

Rate this post
0 useful
not useful
If you really want to have support, then you should give more info. 
Which flash you're using. Do you use the right commands according to the 
datasheet? From your pin configuration I can see that you're using the 
flash in a dual Modus, means two lines. You have to take in account that 
all the examples are designed for quad. Therefore copy paste wouldn't 
help you here.

Author: A. B. (Guest)
Posted on:

Rate this post
0 useful
not useful
Petr K. schrieb:
> void QSPI_WriteEnable(void)

>     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);
>
>     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");

Although I've never used the autopolling feature: Why did you ever think 
of using this mode for write enable??? The "Write Enable" command just 
sets the "Write Enable" bit in the status register of the flash chip. So 
this works instantly, i. e. as soon as the command has been sent to 
the flash the very next "Status Read" command MUST return the status 
register with WE bit set or something is quite wrong. It doesn't make 
any sense to poll the status register several times for the WE bit to 
become set.

Automatic polling only makes sense for commands which require some time 
to finish like page programming, sector erase, mass erase.

Author: Petr K. (buzzer_klaun)
Posted on:
Attached files:

Rate this post
0 useful
not useful
Ou, sorry.

I use: single-SPI mode. It is describe in pdf file:
[[http://www.st.com/content/ccc/resource/technical/d...]]

And problem is:
I try send command to enable write. After send data, I wait on this 
line:
while(QSPI_GetFlagStatus(QSPI_FLAG_SM) == RESET){};

I compared registers, but I don't see any problem.

So I know:
1. GPIO is set correct
2. Init qspi is set wrong.

CLK -(yellow)
SI - (pink)
SO - (blue)

: Edited by User
Author: Joe F. (easylife)
Posted on:

Rate this post
0 useful
not useful
Petr K. schrieb:
> I use: single-SPI mode

- Are you also using a "normal" (non-QSPI) SPI flash memory?
- Which one?
- How do you handle HOLD and WR inputs?

Author: Petr K. (buzzer_klaun)
Posted on:

Rate this post
0 useful
not useful
Type of memory is: IS25LP128

Datasheet: [[http://www.issi.com/WW/pdf/25LP128.pdf]]

Connect to my MCU is:
PB10 - CS flash
PF8 - IO0 (SI)
PF9 - IO1 (SO)
PF10 - SCK

Author: Bülent C. (mirki)
Posted on:

Rate this post
0 useful
not useful
A. B. schrieb:
> Although I've never used the autopolling feature: Why did you ever think
> of using this mode for write enable??? The "Write Enable" command just
> sets the "Write Enable" bit in the status register of the flash chip. So
> this works instantly, i. e. as soon as the command has been sent to
> the flash the very next "Status Read" command MUST return the status
> register with WE bit set or something is quite wrong. It doesn't make
> any sense to poll the status register several times for the WE bit to
> become set.

I've here other experiences. It makes sense to poll the Status everytime 
even it's for the WE command.
In most of the cases you have different Status Registers for some 
commands (e.g. WE) and for the Memory Access itself.

Author: Bülent C. (mirki)
Posted on:

Rate this post
0 useful
not useful
Petr K. schrieb:
> while(QSPI_GetFlagStatus(QSPI_FLAG_SM) == RESET){};

What is inside of QSPI_FLAG_SM?


The Datasheet is saying:
WEL bit: The Write Enable Latch (WEL) bit indicates the status of the 
internal write enable latch. When the
WEL is “0”, the write enable latch is disabled and all write operations, 
including write status register, write
configuration register, page program, sector erase, block and chip erase 
operations are inhibited. When the
WEL bit is “1”, write operations are allowed. The WEL bit is set by a 
Write Enable (WREN) instruction. Each
write register, program and erase instruction must be preceded by a WREN 
instruction. The WEL bit can be
reset by a Write Disable (WRDI) instruction. It will automatically be 
reset after the completion of any write
operation.


Below how I would solve it with HAL
void QSPI_WriteEnable(QSPI_HandleTypeDef *QSPIHandle)
{
  QSPI_CommandTypeDef     sCommand;
  QSPI_AutoPollingTypeDef 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)
  {
    Error_Handler();
  }
  
  /* 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)
  {
    Error_Handler();
  }
}

Author: Petr K. (buzzer_klaun)
Posted on:

Rate this post
0 useful
not useful
I will try to rewrite from HAL to my code. Because I don't use HAL. I 
use LL, but QSPI is not support. When I will find solution I will put it 
here.

Author: A. B. (Guest)
Posted on:

Rate this post
0 useful
not useful
Bülent C. schrieb:

> I've here other experiences. It makes sense to poll the Status everytime
> even it's for the WE command.

Maybe you should have read (and try to understand) my comment:
Yes, of course, it does make sense to check the status register ONCE.
But to attempt to check it several times is plain rubbish.
Either it is already set on the first read after the Write Enable 
command,
or the command failed (for whatever reason). And if it failed, it 
doesn't make sense to check it again. It won't come on magically later.

If the Write Enable command failed, the only reasonable recovery is to 
reset the interface (and maybe the flash chip) and start over.

But anyway, the code posted is rather complete nonsense. Why would one 
enable an interrupt and then poll for this very same event???
(BTW: The same question was posted under different name on ST's 
community)

> In most of the cases you have different Status Registers for some
> commands (e.g. WE) and for the Memory Access itself.

What's that supposed to mean?

Author: Bülent C. (mirki)
Posted on:

Rate this post
0 useful
not useful
A. B. schrieb:
> Yes, of course, it does make sense to check the status register ONCE.
> But to attempt to check it several times is plain rubbish.
> Either it is already set on the first read after the Write Enable
> command,
> or the command failed (for whatever reason). And if it failed, it
> doesn't make sense to check it again. It won't come on magically later.

OK, for at least one Point we're on the same page. It really doesn't 
make sense to check the WEL Bit within the infinity Loop like the TO is 
doing that.
The HAL Driver is given the posibility to incorporate a timeout check 
for the polling of the WEL Bit. This is how I implemented it in my 
application.
/* 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)
  {
    Error_Handler();
  }
The Timeout is set to 100ms. This is in my point of view enough. If the 
WLE Bit isn't set within 100ms, then I've other issues what I'm trying 
to handle it somewhere else.

A. B. schrieb:
> If the Write Enable command failed, the only reasonable recovery is to
> reset the interface (and maybe the flash chip) and start over.
see above

A. B. schrieb:
> But anyway, the code posted is rather complete nonsense. Why would one
> enable an interrupt and then poll for this very same event???
I think you mean the TO's Code?! Yes, agree. The Code from him is really 
nonsense

A. B. schrieb:
>> In most of the cases you have different Status Registers for some
>> commands (e.g. WE) and for the Memory Access itself.
>
> What's that supposed to mean?
You would check the WLE Bit just one time, right? But it's not as simple 
as that! How do you know when exactly you Need to check the WLE Bit? 
Assume you're using your Code for different STM32's with different clock 
Settings or something like that?
That's the reason why I do it like posted above (multiple checks with 
timeout) makes more sense than to check the WLE just once.
The same is for the write/Program sequence. You could write 1 Byte or a 
complete Page at once. After the program command is performed you Need 
to wait until the Bytes are completly written. From where do you know 
how long you have to wait?

: Edited by User
Author: Petr K. (buzzer_klaun)
Posted on:

Rate this post
0 useful
not useful
OK. I have problems with it. So I will starting again.

I split my code to more function with show registers.
Now I have this function:
qspi_gpio_ini();  /* Init GPIO pins */
qspi_dma_init();  /* Init DMA  */
qspi_init();    /* Init QSPI */
qspi_config();    /* Config QSPI */
QSPI_Cmd(ENABLE);  /* Enable QSPI */

When I resolve this function I will set Write Enable function and other. 
:)

Here is Config pins. It is OK. It is work.
void qspi_gpio_ini(void)
{
  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOF);
  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOB);
  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);
  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_SetAFPin_8_15(    GPIOB, LL_GPIO_PIN_10,  LL_GPIO_AF_9);
}

Init DMA. Here I don't know if it is work fine.
/**
 * Set register:
 * S0FCR = 0x00000021
 * s1FCR = 0x00000021
 * S2CR  = 0x16000419
 * S2FCR = 0x16000419
 * S2NDTR = 0x00000004
 * S2PAR = 0xA0001020
 * S3FCR = 0x00000021
 * S4FCR = 0x00000021
 * S5FCR = 0x00000021
 * S6FCR = 0x00000021
 * S7FCR = 0x00000021
 */
void qspi_dma_init(void)
{
  /*set from. DM00224583.pdf, from page 247, table 28 */
  LL_AHB1_GRP1_EnableClock(    LL_AHB1_GRP1_PERIPH_DMA2                  );
  LL_DMA_SetChannelSelection(    DMA2, LL_DMA_STREAM_2, LL_DMA_CHANNEL_11          );
  LL_DMA_SetDataTransferDirection(DMA2, LL_DMA_STREAM_2, LL_DMA_DIRECTION_PERIPH_TO_MEMORY  );
  LL_DMA_SetStreamPriorityLevel(  DMA2, LL_DMA_STREAM_2, LL_DMA_PRIORITY_LOW          );
  LL_DMA_SetMode(          DMA2, LL_DMA_STREAM_2, LL_DMA_MODE_NORMAL          );
  LL_DMA_SetPeriphIncMode(    DMA2, LL_DMA_STREAM_2, LL_DMA_PERIPH_NOINCREMENT      );
  LL_DMA_SetMemoryIncMode(    DMA2, LL_DMA_STREAM_2, LL_DMA_MEMORY_INCREMENT        );
  LL_DMA_SetPeriphSize(      DMA2, LL_DMA_STREAM_2, LL_DMA_PDATAALIGN_BYTE        );
  LL_DMA_SetMemorySize(      DMA2, LL_DMA_STREAM_2, LL_DMA_MDATAALIGN_BYTE        );
  LL_DMA_DisableFifoMode(      DMA2, LL_DMA_STREAM_2                    );
  LL_DMA_SetMemoryAddress(    DMA2, LL_DMA_STREAM_2, (uint32_t)FlashAddr          );
  LL_DMA_SetDataLength(      DMA2, LL_DMA_STREAM_2, sizeof(FlashAddr)          );
  LL_DMA_SetPeriphAddress(    DMA2, LL_DMA_STREAM_2, (uint32_t)&QUADSPI->DR        );
  LL_DMA_EnableIT_HT(        DMA2, LL_DMA_STREAM_2                    );
  LL_DMA_EnableIT_TC(        DMA2, LL_DMA_STREAM_2                    );
  LL_DMA_EnableStream(      DMA2, LL_DMA_STREAM_2                    );
  QSPI_DMACmd(ENABLE);  //enable DMAEN bit to DMA
}

ANd now. 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_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 = 4;              //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;    //
  QSPI_Init(&QSPI_InitStructure);
}

After init is configure...
/**
 * Set registers:
 * CCR->ADSIZE  =  0x02
 * CCR->DHHC  =  0x01
 * CCR->IMODE  =  0x01
 */
void qspi_config(void)
{
  QSPI_SetFIFOThreshold(0);

  /* 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_InitStructure.QSPI_ComConfig_DMode       = QSPI_ComConfig_DMode_NoData;        //data phase is skipped

  QSPI_ComConfig_InitStructure.QSPI_ComConfig_DHHC        = QSPI_ComConfig_DHHC_Enable;        //Delay the data output by 1/4 of a QUADSPI output clock cycle.
}

And the last function where I don't know.... Is it configure good?

Author: Petr K. (buzzer_klaun)
Posted on:
Attached files:

Rate this post
0 useful
not useful
I modificated speed, and now I get this datas.... Now it is better, 
but....

Author: Petr K. (buzzer_klaun)
Posted on:
Attached files:

Rate this post
0 useful
not useful
Hello,

I analyze my problem. And my init qspi is good, because:
1. Init GPIO is OK. Communication is workign.
2. Init qspi (default setting) is good, because I can send everything.

And now, I'm looking on my program:
1. Send command 0x06 is OK.
2. Send command 0x05 is OK.
3. Receive datas is wrong. Because they have 9 bits.

And I don't know, why the receive datas have 9bits.

What do you think, what is wrong?
/* 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);

    while(QSPI_GetFlagStatus(QSPI_FLAG_SM) == RESET)

Author: Petr K. (buzzer_klaun)
Posted on:

Rate this post
0 useful
not useful
Ok. Problem with more 1bit is here:

Bad:
QSPI_InitStructure.QSPI_SShift    = QSPI_SShift_HalfCycleShift

Good:
QSPI_InitStructure.QSPI_SShift    = QSPI_SShift_NoShift;

But program is still waiting on this line:
while(QSPI_GetFlagStatus(QSPI_FLAG_SM) == RESET){};

: Edited by User

Reply

Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]




Bild automatisch verkleinern, falls nötig
Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.