Hi,
I have a class which contains multiple tasks. The purpose of this class is to package and transmit data to a remote processor; the transmission is via SPI using DMA (to minimise CPU interaction as much as possible).
The tasks receive data (via pointer) via queue from other classes. Each task appends the received data to the current transmit buffer (which is one of several within a pool). I have a timer which calls a function every 10ms, which then initiates the SPI DMA transfer of the current transmit buffer.
I’m trying to ensure that when the timer function is called, no further appends to the current transmit buffer are made. I’d also appreciate any input as to considerations I need to make/might be missing regarding ensuring one task isn’t interrupted by another while appending its received data to the transmit buffer.
Some code:
The below is representative of one of the several (~5) tasks which receives data and appends it to the current transmit buffer.
static void task1(void *pvParameters)
{
(void) pvParameters;
//A BaseType_t variable for capturing the xQueueReceive() result
BaseType_t queueStatus;
//Instantiate a variable for receiving the byte array pointer
uint8_t (*taskAData)[TASK_A_DATA_SIZE];
for (;;) {
//Receive the data
queueStatus = xQueueReceive(taskAQueue, &taskAData, pdMS_TO_TICKS(portMAX_DELAY);
if (queueStatus == pdPASS) {
//Check if the received data will fit in the current transmit buffer
if (transmitBufferPoolByteIndex[currentTransmitBufferIndex] + TASK_A_DATA_SIZE <= (TRANSMIT_BUFFER_SIZE)) {
//Data does fit into buffer; append data
memcpy(&transmitBuffer[currentTransmitBufferIndex][transmitBufferPoolByteIndex[currentTransmitBufferIndex]], *taskAData, TASK_A_DATA_SIZE);
//Update the byte index of the current transmit buffer
transmitBufferPoolByteIndex[currentTransmitBufferIndex] += TASK_A_DATA_SIZE;
}
}
}
}
In the above task, if the received data doesn’t fit in the current transmit buffer, the timer function is called directly (to transmit the full buffer), the timer is reset, and the received data is written to the start of the next transmit buffer in the pool. I’ve excluded that code from the above excerpt for simplicity.
The below is representative of the timer function which finalises the current transmit buffer and initiates the SPI DMA transfer.
void timerFunction(void)
{
//Add some metadata to the current transmit buffer
//E.g. buffer length, termination characters, etc.
//Initiate SPI DMA transfer of the current transmit buffer
//Increment the transmit buffer pool index variable
currentTransmitBufferIndex++;
if (currentTransmitBufferIndex == NUMBER_OF_TRANSMIT_BUFFERS) {
currentTransmitBufferIndex = 0x00;
}
//Set the byte index position of the new/current transmit buffer
transmitBufferPoolByteIndex[currentTransmitBufferIndex] = 0x00;
}
What I’d like to understand is what is the optimal way to allow the timer function to perform the final processing on the current transmit buffer (and then increment the transmit buffer pool index as shown above), ensuring that the other ~5 tasks aren’t interacting with the buffer at the ‘same’ time. Would a semaphore, mutex, task notification, etc. be the ‘right’ way to go here?
Any input would be greatly appreciated as always!