cancel
Showing results for 
Search instead for 
Did you mean: 

Not able to read data from SPI2 Interface on STM32F4 board

Posted on March 03, 2018 at 14:46

Hi

I would like to get suggestions and recommendations about this issue. I can see on Scope that my SPI Slave device ADS7959 (ADC) is talking back over SPI but when I debug my code and check the data read is always zero when it should be something different.

My code for setting up the SPI2 and Pins is the following:

    GPIO_StructInit(&GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_13 | GPIO_Pin_15);

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

    GPIO_Init(GPIOB, &GPIO_InitStructure); //!< @pinSetup PB13: SPI2_SCK, PB15: SPI2_MOSI GPIO setup

    

    GPIO_StructInit(&GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

    GPIO_Init(GPIOB, &GPIO_InitStructure); //!< @pinSetup PB14: SPI2_MISO GPIO setup

    

    // connect SPIx pins to SPI alternate function

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2); //!< @pinSetup PB15: SPI2_MOSI AF setup

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_SPI2); //!< @pinSetup PB14: SPI2_MISO AF setup

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_SPI2); //!< @pinSetup PB13: SPI2_SCK  AF setup

   RCC->APB1RSTR |=  RCC_APB1RSTR_SPI2RST;

   RCC->APB1RSTR &= ~RCC_APB1RSTR_SPI2RST;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);

    

    SPI_InitTypeDef SPI_InitStruct;

    SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // set to full duplex mode, seperate MOSI and MISO lines

    SPI_InitStruct.SPI_Mode = SPI_Mode_Master;     // transmit in master mode, NSS pin has to be always high

    SPI_InitStruct.SPI_DataSize = SPI_DataSize_16b; // one packet of data is 8 bits wide

    SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;        // clock is low when idle

    SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;      // data sampled at first edge

    SPI_InitStruct.SPI_NSS = SPI_NSS_Soft;// | SPI_NSSInternalSoft_Set; // set the NSS management to internal and pull internal NSS high

    SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; // see freq notes above

    SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;// data is transmitted MSB first

    SPI_InitStruct.SPI_CRCPolynomial = 0x07; // arbitrary (not using), just can't be <= 1 or fails init with ASSERT()

    SPI_Init(SPI2, &SPI_InitStruct);

        

        SPI2->CR1 &= (uint16_t)~((uint16_t)SPI_CR1_CRCEN);

         

    // enable SPI peripheral

    SPI_Cmd(SPI2, ENABLE);

To write and read data to/from SPI:

uint16_t AuxAdc::writeWord(uint16_t word)

{

    ASSERT_AUXADC_CS;

    for( uint32_t i = 0; i<firstClockWait; i++ ){asm('nop');} // see timing notes in header

    SPI2->DR = word; // write data to be transmitted to the SPI data register

    

        

        uint32_t timeout = 0;

    while( !(SPI2->SR & SPI_I2S_FLAG_TXE) ) // wait until transmit complete

    {

        if( timeout++ > 50000 )

        {

            RELEASE_AUXADC_CS;

            return 0; //!< @TODO RG: need to report this

        }

    }

    timeout = 0;

    while( !(SPI2->SR & SPI_I2S_FLAG_RXNE) ) // wait until receive complete

    {

        if( timeout++ > 50000 )

        {

            RELEASE_AUXADC_CS;

            return 0; //!< @TODO RG: need to report this

        }

    }

    timeout = 0;

    while( SPI2->SR & SPI_I2S_FLAG_BSY ) // wait until SPI is not busy anymore

    {

        if( timeout++ > 50000 )

        {

            RELEASE_AUXADC_CS;

            return 0; //!< @TODO RG: need to report this

        }

    }

       

    for( uint32_t i = 0; i<lastClockWait; i++ ){asm('nop');} // see timing notes in header

    RELEASE_AUXADC_CS;

    for( uint32_t i = 0; i<postWait; i++ ){asm('nop');} // see timing notes in header

    return SPI2->DR; // return received data from SPI data register

} // end writeWord()

Not sure what exactly could be wrong, I already tried different board with same effect.

Using the debugger (IAR) and checking SPI->DR it never changes to a value even when I am writing to it. is this maybe showing a symptom of malfunction?

4 REPLIES 4
Posted on March 03, 2018 at 14:57

The debug view of the peripheral registers is invasive (modifies content, changes status).

You write to a different DR than you read, so you're not implicitly going to see the same data, it is NOT a memory cell.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on March 03, 2018 at 15:07

I understand it is invasive but not sure how to debug the issue of not reading data from SPI interface. Any clues/ideas to troubleshoot this problem? I think my configuration is correct due I am seeing data going out/in

Thanks

Posted on March 03, 2018 at 15:35

You'd likely want to output diagnostics yourself via SWO(SWV) or USART so you can see what the code sees.

STM32F4xx_DSP_StdPeriph_Lib_V1.8.0\Project\STM32F4xx_StdPeriph_Examples\SPI\SPI_FLASH\spi_flash.c

/**

* @brief Sends a byte through the SPI interface and return the byte received

* from the SPI bus.

* @param byte: byte to send.

* @retval The value of the received byte.

*/

uint8_t sFLASH_SendByte(uint8_t byte)

{

/*!< Loop while DR register in not empty */

while (SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_TXE) == RESET);

/*!< Send byte through the SPI1 peripheral */

SPI_I2S_SendData(sFLASH_SPI, byte);

/*!< Wait to receive a byte */

while (SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_RXNE) == RESET);

/*!< Return the byte read from the SPI bus */

return SPI_I2S_ReceiveData(sFLASH_SPI);

}
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on March 03, 2018 at 23:05

//!< @TODO RG: need to report this

Then report this (it's enough to set a flag in memory and check it afterwards, even in debugger).

Also, if you want to run this level of paranoia, qualify the 'timeout' variable as volatile and make sure the constant is properly determined for your particular setup, not just pulled out of the thin air.

JW