Author Topic: STM32F0 SPI 8bit communication frame (errata?)  (Read 15963 times)

0 Members and 1 Guest are viewing this topic.

Offline hub.martin

  • Contributor
  • Posts: 22
  • Country: cz
    • martinhubacek.cz
STM32F0 SPI 8bit communication frame (errata?)
« on: October 03, 2013, 01:49:05 pm »
Hello,

I'm porting NRF24l01+ driver library to STM32F0 Discovery kit. I'm unable to send 8bit SPI data frame. Data size bits in CR2 register are ok and set to 8bit by datasheet but I see 16 clock on line. There's errata on SPI on this chip but I'm not sure if this is the case.

See attached pictures

There's also someone who found the same issue.
https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2Fcortex_mx_stm32%2FSTM32F0%20Trying%20to%20use%20SPI2%20in%208-bit%20mode%2C%20but%20each%20transfer%20causes%2016%20clock%20cycles&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=155

Thanks for any idea

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8229
  • Country: 00
Re: STM32F0 SPI 8bit communication frame (errata?)
« Reply #1 on: October 03, 2013, 03:10:38 pm »
You showed the set-up sequence. What's your transmission sequence?

I haven't tried F0 but have used F103, with no problem. The spi peripherals are similar (identical?) so I would expect it to work.
================================
https://dannyelectronics.wordpress.com/
 

Offline AndreasF

  • Frequent Contributor
  • **
  • Posts: 251
  • Country: gb
    • mind-dump.net
Re: STM32F0 SPI 8bit communication frame (errata?)
« Reply #2 on: October 03, 2013, 06:42:55 pm »
Could it be a simple bug in the library? I would check if the registers are actually set as they are supposed to be set.
my random ramblings mind-dump.net
 

Offline hub.martin

  • Contributor
  • Posts: 22
  • Country: cz
    • martinhubacek.cz
Re: STM32F0 SPI 8bit communication frame (errata?)
« Reply #3 on: October 03, 2013, 06:53:28 pm »
Quote
Could it be a simple bug in the library? I would check if the registers are actually set as they are supposed to be set.
That was the first thing I've checked. First post: "Data size bits in CR2 register are ok."

Quote
What's your transmission sequence?
I'm at home right now so don't have the code right now with me, but writing is as simple as write data to the SPI1->DR. I use STMF100 and STMF4 and SPI is there ok. But on F0 it has to be crippled a little (because of smaller silicon size and price), also SPI peripheral is able to switch to half-duplex I2S transmission so I guess this is a completely new block from ST.

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 892
  • Country: us
Re: STM32F0 SPI 8bit communication frame (errata?)
« Reply #4 on: October 05, 2013, 03:08:05 am »
If you think it's actually running in 16-bit mode, put a known value in for the second byte and see if it shows up on the decode trace. It seems unlikely that they're sending an extra byte of zeros--perhaps there's an off-by-one error in the setup? Are you using DMA?
 

Offline ealex

  • Frequent Contributor
  • **
  • Posts: 291
  • Country: ro
Re: STM32F0 SPI 8bit communication frame (errata?)
« Reply #5 on: October 05, 2013, 06:19:10 am »
Hello
I've had the same problem with the SPI on stm32f0 : the peripheral was configured in 8 bit mode but it would write 16 bits, the first 8 the actual data and the next 8 just 0.

I was not using the stm peripheral. library - just the platform header file.
In my case the problem was in the SPI typedef in stm32f0...h: the data type that was defined for the SPI data register is 16 bits: the compiler (gcc) will create that operation as a 16 bit write even if i casted all types to uint8

My fix was to alter the header file: create a union for the data register: two uint8 over a uint16 type or redefine the data register as uint8 DRH and DRL -> the write operation will explicitly be an 8 bits one and the compiler / peripheral will not get confused: SPI_DR typedef in the code below

in stm32f0xx.h
Code: [Select]

typedef union {
    uint16_t DR;
    struct{
        unsigned char DR0;
        unsigned char DR1;
    };
}SPI_DR;


typedef struct
{
 __IO uint16_t CR1;      /*!< SPI Control register 1 (not used in I2S mode),       Address offset: 0x00 */
 uint16_t  RESERVED0;    /*!< Reserved, 0x02                                                            */
 __IO uint16_t CR2;      /*!< SPI Control register 2,                              Address offset: 0x04 */
 uint16_t  RESERVED1;    /*!< Reserved, 0x06                                                            */
 __IO uint16_t SR;       /*!< SPI Status register,                                 Address offset: 0x08 */
 uint16_t  RESERVED2;    /*!< Reserved, 0x0A                                                            */
 __IO SPI_DR DR;       /*!< SPI data register,                                   Address offset: 0x0C */
 uint16_t  RESERVED3;    /*!< Reserved, 0x0E                                                            */
 __IO uint16_t CRCPR;    /*!< SPI CRC polynomial register (not used in I2S mode),  Address offset: 0x10 */
 uint16_t  RESERVED4;    /*!< Reserved, 0x12                                                            */
 __IO uint16_t RXCRCR;   /*!< SPI Rx CRC register (not used in I2S mode),          Address offset: 0x14 */
 uint16_t  RESERVED5;    /*!< Reserved, 0x16                                                            */
 __IO uint16_t TXCRCR;   /*!< SPI Tx CRC register (not used in I2S mode),          Address offset: 0x18 */
 uint16_t  RESERVED6;    /*!< Reserved, 0x1A                                                            */
 __IO uint16_t I2SCFGR;  /*!< SPI_I2S configuration register,                      Address offset: 0x1C */
 uint16_t  RESERVED7;    /*!< Reserved, 0x1E                                                            */
 __IO uint16_t I2SPR;    /*!< SPI_I2S prescaler register,                          Address offset: 0x20 */
 uint16_t  RESERVED8;    /*!< Reserved, 0x22                                                            */   
} SPI_TypeDef;
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8229
  • Country: 00
Re: STM32F0 SPI 8bit communication frame (errata?)
« Reply #6 on: October 05, 2013, 10:40:09 am »
Quote
the compiler (gcc) will create that operation as a 16 bit write even if i casted all types to uint8

Even if the compiler does that, the hardware shouldn't, as you have specified the width to be 8 bits.

Puzzling.
================================
https://dannyelectronics.wordpress.com/
 

Offline Harvs

  • Super Contributor
  • ***
  • Posts: 1184
  • Country: au
Re: STM32F0 SPI 8bit communication frame (errata?)
« Reply #7 on: October 05, 2013, 11:04:58 am »
Quote
the compiler (gcc) will create that operation as a 16 bit write even if i casted all types to uint8

Even if the compiler does that, the hardware shouldn't, as you have specified the width to be 8 bits.

Puzzling.

It's been a while since I used the F0 so my memory is patchy (and I can't look it up at the moment.)  But I recall that when configured in <32bit mode the register operates as a multi-byte buffer.  I.e. write a 32bit word to it while it's in 8-bit mode and it will send it as 4 single byte transfers. A 32bit word in 16bit mode will send two 16bit transfers...
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8229
  • Country: 00
Re: STM32F0 SPI 8bit communication frame (errata?)
« Reply #8 on: October 05, 2013, 11:30:09 am »
Quote
But I recall that when configured in <32bit mode the register operates as a multi-byte buffer.

Those are 16-bit registers so you cannot write 32 bits to them.

Quote
I.e. write a 32bit word to it while it's in 8-bit mode and it will send it as 4 single byte transfers. A 32bit word in 16bit mode will send two 16bit transfers...

If so, it must be a bug - it defeats the purpose to have the data frame definition.

I doubt, however, that's the case - something else is at play here. Does the errata mention it?

================================
https://dannyelectronics.wordpress.com/
 

Offline Harvs

  • Super Contributor
  • ***
  • Posts: 1184
  • Country: au
Re: STM32F0 SPI 8bit communication frame (errata?)
« Reply #9 on: October 05, 2013, 12:06:08 pm »
Quote
But I recall that when configured in <32bit mode the register operates as a multi-byte buffer.

Those are 16-bit registers so you cannot write 32 bits to them.
Yes you're right, as I said it's been a while, the actual register you write to is 16-bit.  However, it's got a 32-bit FIFO behind it as per the attachment.  That's what I was thinking of.

Quote
Quote
I.e. write a 32bit word to it while it's in 8-bit mode and it will send it as 4 single byte transfers. A 32bit word in 16bit mode will send two 16bit transfers...

If so, it must be a bug - it defeats the purpose to have the data frame definition.

I doubt, however, that's the case - something else is at play here. Does the errata mention it?

There is a manual, RM0091 Reference manual, that explains all this quite well (along with every other peripheral).  In fact there's about three pages on using the FIFO and packing modes in the SPI.
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8229
  • Country: 00
Re: STM32F0 SPI 8bit communication frame (errata?)
« Reply #10 on: October 05, 2013, 12:19:32 pm »
Quote
In fact there's about three pages

A few pages earlier, it also described how the mcu is to behave with different frame length. That's what you need to read.

If the mcu doesn't behave as described in the datasheet, it is a bug.

But we have never seen the full code so we will never know.
================================
https://dannyelectronics.wordpress.com/
 

Offline ealex

  • Frequent Contributor
  • **
  • Posts: 291
  • Country: ro
Re: STM32F0 SPI 8bit communication frame (errata?)
« Reply #11 on: October 06, 2013, 04:54:49 am »
It might be a documentation problem, but the peripheral behaves as Harvs said: in 8 bit mode an 32 or 16 bit access will load 4 or 2 bytes in the internal FIFO -> you will end up with several operation even if you configured it in 8 bit mode.
The  only way to make is behave as indented is to make an 8 bit write access to the FIFO registers.

I've never read RM0091 - discovered the fix after loosing an entire day on the issue ...
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8229
  • Country: 00
Re: STM32F0 SPI 8bit communication frame (errata?)
« Reply #12 on: October 06, 2013, 11:48:39 am »
Quote
in 8 bit mode an 32 or 16 bit access will load 4 or 2 bytes in the internal FIFO

I don't know how you could have 32-bit access to the internal fifo, given that it is 16-bit.

Quote
discovered the fix after loosing an entire day on the issue ...

That's very convoluted.

You could have just written to a uint8_t pointer pointed to SPIx_DR if you are writing 8-bit or less data.

================================
https://dannyelectronics.wordpress.com/
 

Offline hub.martin

  • Contributor
  • Posts: 22
  • Country: cz
    • martinhubacek.cz
Re: STM32F0 SPI 8bit communication frame (errata?)
« Reply #13 on: October 06, 2013, 07:40:00 pm »
Hello to all. Thanks for all your code and ideas.
It seems that I really have to cast writing value to uint8_t. I've also found function SPI_SendData8(SPI1, data); from the library which does the same.
The new code with SPI_SendData8(SPI1, data); really makes just 8 CLK pulses so it was my mistake of not understanding of how FIFO in STM32F works.
I do more test tomorrow.

Thanks again

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8229
  • Country: 00
Re: STM32F0 SPI 8bit communication frame (errata?)
« Reply #14 on: October 06, 2013, 07:43:46 pm »
Quote
It seems that I really have to cast writing value to uint8_t. I've also found function SPI_SendData8(SPI1, data);

The datasheet is fairly clear about this: writing to a 16-bit SPIx_DR will send out more pulses; typcasting the data to uint8_t before assigning it to SPIx_DR doesn't solve the problem.

You have to write to a (uint8_t) pointer pointed to SPIx_DR to limit the pulses. That's effectively what SPI_SendData8() does.
================================
https://dannyelectronics.wordpress.com/
 

Offline hub.martin

  • Contributor
  • Posts: 22
  • Country: cz
    • martinhubacek.cz
Re: STM32F0 SPI 8bit communication frame (errata?)
« Reply #15 on: October 07, 2013, 01:42:20 pm »
Perfect, it is working now.

This is the right writing sequence for 8 bit writes:
Code: [Select]
uint8_t spiSend(uint8_t data)
{
while((SPI1->SR&SPI_I2S_FLAG_TXE)==RESET);
SPI_SendData8(SPI1,data);
while((SPI1->SR & SPI_I2S_FLAG_RXNE)==RESET);
return SPI_ReceiveData8(SPI1);
}

Also I had to set RX FIFO level to quarter, so the SPI_I2S_FLAG_RXNE bit is set even when I receive just 8 bit
Code: [Select]
SPI_RxFIFOThresholdConfig(SPI1, SPI_RxFIFOThreshold_QF);
Thanks to everyone and specially to dannyf.

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8229
  • Country: 00
Re: STM32F0 SPI 8bit communication frame (errata?)
« Reply #16 on: October 07, 2013, 06:47:40 pm »
I am glad that it worked out for you.
================================
https://dannyelectronics.wordpress.com/
 

Offline jaakjensen

  • Newbie
  • Posts: 1
  • Country: us
Re: STM32F0 SPI 8bit communication frame (errata?)
« Reply #17 on: July 21, 2020, 04:05:43 am »
Hi Ealex,

I just wanted to post on here to thank you very much for your suggestion about turning the DR register into a union. I had been tearing my hair out all night... I was almost at the brink of tears... until I found your advice!

I was trying to port over some code to an STM32L432 that I wrote for STM32f405 but the data frame format declarations differ between the two devices. STM32f405 doesn't do the data packing that STM32l432 does.

Using the code below and writing to the register using:
pSPIx->DR.DR0 = *(pTxBuffer);

Did the trick! Thank you so very much. You made my night <3 <3 <3

 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf