Skip to main content
JulienD
Associate III
May 15, 2015
Question

Strange reading over SPI

  • May 15, 2015
  • 22 replies
  • 3655 views
Posted on May 15, 2015 at 19:15

Hi,

I'm porting an implementation of SD over spi to stm2 using Cube library.

It seems that the communication micro to sd card is ok, it seems that the sd card

answers like it should but it looks like the microcontroler does not interpret correctly

the data on the spi bus.

To get this conclusion, I asked the micro to echo each byte received on SPI to an uart.

On the logic analyzer screen capture joined, you can see :

- on channel 5 (green), data micro -> SD

- on channel 7 (pink), data SD -> micro

- on channel 3 (orange), the uart echo.

Each byte on channel 3 should be the same of the preceeding byte on channel 7 which is

not always the case.

Here's the initialization code of the spi channel :

   __SPI2_CLK_ENABLE();

    GPIO_InitStructure.Pin   = GPIO_Pin_SPI_SD_SCK | GPIO_Pin_SPI_SD_MOSI;

    GPIO_InitStructure.Mode  = GPIO_MODE_AF_PP;

    GPIO_InitStructure.Pull = GPIO_NOPULL;

    GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;

    GPIO_InitStructure.Alternate = GPIO_AF5_SPI2;

    HAL_GPIO_Init(GPIO_SPI_SD, &GPIO_InitStructure);

    GPIO_InitStructure.Pin   = GPIO_Pin_SPI_SD_MISO;

    GPIO_InitStructure.Mode  = GPIO_MODE_INPUT;

    GPIO_InitStructure.Pull = GPIO_PULLUP;   // obligatoire

    HAL_GPIO_Init(GPIO_SPI_SD, &GPIO_InitStructure);

    /* SPI configuration */

    hndSPI.Instance = SPI_SD;

    hndSPI.Init.Mode = SPI_MODE_MASTER;

    hndSPI.Init.Direction = SPI_DIRECTION_2LINES;

    hndSPI.Init.DataSize = SPI_DATASIZE_8BIT;

    hndSPI.Init.CLKPolarity = SPI_POLARITY_LOW;

    hndSPI.Init.CLKPhase = SPI_PHASE_1EDGE;

    hndSPI.Init.NSS = SPI_NSS_SOFT;

    hndSPI.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; // 72000kHz/256=281kHz < 400kHz

    hndSPI.Init.FirstBit = SPI_FIRSTBIT_MSB;

    hndSPI.Init.TIMode = SPI_TIMODE_DISABLED; // todo valeur au hasard = motorola, sinon TI

    hndSPI.Init.CRCPolynomial = 7;

    hndSPI.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;

    HAL_SPI_Init(&hndSPI);

Here's how I read over it :

BYTE rcvr_spi() {

    uint8_t rx;

    uint8_t tx = 0xff;

    HAL_SPI_TransmitReceive(&hndSPI, &tx, &rx, 1, 50);

    HAL_UART_Transmit(&huart4, &rx, 1, 50);

    return rx;

}

Does anybody have an idea of what could be wrong ?

Regards

Julien
    This topic has been closed for replies.

    22 replies

    waclawek.jan
    Super User
    May 15, 2015
    Posted on May 15, 2015 at 23:59

    Similar symptoms were reported several times, e.g.

    https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a%2f%2fmy.st.com%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fcortex_mx_stm32%2fSTM32%20SPI%20Spoiled%20Bits&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=178

    Unfortunately, never came to definitive conclusion.

    Could you please try to produce a minimal but complete compilable example, best for a DISCO board, which exhibits the symptoms, and post it here?

    Thanks,

    JW

    PS. I suspect this may besome timing-sensitive setup problem, in which case it may be difficult to produce an example. Try recompiling the application with different optimization settings first.
    JulienD
    JulienDAuthor
    Associate III
    May 16, 2015
    Posted on May 16, 2015 at 11:03

    Hi Jan

    Thanks for your answer.

    Very interesting but not really reassuring link...

    Unfortunately I don't have a discovery kit right now.

    I will try several things :

    - using other SPI port.

    - using most recent hal lib

    - don't use hal lib.

    I'll update.

    JulienD
    JulienDAuthor
    Associate III
    May 16, 2015
    Posted on May 16, 2015 at 15:26

    First update :

    - used SPI1 instead of SPI2 -> no change

    - wire miso to mosi, write a sequence of bytes (from 0 to 0xFF) over SPI. Read over SPI after each byte written, write the read value

    on uart (should get 0 to 0xFF) : The funky behaviour is reproduced and we can see a ''sequence'' +1 / -1. Capture joined. (spi3.png)

    - ported the previous code to nucleo F411, works fine...

    To create the code for any target :

    - use cubemx to configure, one SPI, one UART

    - auto generate the code

    - in main.c juste before ''while(1);'' insert :

    uint8_t i;

    for (i = 0; i < 0xFF; i++) {

    uint8_t rx, tx;

    tx = i;

    HAL_SPI_TransmitReceive(&hspi2, &tx, &rx, 1, 10);

    HAL_UART_Transmit(&huart4, &rx, 1, 50);

    }

    That's all.

    - used the previous code but sent each byte twice shows that it is not a +1 / -1 sequence but more something looking like

    a bit not shifted. capture joined (spi4.png)

    ________________

    Attachments :

    spi3.png : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I0eE&d=%2Fa%2F0X0000000bcA%2FRqi3dpWXPJrofAZ101aCxN0rxrlNKNWiHPwBgg81JqE&asPdf=false

    spi4.png : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I0fQ&d=%2Fa%2F0X0000000bc9%2FJf6szqug.ggsMG_vxFq51T1HP8K0Vag587qoQwgBW6w&asPdf=false
    JulienD
    JulienDAuthor
    Associate III
    May 16, 2015
    Posted on May 16, 2015 at 15:48

    Update 2 :

    - tried with up to date version of cube lib (1.2), no change.

    JulienD
    JulienDAuthor
    Associate III
    May 16, 2015
    Posted on May 16, 2015 at 18:56

    Update 3 :

    tried direct registers access instead of hal lib for read/write :

    replaced

            HAL_SPI_TransmitReceive(&hspi2, &tx, &rx, 1, 10);

    by

        while ((SPI2->SR & SPI_SR_TXE) == 0);

        SPI2->DR = tx;

        while ((SPI2->SR & SPI_SR_RXNE) == 0);

        *rx = SPI2->DR;

    -> same strange result.

    waclawek.jan
    Super User
    May 16, 2015
    Posted on May 16, 2015 at 23:40

    So you could not reproduce it on a '411? That's strange, as the '4xx should be quite similar to '2xx... Did you use a similar clock setup?

    Did you try the different optimization setting on the original hardware? Any change?

    The fault pattern appears to be that the Nth byte's LSB is taken from the (N-1)-th byte's LSB. The strange thing is that the transfer is set to MSB-first, so if the SPI would contain a plain shift register, the LSB of previous byte is followed by the MSB...

    One more thing, don't you initialize the SPI several times after each other, e.g. don't you have a bootloader where the SPI is initialized, than the main taking over and SPI being initialized for the second time?

    JW

    JulienD
    JulienDAuthor
    Associate III
    May 17, 2015
    Posted on May 17, 2015 at 11:25

    The original compilation was without optimisation. Since, I've tried -O1 -O2 -O3, always the same result.

    Quote :

    ''

    as the '4xx should be quite similar to '2xx...

    ''

    Nucleo is F411, the original board is L

    As they are not from the same familly, I did not succeed in matching F4 configuration to

    L1. But I think I succeeded in finding a common configuration. In such case, L1 still fail

    while F4 still works. 2 screenshots joined for clock configuration.

    I have only one initialization (autogenerated by cubeMx). Flash is done thru usb/stlink.

    ________________

    Attachments :

    F4.png : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I0d6&d=%2Fa%2F0X0000000bc8%2FglVgB_tSprAPwu1RJEytYrBkU6B6BUJpt.aS.VT1U8M&asPdf=false

    L1.png : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I0Tp&d=%2Fa%2F0X0000000bc7%2FBvNIpymebfdawUAgCQDoFCT_76q9ED2gd_8ZW8rXI7M&asPdf=false
    waclawek.jan
    Super User
    May 21, 2015
    Posted on May 21, 2015 at 09:11

    >L1 still fail while F4 still works.

    I have an 'L1 DISCOVERY board at hand,  but I really don't want to get involved with CubeMX.

    Can you please post the generated sources of minimal program which exhibits the problem, together with the binary (.elf)?

    JW

    JulienD
    JulienDAuthor
    Associate III
    May 25, 2015
    Posted on May 25, 2015 at 12:36

    Can you tell me which MCU is on your board  ?

    L100RC

    L152RB

    L152RC

    waclawek.jan
    Super User
    May 25, 2015
    Posted on May 25, 2015 at 12:51

    STM32L152RBT6

    (So far, I did not realize that there are several versions of the STM32L1-DISCOVERY around)

    JW