10 byte offset when fetching a structure from a queue with xQueueReceiveFromISR()

ajellisuk wrote on Wednesday, May 23, 2018:


I have a project where I am collecting packets of data using an STM32F745 and then sending them via an SPI port to a master device (the mcu is an spi slave). When I receive the packets of data I place them into a buffer held within a structure, and place the structure in a queue. My SPI ISR retrieves the structures from the queue and copies them into a dma buffer ready for sending to the master device. The problem I have is that when I retrive the structure from the queue, the data appears to be offset by 8 bytes. I have looked at this page https://www.freertos.org/a00118.html for an example of how to queue a structure, but am still having problems.
My structure is:

typedef struct tSPIPacket
 uint8_t flags;
 uint8_t checksum;
 uint8_t framecount;
 uint8_t frametime;
 uint64_t timestamp;

 uint8_t size;    //size of structure, not amount of data
 uint8_t packetid;   //an id for the entire packet (large data split across transfers have same id)
 uint8_t xferid;   //id for transfer in packet (0=first transfer for packet, 1=second etc)
 uint8_t xfersize;  //number of data bytes in this transfer
 uint32_t totaldatasize;   //total amount of data in the packet
 uint32_t datatype;   //fourcc, 

 uint8_t data[INTERNAL_BUFF_SIZE];
} SPI_Packet;

extern SPI_Packet Spi_Buffer;
extern SPI_Packet *Spi_Buffer2;

Then the code for creating the queue, and placing data onto the queue is:

spi_queue = xQueueCreate( 100, sizeof( SPI_Packet  *) );

memcpy(Spi_Buffer.data[0], <incoming data>, INTERNAL_BUFF_SIZE);
      // Fill out the packet header
      Spi_Buffer.flags = 0;
      Spi_Buffer.checksum = 0;
      Spi_Buffer.framecount = 1;
      Spi_Buffer.frametime = 1;
      Spi_Buffer.timestamp = 1;
      Spi_Buffer.size = sizeof(SPI_Packet);
      Spi_Buffer.packetid = 0;
      Spi_Buffer.xferid = 0;
      Spi_Buffer.xfersize = INTERNAL_BUFF_SIZE;
      Spi_Buffer.totaldatasize = INTERNAL_BUFF_SIZE + sizeof(SPI_Packet);
      Spi_Buffer.datatype =  FOURCC;
&Spi_Buffer, ( TickType_t ) 0 );
      SPI_Packet *spitmp=&Spi_Buffer;
      xQueueSend( spi_queue, ( void * ) spitmp, ( TickType_t ) 0 );
And the code for retriving the structures and placing them into the dma buffer is:
// Arm the SPI and DMA to Tx bytes from aSPITxBuffer
            if ( xQueueReceiveFromISR( spi_queue, ( void * ) &(Spi_Buffer2), & xTaskWokenByReceive) )
                memset ( aSPITxBuffer, 0, 256 ); // ensure tx buffer is clear
                memcpy(&aSPITxBuffer[1], &Spi_Buffer2, 256);
                HAL_SPI_TransmitReceive_DMA(&hspi5, (uint8_t*)&aSPITxBuffer[0], (uint8_t *)&aSPIRxBuffer[0], 256);
                return; // Return from he as we don't want to be re armed for receive only

            if ( xTaskWokenByReceive != pdFALSE )
                /* We should switch context so the ISR returns to a different task.
                   NOTE:  How this is done depends on the port you are using.  Check
                   the documentation and examples for your port. */
                HAL_SPI_Receive_DMA(&hspi5, (uint8_t *)aSPIRxBuffer, 7);
                taskYIELD ();

I am using the intermediate buffer aSPITxBuffer to make this issue easier to debug.
Can someone please suggest why I’m getting the 8 byte offset when I retrieve Spi_Buffer2 from the queue please?
Thanks in advance

richard_damon wrote on Thursday, May 24, 2018:

Your memcpy call places the data at &aSPITxBUFFER[1], and then you send &aSPITxBuffer[0]. I don’t see a definition of the buffer, but that seems to be a possible source of an offset.

ajellisuk wrote on Thursday, May 24, 2018:

Hi Richard

Thank you for your reply.

The definition of the buffer is:

uint8_t aSPITxBuffer[282] = {0};

The reson for the 1 byte offset with memcopy is because when the spi transfer is started, the first by of the buffer is droped by the master as it is clocked out with the write cycle. If I create a dummby buffer like the one below:

uint8_t aSPITestTxBuffer[21] = {0x00,0xDE,0xAD,0xBE,0xEF,0x60,0x0D,0xF0,0x0D,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x00};

I can perform the same memcopy witht he 1 byte offset and the spi transfer works correctly. I.E:

memcpy(&aSPITxBuffer[1], &aSPITestTxBuffer, 21);
				HAL_SPI_TransmitReceive_DMA(&hspi5, (uint8_t*)&aSPITxBuffer[0], (uint8_t *)&aSPIRxBuffer[0], 256); // 272 is the max no bytes the cavium can hadnle in 1 go

The problem is when I’m trying to retrive the data from the queue. Previosuly I have placed the output of the queue straight into the dma buffer, and I saw the same issue at the master.