2015-05-08 01:03 PM
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 #spi-double-buffer2015-05-11 06:29 AM
>
while ( used_spi->SR & I2C_SR1_RXNE == 0 )
This is a big part of the problem. Since I2C_SR1_RXNE is not (ever) == 0, this loop never waits at all, so you're fetching the Rx byte before it's there. Also I2C_SR1_RXNE != SPI_SR_RXNE, i.e. you're checking the wrong bit. There are analogous problems in your TXE test, but with only 2 bytes in your transaction you probably haven't tripped over them yet.2015-05-11 06:41 AM
Hi Bruce,
thank you very much. Looks like I got the operator precedence wrong :(cheers,Torsten2015-05-11 08:56 AM
And in addition, I've used the wrong macros for the bits to test. Two lines of code with 4 bugs :(