cancel
Showing results for 
Search instead for 
Did you mean: 

Strange reading over SPI

JulienD
Senior
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
22 REPLIES 22
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&currentv...

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
Senior
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
Senior
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
Senior
Posted on May 16, 2015 at 15:48

Update 2 :

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

JulienD
Senior
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.

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
Senior
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
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
Senior
Posted on May 25, 2015 at 12:36

Can you tell me which MCU is on your board  ?

L100RC

L152RB

L152RC