本文开始介绍WSF相关API接口,了解其接口之后便于了解其具体的使用。
2、WSF框架API
2.1 Buffer
WSF缓冲管理服务,基于内存池的动态内存分配服务,相关文件见于:wsf_buf.c/h
。
c
/*! \brief Buffer pool descriptor structure */
typedef struct
{
uint16_t len; /*!< \brief Length of buffers in pool */
uint8_t num; /*!< \brief Number of buffers in pool */
} wsfBufPoolDesc_t;
uint32_t WsfBufInit(uint8_t numPools, wsfBufPoolDesc_t *pDesc);
缓冲池描述结构如上,通过WsfBufInit()
进行初始化,确定了buffer的数量,以及每个buffer的长度。
初始化函数仅需要在系统初始化阶段调用一次。
实现示例如下:
c
//定义 WSF Buffer Pools
#define WSF_BUF_POOLS 5
// Default pool descriptor.
static wsfBufPoolDesc_t poolDescriptors[WSF_BUF_POOLS] = {
{32, 8}, {64, 4}, {128, 4}, {256, 4}, {1024, 2},
};
//初始化
WsfBufInit(WSF_BUF_POOLS, poolDescriptors);
关于buffer的分配以及释放操作接口:
c
/*************************************************************************************************/
/*!
* \brief Allocate a buffer.
*
* \param len Length of buffer to allocate.
*
* \return Pointer to allocated buffer or NULL if allocation fails.
*/
/*************************************************************************************************/
void *WsfBufAlloc(uint16_t len);
/*************************************************************************************************/
/*!
* \brief Free a buffer.
*
* \param pBuf Buffer to free.
*/
/*************************************************************************************************/
void WsfBufFree(void *pBuf);
2.2 队列
WSF队列服务是一个通用的队列服务,在整个软件系统中被广泛使用。队列服务接口在wsf_queue.h/c
中定义与实现。
c
/*! \brief Initialize a queue */
#define WSF_QUEUE_INIT(pQueue) \
{ \
(pQueue)->pHead = NULL; \
(pQueue)->pTail = NULL; \
}
/**************************************************************************************************
Data Types
**************************************************************************************************/
/*! \brief Queue structure */
typedef struct
{
void *pHead; /*!< \brief head of queue */
void *pTail; /*!< \brief tail of queue */
} wsfQueue_t;
通过宏WSF_QUEUE_INIT
初始化一个队列结构。
队列操作说明:
WsfQueueEnq
,将一个元素入队到队列的结尾。WsfQueueDeq
,从队列的头部取出一个元素。WsfQueuePeek
,则仅仅是查看队列头部的元素(并不从队列中出列)。WsfQueuePush
,将一个元素入队到队列的头部。WsfQueueInsert
,在队列中插入一个元素;WsfQueueRemove
,从队列中移除一个元素;
c
/*************************************************************************************************/
/*!
* \brief Enqueue an element to the tail of a queue.
*
* \param pQueue Pointer to queue.
* \param pElem Pointer to element.
*/
/*************************************************************************************************/
void WsfQueueEnq(wsfQueue_t *pQueue, void *pElem);
/*************************************************************************************************/
/*!
* \brief Peek the head of a queue.
*
* \param pQueue Pointer to queue.
*
* \return Pointer to element that has been dequeued or NULL if queue is empty.
*/
/*************************************************************************************************/
void *WsfQueuePeek(wsfQueue_t *pQueue);
/*************************************************************************************************/
/*!
* \brief Dequeue an element from the head of a queue.
*
* \param pQueue Pointer to queue.
*
* \return Pointer to element that has been dequeued or NULL if queue is empty.
*/
/*************************************************************************************************/
void *WsfQueueDeq(wsfQueue_t *pQueue);
/*************************************************************************************************/
/*!
* \brief Push an element to the head of a queue.
*
* \param pQueue Pointer to queue.
* \param pElem Pointer to element.
*/
/*************************************************************************************************/
void WsfQueuePush(wsfQueue_t *pQueue, void *pElem);
/*************************************************************************************************/
/*!
* \brief Insert an element into a queue. This function is typically used when iterating
* over a queue.
*
* \param pQueue Pointer to queue.
* \param pElem Pointer to element to be inserted.
* \param pPrev Pointer to previous element in the queue before element to be inserted.
* Note: set pPrev to NULL if pElem is first element in queue.
* \return None.
*/
/*************************************************************************************************/
void WsfQueueInsert(wsfQueue_t *pQueue, void *pElem, void *pPrev);
/*************************************************************************************************/
/*!
* \brief Remove an element from a queue. This function is typically used when iterating
* over a queue.
*
* \param pQueue Pointer to queue.
* \param pElem Pointer to element to be removed.
* \param pPrev Pointer to previous element in the queue before element to be removed.
*/
/*************************************************************************************************/
void WsfQueueRemove(wsfQueue_t *pQueue, void *pElem, void *pPrev);
2.3 消息
WSF消息服务用于在WSF事件处理中传递消息,定义:wsf_msg.h/c
。
消息缓存分配WsfMsgAlloc
,发送通过:WsfMsgSend
,发送到事件处理器。
数据消息缓存分配使用WsfMsgDataAlloc
,发送依然使用:WsfMsgSend
。
c
/*************************************************************************************************/
/*!
* \brief Allocate a data message buffer to be sent with WsfMsgSend().
*
* \param len Message length in bytes.
* \param tailroom Tailroom length in bytes.
*
* \return Pointer to data message buffer or NULL if allocation failed.
*/
/*************************************************************************************************/
void *WsfMsgDataAlloc(uint16_t len, uint8_t tailroom);
/*************************************************************************************************/
/*!
* \brief Allocate a message buffer to be sent with WsfMsgSend().
*
* \param len Message length in bytes.
*
* \return Pointer to message buffer or NULL if allocation failed.
*/
/*************************************************************************************************/
void *WsfMsgAlloc(uint16_t len);
/*************************************************************************************************/
/*!
* \brief Free a message buffer allocated with WsfMsgAlloc().
*
* \param pMsg Pointer to message buffer.
*/
/*************************************************************************************************/
void WsfMsgFree(void *pMsg);
/*************************************************************************************************/
/*!
* \brief Send a message to an event handler.
*
* \param handlerId Event handler ID.
* \param pMsg Pointer to message buffer.
*/
/*************************************************************************************************/
void WsfMsgSend(wsfHandlerId_t handlerId, void *pMsg);
消息与队列的结合:
c
/*************************************************************************************************/
/*!
* \brief Enqueue a message.
*
* \param pQueue Pointer to queue.
* \param handlerId Set message handler ID to this value.
* \param pMsg Pointer to message buffer.
*/
/*************************************************************************************************/
void WsfMsgEnq(wsfQueue_t *pQueue, wsfHandlerId_t handlerId, void *pMsg);
/*************************************************************************************************/
/*!
* \brief Dequeue a message.
*
* \param pQueue Pointer to queue.
* \param pHandlerId Handler ID of returned message; this is a return parameter.
*
* \return Pointer to message that has been dequeued or NULL if queue is empty.
*/
/*************************************************************************************************/
void *WsfMsgDeq(wsfQueue_t *pQueue, wsfHandlerId_t *pHandlerId);
/*************************************************************************************************/
/*!
* \brief Get the next message without removing it from the queue.
*
* \param pQueue Pointer to queue.
* \param pHandlerId Handler ID of returned message; this is a return parameter.
*
* \return Pointer to the next message on the queue or NULL if queue is empty.
*/
/*************************************************************************************************/
void *WsfMsgPeek(wsfQueue_t *pQueue, wsfHandlerId_t *pHandlerId);
2.4 定时器
WSF定时器服务由WSF事件处理使用。
当定时器超时,相应关联的事件处理器将执行。
c
/*! \brief Timer ticks data type */
typedef uint32_t wsfTimerTicks_t;
/*! \brief Timer structure */
typedef struct wsfTimer_tag
{
struct wsfTimer_tag *pNext; /*!< \brief pointer to next timer in queue */
wsfMsgHdr_t msg; /*!< \brief application-defined timer event parameters */
wsfTimerTicks_t ticks; /*!< \brief number of ticks until expiration */
uint32_t count;
uint8_t mode; /*!< \brief one shot or periodic */
wsfHandlerId_t handlerId; /*!< \brief event handler for this timer */
bool_t isStarted; /*!< \brief TRUE if timer has been started */
} wsfTimer_t;
void WsfTimerInit(void);
void WsfTimerInit(void);
初始化timer服务,仅在系统初始化阶段调用一次。
Wsf支持秒级定时器与毫秒级的定时器,定时器启动与停止:
WsfTimerStartSec
WsfTimerStartMs
WsfTimerStop(wsfTimer_t *pTimer)
void WsfTimerUpdate(wsfTimerTicks_t ticks);
用于更新定时器服务的tick,通常需要在定时器移植代码中调用。
c
/*************************************************************************************************/
/*!
* \brief Service expired timers for the given task. This function is typically called only
* WSF OS porting code.
*
* \param taskId OS Task ID of task servicing timers.
*
* \return Pointer to next expired timer or NULL if there are no expired timers.
*/
/*************************************************************************************************/
wsfTimer_t *WsfTimerServiceExpired(wsfTaskId_t taskId);
特定任务定时器服务超期,参数为OS Task ID。返回下一超时定时器指针,或NULL(无超时定时器)。
c
/*************************************************************************************************/
/*!
* \brief Check if there is an active timer and if there is enough time to
* go to sleep.
*/
/*************************************************************************************************/
uint8_t WsfTimerSleepCheck(uint32_t *sleep_ms);
// 基于RTC ticks更新WSF定时器
void WsfTimerSleepUpdate(void);
检查是否有活跃定时器,以及是否有足够时间进行休眠。
2.5 事件处理程序
WSF事件处理程序从软件系统中接收WSF事件、消息、以及定时器超时通知。事件处理程序被协议栈的主要子系统使用。事件处理程序的接口在wsf_os.h
文件中定义。
相关数据类型:
c
/*! \brief Event handler ID data type */
typedef uint8_t wsfHandlerId_t;
/*! \brief Event handler event mask data type */
typedef uint16_t wsfEventMask_t;
/*! \brief Task ID data type */
typedef wsfHandlerId_t wsfTaskId_t;
/*! \brief Task event mask data type */
typedef uint8_t wsfTaskEvent_t;
/*! \brief Idle check function. */
typedef bool_t (*WsfOsIdleCheckFunc_t)(void);
事件处理程序通用消息结构。
c
/*! \brief Common message structure passed to event handler */
typedef struct
{
uint16_t param; /*!< \brief General purpose parameter passed to event handler */
uint8_t event; /*!< \brief General purpose event value passed to event handler */
uint8_t status; /*!< \brief General purpose status value passed to event handler */
} wsfMsgHdr_t;
事件处理回调函数:
c
/*************************************************************************************************/
/*!
* \brief Event handler callback function.
*
* \param event Mask of events set for the event handler.
* \param pMsg Pointer to message for the event handler.
*/
/*************************************************************************************************/
typedef void (*wsfEventHandler_t)(wsfEventMask_t event, const void *pMsg);
为时间处理程序设置一个事件:void WsfSetEvent(wsfHandlerId_t handlerId, wsfEventMask_t event);
对于任务调度Locking,WSF提供了任务调度的锁定和解锁接口,这使得在抢占式多任务环境中可以进行操作:
c
/*************************************************************************************************/
/*!
* \brief Lock task scheduling.
*/
/*************************************************************************************************/
uint32_t WsfTaskLock(void);
/*************************************************************************************************/
/*!
* \brief Unlock task scheduling.
*/
/*************************************************************************************************/
void WsfTaskUnlock(uint32_t lock);
2.6 关键区(Critical Section)
WSF提供了关键区域宏,用于在可能在中断上下文中执行的代码中保护全局数据。Critical Section的相关接口在wsf_cs.h
中定义。
c
#define WSF_CS_INIT(cs)
#define WSF_CS_ENTER(cs) WsfCsEnter()
#define WSF_CS_EXIT(cs) WsfCsExit()
其中,关于Critical Section的实现,需要结合使用平台处理器的特性进行修改,如进入CS,关闭全局中断等操作。
2.7 NVM
提供NVM操作接口。可用于在NVM中存储的数据,实现本地数据直接加载。需要使用pal_flash.c/h
相关接口,进行平台适配。
c
typedef void (*WsfNvmCompEvent_t)(bool_t status);
//初始化WSF NVM
void WsfNvmInit(void);
bool_t WsfNvmReadData(uint64_t id, uint8_t *pData, uint16_t len, WsfNvmCompEvent_t compCback);
bool_t WsfNvmWriteData(uint64_t id, const uint8_t *pData, uint16_t len, WsfNvmCompEvent_t compCback);
bool_t WsfNvmEraseData(uint64_t id, WsfNvmCompEvent_t compCback);