cancel
Showing results for 
Search instead for 
Did you mean: 

[Solved] [STM32F205] Occasional spurious SPI write in half-duplex polling mode

PA:99
Associate II

I'm reading a temperature sensor (TC77) via SPI, with the following code (using the old StdPeriph lib):

int16_t hdw_tc77_getTempRegister(void)
{
    int16_t tempRegister; /*TC77 TEMP register*/
    SPI_InitTypeDef  SPI_InitStructure;
 
    /*SPI config and init*/
    SPI_StructInit(&SPI_InitStructure);
    PFM_SPI_A_CLK_INIT(PFM_SPI_A_CLK, ENABLE);
    SPI_CalculateCRC(PFM_SPI_A, DISABLE);
    SPI_I2S_DeInit(PFM_SPI_A);
    SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Rx;
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    SPI_Init(PFM_SPI_A, &SPI_InitStructure);
    SPI_Cmd(PFM_SPI_A, ENABLE);
 
    /*Data read*/
    while(SPI_I2S_GetFlagStatus(PFM_SPI_A, SPI_I2S_FLAG_BSY) == SET) ;
    while(SPI_I2S_GetFlagStatus(PFM_SPI_A, SPI_I2S_FLAG_TXE) != SET) ;
    hdw_TempCSCmd(ENABLE); /*Chip select of TC77*/
    SPI_I2S_ReceiveData(PFM_SPI_A); /*Clear RXNE*/
    SPI_I2S_SendData(PFM_SPI_A, 0x0000);
    while(SPI_I2S_GetFlagStatus(PFM_SPI_A, SPI_I2S_FLAG_RXNE) != SET) ;
    tempRegister = (int16_t)SPI_I2S_ReceiveData(PFM_SPI_A);
    hdw_TempCSCmd(DISABLE);
    SPI_I2S_DeInit(PFM_SPI_A);
 
    return tempRegister;
}

The TC77 is alone on the SPI bus (there is another chip that is not used, its CS being permanently held high) and that function is the only access to the SPI bus in the code.

This reading is done every 10 seconds, and works properly for a few hours.

The following screenshot shows the corresponding SPI traffic.

0693W00000GXmImQAL.pngBut after a few hours, instead of the normal SPI 16-bits frame seen above, a 87-bit frame is sent and wrecks havoc in the TC77 configuration (for which the first 16 bits of the clock are a read and the next 16 bits are a write to the config register).

After that broken frame, the polling continues normally (but now the TC77 has been shutdown by the spurious command, in that mode it returns the manufacturer ID instead of the temperature).

The following screenshot shows that unexpected long frame.

0693W00000GXmOGQA1.png 

This looks like a marginal issue, because it happens for one variant of the firmware, but not on another one using exactly the same read function. It also appears to be hardware dependent, as it happens consistently after a few hours on several boards, while others are running for 1+ month without issue.

Can someone help me with this/point me in a direction to investigate further?

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

> SPI_Direction_1Line_Rx

In master, one line receive only mode (BIDIMODE=0 and RXONLY=1), the clock is sent out continuously.

Because of this, if an interrupt happens while CS is low, the clock will continue to tick away until it returns and you disable the peripheral.

The solution is to use 2-line mode with the MOSI pin uninitialized. (Or disable interrupts during the critical section of code.)

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

2 REPLIES 2
TDK
Guru

> SPI_Direction_1Line_Rx

In master, one line receive only mode (BIDIMODE=0 and RXONLY=1), the clock is sent out continuously.

Because of this, if an interrupt happens while CS is low, the clock will continue to tick away until it returns and you disable the peripheral.

The solution is to use 2-line mode with the MOSI pin uninitialized. (Or disable interrupts during the critical section of code.)

If you feel a post has answered your question, please click "Accept as Solution".
PA:99
Associate II

Thank you a lot for your clear and amazingly fast answer!

PA