Skip to main content
MBosc.1
Associate
December 3, 2018
Solved

SPI receive wrong LSB.

  • December 3, 2018
  • 2 replies
  • 1600 views

Hello,

I'm using a Murata CMWX1ZZABZ embedding a STM32L082 and the HAL v1.8.1.

HAL_SPI_TransmitReceive() returns wrong LSB data :

-expected : 0x33, received : 0x33 : OK

-expected : 0xAA33, received : 0xAB32 : error

-expected : 0x00, 0x01, 0x02, 0x03..., 0xFE, 0xFF, received : 0x01 0x00, 0x03, 0x02, ..., 0xFF, 0xFE : error

The logic analyser shows the expected values from a 23LC1024 SPI memory slave :

0690X000006CdukQAC.png

The two last bytes are AA33 as expected.

Here is the initialization function and the receive function wrapper :

SPI_HandleTypeDef _hspi;
 
void configureSPI(void)
{
 
 /* Peripheral clock enable */
 __HAL_RCC_SPI2_CLK_ENABLE();
 
 _hspi.Instance = SPI2;
 _hspi.Init.Mode = SPI_MODE_MASTER;
 _hspi.Init.Direction = SPI_DIRECTION_2LINES;
 _hspi.Init.DataSize = SPI_DATASIZE_8BIT;
 _hspi.Init.CLKPolarity = SPI_POLARITY_LOW;
 _hspi.Init.CLKPhase = SPI_PHASE_1EDGE;
 _hspi.Init.NSS = SPI_NSS_SOFT;
 _hspi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
 _hspi.Init.FirstBit = SPI_FIRSTBIT_MSB;
 _hspi.Init.TIMode = SPI_TIMODE_DISABLE;
 _hspi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
 HAL_SPI_Init(&_hspi);
 
 /* Enable the peripheral clock of GPIOB */
 RCC->IOPENR |= RCC_IOPENR_GPIOBEN;
 
 /* (1) Select AF mode (10) on PB12, PB13, PB14, PB15 */
 /* (2) AF0 for SPI2 signals */
 GPIOB->MODER = (GPIOB->MODER 
 & ~(GPIO_MODER_MODE12 | GPIO_MODER_MODE13 | \
 GPIO_MODER_MODE14 | GPIO_MODER_MODE15))\
 | (GPIO_MODER_MODE12_1 | GPIO_MODER_MODE13_1|\
 GPIO_MODER_MODE14_1 | GPIO_MODER_MODE15_1); /* (1) */
 GPIOB->AFR[1] = (GPIOB->AFR[1] & \
 ~((0xF<<(4*4)) | (0xF<<(4*5)) |\
 (0xF<<(4*6)) | ((uint32_t)0xF<<(4*7)))); /* (2) */
}
 
size_t spiRead(void* self, void* data, size_t size)
{
 (void)(self);
 uint8_t* d = data;
 memset(d, 0xff, size);
 if(HAL_SPI_TransmitReceive(&_hspi, d, d, size, 100) != HAL_OK)
 {
 return 0;
 }
 /* prints ab32 instead of aa33 */
 for(size_t i = 0; i < size; i++)
 {
// d[i] ^= 1; /* toggle last bit, FIXME, why ? */
 printf("%02x", d[i]);
 }
 return size;
}

I saw several similar questions but none gave a working answer. Any idea ?

Thank you.

    This topic has been closed for replies.
    Best answer by waclawek.jan

    Set SPI_SCK pin's drive higher in OSPEEDR.

    See Last data bit or CRC calculation may be corrupted for the data received

    in master mode depending on the feedback communication

    clock timing with respect to the APB clock (SPI or I2S) erratum.

    JW

    2 replies

    waclawek.jan
    waclawek.janBest answer
    Super User
    December 3, 2018

    Set SPI_SCK pin's drive higher in OSPEEDR.

    See Last data bit or CRC calculation may be corrupted for the data received

    in master mode depending on the feedback communication

    clock timing with respect to the APB clock (SPI or I2S) erratum.

    JW

    MBosc.1
    MBosc.1Author
    Associate
    December 4, 2018

    Thank you, It worked.

    GPIOB->OSPEEDR |= (0x3 << 26);

    Or using the HAL GPIO init function :

    pin.Mode = GPIO_MODE_AF_PP;
    pin.Pull = GPIO_PULLUP;
    pin.Alternate = GPIO_AF0_SPI2;
    pin.Speed = GPIO_SPEED_FREQ_VERY_HIGH;

    I reproduce the same error when the speed is "very high" but the mode is "open drain" instead of "push pull".

    I found the erratum you are talking about in the ES0293 document related to the STM32L072 µC.

    Mickael