web-dev-qa-db-ja.com

STM32マイクロコントローラーでアトミックな変数のタイプ/サイズはどれですか?

STM32マイクロコントローラーのデータタイプは次のとおりです: http://www.keil.com/support/man/docs/armcc/armcc_chr1359125009502.htm

これらのマイクロコントローラは、32ビットARMコアプロセッサを使用します。

自動アトミック読み取りおよびアトミック書き込みアクセスを持つデータタイプはどれですか。

32ビットのすべてのデータ型は(プロセッサが32ビットであるため)実行し、64ビットのすべてのデータ型は実行しない(64ビットのWordの読み取りまたは書き込みに少なくとも2つのプロセッサ操作が必要になるため) )、ただしbool(1バイト)、およびuint16_t/int16_t(2バイト)?

コンテキスト:STM32上の複数のスレッド(シングルコアですが、複数のスレッド、つまり「タスク」と呼ばれる FreeRTOS )間で変数を共有しており、アトミックを適用する必要があるかどうかを知る必要があります割り込みをオフにしたり、ミューテックスを使用したりしてアクセスします。

更新:

このサンプルコードを参照してください。

volatile bool shared_bool;
volatile uint8_t shared u8;
volatile uint16_t shared_u16;
volatile uint32_t shared_u32;
volatile uint64_t shared_u64;
volatile float shared_f; // 32-bits
volatile double shared_d; // 64-bits

// Task (thread) 1
while (1)
{
    // Write to the values in this thread.
    // What I write to each variable will vary. Since other threads
    // are reading these values, I need to ensure my *writes* are atomic, or else
    // I must use a mutex to prevent another thread from reading a variable in the middle
    // of this thread's writing.
    shared_bool = true;
    shared_u8 = 129;
    shared_u16 = 10108;
    shared_u32 = 130890;
    shared_f = 1083.108;
    shared_d = 382.10830;
}

// Task (thread) 2
while (1)
{
    // Read from the values in this thread.
    // What thread 1 writes into these values can change at any time, so I need to ensure
    // my *reads* are atomic, or else I'll need to use a mutex to prevent the other 
    // thread from writing to a variable in the midst of reading
    // it in this thread.
    if (shared_bool == whatever)
    {
        // do something
    }
    if (shared_u8 == whatever)
    {
        // do something
    }
    if (shared_u16 == whatever)
    {
        // do something
    }
    if (shared_u32 == whatever)
    {
        // do something
    }
    if (shared_u64 == whatever)
    {
        // do something
    }
    if (shared_f == whatever)
    {
        // do something
    }
    if (shared_d == whatever)
    {
        // do something
    }
}

上のコードで、ミューテックスを使用せずにこれを行うことができる変数はどれですか?私の疑いは次のとおりです:

  1. volatile bool:安全-ミューテックスは不要
  2. volatile uint8_t:安全-ミューテックスは不要
  3. volatile uint16_t:安全-ミューテックスは不要
  4. volatile uint32_t:安全-ミューテックスは不要
  5. volatile uint64_t:安全ではない-重要なセクションまたはMUTEXを使用する必要があります!
  6. volatile float:安全-ミューテックスは不要
  7. volatile double:安全ではない-重要なセクションまたはMUTEXを使用する必要があります!

FreeRTOSのクリティカルセクションの例:
- https://www.freertos.org/taskENTER_CRITICAL_taskEXIT_CRITICAL.html

// Force atomic access with these critical section atomic access guards.
taskENTER_CRITICAL();
// do the (now guaranteed to be safe) read or write here
taskEXIT_CRITICAL();

関連していますが、私の質問には答えていません:

  1. ARMのアトミック操作
  2. ARM:intからの書き込み/読み取りはアトミックですか?
  3. (8ビットAVR [およびArduino]マイクロコントローラーの原子性に関する私自身の質問と回答): https://stackoverflow.com/a/39693278/4561887
  4. https://stm32f4-discovery.net/2015/06/how-to-properly-enabledisable-interrupts-in-arm-cortex-m/
10
Gabriel Staples

この質問に対する最後の決定的な回答については、「私の質問に対する最終的な回答」というタイトルのセクションに直接ジャンプしてください。

UPDATE 2018年10月30日:(少し)間違ったドキュメント(誤ってまったく同じことを言っていました)を誤って参照していたため、ここの回答で修正しました。詳細については、この回答の下部にある「2018年10月30日の変更に関する注意」を参照してください。

私はここですべての単語を理解しているわけではありませんが、ARM v7-Mアーキテクチャリファレンスマニュアルオンラインソース ;- PDFファイルの直接ダウンロード )(原子性については説明していないため、テクニカルリファレンスマニュアル[TRM]ではありません)は、私の仮定を検証します。

enter image description here

だから...私の質問の最後にある私の7つの仮定はすべて正しいと思います。 [2018年10月30日:はい、そのとおりです。詳細については、以下を参照してください。]


UPDATE 2018年10月29日:

もう1つの小さなヒント:

FreeRTOSの創設者、エキスパート、およびコア開発者であるRichard Barryは、tasks.c...

/ *変数のタイプがBaseType_tであるため、クリティカルセクションは必要ありません。 * /

... STM32で「unsigned long」(4バイト)の揮発性変数を読み取るとき。 これは、彼が少なくとも100%確実に4バイトの読み取りと書き込みがSTM32でアトミックであることを意味します彼は小さいバイトの読み取りについては言及していません、しかし4バイトの読み取りの場合、彼は決定的に確信しています。私は、4バイトの変数がネイティブプロセッサの幅であること、そして Word-aligned がこれが真であるために重要であると想定する必要があります。

tasks.c、FreeRTOS v9.0.0の2173-2178行。例:

UBaseType_t uxTaskGetNumberOfTasks( void )
{
    /* A critical section is not required because the variables are of type
    BaseType_t. */
    return uxCurrentNumberOfTasks;
}

彼はこの正確なフレーズを使用しています...

/ *変数のタイプがBaseType_tであるため、クリティカルセクションは必要ありません。 * /

...このファイルの2つの異なる場所。

私の質問への最終的な回答:すべてのタイプ<= 4バイト(以下の9行のリストにあるすべての太字タイプ)はアトミックです。

さらに、上のスクリーンショットに示すように、p141のTRMを詳しく調べると、指摘したい主要な文章は次のとおりです。

ARMv7-Mでは、single-copy atomicプロセッサアクセスは次のとおりです。
•すべてのbyteアクセス。
•allhalfwordは、ハーフワード境界で整列された位置にアクセスします。
•すべてWordは、Wordに揃えられた場所にアクセスします。

また、 このリンクごとに の場合、「ARM CおよびC++に実装されている基本的なデータ型」(STM32の場合)の場合)には次のことが当てはまります。

  1. bool/_Boolは「バイト境界」(1バイト境界)
  2. int8_t/uint8_tは「バイト境界」(1バイト境界)
  3. int16_t/uint16_tは「ハーフワード境界整列」(2バイト境界整列)です
  4. int32_t/uint32_tは「ワード境界整列」(4バイト境界整列)です
  5. int64_t/uint64_tは「ダブルワード境界」(8バイト境界)です<-保証された原子ではありません
  6. floatは「Word境界で整列」(4バイト境界で整列)
  7. doubleは "doubleword-aligned"(8バイト境界で整列)<-保証されていない原子
  8. long doubleは「ダブルワード境界」(8バイト境界)です<-保証されていない原子
  9. すべてのポインタは「ワード境界」(4バイト境界)です

これは、上記のすべての太字の行に自動アトミック読み取りおよび書き込みアクセスがあることを最終的に示す必要がある証拠を理解していることを意味します(ただし、インクリメントはしません) /もちろん減少、これは複数の操作です)。 これが私の質問に対する最終的な回答です。この原子性の唯一の例外は、私が考えるパックされた構造体にある可能性があります。これらのその他の自然に配置されたデータ型は自然に配置されない場合があります。

また、テクニカルリファレンスマニュアルを読むとき、「シングルコピーアトミック性」は明らかに「シングルコアCPUアトミック性」または「シングルCPUコアアーキテクチャ上のアトミック性」を意味するだけであることに注意してください。これは、「マルチプロセッシングシステム」またはマルチコアCPUアーキテクチャを指す「マルチコピーアトミック性」とは対照的です。ウィキペディアは、「マルチプロセッシングとは、単一のコンピューターシステム内で2つ以上の中央処理装置(CPU)を使用すること」( https://en.wikipedia.org/wiki/Multiprocessing )と述べています。

私の問題のアーキテクチャ STM32F767ZI (ARM Cortex-M7コアを使用)は、シングルコアアーキテクチャであるため、「上記のTRMから引用した「単一コピーの原子性」が適用されます。

参考文献:

2018年10月30日の変更に関するメモ:

11
Gabriel Staples

アトミックとはどういう意味か。

単純なロードまたはストア操作ではない場合

a += 1;

その場合、すべてのタイプがアトミックではありません。

単純なストアまたはロード操作の32ビットの場合、16ビットと8ビットのデータ型はアトミックです。レジスタの値を正規化する必要がある場合、8ビットと16ビットのストアとロードはアトミックではない可能性があります。

ハードウェアがビットバンディングをサポートしている場合、ビットバンディングを使用すると、ビットバンディングをサポートするメモリ領域のビット操作(セットおよびリセット)はアトミックです。

注意。

コードが非境界整列操作を許可しない場合、8ビットと16ビットの操作はアトミックでない可能性があります。

1
P__J__

アトミックな「算術」はCPUコアレジスタで処理できます。

任意のタイプにすることができます1または4バイトはアーキテクチャと命令セットに依存します

しかし、任意の変更メモリ内にある変数少なくとも3つのシステムステップを実行します。RMW =レジスタへのメモリの読み取り、レジスタの変更、およびメモリへのレジスタの書き込み。

したがって、アトミック変更は、CPUレジスタの使用を制御する場合にのみ可能です。これは、純粋なアセンブラを使用する必要があり、CまたはCppコンパイラを使用しないことを意味します。

C\Cppコンパイラを使用すると、グローバル変数またはグローバル静的変数がメモリに配置されるため、C\Cppはアトミックアクションとタイプを提供しません

注:アトミック変更には、たとえば「FPUレジスタ」を使用できますが(実際にそれが必要な場合)、コンパイラから非表示にする必要があり、RTOSアーキテクチャにはFPUがあります。

0
denis krasutski