Follow+Star Public Account, don’t miss the wonderful content
Author | strongerHuang
WeChat Official Account | Embedded Column
Embedded Column
1
Embedded Column
2
Embedded Column
3
Here, the official basic code for implementing this solution is provided (for reference only).
xMessageBufferSend(){ /* If a time out is specified and there isn't enough space in the message buffer to send the data, then enter the blocked state to wait for more space. */ if( time out != 0 ) { while( there is insufficient space in the buffer && not timed out waiting ) { Enter the blocked state to wait for space in the buffer } } if( there is enough space in the buffer ) { write data to buffer sbSEND_COMPLETED() }}
xMessageBufferReceive(){ /* If a time out is specified and the buffer doesn't contain any data that can be read, then enter the blocked state to wait for the buffer to contain data. */ if( time out != 0 ) { while( there is no data in the buffer && not timed out waiting ) { Enter the blocked state to wait for data } } if( there is data in the buffer ) { read data from buffer sbRECEIVE_COMPLETED() }}
If a task enters a blocked state in xMessageBufferReceive() waiting for the buffer to contain data, sending data to the buffer must unblock that task so it can complete its operation.
When xMessageBufferSend() calls sbSEND_COMPLETED(), the task will not be blocked.
ISR unblocks the task by passing the message buffer handle as a parameter to the xMessageBufferSendCompletedFromISR() function.
As shown by the arrows in the figure, where the sending and receiving tasks are located on different MCU cores:
Embedded Column
4
When there is only one message buffer, it is easy to pass the message buffer handle to xMessageBufferSendCompletedFromISR().
-
If hardware allows, each message buffer can use a different interrupt line, thus keeping a one-to-one mapping between interrupt service routines and message buffers.
-
The interrupt service routine can simply query each message buffer to see if it contains data.
-
A single message buffer can replace multiple message buffers by passing metadata (what the message is, who the intended recipient of the message is, etc.) along with the actual data.
/* Added to FreeRTOSConfig.h to override the default implementation. */#define sbSEND_COMPLETED( pxStreamBuffer ) vGenerateCoreToCoreInterrupt( pxStreamBuffer )/* Implemented in a C file. */void vGenerateCoreToCoreInterrupt( MessageBufferHandle_t xUpdatedBuffer ){size_t BytesWritten;/* Called by the implementation of sbSEND_COMPLETED() in FreeRTOSConfig.h. If this function was called because data was written to any message buffer other than the control message buffer then write the handle of the message buffer that contains data to the control message buffer, then raise an interrupt in the other core. If this function was called because data was written to the control message buffer then do nothing. */if( xUpdatedBuffer != xControlMessageBuffer ) { BytesWritten = xMessageBufferSend( xControlMessageBuffer, &xUpdatedBuffer, sizeof( xUpdatedBuffer ), 0 );/* If the bytes could not be written then the control message buffer is too small! */configASSERT( BytesWritten == sizeof( xUpdatedBuffer );/* Generate interrupt in the other core (pseudocode). */GenerateInterrupt(); }}
Then, the ISR reads the control message buffer to obtain the handle and passes it as a parameter to xMessageBufferSendCompletedFromISR():
void InterruptServiceRoutine( void ){MessageBufferHandle_t xUpdatedMessageBuffer;BaseType_t xHigherPriorityTaskWoken = pdFALSE;/* Receive the handle of the message buffer that contains data from the control message buffer. Ensure to drain the buffer before returning. */while( xMessageBufferReceiveFromISR( xControlMessageBuffer, &xUpdatedMessageBuffer, sizeof( xUpdatedMessageBuffer ), &xHigherPriorityTaskWoken ) == sizeof( xUpdatedMessageBuffer ) ) { /* Call the API function that sends a notification to any task that is blocked on the xUpdatedMessageBuffer message buffer waiting for data to arrive. */ xMessageBufferSendCompletedFromISR( xUpdatedMessageBuffer, &xHigherPriorityTaskWoken ); }/* Normal FreeRTOS "yield from interrupt" semantics, where xHigherPriorityTaskWoken is initialised to pdFALSE and will then get set to pdTRUE if the interrupt unblocks a task that has a priority above that of the currently executing task. */portYIELD_FROM_ISR( xHigherPriorityTaskWoken );}
Of course, the above only provides the basic principles and methods; specific implementations need to be combined with the actual project situation. For more related content, please refer to the official relevant materials.
———— END ————
Click “Read Original” to see more shares, welcome to share, collect, like, and view.