cancel
Showing results for 
Search instead for 
Did you mean: 

AutoPolling QSPI and memory erase

Pilous Droip
Senior
Posted on February 16, 2018 at 19:52

Hello friends.

I have a problem. I erase external memory. But this procedure last long time. So I set autopolling mode with interrupt. But It doesn't work.

When I send erase command I need wait on WIP bit in status register. And when QIP bit is set, I need generate interrupt.

And program work:

  1. Send 0x06 - enable write to memory
  2. Send erase memory 0xC7
  3. Set autopolling mode

And when I set autopolling mode, immediately is generating interrupt. And it is wrong.

Any idea, what is wrong?

0690X00000609i6QAA.png

So. Here is my autopolling initializion.

void QSPI_AutoPollingMemReady(void)

{

uint32_t tmpreg = 0;

while (QUADSPI->SR & QUADSPI_SR_BUSY) {};

QUADSPI->PSMAR = 0x0000;

QUADSPI->PSMKR = 0x0101;

QUADSPI->CR &= ~ QUADSPI_CR_PMM; /* AND Match Mode */

QUADSPI->CR |= QUADSPI_CR_APMS; //enable autopolling

QUADSPI->DLR = 0x00; //data lenght 0-1bytes; 1-2bytes; 2-3bytes.....

tmpreg = QUADSPI->CCR;

tmpreg &= 0x90800000;

tmpreg |=

(0x00 << QUADSPI_CCR_DDRM_Pos) | // Disable DDR mode

(0x00 << QUADSPI_CCR_DHHC_Pos) | // Delay the data output using analog delay

(0x00 << QUADSPI_CCR_SIOO_Pos) | // Send instruction on every transaction

(0x02 << QUADSPI_CCR_FMODE_Pos) | // function QSPI (0-indirect write); (1-indirect read); (2-autopolling)

(0x01 << QUADSPI_CCR_DMODE_Pos) | // Data mode (0-nodata); (1-data on single line); .....

(0x00 << QUADSPI_CCR_DCYC_Pos) | // Dummy cycle

(0x00 << QUADSPI_CCR_ABSIZE_Pos) | // size of alternate bytes (0-8bit); (1-16bit); (2-24bit); (3-32bit)

(0x00 << QUADSPI_CCR_ABMODE_Pos) | // Alternate mode (0-no alternate); (1-alternate on single line)

(0x02 << QUADSPI_CCR_ADSIZE_Pos) | // size of address bytes (0-8bit); (1-16bit); (2-24bit); (3-32bit)

(0x00 << QUADSPI_CCR_ADMODE_Pos) | // Address mode (0-no address); (1-address on a single line)

(0x01 << QUADSPI_CCR_IMODE_Pos ) | // Instruction mode (0-no instruction); (1-instruction on signel line)

(READ_STATUS_REG_CMD << QUADSPI_CCR_INSTRUCTION_Pos); // Instruction send on SPI 0x05

QUADSPI->CCR = tmpreg;

asm(''NOP'');

QUADSPI->FCR = 0x00; //clear flag

asm(''NOP'');

/*Enable Interrupts*/

tmpreg = QUADSPI->CR ;

tmpreg |= (uint32_t)((QUADSPI_CR_SMIE | QUADSPI_SR_SMF | QUADSPI_CR_FTIE | QUADSPI_SR_FTF | QUADSPI_CR_TEIE | QUADSPI_SR_TEF) & 0x001F0000);

QUADSPI->CR = tmpreg ;

}

And here is my interrupt:

void QUADSPI_IRQHandler(void)

{

if((QUADSPI->SR & QUADSPI_SR_FTF))

{

QUADSPI->FCR = (uint32_t)((QUADSPI_CR_SMIE | QUADSPI_SR_SMF) & 0x001F0000);

/* Disable the QSPI FIFO Threshold, Transfer Error and Status Match Interrupts */

QSPI_disable_IT((QUADSPI_CR_SMIE | QUADSPI_SR_SMF | QUADSPI_CR_FTIE | QUADSPI_SR_FTF | QUADSPI_CR_TEIE | QUADSPI_SR_TEF), DISABLE);

usart_puts(''\r\nErase success\r\n'');

}

LL_GPIO_TogglePin(GPIOB, GREEN);

}

#quadspi #nucleo-f767zi #stm32f767zi
6 REPLIES 6
AVI-crak
Senior
Posted on February 17, 2018 at 03:51

QUADSPI polling status mask register (QUADSPI _PSMKR)

QUADSPI polling status match register (QUADSPI _PSMAR)

Mask and stencil for checking the flag in automatic mode of infinite reading.

PSMKR - the mask resets all the irrelevant bits when reading the flag, PSMAR performs the XOR operation with the result = if there is a complete match, the interrupt will occur. Any other value that does not match the mask and the stencil is ignored.
Posted on February 17, 2018 at 12:13

Yes. This is my problem.

I have got PSMAR and PSMKR wrong set. And I don't know, how to set good value.

So, I know this.

  1. Call erase.
  2. Erase set last bit WIP to HIGH.
  3. Set autopolling.

And what I must set to register PSMAR and PSMKR?

Is this value good? What do you mean?

QUADSPI->PSMKR = 0x01;

QUADSPI->PSMAR = 0x00;

0690X00000609irQAA.png0690X00000609jiQAA.png
Posted on February 17, 2018 at 13:06

Mask and stencil are applied to the full width (it is desirable).

Memory responds in a loop all the time, it's not one byte - but 4. It looks something like this:

mask 0x01010101 - the remaining bits will be reset

stencil 0x00000000 - wait for the answer to match (your case is now 0x01 -> expect 0x00).

If you want to control two bits or more - they all need to get into the mask, even if they are at the start zero.

The mask is a binary operation '&', the stencil is a binary operation '^'.

An additional problem is the direction of reading the bits (high / low). In this problem, you can easily lose the goal. The easiest option is to catch the answer during debugging (it might surprise you). The way it will look - it's easy to build a mask and a stencil.

Posted on February 17, 2018 at 13:41

I don't understand. 

:((

 But I try applicated to my code and it is working fine. But how...... 

Ok. I go to study. Sometimes an easy problem is a difficult problem.  Thank you.

For all. Here is my working solution:

void QSPI_AutoPollingMemReady(void)

{

uint32_t tmpreg = 0;

while (QUADSPI->SR & QUADSPI_SR_BUSY) {};

tmpreg = QUADSPI->PIR ;

tmpreg &= 0xFFFF0000 ; /* Clear Polling interval Bits */

tmpreg |= 0x10; /* Set the QSPI Polling Interval Bits */

QUADSPI->PIR = tmpreg; /* Write the PIR Register */

QUADSPI->PSMAR = 0x00000000 ;

QUADSPI->PSMKR = 0x01010101 ; /* Busy Bit */

QUADSPI->CR &= ~ QUADSPI_CR_PMM; /* AND Match Mode */

QUADSPI->CR |= QUADSPI_CR_APMS; //enable autopolling

QUADSPI->DLR = 0x00; //data lenght 0-1bytes; 1-2bytes; 2-3bytes.....

tmpreg = QUADSPI->CCR;

tmpreg &= 0x90800000;

tmpreg |=

(0x00 << QUADSPI_CCR_DDRM_Pos) | // Disable DDR mode

(0x00 << QUADSPI_CCR_DHHC_Pos) | // Delay the data output using analog delay

(0x00 << QUADSPI_CCR_SIOO_Pos) | // Send instruction on every transaction

(0x02 << QUADSPI_CCR_FMODE_Pos) | // function QSPI (0-indirect write); (1-indirect read); (2-autopolling)

(0x01 << QUADSPI_CCR_DMODE_Pos) | // Data mode (0-nodata); (1-data on single line); .....

(0x00 << QUADSPI_CCR_DCYC_Pos) | // Dummy cycle

(0x00 << QUADSPI_CCR_ABSIZE_Pos) | // size of alternate bytes (0-8bit); (1-16bit); (2-24bit); (3-32bit)

(0x00 << QUADSPI_CCR_ABMODE_Pos) | // Alternate mode (0-no alternate); (1-alternate on single line)

(0x02 << QUADSPI_CCR_ADSIZE_Pos) | // size of address bytes (0-8bit); (1-16bit); (2-24bit); (3-32bit)

(0x00 << QUADSPI_CCR_ADMODE_Pos) | // Address mode (0-no address); (1-address on a single line)

(0x01 << QUADSPI_CCR_IMODE_Pos ) | // Instruction mode (0-no instruction); (1-instruction on signel line)

(READ_STATUS_REG_CMD << QUADSPI_CCR_INSTRUCTION_Pos); // Instruction send on SPI

QUADSPI->CCR = tmpreg;

QUADSPI->FCR = QUADSPI_FCR_CSMF; //clear flag

/*Enable Interrupts*/

QUADSPI->CR &= ~QUADSPI_CR_TOIE; //disable Timeout interrupt

QUADSPI->CR |= QUADSPI_CR_SMIE; //enable Status Match interrupt

QUADSPI->CR &= ~QUADSPI_CR_FTIE; //disable Fifo treshold interrupt

QUADSPI->CR &= ~QUADSPI_CR_TEIE; //disable transfer error interrupt

}

void QUADSPI_IRQHandler(void)

{

if((QUADSPI->SR & QUADSPI_SR_SMF))

{

QUADSPI->FCR |= QUADSPI_FCR_CSMF;

QUADSPI->CR &= ~QUADSPI_CR_SMIE; //Disable interrupt

usart_puts('\r\nErase The End\r\n');

}

LL_GPIO_TogglePin(GPIOB, GREEN);

}
Pilous Droip
Senior
Posted on February 19, 2018 at 10:56

I try to understand it.

0690X00000609jdQAA.png

for check WIP bit I used:

QUADSPI->PSMAR = 0x00000000 ;

QUADSPI->PSMKR = 0x01010101 ;

but for check WEL bit I used:

QUADSPI->PSMAR = 0x02;

QUADSPI->PSMKR = 0x02;

Can anyone describe the use of PSMAR and PSMKR?

Posted on February 19, 2018 at 13:19

I already said how it's done.

There is no point in understanding, there are a lot of conditions and confusion. It is much easier to read the answer in a simple way, it will look exactly like this - how you need to process it. The status response always has a size of 8 bits, and it repeats in a loop until a clock signal is sent to the memory chip. (First, you need to give the status reading command.) But the answer may differ from the documentation, primarily externally. A WIP can be the first least significant bit, or maybe the most significant bit. I abandoned the idea of guessing, it is easier for me to consider the answer from the debugger.

You got a cast, and WIP is in the low bit. In this case, you need to reset everything except PSMKR 0x01010101. Now you can catch the necessary condition for you WIP = 0 PSMAR = 0x0, WIP = 1 PSMAR = 0x01010101.

Sequence for recording:

1) Enable recording

2) Wait for the WEL flag (1), WIP (not important) - very fast

3) Wait for the WIP flag (1), WEL (not important) - 1 ~ 10mc

4) write to the address

5) remove the CS signal, and read the flags again before the complete coincidence of WEL (0), WIP (0) - 1 ~ 500mc.