在介绍了WSF的基础情况,API接口以及具体平台的移植之后,本文具体介绍WSF的应用该如何来写,包括框架的初始化、定时器的应用,外部事件的应用等等。作为一个简易的OS抽象层,在裸机平台上实现简单的任务的调度与分发也是非常方便。
4、WSF应用示例
4.1 WSF框架初始化
c
//1. 定义 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},
};
//2. 需要使用NVM,则需要移植相关硬件平台实现,pal_flash.h/c
WsfNVMInit();
// 平台初始化,以适应WSF,pal_sys.h/c
PalSysInit();
// 设置定时器用于WSF调度器
WsfOsInit();
WsfTimerInit();
// sys_tick用于更新WsfTimerUpdateTicks
sys_tick_callback_set(WsfTimerUpdateTicks);
// 初始化缓冲池
uint32_t wsfBufMemLen = WsfBufInit(WSF_BUF_POOLS, poolDescriptors);
// 必要需要检查是否有足够的动态内存
// 预留heap内存
//WsfHeadAlloc(wsfBufMemLen);
//
// Create app task
//
wsfHandlerId_t handlerId = WsfOsSetNextHandler(app_handler);
app_init(handlerId);
// 主函数中,调用wsfOsDispatcher
while (1)
{
wsfOsDispatcher(); //涉及Critical Section
// 若需要进行低功耗处理
}
4.2 应用定义
第一步,创建Task,需要指定任务定义的handler;
c
void app_handler(wsfEventMask_t event, const void *param)
{
const wsfMsgHdr_t *msg = (const wsfMsgHdr_t *)param;
if (msg != NULL)
{
switch (msg->event)
{
case APP_TIMER_MSG:
//TODO: 定时器处理函数
break;
//App Task Message, 用户自定义
default:
break;
}
}
// Handle events,若无消息,判断是否为事件
else
{
if (event & APP_BTN_EVT)
{
//TODO: BTN EVT
}
}
}
WsfOsSetNextHandler
的执行将会返回一个handler ID,wsfHandlerId_t
,因此,这里通过代码进行封装。
为了任务管理比较方便,我们根据需要,可以创建一个控制块(Control Block)结构体来进行管理,将需要的消息队列、handle_id、定时器等进行封装起来。
c
/* Main control block of the app task */
struct APP_CB_T
{
wsfQueue_t msg_queue;
wsfHandlerId_t handle_id;
wsfTimer_t app_timer;
};
c
int app_init(uint8_t handle_id)
{
/* store handler ID */
app_cb.handle_id = handle_id;
/* init rx queue */
WSF_QUEUE_INIT(&app_cb.msg_queue);
app_cb.app_timer.handlerId = handle_id;
app_cb.app_timer.msg.event = APP_TIMER_MSG;
return 0;
}
可以根据需要,来设置app定时器,可以单次触发,也可以周期性的触发定时器,不断触发任务执行。
c
WsfTimerStartMs(&app_cb.app_timer, 2000); //2s 触发定时器
对于事件应用而言,例如实现一个按键时间,则可以在按键中断来触发事件,当事件触发之后,应用相关处理触发。
c
WsfSetEvent(app_cb.handle_id, APP_BTN_EVT);
通过外部事件、定时器中断等实现了APP Task任务的触发,实现调用,整体使用也比较方便。
持续更新,系列文章,收藏关注吧!