学习一下freertos stream buffer
最近在自己从0到1写rtos,主要是为了学习rtos,并没有其他卵用,光学会调API是不够的,看源码又恼火,所以学习的最好办法还是根据自己的理解自己动手撸代码,虽然大部分思路都是抄的freertos或者rt thread(主要是抄思路,代码还是自己按理解写的),抄完调通的时候rtos也就基本掌握了。
- 废话不多说,直接分析代码吧,先从StreamBuffer_t这个控制块或者说handle
说起。
typedef struct StreamBufferDef_t
{
volatile size_t xTail;
volatile size_t xHead;
size_t xLength;
size_t xTriggerLevelBytes;
volatile TaskHandle_t xTaskWaitingToReceive;
volatile TaskHandle_t xTaskWaitingToSend;
uint8_t *pucBuffer;
uint8_t ucFlags;
} StreamBuffer_t;
- 接下来就是喜闻乐见的分析xStreamBufferGenericCreateStatic这个函数了,因为我通常用静态内存分配,所以是这个函数。
StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes,
size_t xTriggerLevelBytes,
BaseType_t xIsMessageBuffer,
uint8_t * const pucStreamBufferStorageArea,
StaticStreamBuffer_t * const pxStaticStreamBuffer )
{
StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) pxStaticStreamBuffer;
StreamBufferHandle_t xReturn;
uint8_t ucFlags;
- StaticStreamBuffer_t StreamBuffer_t 其实是一样的(自己跳转看定义),StreamBufferHandle_t是上面两个的指针,不知道freertos搞这么多定义干什么,跳来跳去,一点也不干净。
if( xTriggerLevelBytes == ( size_t ) 0 )
{
xTriggerLevelBytes = ( size_t ) 1;
}
if( xIsMessageBuffer != pdFALSE )
{
ucFlags = sbFLAGS_IS_MESSAGE_BUFFER | sbFLAGS_IS_STATICALLY_ALLOCATED;
}
else
{
ucFlags = sbFLAGS_IS_STATICALLY_ALLOCATED;
}
- 其实这里还可以搞成message buffer,根据传入的参数xIsMessageBuffer不同而复用。
configASSERT( xBufferSizeBytes > sbBYTES_TO_STORE_MESSAGE_LENGTH );
- 如果是message buffer,每条消息大小不能小于4bytes。
if( ( pucStreamBufferStorageArea != NULL ) && ( pxStaticStreamBuffer != NULL ) )
{
prvInitialiseNewStreamBuffer( pxStreamBuffer,
pucStreamBufferStorageArea,
xBufferSizeBytes,
xTriggerLevelBytes,
ucFlags );
pxStreamBuffer->ucFlags |= sbFLAGS_IS_STATICALLY_ALLOCATED;
traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer );
xReturn = ( StreamBufferHandle_t ) pxStaticStreamBuffer;
}
else
{
xReturn = NULL;
traceSTREAM_BUFFER_CREATE_STATIC_FAILED( xReturn, xIsMessageBuffer );
}
return xReturn;
}
- 实际上是调用prvInitialiseNewStreamBuffer进行真正的stream buffer(message buf)初始化。
static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
uint8_t * const pucBuffer,
size_t xBufferSizeBytes,
size_t xTriggerLevelBytes,
uint8_t ucFlags )
{
#if( configASSERT_DEFINED == 1 )
{
const BaseType_t xWriteValue = 0x55;
configASSERT( memset( pucBuffer, ( int ) xWriteValue, xBufferSizeBytes ) == pucBuffer );
}
#endif
( void ) memset( ( void * ) pxStreamBuffer, 0x00, sizeof( StreamBuffer_t ) );
pxStreamBuffer->pucBuffer = pucBuffer;
pxStreamBuffer->xLength = xBufferSizeBytes;
pxStreamBuffer->xTriggerLevelBytes = xTriggerLevelBytes;
pxStreamBuffer->ucFlags = ucFlags;
}
- 就是给结构体赋值,注意一下pucBuffer是正真存储数据的内存,应该是个uint8_t 或者void *指针。
BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer )
{
StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
BaseType_t xReturn = pdFAIL;
#if( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxStreamBufferNumber;
#endif
configASSERT( pxStreamBuffer );
#if( configUSE_TRACE_FACILITY == 1 )
{
uxStreamBufferNumber = pxStreamBuffer->uxStreamBufferNumber;
}
#endif
taskENTER_CRITICAL();
{
if( pxStreamBuffer->xTaskWaitingToReceive == NULL )
{
if( pxStreamBuffer->xTaskWaitingToSend == NULL )
{
prvInitialiseNewStreamBuffer( pxStreamBuffer,
pxStreamBuffer->pucBuffer,
pxStreamBuffer->xLength,
pxStreamBuffer->xTriggerLevelBytes,
pxStreamBuffer->ucFlags );
xReturn = pdPASS;
#if( configUSE_TRACE_FACILITY == 1 )
{
pxStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber;
}
#endif
traceSTREAM_BUFFER_RESET( xStreamBuffer );
}
}
}
taskEXIT_CRITICAL();
return xReturn;
}
- 重置stream buf, 仅当没有发送和接收任务阻塞在这个stream buf上时。
BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel )
{
StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
BaseType_t xReturn;
configASSERT( pxStreamBuffer );
if( xTriggerLevel == ( size_t ) 0 )
{
xTriggerLevel = ( size_t ) 1;
}
if( xTriggerLevel <= pxStreamBuffer->xLength )
{
pxStreamBuffer->xTriggerLevelBytes = xTriggerLevel;
xReturn = pdPASS;
}
else
{
xReturn = pdFALSE;
}
return xReturn;
}
- 通过这里分析pxStreamBuffer->xLength应该是这个stream buf能存下的最大bytes数,xTriggerLevel就是说当达到多少个bytes后去通知挂起的任务(stream buffer都是用的通知的形式,所以基本上是用于一对一的任务同步用)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)