カランのブログ

ソフトウェアエンジニア / 台湾人 / 福岡生活

今のモード ライト

avr-libcには、<util/atomic.h>というものがあります。最初の反応は、AVRは単一コアなのになぜatomicが必要なのかということですので、説明を見てみました。

このヘッダーファイルのマクロは、アトミックまたは非アトミックに実行されることが保証されたコードブロックに対応しています。この文脈での「アトミック」という用語は、対応するコードが割り込みを受けることができないことを指します。

マイクロコントローラでも、さまざまな割り込みを使用することができるため、プログラムの実行は途中で中断される可能性があります。atomicを使用することで、その中に含まれるコードセグメントが割り込みに影響を受けないように保証することができます(一時的に割り込みを停止します)。

ATOMIC_BLOCK(ATOMIC_FORCEON) {
  // 重要な処理を行う
}

直感的には、cli()sei()の組み合わせに似ていますが、ドキュメントの説明によると、さらに多くのことが行われているようです。内部の実装は次のようになっています:

#define ATOMIC_BLOCK(type) for ( type, __ToDo = __iCliRetVal(); \
                           __ToDo ; __ToDo = 0 )

typeを引数として受け取ることができ、ATOMIC_RESTORESTATEATOMIC_FORCEONの2つの引数を渡すことができます。

#define ATOMIC_RESTORESTATE uint8_t sreg_save \
    __attribute__((__cleanup__(__iRestore))) = SREG

これはseiの効果に似ていますが、より興味深いのは__attribute__の使用です。GCCでは、変数や関数がどのように保存されるべきかを決定するために__attribute__を使用することができます。これはlibcの実装で定義されている動作であり、AVRの場合は次のように書くことができます:

#include <avr/pgmspace.h>
const int my_var[2] PROGMEM = { 1, 2 };

ここでのPROGMEMは実際には__attribute__です:

#ifndef __ATTR_PROGMEM__
#define __ATTR_PROGMEM__ __attribute__((__progmem__))
#endif

通常、変数はメモリに格納されますが、マイクロコントローラではメモリが非常に制限されています。ただし、一般的なコンピュータとは異なり、通常、マイクロコントローラのコードは事前に書かれ、コンパイル後にプログラムメモリ(フラッシュメモリ)に直接書き込まれます。プログラムコードが少ない場合、フラッシュメモリに余分なスペースが残ることがあり、その場合はPROGMEMを使用して変数をフラッシュメモリに格納し、メモリ使用量を減らすことができます。読み取り時には、pgm_read_wordを使用して変数を読み取ることができます。

ATOMIC_BLOCKに戻ると、展開すると次のようなコードになります:

for (uint8_t sreg_save __attribute__((__cleanup__(__iRestore))) = 0;  __ToDo = __iCliRetVal(); __ToDo ; __ToDo = 0) {
   // 重要な処理を行う
}

このようにして、割り込みの影響を受けずにコードの実行が保証されます。forループを使用するこのテクニックは、驚くべきものであり、このように応用することは全く考えていませんでした。

次の記事

node.js ファイルの読み込みの詳細

前の記事

リミックスのフォームとデータ読み取りメカニズムの探討

この文章が役に立つと思うなら、下のリンクで応援してくれると大変嬉しいです✨

Buy me a coffee

作者

Kalan 頭像照片,在淡水拍攝,淺藍背景

愷開 | Kalan

Kalan です。台湾出身で、2019年に日本へ転職し、福岡に住んでいます。フロントエンド開発に精通しているだけでなく、IoT、アプリ開発、バックエンド、電子工作などの分野にも挑戦しています。 最近、エレキギターを始めました。ブログを通じて、より多くの人と交流できればと思っています。気軽に絡んでください