cancel
Showing results for 
Search instead for 
Did you mean: 

Interesting bug in SPI. Send 14 bits instead of 8 + BSY flag. (STM32L010K8) [solved]

VDery.1
Associate II

I used SPI. 8 bit. HCLK / PCLK1 / PCLK2 is 1 MHz from HSI. I've run the standard code many times:

SPI->CR1 = 0;
SPI->CR1 = (0x7 << 3) | (1u << 2);
SPI->CR2 = (1 << 2);  // Without OVR.
SPI->CR1 |= 1 << 6;   // Enable.

It worked. Many launches after that, I started getting BSY flag after line 4. If I then execute this line:

SPI->DR = 0;

I get this in a boolean analyzer:

0693W00000HqKvxQAF.pngI was doing RCC RESET SPI. I turned SPI on and off in RCC ENABLE. It did not help. If after that I send 0xFF, then I received 0b00000011 in the logic analyzer. If I further sent 0x00, I received 0b11111100. Etc. I got an offset of 6 bits. All submissions were further shifted by 6 bits.

I came up with a solution:

SPI->CR1 = 0;
SPI->CR1 = (0x7 << 3) | (1u << 2) ;
SPI->CR2 = (1 << 2) ; 
 
// Dirty hack to enable.
*((volatile uint8_t*)&SPI->DR) = 0x00;
SPI->CR1 |= 1 << 6;                    // Enable.
for (volatile int i = 0; i < 10; i++)  // For start transaction.
    ;
while (SPI->SR & (1 << 7))
    ;
volatile uint8_t buf = (uint8_t)SPI->DR;
buf                  = (uint8_t)SPI->DR;
buf                  = (uint8_t)SPI->SR;
buf                  = (uint8_t)SPI->DR;
(void)buf;

This makes one transaction. 14 bit. But after that, all data is sent without offset.

However, there is a better solution. To get rid of the error completely, you need to disconnect the power from the microcontroller for 10 minutes. After that, the problem disappears. Initialization from document starts working immediately.

I think inside the SPI there is a bit counter. This counter may not be reset via RCC_RESET. Also EN set and reset.

Please check this in your VHDL / Verilog / SystemVerilog / other language source code.

It took me 3 hours to discover this.

4 REPLIES 4

There's a dedicated subchapter Procedure for disabling the SPI in the SPI chapter in RM.

I think it's there for a reason.

Also, try to maintain other CR1 bits when clearing SPE.

JW

I read this paragraph. In my device, SPI never turns off. I am using DMA. I am setting up TX and RX channels in a thread. I start the transmission first RX, then TX (SPI is always master). I go into the interrupt from the RX channel. I give back the semaphore.

But when I do an RCC RESET, I expect the core of the periphery to be rebooted. It doesn't work that way. And this is a mistake, I suppose.

If I ended the transaction incorrectly due to a power outage, I should be able to restart at power up. I have to be 100% able to repeat the initialization procedure.

I think it is worth adding information about this to the errata. It will be fair.

> In my device, SPI never turns off.

OK so is this run only once, after reset?

> SPI->CR1 = 0;

Could you please post a minimal, but complete compilable code which exhibits the problem?

JW

VDery.1
Associate II

> OK so is this run only once, after reset?

If I reboot incorrectly, then all reboots after this will result in a wrong start.

> Could you please post a minimal, but complete compilable code which exhibits the problem?

It will be difficult, but I will try. I saw this only 1 time. Because I didn’t turn off the power of the chip for 4 hours. Working constantly with the debugger.