ARMアセンブリにおけるデータ同期とタスク切り替え処理

ARMプロセッサにおける基本的な操作

基本操作1: 汎用レジスタから変数への値転送

基本操作2: ラベルジャンプと条件分岐

基本操作3: 特殊レジスタへの値書き込み

基本操作4: 特殊レジスタからの値読み出しと変数格納

メモリバリア命令の解説

マルチコアプロセッサ環境では、各コアが独自のキャッシュを持っているため、共有メモリへのアクセス時にデータ不整合が発生する可能性があります。同期命令を使用することでこの問題を解決します。

  • DMB (Data Memory Barrier): メモリアクセスの順序保証。この命令より前のメモリアクセスが後のアクセスより先に実行されることを保証します。
  • DSB (Data Synchronization Barrier): 完全な同期保証。この命令より前のすべてのメモリアクセスとキャッシュ操作が完了するまで待機します。
  • ISB (Instruction Synchronization Barrier): 命令ストリームの同期。この命令より後にフェッチされる命令が、前のコンテキスト変更を確実に認識します。

タスク切り替え処理の実装例

__asm void vTaskSwitchHandler(void)
{
    /* プロセススタックポインタ取得 */
    mrs r0, psp
    isb
    
    /* 現在のタスク情報取得 */
    ldr r3, =pxCurrentTask
    ldr r2, [r3]
    
    /* FPU使用チェック */
    tst r14, #0x10
    it eq
    vstmdbeq r0!, {s16-s31}
    
    /* レジスタ保存 */
    mrs r1, control
    stmdb r0!, {r1, r4-r11, r14}
    str r0, [r2]
    
    /* コンテキスト切り替え準備 */
    stmdb sp!, {r3}
    mov r0, #MAX_INTERRUPT_PRIORITY
    msr basepri, r0
    dsb
    isb
    
    /* 次タスク選択 */
    bl vSelectNextTask
    
    /* 割り込み許可 */
    mov r0, #0
    msr basepri, r0
    ldmia sp!, {r3}
    
    /* 新タスクの復帰処理 */
    ldr r1, [r3]
    ldr r0, [r1]
    ldmia r0!, {r3-r11, r14}
    msr control, r3
    
    tst r14, #0x10
    it eq
    vldmiaeq r0!, {s16-s31}
    
    /* スタックポインタ更新 */
    msr psp, r0
    isb
    bx r14
}

ビットフィールドと構造体初期化

typedef union {
    struct {
        uint16_t frame_num : 4;
        uint16_t frame_all : 4;
        uint16_t command   : 8;
        uint16_t channel   : 8;
        uint16_t direction : 1;
        uint16_t reserved1 : 4;
        uint16_t reserved2 : 3;
    } bits;
    uint32_t value;
} CanIdType;

typedef struct {
    CanIdType id;
    CanData data;
} CanFrame;

typedef struct {
    uint16_t command;
    uint16_t status;
    uint16_t speed;
    uint16_t air_status;
    uint16_t frame_count;
    VersionInfo version;
    DateInfo date;
    uint32_t receive_time;
    uint32_t status_time;
    uint32_t command_time;
} GcuInfo;

#pragma DATA_SECTION(gcu_data, "HotData");
GcuInfo gcu_data;

/* 構造体初期化 */
memset(&gcu_data, 0, sizeof(GcuInfo));

タグ: ARM アセンブリ メモリバリア RTOS ビットフィールド

8月3日 23:56 投稿