AnsweredAssumed Answered

why is the following SPI implementation not working?

Question asked by robitzki.torsten on May 8, 2015
Latest reply on May 11, 2015 by robitzki.torsten
Hello,
I have trouble to communicate with a BlueNRG device. I’ve tracked it down to my SPI implementation. Assumed I want to have a „usual“, full duplex SPI master interface on a STM32L152, using CMSIS I initialize the interface as follows: 


    void configure_spi( SPI_TypeDef* spi )
    {
        spi->CR1 = 0 ;


        // fPCLK/4 | master | enabled
        spi->CR1 |=
              SPI_CR1_SSI
            | SPI_CR1_SSM
            | SPI_CR1_MSTR;


        spi->SR = 0;


        spi->CR1 |= SPI_CR1_SPE;
    }


According to Figure 247 in the reference manual on page 755, there is some kind of double buffering and the software should start the transaction with two writes and end the transaction with 2 reads:


    void spi::transmit_receive( const std::uint8_t* out_buffer, std::size_t out_buffer_size, std::uint8_t* in_buffer, std::size_t in_buffer_size )
    {
        assert( out_buffer_size != 0 || in_buffer_size != 0 );


        const std::uint8_t* const out_end = out_buffer + out_buffer_size;
              std::uint8_t* const in_end  = in_buffer + in_buffer_size;


        out_buffer = write_byte( out_buffer, out_end );


        for ( std::size_t bytes_transfered = std::max( out_buffer_size, in_buffer_size ) - 1; bytes_transfered; —-bytes_transfered )
        {
            out_buffer = write_byte( out_buffer, out_end );
            in_buffer = read_byte( in_buffer, in_end );
        }


        read_byte( in_buffer, in_end );
    }


With write_byte and read_byte looking like this:


    static const std::uint8_t* write_byte( const std::uint8_t* out_buffer, const std::uint8_t* out_end )
    {
        while ( used_spi->SR & I2C_SR1_TXE == 0 )
            ;


        if ( out_buffer != out_end )
        {
            used_spi->DR = *out_buffer;
            ++out_buffer;
        }
        else
        {
            used_spi->DR = 0;
        }


        return out_buffer;
    }


    static std::uint8_t* read_byte( std::uint8_t* in_buffer, std::uint8_t* in_end )
    {
        while ( used_spi->SR & I2C_SR1_RXNE == 0 )
            ;


        if ( in_buffer != in_end )
        {
            *in_buffer = used_spi->DR;
            ++in_buffer;
        }
        else
        {
            volatile std::uint8_t dummy = used_spi->DR;
            static_cast< void >( dummy );
        }


        return in_buffer;
    }


Do I misread the diagram? With this implementation, the result looks like I’m missing at least the second byte on the receiving side.


kind regards,
Torsten


Outcomes