cancel
Showing results for 
Search instead for 
Did you mean: 

SPI bugs in F446/429?

Mikas Longbardi
Associate II
Posted on August 21, 2017 at 03:58

Surely this issue has been beaten to death already?

SPI3:

Are there any known 'end of byte/word transmit' function (soft/hardware)

working on SPI3 in master mode? Actually in 'any' mode,  im just doing

simple plain periodic (plenty of dead time in between transmits, not

constant that would hold BSY low) transmit with no interference (i hope)

of  NSS/SSI crap, only GPIO pin as strobe for external shift register.

I cant detect any SPI BSY being set during transmission as it should be!

Is there any specific setup flow and init of SPI logic needed?

SPI3->DR = ledbuff;                                  //Write SPI transmit reg 

while((SPI3->SR & SPI_SR_TXE) == 0)  //Test until TXE flag is 1

{}

while((SPI3->SR & SPI_SR_BSY) == 1)  //Test until Busy flag is 0

{}

According to errata for rev A of F446 and rev11 for F429 there are complex

bugs in SPI module and equal complex suggestions for workarounds that

apparently dont work ,BSY mentioned.

Is there a workaround that one could use RXNE (MISO-MOSI loopback)

or something else as a detector?

Contemplating use USART instead since it works out of the box by detecting

TC flag unfortunately USART's in synchronous mode is much slower then SPI.
14 REPLIES 14
Posted on August 26, 2017 at 14:58

That == 1 is not the right test for the bit mask chosen, != 0 would work

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Mikas Longbardi
Associate II
Posted on August 27, 2017 at 23:55

>>>That == 1 is not the right test for the bit mask chosen, != 0 would work

Sorry to say but that (not equal to zero) is as stone dead as my  ==1

//Test until Busy flag is 0

>>>Um, SPI_SR_BSY is 0x80, not 0x01.

Hum, what's this 0x80? It's address?

Then this ST manufactured code also wrong?

while((RCC->CR & RCC_CR_PLLRDY) == 0) {}
Mikas Longbardi
Associate II
Posted on August 28, 2017 at 03:31

Right, had completely forgot , thanks Clive and Vangelis!

Late night edit:

Went back to SPI and spoked around a bit more why

while((SPI3->SR & SPI_SR_BSY) !=0) {}  //Test BSY if it's 1, if 0 then exit test.

didnt work and pondered if there is some kind of delay issues with BSY 

(errata talks about sync issues with internal buses) or the cpu is to quick

to test BSY and sure enough 12 nop's is what it took to detect BSY.

asm('nop; '); // nop instruction as delay

asm('nop; '); // nop instruction as delay

asm('nop; '); //nop instruction as delay

asm('nop; '); //nop instruction as delay

asm('nop; '); // nop instruction as delay

asm('nop; '); // nop instruction as delay

asm('nop; '); // nop instruction as delay

asm('nop; '); // nop instruction as delay

asm('nop; '); // nop instruction as delay

asm('nop; '); // nop instruction as delay

asm('nop; '); // nop instruction as delay

asm('nop; '); // nop instruction as delay

while((SPI3->SR & SPI_SR_BSY) !=0) {} //Test BSY if it's 1, if 0 then exit test.

or 2 dummy reads/writes to 'something' also works such as

GPIOC->BSRR = GPIO_BSRR_BR_11; //Set PC11 low, used as delay

GPIOC->BSRR = GPIO_BSRR_BR_11; //Set PC11 low, used as delay

while((SPI3->SR & SPI_SR_BSY) !=0) {} //Test BSY if it's 1, if 0 then exit test.

I noted that detecting BSY is 'SPI clock rate sensitive' nop's bails out if rate

to high while dummy's obviously longer and behaves more like detecting

NRXE.

Perhaps also why Williams HAL code above works, loads of delays checking

HALs dependencies etc, etc what not's.

Posted on August 28, 2017 at 01:51

You're doing a bit wise AND so 0x40 & 0x80 = 0, so a comparison with 0 or not 0 will work

0x80 & 0x80 = 0x80

It is a bit in a register, ie bit 7, or (1 << 7)

0690X000006042KQAQ.jpg
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on August 28, 2017 at 01:52

Hi Mikas!

'while((SPI3->SR & SPI_SR_BSY) == 1)  //Test until Busy flag is 0

{}'

At the above code (SPI3->SR & SPI_SR_BSY) is not a logical argument but an arithmetic value.

This means, if this value is not equal to another arithmetic value like 1  the logic ((SPI3->SR & SPI_SR_BSY) == 1)  will never be true because 0x0080 or 0x0000 (SR register ANDed with 0x0080) is never equal to one!

In the above comparison (SPI3->SR & SPI_SR_BSY) is an intermediate value stored in a register usualy R0 or R1.

'Then this ST manufactured code also wrong?

while((RCC->CR & RCC_CR_PLLRDY) == 0) {}'

This code is not wrong because the intermediate arithmetic value (RCC->CR & RCC_CR_PLLRDY) may be equal to zero when the flag at register RCC_CR is zero.

Regards

vf