あなたの天然記念物
ホーム更新雑談Perl鉄ゲタランドナーコースガイド自転車Linuxリンク経歴連絡先

時間待ちループ撲滅運動 (2012.03.06)

マイコンの時間待ちにループなど俺が許さん

CPU使用時間に課金(※)されないからって、なんてことするんだ。 そんなに余裕あるなら、機能追加するから。 それでも余裕あるなら、クロック下げるから。 という訳でI2Cを使うアプリケーション側がデータ送信完了待ちでループしてるのを改善しました。
※汎用機ではCPU使用時間単価○○円/秒とか、使用者1人ずつの料金に加算されるのが当たり前です。
前回のページで言ってた下記はボツ。
 >送信要求よこしたタスクを止めてI2Cの処理完了時に再開するつもりです。既にFreeRTOSを使ってるので、処理停止/再開なんて朝飯前です。のはずです。だといいなあ。
ボツの理由は、送信要求寄越したタスクが止まる前に送信完了すると実行中のタスクに起動予約出してしまい、それが空振り(違反じゃない)、 その後、予定通りタスクを止めると誰も起動させないので、そこで止まったままになるから。こりゃ大失敗。 大まかな流れは割り込みルーチンの中からコールバック呼び出し、キューにダミーデータ1個送信、アプリケーション側がキューから受信で待ち合わせ。
//lpc17xx_i2c.cのI2C_MasterHandler()末尾
end_stage:
    // Disable interrupt
    I2C_IntCmd(I2Cx, 0);
    // Send stop
    I2C_Stop(I2Cx);
    I2C_MasterComplete[tmp] = TRUE;
    //送受信完了したので、制御用のポインタクリアとコールバック
    i2cdat[tmp].txrx_setup = NULL;
    if (txrx_setup->callback)
    {
        (*txrx_setup->callback)();
    }

//I2Cの割り込み処理中のコールバック
void sil_callback(void)
{
    portBASE_TYPE HigherPriorityTaskWoken = pdFALSE;
    xQueueSendFromISR(instance.pQueueI2C, "i", &HigherPriorityTaskWoken);
    if (HigherPriorityTaskWoken)
    {
        //中身はvPortYieldFromISR
        taskYIELD();
    }
}

//アプリケーション側は処理完了を待つ
    I2C_MasterTransferData(pSil->pSelectI2C, &pSil->tIMST, I2C_TRANSFER_INTERRUPT);
    //転送完了後、キューにダミーデータが入るのでそれを待つ
    uint8_t ucDummy;
    xQueueReceive(pSil->pQueueI2C, &ucDummy, portMAX_DELAY);
    //完了フラグを刈り取る
    I2C_MasterTransferComplete(pSil->pSelectI2C);

さて、今回の鉄ゲタコーナーは…ありません(ほっ)。

まあ、どうせ話が通じないと思うので、あとはソース見てください(^^;
yrntrlmnmnt20120213-2.zip (251,120 バイトをVPSから 00:05 で)