Skip to main content
Frederic REMY
Associate
June 9, 2017
Solved

STM32F091RCT6 SPI Peripheral weird behavior with 8 bits data mode

  • June 9, 2017
  • 14 replies
  • 3146 views
Posted on June 09, 2017 at 11:23

Hello,

I have a

weird

  behavior with STM32F091RCT6 SPI Peripheral on Nucleo Evaluation Board.

I want to interface with a 25LC640 SPI eeprom with 8 bits data mode

When i want to send a byte, i see On Oscilloscope 16 clocks pulse instead of 8 !!

I have tested several setting, i have the good number of pulses for 9 bits data size and more .

Context :

STM32F091RCT6

HAL library 1.6

Keil IDE & compiler : 5.06

SPI2 Peripheral on Port B Pin 13,14,15 Master Mode without NSS pin

SPI setup like this :

void MX_SPI2_Init(void)

{

  hspi2.Instance = SPI2;

  hspi2.Init.Mode = SPI_MODE_MASTER;

  hspi2.Init.Direction = SPI_DIRECTION_2LINES;

  hspi2.Init.DataSize = SPI_DATASIZE_8BIT;

  hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH;

  hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;

  hspi2.Init.NSS = SPI_NSS_SOFT;

  hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;

  hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;

  hspi2.Init.TIMode = SPI_TIMODE_DISABLE;

  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;

  hspi2.Init.CRCPolynomial = 8;

  hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;

  hspi2.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;

  if (HAL_SPI_Init(&hspi2) != HAL_OK)

  {

    Error_Handler();

  }

}

    __HAL_RCC_SPI2_CLK_ENABLE();

       __HAL_SPI_ENABLE(spiHandle);        

 

    /**SPI2 GPIO Configuration    

    PB13     ------> SPI2_SCK

    PB14     ------> SPI2_MISO

    PB15     ------> SPI2_MOSI

    */

    GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;

    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

    GPIO_InitStruct.Pull = GPIO_NOPULL;

    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

    GPIO_InitStruct.Alternate = GPIO_AF0_SPI2;

    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

Sending function :

static uint8_t eep_SpiSendByte (uint8_t data)

{

    while (( EE_SPI->SR & SPI_SR_TXE_Msk) == RESET);             // Wait for empty transmit buffer

    EE_SPI->DR = data;                                                                      

    while (( EE_SPI->SR & SPI_SR_RXNE_Msk) == RESET);           // Wait for received buffer with new data

    return (uint8_t)EE_SPI->DR;

}

Thanks

#stm32f091-spi-spi_datasize_8bit #hal-v1.6
This topic has been closed for replies.
Best answer by waclawek.jan
Posted on June 16, 2017 at 11:47

while ((EE_SPI->SR & SPI_SR_RXNE_Msk) == RESET)

You want to put a semicolon ; or an empty compound statement {} after this statement.

JW

14 replies

waclawek.jan
Super User
June 9, 2017
Posted on June 09, 2017 at 11:33

*(volatile uint8_t*)&EE_SPI->DR = data;   

Zt Liu
Senior III
June 9, 2017
Posted on June 09, 2017 at 12:02

I think the above is the correct answer.

AvaTar
Senior III
June 9, 2017
Posted on June 09, 2017 at 11:45

Or perhaps this:

while (( EE_SPI->SR & SPI_SR_TXE_Msk) == RESET); // Wait for empty transmit buffer

The TXE flag set does not mean the send finished, only the send data are moved to the hardware send reg.

I fell into this trap some time ago ...

waclawek.jan
Super User
June 9, 2017
Posted on June 09, 2017 at 11:52

Perhaps, but it's more likely it's the 'data packing' feature, see RM0090  'data packing' subchapter of the SPI chapter.

A recurring issue here ever since the 'enhanced' SPIs appeared, first with 'F0.

JW

Frederic REMY
Associate
June 9, 2017
Posted on June 09, 2017 at 12:08

@ Avatar,

tanks for your suggestion, but i have yet the datasize problem on the fisrt byte !

When I send read instruction to 25LC640, it is the first byte after starting execution of program !

Frederic REMY
Associate
June 14, 2017
Posted on June 14, 2017 at 12:42

The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6sd&d=%2Fa%2F0X0000000bx9%2FJp_.W_1wbImvwjMGmQvsNnW_jzlcOwrc8svwRqrT4hc&asPdf=false
June 14, 2017
Posted on June 14, 2017 at 13:40

But you don't have to use the 4 bit mode ! Have you tried the solution

Waclawek.Jan

gave you in the first reply ?

He even explained why you have this behavior, i.e. the data packing feature.

With his solution you want have to do all that stuff you do...

Frederic REMY
Associate
June 14, 2017
Posted on June 14, 2017 at 14:24

@ Krall

Tanks for your reply :)

But i need to send one byte separately, and in 8 bits mode I have allways two bytes 16 pulses on Clock pin.

I can't use the data packing

Our driver work like this :

uint8_t eep_ReadByte (uint32_t adress)

{

    volatile uint8_t tmpRead;                                                /* For Trace

    EEP_CS_ENABLE;

    delayUS(5);

    eep_SpiSendByte(0x03);                                                /* Commande de lecture */

#if (defined EEP_25LC010) || (defined EEP_25LC020)

    eep_SpiSendByte((uint8_t)adress);                                /* Adresse à lire */

#elif defined EEP_25LC040

    #error 'code non ecrit'                                                      /* Autres instruction */

#elif defined EEP_25LC160 || (defined EEP_25LC320) || (defined EEP_25LC640) || (defined EEP_25LC256) || (defined EEP_25LC512)

    eep_SpiSendByte((uint8_t) adress >> 8);

    eep_SpiSendByte((uint8_t) adress);

#endif

    tmpRead = eep_SpiReceiveByte();

      TmpReadDebug = tmpRead ;                                         // for trace

    delayUS(5);

    EEP_CS_DISABLE;

    return tmpRead;

}

I have several other functions to managed a 25LCxxx witch are based on the following function :

Complementary eep_SpiSendByte and eep_SpiReceivedByte.

I didn't use HAL library because its too heavy and too slow in small STM32 for our product. (only for valid chip initialisation).

The 25LCxx Frame is divided in three part

instruction 8 bits

Adress 16 bits

Data 8 bits and more if need more data.

how i can now when one byte or two nibbles are receveid in RxFifo ?

while ((EE_SPI->SR & SPI_SR_RXNE_Msk) == RESET);        // Waiting Reception of Low Nibble

Or

while ((EE_SPI->SR & 0x0600) != 0x0400 )            // Waiting Two data In Fifo

June 14, 2017
Posted on June 14, 2017 at 14:36

You didn't read carefully my answer, or didn't understand it completely.

Your function to send a byte is

static uint8_t eep_SpiSendByte (uint8_t data){ while (( EE_SPI->SR & SPI_SR_TXE_Msk) == RESET);// Wait for empty transmit buffer EE_SPI->DR = data; while (( EE_SPI->SR & SPI_SR_RXNE_Msk) == RESET);// Wait for received buffer with new data return (uint8_t)EE_SPI->DR;}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

And

told you that you should in fact write it like this

static uint8_t eep_SpiSendByte (uint8_t data){ while (( EE_SPI->SR & SPI_SR_TXE_Msk) == RESET);// Wait for empty transmit buffer *(volatile uint8_t*)&EE_SPI->DR = data; while (( EE_SPI->SR & SPI_SR_RXNE_Msk) == RESET);// Wait for received buffer with new data return (uint8_t)EE_SPI->DR;}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

The only difference is at line 4, it will force an 8-bit access to the data register of the SPI peripheral and it will send only 8 bits. No need to change to 4 bits mode at all. Try it and you will see by yourself.

Edit: why is this being moderated ? Syntax highlighter ?

AvaTar
Senior III
June 14, 2017
Posted on June 14, 2017 at 16:08

Edit: why is this being moderated ? Syntax highlighter ?

I strongly suspect they check every code snippet with <LARGE DATABASES> for copyright protection violations before rolling it out.

And there seems to be a list of code words that trigger a detour through moderation.

Frederic REMY
Associate
June 16, 2017
Posted on June 16, 2017 at 10:37

I test the solution given by waclawek.jan and i understood it with Kraal explanation.

Thanks a lot !!

Now i could seed 4 separated bytes on scope. But it work if I put a little delay after the last wrote of the data register to received the the reading byte !

I have tested three solutions , and I think there is a strange behavior of Rx Fifo in STM32F091.  Only one with the delay works.

Normal Case Doesn't work all reading value are 0 :

static uint8_t eep_SpiReceiveByte (void)

{

    while ((EE_SPI->SR & SPI_SR_TXE_Msk) == RESET); // Attente du buffer de transmission vide

    *(volatile uint8_t*)&EE_SPI->DR = 0xFF; // 8 cycles d'horloge

    while ((EE_SPI->SR & SPI_SR_RXNE_Msk) == RESET)

    return (uint8_t)EE_SPI->DR;

}

Corrected previously case with delay :

static uint8_t eep_SpiReceiveByte (void)

{

    while ((EE_SPI->SR & SPI_SR_TXE_Msk) == RESET); // Attente du buffer de transmission vide

    *(volatile uint8_t*)&EE_SPI->DR = 0xFF; // 8 cycles d'horloge

    while ((EE_SPI->SR & SPI_SR_RXNE_Msk) == RESET)

    delayUS(10);

    return (uint8_t)EE_SPI->DR; }

Tested Reception with Rx Fifo Level in FRLVL[1:0] in Status Register like this :

static uint8_t eep_SpiReceiveByte (void)

{

    while ((EE_SPI->SR & SPI_SR_TXE_Msk) == RESET); // Attente du buffer de transmission vide

    *(volatile uint8_t*)&EE_SPI->DR = 0xFF;         // 8 cycles d'horloge

    while ((EE_SPI->SR & SPI_SR_RXNE_Msk) == RESET)

    while ((EE_SPI->SR & 0x0600) != 0x0000)

    while ((EE_SPI->SR & 0x0600) != 0x0200)

    return (uint8_t)EE_SPI->DR;

This last method work for the first eeprom reading byte, after we have always the same value.

Whe also tested empty Transmit buffer before transmit with this method :

static uint8_t eep_SpiReceiveByte (void)

{

    while ((EE_SPI->SR & 0x1800) != 0x0000)

    while ((EE_SPI->SR & SPI_SR_TXE_Msk) == RESET); // Attente du buffer de transmission vide

    *(volatile uint8_t*)&EE_SPI->DR = 0xFF; // 8 cycles d'horloge

    while ((EE_SPI->SR & SPI_SR_RXNE_Msk) == RESET)

    return (uint8_t)EE_SPI->DR;

Nothing better !

It appears that RXNE is not a good information to now if a valid byte is in the receveid buffer.

How does the Rx Fifo work ?

waclawek.jan
waclawek.janBest answer
Super User
June 16, 2017
Posted on June 16, 2017 at 11:47

while ((EE_SPI->SR & SPI_SR_RXNE_Msk) == RESET)

You want to put a semicolon ; or an empty compound statement {} after this statement.

JW

Frederic REMY
Associate
June 16, 2017
Posted on June 16, 2017 at 14:26

It's work now ................

Oupsss

>:(

Thanks