PRSEV ライブラリ

複数の違った振る舞いをするアプリケーションをひとつのバイナリに格納する方法と、イベント状態ごとに関数定義する方法を提供します。

App_Tag のエンドデバイスでは、複数のセンサーの取り扱いについて一つのアプリケーションにまとめて、設定により動作を切り替えています。

各 vProcessEv_???.c ファイルには、個別の振る舞いをするアプリケーションの定義や手続きが含まれます。

コールバック関数の定義

コールバック関数は静的に定義するので、複数のアプリケーション動作をひとつにまとめるには都合が良くありません。ここでは、ソースファイル中に static 定義します。

/**
* ハードウェア割り込み
* @param u32DeviceId
* @param u32ItemBitmap
* @return
*/
static uint8 cbAppToCoNet_u8HwInt(uint32 u32DeviceId, uint32 u32ItemBitmap) {
uint8 u8handled = FALSE;
switch (u32DeviceId) {
default:
break;
}
return u8handled;
}
/**
* ハードウェアイベント(遅延実行)
* @param u32DeviceId
* @param u32ItemBitmap
*/
static void cbAppToCoNet_vHwEvent(uint32 u32DeviceId, uint32 u32ItemBitmap) {
}
/**
* メイン処理
*/
static void cbAppToCoNet_vMain() {
/* handle serial input */
vHandleSerialInput();
}
/**
* ネットワークイベント
* @param eEvent
* @param u32arg
*/
static void cbAppToCoNet_vNwkEvent(teEvent eEvent, uint32 u32arg) {
}
/**
* RXイベント
* @param pRx
*/
static void cbAppToCoNet_vRxEvent(tsRxDataApp *pRx) {
}
/**
* TXイベント
* @param u8CbId
* @param bStatus
*/
static void cbAppToCoNet_vTxEvent(uint8 u8CbId, uint8 bStatus) {
// 送信完了
ToCoNet_Event_Process(E_ORDER_KICK, 0, vProcessEvCore);
}

最後に一覧のtsCbHandler構造体を用意します。

/**
* アプリケーションハンドラー定義
* 使わないものは NULL にする。
*/
static tsCbHandler sCbHandler = {
NULL, // cbAppToCoNet_u8HwInt,
cbAppToCoNet_vHwEvent,
NULL, // cbAppToCoNet_vMain,
NULL, // cbAppToCoNet_vNwkEvent,
NULL, // cbAppToCoNet_vRxEvent,
cbAppToCoNet_vTxEvent
};

状態の定義

利用するイベントの数だけ定義を行います。

/**
* イベント処理関数リスト
*/
static const tsToCoNet_Event_StateHandler asStateFuncTbl[] = {
PRSEV_HANDLER_TBL_DEF(E_STATE_IDLE),
PRSEV_HANDLER_TBL_DEF(E_STATE_RUNNING),
PRSEV_HANDLER_TBL_DEF(E_STATE_APP_WAIT_TX),
PRSEV_HANDLER_TBL_DEF(E_STATE_APP_SLEEP),
PRSEV_HANDLER_TBL_TRM
};

実体は以下のように定義します。

PRSEV_HANDLER_TBL_DEF(E_STATE_IDLE, tsEvent *pEv, teEvent eEvent, uint32 u32evarg) {
// 開始時の状態
if (eEvent == E_EVENT_START_UP) {
// 電源投入またはスリープ復帰時のイベント処理
...
ToCoNet_Event_SetState(pEv, E_STATE_RUNNING);
}
}
PRSEV_HANDLER_TBL_DEF(E_STATE_RUNNING, tsEvent *pEv, teEvent eEvent, uint32 u32evarg) {
// 実行中(センサーの取得、送信要求など)
bOk = bTransmitToParent( ... ); // 送信処理を行う if ( bOk ) {
ToCoNet_Event_SetState(pEv, E_STATE_APP_WAIT_TX);
} else {
ToCoNet_Event_SetState(pEv, E_STATE_APP_SLEEP);
}
}
PRSEV_HANDLER_TBL_DEF(E_STATE_APP_WAIT_TX, tsEvent *pEv, teEvent eEvent, uint32 u32evarg) {
// 送信完了待ち
if (..) {
ToCoNet_Event_SetState(pEv, E_STATE_APP_SLEEP); // スリープ状態へ遷移
}
}
PRSEV_HANDLER_DEF(E_STATE_APP_SLEEP, tsEvent *pEv, teEvent eEvent, uint32 u32evarg) {
// スリープ手続き(以下にコード例)
if (eEvent == E_EVENT_NEW_STATE) {
// Sleep は必ず E_EVENT_NEW_STATE 内など1回のみ呼び出される場所で呼び出す。
V_PRINTF(LB"Sleeping...");
V_FLUSH();
// Mininode の場合、特別な処理は無いのだが、ポーズ処理を行う
ToCoNet_Nwk_bPause(sAppData.pContextNwk);
// 周期スリープに入る
// - 初回は5秒あけて、次回以降はスリープ復帰を基点に5秒
vSleep(sAppData.sFlash.sData.u32Slp, sAppData.u16frame_count == 1 ? FALSE : TRUE, FALSE);
}
}

イベント処理関数

イベント処理関数を以下のように定義しておきます。先程の状態の定義で用意した asStateFuncTbl に従って、イベント処理が行われます。

/**
* イベント処理関数
* @param pEv
* @param eEvent
* @param u32evarg
*/
static void vProcessEvCore(tsEvent *pEv, teEvent eEvent, uint32 u32evarg) {
ToCoNet_Event_StateExec(asStateFuncTbl, pEv, eEvent, u32evarg);
}

初期化処理

以下のようにグローバル変数として用意した psCbHandler, pvProcessEv1 に値を格納する初期化関数を用意しておきます。

/**
* アプリケーション初期化
*/
void vInitAppStandard() {
psCbHandler = &sCbHandler;
pvProcessEv1 = vProcessEvCore;
}

アプリケーションの実行

コールバック関数を格納するメインファイルについて説明します。メインファイルでは、上記で定義した個々の処理用の関数を呼び出す処理を行います。

ユーザ定義イベント処理関数とTWELITE NET のコールバック関数は以下のように定義しておきます。関数ポインタで指定されるアプリケーション独自のコールバック関数を呼び出し、アプリケーション独自のユーザ定義イベント処理を実行します。

void cbAppColdStart(bool_t bInit) {
if (bInit == FALSE) {
...
} else {
switch(u8AppType) {
case 0x00: vInitAppStandard(); break;// AppStandard で起動
...
}
...
ToCoNet_Event_Register_State_Machine(pvProcessEv1);
}
}
/**
* メイン処理
*/
void cbToCoNet_vMain(void) {
if (psCbHandler && psCbHandler->pf_cbToCoNet_vMain) {
(*psCbHandler->pf_cbToCoNet_vMain)();
}
}
/**
* 受信処理
*/
void cbToCoNet_vRxEvent(tsRxDataApp *pRx) {
if (psCbHandler && psCbHandler->pf_cbToCoNet_vRxEvent) {
(*psCbHandler->pf_cbToCoNet_vRxEvent)(pRx);
}
}
/**
* 送信完了イベント
*/
void cbToCoNet_vTxEvent(uint8 u8CbId, uint8 bStatus) {
if (psCbHandler && psCbHandler->pf_cbToCoNet_vTxEvent) {
(*psCbHandler->pf_cbToCoNet_vTxEvent)(u8CbId, bStatus);
}
}
/**
* ネットワークイベント
* @param eEvent
* @param u32arg
*/
void cbToCoNet_vNwkEvent(teEvent eEvent, uint32 u32arg) {
if (psCbHandler && psCbHandler->pf_cbToCoNet_vNwkEvent) {
(*psCbHandler->pf_cbToCoNet_vNwkEvent)(eEvent, u32arg);
}
}
/**
* ハードウェアイベント処理(割り込み遅延実行)
*/
void cbToCoNet_vHwEvent(uint32 u32DeviceId, uint32 u32ItemBitmap) {
if (psCbHandler && psCbHandler->pf_cbToCoNet_vHwEvent) {
(*psCbHandler->pf_cbToCoNet_vHwEvent)(u32DeviceId, u32ItemBitmap);
}
}
/**
* ハードウェア割り込みハンドラ
*/
uint8 cbToCoNet_u8HwInt(uint32 u32DeviceId, uint32 u32ItemBitmap) {
bool_t bRet = FALSE;
if (psCbHandler && psCbHandler->pf_cbToCoNet_u8HwInt) {
bRet = (*psCbHandler->pf_cbToCoNet_u8HwInt)(u32DeviceId, u32ItemBitmap);
}
return bRet;
}