FreeRTOS开发实战_链表管理
4.1 链表的特性
在FreeRTOS的链表管理中,采用的是双向链表,其中链表头指针使用xLIST来表示,而链表尾部指针为xMINI_LIST_ITEM。
这个链表有一个非常巧妙的设计在于添加了两个item:
- pvContainer,用来记录这个Item是属于哪一个链表;
- pvOwner,用来扩展Item,可以用来基于链表做客制化的操作;
比如我们客制化的一个链表Item
typedef struct _Rpmsg_Listener { RpmsgCallbackFunction_t pxCallbackFunction; RpmsgSendFunction_t pxSendFunction; ListItem_t xRpmsgListenerListItem; RpmsgEvent_t *mEvent; }RpmsgListener_t; |
刚刚初始化表头后的链表形态如下:
插入Item之后的链表结构如下图:
4.1.1 数据存储
4.1.1.1 表头指针
/* * Definition of the type of queue used by the scheduler. */ typedef struct xLIST { configLIST_VOLATILE UBaseType_t uxNumberOfItems; ListItem_t * configLIST_VOLATILE pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */ MiniListItem_t xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */ } List_t; |
- l uxNumberOfItems:记录链表的ITEM数目;
- l pxIndex:链表游标
- l xListEnd:队尾标志
4.1.1.2 链表表项
/* * Definition of the only type of object that a list can contain. */ struct xLIST_ITEM { configLIST_VOLATILE TickType_t xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */ struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< Pointer to the next ListItem_t in the list. */ struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*< Pointer to the previous ListItem_t in the list. */ void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */ void * configLIST_VOLATILE pvContainer; /*< Pointer to the list in which this list item is placed (if any). */ }; |
- l xItemValue:表项数值,常用于链表排序;
- l pxNext:指针,指向下一个;
- l pxPrevious:指针,指向前一个;
- l pvOwner:指针,常指向TCB;
- l pvContainer:指针,常指向链表表头。
4.2 使用链表
4.2.1 初始化链表
voidvListInitialise( List_t * const pxList )
参数:
- pxList:链表表头指针
4.2.2 初始化表项
voidvListInitialiseItem( ListItem_t * const pxItem )
参数:
- pxItem:链表表项
4.2.3 插入表项
voidvListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )
参数:
- pxList:需要插入的链表
- pxNewListItem:链表项目
4.2.4 链表尾部插入
void vListInsertEnd(List_t * const pxList, ListItem_t * const pxNewListItem )
参数:
- pxList:需要插入的链表
- pxNewListItem:链表项目
4.2.5 移除表项
UBaseType_tuxListRemove( ListItem_t * const pxItemToRemove )
参数:
- pxItemToRemove :需要移除的表项
4.2.6 其他宏定义操作
- l listSET_LIST_ITEM_VALUE
设置Item Value
- l listSET_LIST_ITEM_OWNER
设置List Owner
- l listCURRENT_LIST_LENGTH
当前链表的长度
- l listGET_LIST_ITEM_OWNER
取得链表的Owner
4.3 使用实例
typedef struct _Sensor_Event_ { Sensor mSenor; float values[4]; }SensorEvent_t; /* * Defines the prototype to which timer callback functions must conform. */ typedef void (*SensorCallbackFunction_t)(SensorEvent_t * mListener);
typedef struct _Sensor_Listener { int mSensorType; SensorCallbackFunction_t pxCallbackFunction; ListItem_t xSensorListenerListItem; SensorEvent_t *mEvent; }SensorListener_t;
void ap_RegisterSensorListener(int RegiterID,int mSensorType,SensorCallbackFunction_t mpxCallbackFunction,SensorEvent_t* mEvent) { //Create the new Sensor Listener SensorListener_t *pxNewSensorListener; pxNewSensorListener =(SensorListener_t *)pvPortMalloc( sizeof( SensorListener_t ) ); pxNewSensorListener->mSensorType = mSensorType; pxNewSensorListener->pxCallbackFunction = mpxCallbackFunction; pxNewSensorListener->mEvent=mEvent; vListInitialiseItem( &( pxNewSensorListener->xSensorListenerListItem ) );
#ifdef SUPPORT_GSENSOR //Add the new Item to the list by the Sensor Type if(mSensorType == TYPE_GYROSCOPE) { listSET_LIST_ITEM_VALUE( &( pxNewSensorListener->xSensorListenerListItem ), RegiterID ); listSET_LIST_ITEM_OWNER( &( pxNewSensorListener->xSensorListenerListItem ), pxNewSensorListener ); vListInsert( &xGsensorList, &( pxNewSensorListener->xSensorListenerListItem ) ); } #endif PRINTF("The xGsensorList length is %d\n",listCURRENT_LIST_LENGTH(&xGsensorList)); }
void mw_sensor_init(void) { //Add Listener List for Sensor Listenor #ifdef SUPPORT_GSENSOR vListInitialise( &xGsensorList ); #endif }
#ifdef SUPPORT_GSENSOR //Called by the HAL_Sensor void OnGyroSensorChangedCallBack(float Gxf, float Gyf,float Gzf) { List_t * pxConstList; SensorListener_t* vSensorListener; pxConstList = &xGsensorList; pxConstList->pxIndex = pxConstList->pxIndex->pxNext; while(( void * ) ( pxConstList )->pxIndex != ( void * ) &( ( pxConstList )->xListEnd )) { vSensorListener = (SensorListener_t *)listGET_LIST_ITEM_OWNER( ( pxConstList )->pxIndex ); vSensorListener->mEvent->values[0] = Gxf; vSensorListener->mEvent->values[1] = Gyf; vSensorListener->mEvent->values[2] = Gzf; vSensorListener->pxCallbackFunction( ( SensorEvent_t *) vSensorListener->mEvent); pxConstList->pxIndex = pxConstList->pxIndex->pxNext; } } #endif
BaseType_t ap_unRegisterSensorListener(int RegiterID,int mSensorType) { SensorListener_t* vSensorListener; List_t * pxConstList; if(mSensorType == TYPE_GYROSCOPE) { pxConstList = &xGsensorList; }else { return pdFAIL; } while( (( pxConstList )->pxIndex->xItemValue == RegiterID) &&(( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) ) { ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; } if(( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) { return pdFAIL; } vSensorListener = (SensorListener_t *)listGET_LIST_ITEM_OWNER( ( pxConstList )->pxIndex ); ( void ) uxListRemove(&(vSensorListener->xSensorListenerListItem)); vPortFree(vSensorListener); return pdPASS; } |