cancel
Showing results for 
Search instead for 
Did you mean: 

HAL SPI transmit/receive issues

Konami
Senior

I'm trying to use the HAL SPI driver to do a basic loopback test. I fill a buffer with incrementing values, and send that out while receiving into another buffer using HAL_SPI_TransmitReceive. I have 2 separate conditions both of which show odd behaviour.

  • Using SPI_FIRSTBIT_MSB
    • The data sent out looks okay using a logic analyzer
    • The data received is { 0x00, 0x00, 0x03, 0x02, 0x05, 0x04 ... 0xFF, 0xFE }
    • It seems like it thinks the data is 16-bits wide (not sure why)
    • I don't know why the first two bytes are both zero instead of 0x01, 0x00

  • Using SPI_FIRSTBIT_LSB
    • The data sent out looks okay using a logic analyzer
    • The data received is { 0x00, 0x01, 0x02, ... 0x7F, 0x00, 0x81, ... 0xFE, 0xFF }
    • It seems like it's reading 0x80 as 0x00 for some reason.

Any suggestions as to what could be going on in these two cases?

STM32L083. Code adapted from code generated by CubeMX.

int dal_spi_test ( void )
{
  uint8_t txBuffer[256] = {0};
  uint8_t rxBuffer[256] = {0};
  uint16_t ii;
 
  for ( ii = 0; ii <= 255; ii++)
  {
    txBuffer[ii] = ii;
  }
 
  HAL_StatusTypeDef rc = HAL_SPI_TransmitReceive( &hSpi[id], txBuffer, rxBuffer, u32Size, 1000);
  if ( rc != 0 ) return rc;
 
  int cmp = memcmp( txBuffer, rxBuffer, 256 );
  if ( cmp != 0 ) return cmp;
 
  return 0;
}
 
void spi_init ( void )
{
  __HAL_RCC_SPI2_CLK_ENABLE();
 
  hSpi[id].Instance               = SPI2;
  hSpi[id].Init.Mode              = SPI_MODE_MASTER;
  hSpi[id].Init.Direction         = SPI_DIRECTION_2LINES;
  hSpi[id].Init.DataSize          = SPI_DATASIZE_8BIT;
  hSpi[id].Init.CLKPolarity       = SPI_POLARITY_LOW;
  hSpi[id].Init.CLKPhase          = SPI_PHASE_1EDGE;
  hSpi[id].Init.NSS               = SPI_NSS_HARD_OUTPUT;
  hSpi[id].Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
  hSpi[id].Init.FirstBit          = SPI_FIRSTBIT_LSB;
  hSpi[id].Init.TIMode            = SPI_TIMODE_DISABLE;
  hSpi[id].Init.CRCCalculation    = SPI_CRCCALCULATION_DISABLE;
  hSpi[id].Init.CRCPolynomial     = 7;
  if (HAL_SPI_Init(&hSpi[id]) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
}

4 REPLIES 4
T J
Lead

with CPOL and CPH, you have to check the target device for the correct settings.

although that wont make a difference in loopback mode.

this confused me,,

HAL_SPI_TransmitReceive( &hSpi[id], pu8tBuf, pu8rBuf, u32Size, 1000);

this has nothing to do with that ?

int cmp = memcmp( txBuffer, rxBuffer, 256 );

if ( cmp != 0 ) return cmp;

sorry that I dont use HAL for SPI myself, it confused me...

what is this ? HAL_SPI_TransmitReceive(u32Size) ?

as opposed to this ?

uint8_t txBuffer[256] = {0};

uint8_t rxBuffer[256] = {0};

Bob S
Principal

In other words, you initialize txBuffer, and presumably allocate rxBuffer to receive the data. But your HAL_SPI_TransmitReceive() call uses totally different variables - pu8tBuf, pu8rBuf, u32Size - that are not shown in the code you posted. Is this the actual code that you compile and run?

Konami
Senior

Really sorry about that. I had to remove some customer code which led to the oversight. I am in fact calling the HAL function with the correct buffers. I know this for sure, since I can receive 255/256 bytes correctly on the loop back test.

I've edited the question to reflect the change.

Bob S
Principal

I don't know about the L08 HAL lib, but on the L4, HAL_SPI_TransmitReceive() uses 16-bit transfers even if you set it for 8-bit mode. It sets the FIFIO interrupt to 1/2 full (i.e. 16 bits) as long as the number of bytes to send/receive is > 1. If/when there is only 1 byte left, it then sets the FIFO interrupt to 1/4 (i.e. 8 bits) for that last byte. Doesn't necessarily explain how the bytes got swapped in your first test and not your second one. Though it does look like it *could* be that the last bit of each byte is where the issue is??????? Not sure if THAT makes any sense.

How are you looping the TX back to the RX? A short wire? A long wire? Is there any other circuitry on either signal? Grasping at straws here.