2、WSF框架API

2.1 Buffer

WSF缓冲管理服务,基于内存池的动态内存分配服务,相关文件见于:wsf_buf.c/h

/*! \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的长度。
初始化函数仅需要在系统初始化阶段调用一次

实现示例如下:

//定义 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的分配以及释放操作接口:

/*************************************************************************************************/
/*!
 *  \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中定义与实现。

/*! \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,从队列中移除一个元素;
/*************************************************************************************************/
/*!
 *  \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

/*************************************************************************************************/
/*!
 *  \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);

消息与队列的结合:

/*************************************************************************************************/
/*!
 *  \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事件处理使用。
当定时器超时,相应关联的事件处理器将执行。

/*! \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,通常需要在定时器移植代码中调用。

/*************************************************************************************************/
/*!
 *  \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(无超时定时器)。

/*************************************************************************************************/
/*!
 *  \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文件中定义。

相关数据类型:

/*! \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);

事件处理程序通用消息结构。

/*! \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;

事件处理回调函数:

/*************************************************************************************************/
/*!
 *  \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提供了任务调度的锁定和解锁接口,这使得在抢占式多任务环境中可以进行操作:

/*************************************************************************************************/
/*!
 *  \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中定义。

#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相关接口,进行平台适配。

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);
04-09 20:24