ArduinoライブラリとしてTOPPERS/ASPを使えるようにしたプロジェクトがあります。
このプロジェクトのターゲットデバイスはWio Terminalで、Wi-FiやBLEが使えます。ただ、それを使うためにはFreeRTOSが必要で、先述のTOPPERS/ASPと競合してしまいます。
このライブラリは、TOPPERS/ASPライブラリを使ったArduino スケッチでもWiFiやBLEを使えるようにするため、FreeRTOSの一部のAPIをTOPPERSで実装したものです。
Wio TerminalでWi-Fiを使う場合は、rpcWifiというライブラリを使い、BLEを使う場合はrpcBLEというライブラリを使います。 この二つのライブラリは、rpcUnifiedというライブラリを使っています。 この3つのライブラリが使っているFreeRTOSのAPIに絞って、TOPPERS/ASPで実装しました。
今回は、WiFiやBLEを使ったスケッチをFreeRTOSを省いてビルドし、未定義シンボルとしてリンクエラーの出たFreeRTOSのAPIだけを対象に、TOPPERS/ASPで実装することにしました。
| 未定義シンボル | FreeRTOS API | 実装方法 |
|---|---|---|
pvPortMalloc |
malloc |
|
vPortFree |
free |
|
vPortEnterCritical |
loc_cpu |
|
vPortExitCritical |
unl_cpu |
|
vTaskStartScheduler |
StartToppersASP |
|
xTaskCreate |
cre_tsk |
|
vTaskDelete |
del_tsk |
|
vTaskSuspend |
sus_tsk |
|
vTaskDelay |
dly_tsk |
|
xTaskGetCurrentTaskHandle |
get_tid |
|
xQueueGenericCreate |
xSemaphoreCreateBinary |
cre_sem |
vQueueDelete |
vSemaphoreDelete |
del_sem |
xQueueCreateCountingSemaphore |
xSemaphoreCreateCounting |
cre_sem |
xQueueCreateMutex |
xSemaphoreCreateMutex |
cre_sem |
xQueueGenericSend |
xSemaphoreGive |
sig_sem |
xQueueSemaphoreTake |
xSemaphoreTake |
wai_sem |
xQueueGiveMutexRecursive |
xSemaphoreGiveRecursive |
sig_sem |
xQueueTakeMutexRecursive |
xSemaphoreTakeRecursive |
wai_sem |
xEventGroupCreate |
cre_flg |
|
xEventGroupSetBits |
set_flg |
|
xEventGroupClearBits |
clr_flg |
|
xEventGroupGetBits |
ref_flg |
|
xEventGroupWaitBits |
wai_flg |
FreeRTOSのAPIは、ユーザー向けの関数名と内部で使用している関数名があるようで、下記の表のようにリネームされています。
| マクロ名 | 関数名 |
|---|---|
xSemaphoreCreateMutex |
xQueueGenericCreate |
xSemaphoreCreateCounting |
xQueueCreateCountingSemaphore |
xSemaphoreCreateBinary |
xQueueGenericCreate |
vSemaphoreDelete |
vQueueDelete |
xSemaphoreTakeRecursive |
xQueueTakeMutexRecursive |
xSemaphoreGiveRecursive |
xQueueGiveMutexRecursive |
xSemaphoreTake |
xQueueSemaphoreTake |
xSemaphoreGive |
xQueueGenericSend |
xSemaphoreGiveFromISR |
xQueueGiveFromISR |
このライブラリでは、ユーザー向けの関数名で実装しました。
| FreeRTOS API | 実装方法 |
|---|---|
xTaskCreate |
cre_tsk |
vTaskDelete |
del_tsk |
vTaskSuspend |
sus_tsk |
vTaskDelay |
dly_tsk |
xTaskGetCurrentTaskHandle |
get_tid |
FreeRTOSのタスクはTaskHandle_tで識別され、FreeRTOS\src\task.hに以下のように定義されます。
typedef struct tskTaskControlBlock* TaskHandle_t;struct tskTaskControlBlockはFreeRTOS\src\task.cで定義されるので、APIとしての定義では中身はいりません。
TOPPERSでの実装ではstruct tskTaskControlBlockを、TOPPERSのタスクと対応付けるために使用します。また、FreeRTOSではタスクに名前を付けられるため、名前用の領域も持たせます。
typedef struct tskTaskControlBlock
{
ID tskid;
const char *pcName;
} TCB_t;
TCB_t FreeRTOS_TCB[10];ToppersASPライブラリで用意されているタスク数10個分を、上記の構造体の配列として持たせ、FreeRTOSとTOPPERSのタスクの対応付けのテーブルFreeRTOS_TCBとして領域を確保しておきます。
FreeRTOS APIが呼ばれた場合は、TaskHandle_tのメンバ変数tskidで、TOPPERSのAPIを呼び出します。
tskidからTaskHandle_tを特定するには、FreeRTOS_TCBの中のtskidが等しいものを探して取得します。
ToppersASPライブラリでtskidに使用する値は、TASK1からTASK10までの連続値で割り振ってあるので、FreeRTOS_TCB[tskid - TASK1]でも取得できます。
FreeRTOSのAPIは下記の通りです。
BaseType_t xTaskCreate(TaskFunction_t pxTaskCode, const char *const pcName, const configSTACK_DEPTH_TYPE usStackDepth, void *const pvParameters, UBaseType_t uxPriority, TaskHandle_t *const pxCreatedTask) PRIVILEGED_FUNCTION;| 引数 | 概要 |
|---|---|
pxTaskCode |
タスクの関数 |
pcName |
タスクの名前 |
usStackDepth |
スタックサイズ |
pvParameters |
タスクの関数に渡す引数 |
uxPriority |
タスク優先度 |
pxCreatedTask |
生成したタスクのハンドルを返す |
TOPPERS/ASPでタスクを生成するAPIは下記の通りです。
extern ER cre_tsk(ID tskid, const T_CTSK *pk_ctsk) throw();| 引数 | 概要 |
|---|---|
tskid |
タスクID |
pk_ctsk |
タスク生成情報 |
引数のタスクID(tskid)は、タスク対応付けのテーブルFreeRTOS_TCBで、メンバ変数のtskidが0のものを検索して、割り当てます。tskidの値は割り当てたFreeRTOS_TCBのインデックスにTASK1を足した値を使用します。
| メンバ変数 | 概要 | 設定値 |
|---|---|---|
tskatr |
タスク属性 | TA_ACT(タスクを起動された状態で生成) |
exinf |
タスクの拡張情報 | pvParameters |
task |
タスクのメインルーチンの先頭番地 | pxTaskCode |
itskpri |
タスクの起動時優先度 | TMAX_TPRI - uxPriority |
stksz |
タスクのスタック領域のサイズ | usStackDepth * sizeof(StackType_t) |
stk |
タスクのスタック領域の先頭番地 | NULL(カーネルで割り当て) |
引数のスタックサイズは、Byteサイズを指定するのではなく、StackType_t分の長さの個数になっているので、乗算してByteサイズにしたものを設定します。
FreeRTOSのタスク優先度は2種類あり、「Generic Method
」と「Architecture Optimized Method」があります。
FreeRTOS\src\boards\SAMD51\portmacro.hで「Architecture Optimized Method」が選択されています。
この場合、優先度は0~31の値が取れ、値が大きい方が優先度も高いということになります。
/* Architecture specific optimisations. */
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif一方TOPPERSでは、値が小さい方が優先度が高いので、TOPPERSの最低優先度の値TMAX_TPRIから、引数で与えられたuxPriorityの差としています。
また、TMIN_TPRIより小さい値は取れないので、計算の結果がこの値より小さいときは、TMIN_TPRIとします。
FreeRTOSのAPIは下記の通りです。
void vTaskDelete(TaskHandle_t xTaskToDelete) PRIVILEGED_FUNCTION;TOPPERS/ASPでのタスクを削除するAPIは下記の通りです。
ER del_tsk(ID tskid) throw();これはToppersASPライブラリでは提供されていないので、実装していません。
FreeRTOSのAPIは下記の通りです。
void vTaskSuspend(TaskHandle_t xTaskToSuspend) PRIVILEGED_FUNCTION;TOPPERS/ASPのタスクをサスペンドするAPIは下記の通りです。
ER sus_tsk(ID tskid) throw();引数のxTaskToSuspendを前述の方法でtskidに変換し、TOPPERS側APIを呼び出します。
FreeRTOSのAPIは下記の通りです。
typedef uint32_t TickType_t;
void vTaskDelay(const TickType_t xTicksToDelay) PRIVILEGED_FUNCTION;TOPPERS/ASPのタスク遅延のAPIは下記の通りです。
typedef uint_t RELTIM;
ER dly_tsk(RELTIM dlytim) throw();TickType_tは、FreeRTOS\src\boards\SAMD51\FreeRTOSConfig.hでconfigUSE_16_BIT_TICKSが0に設定されているので、uint32_tが使われます。
両方の取り得る値域は同じで、永遠待ちを示す値も両方とも0xFFFFFFFFで同じなので、変換していません。
FreeRTOSのAPIは下記の通りです。
TaskHandle_t xTaskGetCurrentTaskHandle(void) PRIVILEGED_FUNCTION;TOPPERS/ASPの現在のタスクIDを返すAPIは下記の通りです。
ER get_tid(ID *p_tskid) throw();get_tidで取得したタスクIDを、前述の方法でFreeRTOS_TCBから取得し、戻り値として返します。
| FreeRTOS API | 実装方法 |
|---|---|
xSemaphoreCreateBinary |
cre_sem |
xSemaphoreCreateCounting |
cre_sem |
xSemaphoreCreateMutex |
cre_sem |
vSemaphoreDelete |
del_sem |
xSemaphoreTake |
wai_sem |
xSemaphoreGive |
sig_sem |
xSemaphoreTakeRecursive |
wai_sem |
xSemaphoreGiveRecursive |
sig_sem |
FreeRTOSのセマフォは幾つか種類があり、ミーテックス、バイナリセマフォ、カウンティングセマフォが使われています。
ミーテックスは優先度継承メカニズムを含んでいますが、バイナリセマフォは優先度継承メカニズムは含んでいません。
FreeRTOSのセマフォのAPIは、内部では待ち行列処理の関数にマクロでリネームされていますが、TOPPERSでの実装ではAPIのまま使っています。FreeRTOSのヘッダーファイルでビルドしたものは、待ち行列処理の関数を必要とするので、ライブラリのみ変更した場合リンクエラーになります。
FreeRTOSのセマフォはSemaphoreHandle_tで識別され、FreeRTOS\src\semphr.hに以下のように定義されています。
typedef QueueHandle_t SemaphoreHandle_t;また、QueueHandle_tはFreeRTOS\src\queue.hに以下のように定義されています。
typedef struct QueueDefinition* QueueHandle_t;struct QueueDefinitionはFreeRTOS\src\queue.cで定義されるので、APIとしての定義では中身はいりません。
TOPPERSでの実装ではstruct QueueDefinitionを、TOPPERSのセマフォと対応付けるために使用します。
typedef struct QueueDefinition
{
ID semid;
uint8_t ucQueueType;
ID xMutexHolder;
UBaseType_t uxRecursiveCallCount;
} Queue_t;
Queue_t FreeRTOS_SEM[10];ToppersASPライブラリで用意されているセマフォ数10個分を、上記の構造体の配列として持たせ、FreeRTOSとTOPPERSのセマフォの対応付けのテーブルFreeRTOS_SEMとして領域を確保しておきます。
FreeRTOS APIが呼ばれた場合は、SemaphoreHandle_tのメンバ変数semidで、TOPPERSのAPIを呼び出します。
FreeRTOSのAPIは下記の通りです。
#define semSEMAPHORE_QUEUE_ITEM_LENGTH ((uint8_t)0U)
#define xSemaphoreCreateBinary() xQueueGenericCreate((UBaseType_t)1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE)
QueueHandle_t xQueueGenericCreate(const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType) PRIVILEGED_FUNCTION;本実装でのFreeRTOS APIは下記のようにしました。
SemaphoreHandle_t xSemaphoreCreateBinary(void) PRIVILEGED_FUNCTION;xQueueGenericCreateでは、待ち行列を生成するための引数が用意されていますが、cre_semを呼び出すには引数名が分かりにくいため、xSemaphoreCreateBinaryのAPIで実装しました。
また、xSemaphoreCreateCountingとxSemaphoreCreateMutexでも共通に使用できるよう、内部関数としてxSemaphoreGenericCreateを定義しました。
xSemaphoreGenericCreateの定義は下記の通りです。
SemaphoreHandle_t xSemaphoreGenericCreate(const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount)| 引数 | 概要 |
|---|---|
uxMaxCount |
セマフォの最大資源数 |
uxInitialCount |
セマフォの初期資源数 |
TOPPERS/ASPのセマフォを生成するAPIは下記の通りです。
ER cre_sem(ID semid, const T_CSEM *pk_csem) throw();| 引数 | 概要 |
|---|---|
semid |
セマフォID |
pk_csem |
セマフォ生成情報 |
引数のセマフォID(semid)は、セマフォ対応付けのテーブルFreeRTOS_SEMで、メンバ変数のsemidが0のものを検索して、割り当てます。semidの値は割り当てたFreeRTOS_SEMのインデックスにSEM1を足した値を使用します。
| メンバ変数 | 概要 | 設定値 |
|---|---|---|
sematr |
セマフォ属性 | TA_TPRI(タスクの待ち行列を優先度順に) |
isemcnt |
セマフォの初期資源数 | uxInitialCount(バイナリセマフォの場合は、0) |
maxsem |
セマフォの最大資源数 | uxMaxCount(バイナリセマフォの場合は、1) |
FreeRTOSのAPIは下記の通りです。
#define xSemaphoreCreateCounting(uxMaxCount, uxInitialCount) xQueueCreateCountingSemaphore((uxMaxCount), (uxInitialCount))
QueueHandle_t xQueueCreateCountingSemaphore(const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount) PRIVILEGED_FUNCTION;本実装でのFreeRTOS APIは下記のようにしました。
SemaphoreHandle_t xSemaphoreCreateCounting(const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount) PRIVILEGED_FUNCTION;xSemaphoreCreateBinaryと同様に、xSemaphoreGenericCreateを呼び出しセマフォを生成します。
| 引数 | 概要 | 設定値 |
|---|---|---|
uxMaxCount |
セマフォの最大資源数 | 受け取ったuxMaxCount |
uxInitialCount |
セマフォの初期資源数 | 受け取ったuxInitialCount |
FreeRTOSのAPIは下記の通りです。
#define xSemaphoreCreateMutex() xQueueCreateMutex(queueQUEUE_TYPE_MUTEX)
QueueHandle_t xQueueCreateMutex(const uint8_t ucQueueType) PRIVILEGED_FUNCTION;本実装でのFreeRTOS APIは下記のようにしました。
SemaphoreHandle_t xSemaphoreCreateMutex(void) PRIVILEGED_FUNCTION;xSemaphoreCreateBinaryと同様に、xSemaphoreGenericCreateを呼び出しセマフォを生成します。
| 引数 | 概要 | 設定値 |
|---|---|---|
uxMaxCount |
セマフォの最大資源数 | 1 |
uxInitialCount |
セマフォの初期資源数 | 1 |
FreeRTOSのAPIは下記の通りです。
#define vSemaphoreDelete(xSemaphore) vQueueDelete((QueueHandle_t)(xSemaphore))
void vSemaphoreDelete(QueueHandle_t xQueue) PRIVILEGED_FUNCTION;本実装でのFreeRTOS APIは下記のようにしました。
void vSemaphoreDelete(SemaphoreHandle_t xSemaphore) PRIVILEGED_FUNCTION;TOPPERS/ASPのセマフォを削除するAPIは下記の通りです。
ER del_sem(ID semid) throw();これはToppersASPライブラリでは提供されていないので、実装していません。
FreeRTOSのAPIは下記の通りです。
#define xSemaphoreTake(xSemaphore, xBlockTime) xQueueSemaphoreTake((xSemaphore), (xBlockTime))
BaseType_t xQueueSemaphoreTake(QueueHandle_t xQueue, TickType_t xTicksToWait) PRIVILEGED_FUNCTION;本実装でのFreeRTOS APIは下記のようにしました。
BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait) PRIVILEGED_FUNCTION;TOPPERS/ASPのセマフォを取得するAPIは下記の通りです。
ER twai_sem(ID semid, TMO tmout) throw();| 引数 | 概要 | 設定値 |
|---|---|---|
semid |
セマフォID | xSemaphore->semid |
tmout |
タイムアウト値 | xTicksToWait |
種類がミューテックスでセマフォが獲得できた場合、再入を可能とするため、タスクIDをxSemaphoreに記録しておきます。
FreeRTOSのAPIは下記の通りです。
#define semGIVE_BLOCK_TIME ((TickType_t)0U)
#define xSemaphoreGive(xSemaphore) xQueueGenericSend((QueueHandle_t)(xSemaphore), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK)
BaseType_t xQueueGenericSend(QueueHandle_t xQueue, const void* const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition) PRIVILEGED_FUNCTION;本実装でのFreeRTOS APIは下記のようにしました。
BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore) PRIVILEGED_FUNCTION;TOPPERS/ASPのセマフォに返却するAPIは下記の通りです。
ER sig_sem(ID semid) throw();| 引数 | 概要 | 設定値 |
|---|---|---|
semid |
セマフォID | xSemaphore->semid |
FreeRTOSの実装では待ち行列用のxQueueGenericSendが使われていますが、マクロによって引数の一部が固定値で呼ばれているため、TOPPERS実装ではセマフォの返却として簡易的に実装しました。
種類がミューテックスの場合、再入の最後に呼ばれるため、xSemaphoreのタスクIDを消しておきます。
FreeRTOSのAPIは下記の通りです。
#define xSemaphoreTakeRecursive(xMutex, xBlockTime) xQueueTakeMutexRecursive((xMutex), (xBlockTime))
BaseType_t xQueueTakeMutexRecursive(QueueHandle_t xMutex, TickType_t xTicksToWait) PRIVILEGED_FUNCTION;本実装でのFreeRTOS APIは下記のようにしました。
BaseType_t xSemaphoreTakeRecursive(SemaphoreHandle_t xMutex, TickType_t xTicksToWait) PRIVILEGED_FUNCTION;ミューテックス用の再入可能な呼び出しのための処理を行います。
最初の呼び出しの場合xSemaphoreTakeを呼び出します。
再入であれば、xMutexのカウンターを加算します。
優先度継承については考慮していません。
FreeRTOSのAPIは下記の通りです。
#define xSemaphoreGiveRecursive(xMutex) xQueueGiveMutexRecursive((xMutex))
BaseType_t xQueueGiveMutexRecursive(QueueHandle_t xMutex) PRIVILEGED_FUNCTION;本実装でのFreeRTOS APIは下記のようにしました。
BaseType_t xSemaphoreGiveRecursive(SemaphoreHandle_t xMutex) PRIVILEGED_FUNCTION;ミューテックス用の再入可能な呼び出しのための処理を行います。
xMutexのカウンターを減算し、再入の最後の呼び出しの場合はxSemaphoreGiveを呼び出します。
優先度継承については考慮していません。
| FreeRTOS API | 実装方法 |
|---|---|
xEventGroupCreate |
cre_flg |
xEventGroupSetBits |
set_flg |
xEventGroupClearBits |
clr_flg |
xEventGroupGetBits |
ref_flg |
xEventGroupWaitBits |
wai_flg |
FreeRTOSのイベントグループはEventGroupHandle_tで識別され、FreeRTOS\src\event_groups.hに以下のように定義されます。
typedef struct EventGroupDef_t* EventGroupDef_t;struct EventGroupDef_tはFreeRTOS\src\event_groups.cで定義されるので、APIとしての定義では中身はいりません。
TOPPERSでの実装ではstruct EventGroupDef_tを、TOPPERSのイベントグループと対応付けるために使用します。
typedef struct EventGroupDef_t
{
ID flgid;
} EventGroup_t;
EventGroup_t FreeRTOS_FLG[10];ToppersASPライブラリで用意されているイベントグループ数10個分を、上記の構造体の配列として持たせ、FreeRTOSとTOPPERSのイベントグループの対応付けのテーブルFreeRTOS_FLGとして領域を確保しておきます。
FreeRTOS APIが呼ばれた場合は、EventGroupHandle_tのメンバ変数flgidで、TOPPERSのAPIを呼び出します。
FreeRTOSのAPIは下記の通りです。
EventGroupHandle_t xEventGroupCreate(void) PRIVILEGED_FUNCTION;TOPPERSでイベントグループに相当します。イベントフラグを生成するAPIは下記の通りです。
extern ER cre_flg(ID flgid, const T_CFLG *pk_cflg) throw();| 引数 | 概要 |
|---|---|
flgid |
イベントグループID |
pk_cflg |
イベントグループ生成情報 |
引数のイベントグループID(flgid)は、イベントグループ対応付けのテーブルFreeRTOS_FLGで、メンバ変数のflgidが0のものを検索して、割り当てます。flgidの値は割り当てたFreeRTOS_FLGのインデックスにTASK1を足した値を使用します。
| メンバ変数 | 概要 | 設定値 |
|---|---|---|
flgatr |
イベントグループ属性 | TA_TPRI(タスクの待ち行列を優先度順に) |
iflgptn |
イベントフラグの初期ビットパターン | 0 |
FreeRTOSのAPIは下記の通りです。
EventBits_t xEventGroupSetBits(EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet) PRIVILEGED_FUNCTION;TOPPERS/ASPのビットパターンをセットするAPIは下記の通りです。
ER set_flg(ID flgid, FLGPTN setptn) throw();| 引数 | 概要 | 設定値 |
|---|---|---|
flgid |
イベントフラグID | xEventGroup->flgid |
setptn |
ビットパターン | uxBitsToSet |
xEventGroupSetBitsの戻り値はuxBitsToSetを適用した後の値なので、ref_flgを呼び出しset_flg後の値を取得して戻り値の値としています。
set_flgとref_flgはcpu_locした状態では呼び出せないため、両者の実行の間に割り込まれ値が変わっている場合、FreeRTOSと同様の結果を得られない可能性があります。
FreeRTOSのAPIは下記の通りです。
EventBits_t xEventGroupClearBits(EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear) PRIVILEGED_FUNCTION;TOPPERS/ASPのビットパターンをクリアするAPIは下記の通りです。
ER clr_flg(ID flgid, FLGPTN clrptn) throw();| 引数 | 概要 | 設定値 |
|---|---|---|
flgid |
イベントフラグID | xEventGroup->flgid |
clrptn |
ビットパターン | ~uxBitsToClear |
clrptnはクリアするためのビットマスクとなっているので、反転しています。
xEventGroupClearBitsの戻り値はuxBitsToClearを適用する前の値なので、ref_flgを呼び出しclr_flg前の値を取得して戻り値の値としています。
ref_flgとclr_flgはcpu_locした状態では呼び出せないため、両者の実行の間に割り込まれ値が変わっている場合、FreeRTOSと同様の結果を得られない可能性があります。
FreeRTOSのAPIは下記の通りです。
#define xEventGroupGetBits(xEventGroup) xEventGroupClearBits(xEventGroup, 0)本実装でのFreeRTOS APIは下記のようにしました。
EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup );TOPPERS/ASPのビットパターンを取得するAPIは下記の通りです。
ER ref_flg(ID flgid, T_RFLG *pk_rflg) throw();| 引数 | 概要 | 設定値 |
|---|---|---|
flgid |
イベントフラグID | xEventGroup->flgid |
pk_rflg |
イベントフラグ参照データ |
FreeRTOSの実装では、xEventGroupClearBitsをクリアビットなしで呼び、その戻り値を利用する実装だが、TOPPERSの実装ではclr_flgは呼び出さず、ref_flgだけで実装しました。
FreeRTOSのAPIは下記の通りです。
EventBits_t xEventGroupWaitBits(EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait) PRIVILEGED_FUNCTION;TOPPERS/ASPのビットパターンを待つAPIは下記の通りです。
ER twai_flg(ID flgid, FLGPTN waiptn, MODE wfmode, FLGPTN *p_flgptn, TMO tmout) throw();| 引数 | 概要 | 設定値 |
|---|---|---|
flgid |
イベントフラグID | xEventGroup->flgid |
waiptn |
イベントフラグ参照データ | uxBitsToWaitFor |
wfmode |
待ちモード | xWaitForAllBitsを元にTWF_ANDWかTWF_ORWを設定 |
p_flgptn |
待ち解除時のビットパターン | |
tmout |
タイムアウト | xTicksToWait |
xClearOnExitに対するTOPPERSの定義はTA_CLRがあるが、イベントフラグの属性として生成時に指定するものとなっているため、APIの呼び出しごとに変更できません。そのため、xClearOnExitをが指定された場合は、clr_flgを~uxBitsToWaitForで呼び出しています。
| FreeRTOS API | 実装方法 |
|---|---|
pvPortMalloc |
malloc |
vPortFree |
free |
vPortEnterCritical |
loc_cpu |
vPortExitCritical |
unl_cpu |
vTaskStartScheduler |
StartToppersASP |
FreeRTOSのAPIは下記の通りです。
void *pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION;これは標準ライブラリのmallocを利用します。
FreeRTOSのAPIは下記の通りです。
void vPortFree( void *pv ) PRIVILEGED_FUNCTION;これは標準ライブラリのfreeを利用します。
FreeRTOSのAPIは下記の通りです。
void vPortEnterCritical(void);TOPPERS/ASPの割り込み禁止にするAPIは下記の通りです。
ER loc_cpu(void) throw();vPortEnterCriticalは再入可能となっているので、グローバル変数で再入カウントlock_countを用意し、最初に呼ばれたときにloc_cpuを呼び出します。
FreeRTOSのAPIは下記の通りです。
void vPortExitCritical(void);TOPPERS/ASPの割り込み許可にするAPIは下記の通りです。
ER unl_cpu(void) throw();vPortExitCriticalは再入可能となっているので、グローバル変数で再入カウントlock_countを用意し、最後に呼ばれたときにunl_cpuを呼び出します。
FreeRTOSのAPIは下記の通りです。
void vTaskStartScheduler(void) PRIVILEGED_FUNCTION;ToppersASPライブラリのカーネルを起動するAPIは下記の通りです。
void StartToppersASP(void);Mastering the FreeRTOS Real Time Kernel-A Hands-On Tutorial Guildの日本語訳