cancel
Showing results for 
Search instead for 
Did you mean: 

SPI receive wrong LSB.

MBosc.1
Associate

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.

1 ACCEPTED SOLUTION

Accepted Solutions

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

View solution in original post

2 REPLIES 2

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
Associate

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