2018-02-16 10:52 AM
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:
And when I set autopolling mode, immediately is generating interrupt. And it is wrong.
Any idea, what is wrong?
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 #stm32f767zi2018-02-16 06:51 PM
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.2018-02-17 04:13 AM
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.
And what I must set to register PSMAR and PSMKR?
Is this value good? What do you mean?
QUADSPI->PSMKR = 0x01;
QUADSPI->PSMAR = 0x00;
2018-02-17 05:06 AM
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 resetstencil 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.
2018-02-17 05:41 AM
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);}2018-02-19 01:56 AM
I try to understand it.
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?
2018-02-19 05:19 AM
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 recording2) Wait for the WEL flag (1), WIP (not important) - very fast3) Wait for the WIP flag (1), WEL (not important) - 1 ~ 10mc4) write to the address5) remove the CS signal, and read the flags again before the complete coincidence of WEL (0), WIP (0) - 1 ~ 500mc.