Skip to content

Micro_API

askn37 edited this page Jun 27, 2024 · 15 revisions

Micro_API ツールリファレンス

<Arduino.h>

スケッチ.inoからは無条件で組み込まれるC/C++ヘッダファイル。 他のC言語.c C++言語.cppファイルからは明示的に指定しなければ読み込まれない。

スケッチフォルダ中に最低ひとつは(その中身が空であっても) スケッチ.inoが存在しなければならないので、必ず1回はビルド中に読み込まれることに注意。

__attribute__((weak)) void yield (void)

__attribute__((weak)) void setup (void)

__attribute__((weak)) void loop (void)

__attribute__((weak,OS_main)) int main (void)

これらはユーザー関数で再定義可能な標準C関数のweakスタブ。 再定義されなければ main は以下の関数で代替され、 他は空の関数で代替される。

つまり使用しなくても(typoで関数名を間違えていても)警告にもエラーにもならない。
アセンブラソース.Sで関数実体を代替しても良い。

int main (void) {
  initVariant();  /* #include <variant.h> */
  __builtin_avr_sei();
  setup();
  for (;;) loop();
}

yieldは API内では使われていない。 これはdelayを代替する実装での遅延ループ内で 空き時間に任意のコードを間欠駆動させたり、 タイマーイベントを駆動させたり、 タイムスライスを切り替えるような場合に使われる。

協調的マルチタスク の実装については [TaskChangerサンプル]が詳しい。

<new.h>

依存性: <stdlib.h>

C++クラス記述用のnewdeleteを使用可能にする。 mallocfreeで実装されているため、使用すると出力バイナリ量は約800〜1100byte増加する。

<api/btools.h>

データ操作関数群。

依存性: <inttypes.h> <stddef.h> <avr/pgmspace.h> <util/crc16.h>

このヘッダは <api/macro_api.h> でも組み込まれる。

#define _PTRB(p) ((int8*)&(p))

#define _PTRW(p) ((int16_t*)&(p))

#define _PTRD(p) ((int32_t*)&(p))

#define _PTRQ(p) ((int64_t*)&(p))

#define _PTR8(p) ((uint8_t*)&(p))

#define _PTR16(p) ((uint16_t*)&(p))

#define _PTR32(p) ((uint32_t*)&(p))

#define _PTR64(p) ((uint64_t*)&(p))

ポインタ操作ショートカットマクロ。右辺にも左辺にも使える。

int b_array[] = { 0x1234, 0x5678 };
_PTR8(b_array)[1]; // 0x12 (little endian high byte)

#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))

amtminmax 範囲内に丸めて返す。 マクロなので副作用に注意。

int X = 256;
constrain(X, 0, 255); // return to 255

uint16_t wbits (const uint8_t _bits)

バイト幅ビットマップを2バイト幅に拡大する。半角幅フォントを全角幅フォントに変換する用途。

uint8_t bitrev (const uint8_t _bits)

バイト幅ビットマップのMSB-LSBを、LSB-MSBに反転する。 CRCの右送り/左送りビット反転やフォントデータの鏡像操作用途。

uint16_t bswap16 (uint16_t _word)

uint32_t bswap32 (uint32_t _dword)

uint64_t bswap64 (uint64_t _qword)

マルチバイト変数のエンディアンを入れ替える。(ビッグエンディアン⇔リトルエンディアン相互変換)

なお 1バイト値の上下ニブルを入れ替えるには AVR-GCC固有ビルトイン関数__builtin_avr_swapが使用できる。

void byterev (void* _ptr, size_t _len)

指定バイト列の前後順序を逆転するように直接書き換える。 voidポインタで受けるためcastに注意。 constには使えない。

char btoh (uint8_t _x)

指定バイトの下位4ビットを、HEXキャラクタ[0-9A-F]に変換して返す。 小文字のレターケースが欲しい場合は(ASCIIの場合は)0x20 を論理和する。

uint8_t htob (char _x)

指定文字をHEXキャラクタと見なして、0〜15の数値に変換して返す。 レターケース不問。HEXキャラクタでない場合の結果は不定。

uint8_t stob (char _s[])

指定位置の2文字のHEXキャラクタを、0x00〜0xFFの数値に変換して返す。 レターケース不問。HEXキャラクタでない場合の結果は不定。

char h_str[] = "0123456789ABCDEF";
stob(&h_str[2]); // return to 0x23

short map_short (short x, short in_min, short in_max, short out_min, short out_max)

数値範囲射影変換。ADC取得値などを他の単位系に射影する際に使う。 変換は直線的。 範囲外オーバーフローは(そのほうが便利なので)考慮されない。 範囲外を丸めたい場合は constrain マクロを併用する。 上位下位の順序は逆であっても良く、正負が反転する。

この関数は演算精度がshort型に制限されている。乗除算が使用される。

long map_long (long x, long in_min, long in_max, long out_min, long out_max)

数値範囲射影変換。ADC取得値などを他の単位系に射影する際に使う。 変換は直線的。 範囲外オーバーフローは(そのほうが便利なので)考慮されない。 範囲外を丸めたい場合は constrain マクロを併用する。 上位下位の順序は逆であっても良く、正負が反転する。

乗除算が使用される。

map_longは Arduino互換API のmapに同等。

Macro_API が有効ならば別名mapが宣言されている。

uint8_t csm8 (const void* _data, size_t _len)

8bit 単純加算(ADD)チェックサムを検証する。 すべてのバイトを加算した値の 1の補数を返す。 Intel HEX 等に使われる。

uint8_t bcc8 (const void* _data, size_t _len)

8bit 排他論理和(XOR)チェックサムを検証する。 ISO/JIS規格 SOH/STX/ETXペイロードの BCC などに使われる。

uint8_t crc8 (const void* _data, size_t _len)

8bit CRC を検証する。SMBus の PEC で使われる。 <util/crc16.h>_crc8_ccitt_updateを使用する。

x8 + x2 + x + 1 (0xE0 rev) init 0

uint8_t crc8_ccitt (const void* _data, size_t _len)

8bit CRC(CCITT型)を検証する。 <util/crc16.h>_crc8_ccitt_updateを使用する。

x8 + x2 + x + 1 (0xE0 rev) init -1

uint8_t crc8_ibutton (const void* _data, size_t _len)

8bit CRC(iButton型)を検証する。1-Wireで使われる。 <util/crc16.h>_crc_ibutton_updateを使用する。

x8 + x5 + x4 + 1 (0x8C rev) init 0

uint8_t crc8_dallas (void* _data, size_t _len)

8bit CRC(Dallas型)を検証する。1-Wireで使われる。 _crc_dallas_updateを使用する。

x8 + x5 + x4 + 1 (0x31) init -1

uint8_t _crc_dallas_update (uint8_t _crc, uint8_t _data)

8bit CRC(Dallas型)を計算する。1-Wireで使われる。

x8 + x5 + x4 + 1 (0x31)

uint16_t crc16 (const void* _data, size_t _len)

16bit CRC を検証する。 <util/crc16.h>_crc16_updateを使用する。

x16 + x15 + x2 + 1 (0xA001 rev) init -1

この関数はCRC-16/MODBUSと呼ばれる形式と同一でDATA + crc(Littlendian)の検証結果が0になる。

uint16_t crc16_ccitt (const void* _data, size_t _len)

16bit CRC(CCITT型)を検証する。 <util/crc16.h>_crc_ccitt_updateを使用する。

x16 + x12 + x5 + 1 (0x8408 rev) init -1

この関数はCRC-16/MCRF4XXと呼ばれる形式と同一でCRC-16/CCITT(FALSE)(またはbroken)ではない。 DATA + crc(Littlendian)の検証結果が0になる。

AVRのCRCSCANで使用するCRC16はCRC-16/CCITT(FALSE)形式であることに注意。

uint16_t crc16_xmodem (const void* _data, size_t _len)

16bit CRC(XMODEM型)を検証する。 <util/crc16.h>_crc_xmodem_updateを使用する。

x16 + x12 + x5 + 1 (0x1021) init 0

この関数で得られる検証値は Bigendian でありDATA + crc(Bigendian)の検証結果が0になる。 従ってDATA末尾に検証値を追加するにはbswap16()関数を併用しなければならない。

uint16_t crc16_ccitt_false (const void* _data, size_t _len)

16bit CRC(CCITT型)を検証する。 <util/crc16.h>_crc_xmodem_updateを使用する。

x16 + x12 + x5 + 1 (0x1021) init -1

この関数はCRC-16/CCITT(FALSE)と呼ばれる形式と同一で、得られる検証値は Bigendian でありDATA + crc(Bigendian)の検証結果が0になる。 従ってDATA末尾に検証値を追加するにはbswap16()関数を併用しなければならない。

AVRのCRCSCAN周辺機能で使用する CRC16を求めるのに使用する。

uint32_t crc32 (const void* _data, size_t _len)

32bit CRC を検証する。(省フットプリントだが低速) _crc32_updateを使用する。

x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 (0xEDB88320 rev) init -1

この関数は結果をXOR反転しないCRC-32/JAMCRCと呼ばれる形式と同一でDATA + crc(Littlendian)の検証結果が0になる。 CRC-32/IEEE802.3としての結果を求めるには XOR反転crc ^ ~(uint32_t)0を行えば良い。

AVRのCRCSCAN周辺機能で使用する CRC32はCRC-32/IEEE802.3)形式であることに注意。

uint32_t _crc32_update (uint32_t _crc, uint8_t _data)

32bit CRC を計算する。(省フットプリントだが低速)

x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 (0xEDB88320 rev)


一連の SUM/CRC検証では(検証値のXOR反転をしていなければ)ペイロード全長を _len に渡して 0が返れば 検証成功となる。

一連の SUM/CRC生成では、ペイロードから末尾の SUM/CRC部を除いた _len を渡して得られた結果が 求める SUM/CRC値となるので、それを末尾の SUM/CRC部に書けば良い。

バッファメモリを使わずストリームで逐次的にSUM/CRCを検証・生成するには<util/crc16.h>を利用するとよい。 またいずれの _len も size_t型であるから、最大 32767byteまでしか検証できない。 それ以上の大きさの PGMEN領域を直接検証する場合なども同様に、下位関数を直接使用しなければならない。

_crc_dallas_update_crc32_update<util/crc16.h>ではない。

<api/capsule.h>

カプセル共有体宣言。 主にバイナリペイロード用途。

typedef union capsule16_t

16bit幅共有体。

typedef union capsule32_t

32bit幅共有体。

typedef union capsule64_t

64bit幅共有体。

/* ストリーム中でのエンディアン変換 */
capsule16_t length;
length->bytes[1] = Serial1.read();
length->bytes[0] = Serial1.read();
Serial0.println(length->word, DEC);

#define _CAPS16(ptr) ((capsule16_t*)(&ptr))

#define _CAPS32(ptr) ((capsule32_t*)(&ptr))

#define _CAPS64(ptr) ((capsule64_t*)(&ptr))

カプセル変換マクロ。

/* 連結計時器捕獲採取 */
uint32_t count1;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
  _CAPS32(count1)->words[0] = TCB0.CCMP;
  _CAPS32(count1)->words[1] = TCB1.CCMP;
}
Serial.println(count1, DEC);

<api/CLKCTRL_***.h>

***modernAVR megaAVR reduceAVRの何れか。 initVariantから呼ばれるCPU主クロック設定の実体が定義されている。 {build.core}に応じて対応するファイルは異なり、どれが使われるかは <variant.h>で指定される。

依存性:<api/io.h>

inline void _CLKCTRL_SETUP (void)

対象 MCUの内蔵発振器と分周器で生成可能なすべての F_CPU 値に対応した設定を施す。 最高速度は 24Mhz(あるいは 8M、20M、32Mhz)、最低速度は 512Hz(あるいは 500Hz)である。 ボードサブメニューで選べるのはその代表的な一部にすぎない。

  • 外部発振器には対応していない。それを使うには自前で設定しなければならない。

<api/memspace.h>

依存性:<avr/io.h> <avr/pgmspace.h>

#define NVMEM

セクション".nvmem"に指定要素を配置する属性。

これを指定した要素は、初期値を与えても無視される。 ゼロ初期化もされない。 確保領域はプログラムコードより後方に配置される。 従って 64KiB 境界より前に配置されるとは限らない。

const char nvm_store[PROGMEM_PAGE_SIZE] PGM_ALIGN NVMEM;

PROGMEM属性との違いは配置される領域が異なるのと初期化されないことで、その他の機能は同じである。 なのでこの領域宣言は(64KiB境界を超えていなければ)<String.h>P()マクロでポインタ参照ができるからprintコマンドでも直接扱える。

この属性の使い方は フラッシュメモリ領域を読み書きする実演その1 に詳しい。

#define ROMEM

セクション".progmem.nvm"に指定要素を配置する属性。

これを指定した要素は、初期値を与えることが出来る。 しなければゼロ初期化される。 確保領域はプログラムの前方(64KiB境界以前)の PROGMEM属性領域より後方かつ プログラムコード前方に優先して配置される。

const char nvm_store[] PGM_ALIGN ROMEM = "Hello World!";

PROGMEM属性は<avr/pgmspace.h>で定義される。
PROGMEM属性との違いは配置される領域が異なるだけで、その他の機能は同じである。なのでこの領域宣言は(64KiB境界を超えていなければ)<String.h>P()マクロでポインタ参照ができるからprintコマンドでも直接扱える。
<String.h>が扱うのは正確にはPGM_tクラス属性。

#define NIMEM

セクション".noinit"に指定要素を配置する属性。

これを指定したデータ要素は、初期値を与えても無視される。 初期化されることはなく、単に SRAM領域が予約されるだけである。 必然的にconst修飾子を付すべきではない。

char random_seed[128] NIMEM;  /* 1024 bit seed */

この属性の使い方は SRAMによる疑似不揮発メモリ実演 に詳しい。

#define CODEMEM

セクション".text"に指定要素を配置する属性。 一般的な実行可能コード(関数他)の規定属性。

これを指定した要素はコード領域に配置され、読み出し可能、実行可能、書き込み不可の属性が付与される。

#define DATAMEM

セクション".data"に指定要素を配置する属性。 一般的な初期化済みデータ要素の規定属性。

これを指定した要素は SRAM領域に配置され、読み出し可能、書き込み可能、実行不可の属性が付与される。

#define EEPROM

セクション".eeprom"に指定要素を配置する属性。

これを指定した要素は EEPROM領域に配置され、読み出し可能、実行不可、書き込み不可の属性が付与される。

<avr/eeprom.h>で定義されるEEMEM属性と同等だが、コードのどこからも参照されていない場合でもコンパイラによる最適化削除がされない点で異なる。 EEPROM領域を初期化するための ".eep"(HEX形式)ファイルを作成する場合に利用できる。

#define PRODSIG

セクション".signature"に指定要素を配置する属性。

これを指定した要素はどこにも配置されず、読み出し可能、書き込み不可、実行不可の属性が付与される。 PRODSIG領域に配置されたデータ構造のテンプレートを定義する際に利用できる。

#define USERSIG

セクション".user_signatures"に指定要素を配置する属性。

これを指定した要素は通常はどこにも配置されず、読み出し可能、書き込み可能、実行不可の属性が付与される。 この属性はコードのどこからも参照されていない場合でもコンパイラによる最適化削除されることはない。 USERROW領域に配置されたデータ構造のテンプレートを定義する際に利用できる。

定義した初期値は ".urow"(HEX形式)ファイルには書き出されるので、USERROW 領域に書き込めるファイルとして使用できる。

#define BOOTSIG

セクション".boot_signatures"に指定要素を配置する属性。

これを指定した要素は通常はどこにも配置されず、読み出し可能、書き込み可能、実行不可の属性が付与される。 この属性はコードのどこからも参照されていない場合でもコンパイラによる最適化削除されることはない。 BOOTROW領域に配置されたデータ構造のテンプレートを定義する際に利用できる。

定義した初期値は ".brow"(HEX形式)ファイルには書き出されるので、BOOTROW 領域に書き込めるファイルとして使用できる。
BOOTROW 領域は、2024/01時点では AVR_DU、AVR_EB 系統にのみ搭載されている。他の系統では使用できない。AVR_DUの場合、BOOTROW 領域は USBデスクリプターテーブルを(コード/データ空間を圧迫せずに)保存しておくのに活用できる。

#define PGM_ALIGN

指定要素をPROGMEM_PAGE_SIZE境界に配置する属性。

これを付加した要素は、ページ内で完結する。 つまりPROGMEM_PAGE_SIZEに満たない大きさの要素は 次の要素までの間に余白が空く。

const char nvm_store0[4] PGM_ALIGN NVMEM;
/* ここに隙間が空く : あるいは隣接するとは限らない */
const char nvm_store1[4] PGM_ALIGN NVMEM;
  • PGM_ALIGNまたはPAGE_ALIGNをない領域に消去/書込を行うと 同一ページ内に属していた他の情報は破壊されうる。

#define PAGE_ALIGN(sect)

後続要素を指定セクション"sect"PROGMEM_PAGE_SIZE境界に配置する属性。 セクション名は ".text" ".progmem" ".nvmem" が有効。

PGM_ALIGN属性と違って効果を発揮するのは直後の同じセクションに属する要素だけである。

PAGE_ALIGN(".nvmem");
const char nvm_store0[4] NVMEM;
/* ここに隙間は空かず密に配置される */
const char nvm_store1[4] NVMEM;

ただしこれは複数の要素を一度に書き換えねばならないのと同義なので メモリ管理を完全に自前で行うのでなければ使用することはないだろう。 普通は構造体(セクター)を定義して、ページ単位で領域割り付けと書き換えを行うべきだ。

  • PGM_ALIGNまたはPAGE_ALIGNを伴わない領域に消去/書込を行うと 同一ページ内に属していた他の情報は破壊されうる。

<peripheral.h>

ボード選択固有ペリフェラル定義。 {build.variant} 位置に置かれる。 <api/HarfUART.h><api/TWIM.h> が使用される際の 固有外部端子情報(ポート割付)が列挙され、 これを読むことでペリフェラル周辺機能のインスタンスが準備される。 未使用で実体化されないインスタンスはFLASHに書き込まれない。

依存性: <api/HarfUART.h> <api/TWIM.h> <avr/io.h>

<api/Portmux.h>

PORTMUXに関する構造体を宣言する。 これは<api/HarfUART.h> <api/TWIM.h>等のインスタンス宣言に使われる。

依存性:<avr/io.h>

<api/power.h>

CPU休止制御補助。 いずれも全体割込は許可される。 既定の割込条件を満たすとCPUは再活性化される。

依存性:<avr/sleep.h>

#define power_down()

SLEEP_MODE_PWR_DOWN設定で休止する。 CPU主クロックも停止する。 外部ピン割込または RTC/PIT周辺機能の割込、WDT割込またはリセットのみが、この状態から脱することができる。 外部ピン割込は ISC_BOTHEDGE または ISC_LOWLEVEL でなければならない。 再開時にはCPU主クロック安定化遅延がかかる。

#define power_idle()

SLEEP_MODE_IDLE設定で休止する。 CPU動作のみ休止し、他の周辺機能はすべて活性状態に置かれる。

#define power_standby()

SLEEP_MODE_STANDBY設定で休止する。 RUNSTDBYフラグが許可されていない周辺機能へのクロック供給も停止する。

#define power_adc()

可能ならSLEEP_MODE_ADC設定で休止する。 それがない MCU品種では SLEEP_MODE_IDLEあるいは SLEEP_MODE_STANDBYで休止する。 (後述)

#define SLEEP_MODE_ADC

SLEEP_MODE_ADC は reduceAVR 系統でのみ機能する。 それ以外では他の別名として定義されるが、 どちらであってもADCn_CTRLARUNSTDBYフラグを立てれば SLEEP_MODE_STANDBYで機能するため この休止オプションを明示的に選ぶ意味はない。

  • megaAVR or tinyAVR-0/1 --> SLEEP_MODE_IDLE
  • modernAVR or tinyAVR-2 --> SLEEP_MODE_STANDBY

この定義はTCA0_CTRLARUNSTDBYフラグの有無と一致するようになっている。

<api/Print.h>

<api/HarfUART.h><api/TWIM.h> 等で使われる print支援クラス。 いずれも自身のオブジェクトを返すので、メソッドチェーンを後続できる。

reduceAVR では実質使用不可

Print& ln (void)

\r\nを出力する。 空引数のprintln(void)もこの動作をする。

Print& print (...)

Print& println (...)

指定の数値や文字列を出力する。 println(...)は出力末尾に\r\nを付加する。
第1引数は各型の変数またはF() P()マクロを受け取る。
追加の 第2引数は出力変換する基数、または小数点以下桁数、または+符号出力許可、
第3引数は最低出力文字列長で、正数で右寄せ、負数で左寄せを行う。

printfライブラリはリンクされないが、多様な型を混ぜて使うとその分のリソースが増加する。
結果としてprintf(...)を使ったほうが効率の高まる場合もある。

int number = 20;
Serial
.println(number)                // char型文字出力
.println(number, DEC)           // 10進数値出力(char型でも数値として出力)
.println(number, OCT)           // 8進数値出力
.println(number, BIN)           // 2進数値出力
.println(number, HEX)           // 16進数値出力
.println(number, SIGN, -10)     // 10進符号付き左寄せ10カラム空白埋め出力
.println(number, ZFILL, 10)     // 10進符号なし右寄せ10カラムゼロ埋め出力
.println(number, ZFILL|HEX, 4)  // 16進符号なし右寄せ4カラムゼロ埋め出力
.println(number, ZHEX, 4)       // 同上
;
Serial.println("foo");          // 文字列出力(null文字打ち切り)
Serial.println(F("bar"));       // 文字列定数出力(const PROGMEM)
Serial.println(_str, _len);     // 文字列指定桁出力(null文字含む)
;
Serial.println(_float, 3, 10);  // 浮動小数点以下3桁右寄せ10カラム出力
;
Serial.println(...).flush();    // エラー:これはチェーン出来ない(仮想関数ではない)

浮動小数点出力では、指数表現を含む表現範囲外は inf または ovf で表される。(簡易実装のため)

reduceAVR では実質使用不可

Print& printf ("%format", ...)

printfフォーマットに従って出力する。フォーマット文はF() P()マクロで指定しても良い。

printfライブラリをリンクするため、その分の実装記憶が増大する。(最大約1.5K)

浮動小数点表現指示子%fは、追加のライブラリ結合を必要とする。
Build "printf" サブメニューで許可。(最大約2.5K追加)

reduceAVR では実質使用不可

Print& printHex (const uint8_t* _source, size_t _length, uint8_t _separator = 0)

指定のバイト列から指定の長さを読んで、16進HEXダンプリスト出力する。 _separator を略すとベタ書き、文字を指定するとそれをバイト間に挿入する。

reduceAVR では実質使用不可

size_t write (const uint8_t* _buffer, size_t _length)

size_t write (const PGM_t* _buffer, size_t _length)

指定のバイト列を指定の長さまで書き出す。 実際に書けた長さを返す。 メソッドチェーンはできない。 バイト列はF()マクロで指定しても良い。

size_t puts (const char _str[])

size_t puts (const PGM_t _str[])

ヌル文字\0で終端された文字列を出力する。 書けた長さを返す。 メソッドチェーンはできない。 文字列はF()マクロで指定しても良い。

<api/String.h>

print文でプログラムメモリ定義定数列を扱えるようにする支援クラス。

#define F(pmem_str) (reinterpret_cast<const PGM_t *>(PSTR(pmem_str)))

指定の文字列をプログラムメモリに配置する支援マクロ。 PGM_t参照クラス型を返す。

Serial.println(F("foo"));

#define P(pmem_ptr) (reinterpret_cast<const PGM_t *>(pmem_ptr))

指定のPROGMEM属性ポインタを PGM_t参照クラス型に変換して返す。 F()マクロに対応した関数なら、それに変えて使用できる。

const uint8_t display_init[] PROGMEM = {...};

Wire.start(OLED_ADDR).write(P(display_init), sizeof(display_init));

<api/UsartBaseClass.h>

<api/HarfUART.h>等が使う基底クラス。 これを継承することで制御が異なる仕様 (単線半二重やRS485等) のbegin/endを実装するのに使う。

半二重通信用。割込バッファは使用しない。

<variant.h>

ボード選択固有宣言。 {build.variant} 位置に置かれる。 外部ピンや固有ペリフェラルの情報が書かれている。

依存性: <variant_io.h>

#define AVR_NVMCTRL

NVMCTRL version を表明する。以下の値が定義されている。

  • 0 tinyAVR-0/1/2 系統と megaAVR-0 系統
  • 1 (未使用)
  • 2 AVR_DA/DB/DD 系統
  • 3 AVR_EA 系統
  • 4 AVR_DU 系統
  • 5 AVR_EB 系統

#define AVR_EVSYS

EVSYS 実装世代を表明する。以下の値が定義されている。

  • 100 tinyAVR-0 系統
  • 101 tinyAVR-1 系統
  • 200 megaAVR-0 系統
  • 201 tinyAVR-2 系統と AVR_DA/DB/DD 系統
  • 202 AVR_DU/EA/EB 系統

#define PIN_Pxn [number]

特定の外部ピンを指す定数マクロ。 modernAVR / megaAVR での採番は;

PORTA レジスタIOアドレス 0x0400 を起点として PORT[A-G].PIN[0-7]_CTRL レジスタを指す 8bit幅インデックス値(の 10進表現)

  • 0x0400 に加算すると直接 PORT[A-G]_PIN[0-7]_CTRL レジスタIOアドレスに一致する
  • 更に ~31 との論理積を取ると PORT[A-G] レジスタIOアドレスに一致する
  • b[765] は 0~6 で PORT[A-G] を表す ※ 7==PORTHは存在しない
  • b[4] は 1固定
  • b[3] は 0固定
  • b[210] は 0~7 で PIN[0-7]_bp マクロ定数値に一致

<api/macro_digital.h>も参照のこと。

reduceAVR はこのルールに従わず独自の採番となる

inline void initVariant (void)

既定の main から呼ばれる、ボード固有ペリフェラル初期化関数。 指定のF_CPUに合致するよう主クロック制御器を調律する。

またすべての外部ピンのデジタル入力緩衝部を無効(ISC_INPUT_DISABLE)にする。 詳しくは各個別 AVR データシートを参照のこと。

<variant_io.h>

ボード選択固有宣言の補助ヘッダ。 {build.variant} 位置に置かれる。 異なるバリアント間で、同一だが異名宣言されているような データシート由来の差異を隠蔽するマクロや構造体、列挙型が書かれる。 部分的には アセンブラソース.Sでも利用可能。

依存性:<avr/io.h>

#define USART_RS485_EXT_gc

#define USART_RS485_INT_gc

AVR_Dx 系統以降に対してのみ、megaAVR-0 tinyAVR-0/1/2 系統互換の RS485 設定フラグを定義する。

データシートにUSART_RS485_INT_gc相当は記載のない予約ビットだが 実際のMCUでは正しく読み書きできて意図したとおりに機能する。 これがないと単線半二重駆動時に必要な自動方向切替遅延サイクルが挿入されず、 外部ゲート素子連携が意図通りに制御できない。

将来のシリコン改定で改定されるか、エラッタとして除去されるか、データシートに追記されるかは不確実。

有効ならAVR_MEGAAVR_LIKE_MODERNAVRマクロが宣言される。

/* for UPDI communication host setup */

/* before setting : pinMode(TXD, INPUT_PULLUP) */
/*   and TPI mode : pinMode(XCK, OUTPUT) */

#if defined(AVR_MEGAAVR_LIKE_MODERNAVR)
/* megaAVR-0 RS485 single wire settings : auto driving XDIR */
USART0_CTRLA = USART_LBME_bm         /* single wire loopback mode enable */
             | USART_RS485_EXT_gc    /* auto XDIR output control enable */
             | USART_RS485_INT_gc;   /* auto XDIR delay cycle enable */
#else
USART0_CTRLA = USART_LBME_bm         /* single wire loopback mode enable */
             | USART_RS485_ENABLE_gc /* auto XDIR output control enable */
             | 0x02;                 /* AVR Dx undocumented bit flag enable */
#endif
USART0_CTRLC = USART_CHSIZE_8BIT_gc
             | USART_PMODE_EVEN_gc
             | USART_CMODE_ASYNCHRONOUS_gc
             | USART_SBMODE_2BIT_gc;
USART0_CTRLB = USART_TXEN_bm
             | USART_RXEN_bm
             | USART_ODME_bm         /* single wire open-drain mode enable */
             | USART_RXMODE_NORMAL_gc;
  • 単線半二重非同期RS485は UDPI通信ホスト(XDIR付)を、 単線半二重同期RS485は TPI通信ホスト(XDIR+XCK付)を、 それぞれ簡単にハードウェアUSARTで実装できる。

#define EVSYS_CHANNEL_***_gc (etc...)

EVSYS_CHANNEL0_***_gc に対するチャネル指定なしの別名定義。 AVR_EVSYS == 200 || 201 に対し AVR_EVSYS == 202 の糖衣文を与える。 対応する機能がない場合は定義されていない。

イベントジェネレーターを使用する RTC/PITと、PORTn群は従前の記法が必要。

typedef enum EVSYS_CHANNEL0_enum (etc...)

megaAVR-0 系統のEVSYS事象システムに対して AVR_Dx 系統(AVR_EVSYS==200)互換の糖衣文を与える。 この系統は機能的には以後の系統に対する下位互換だが、 当代に限って命名規則に後世代との一貫性が欠けるのを隠蔽できる。

物理的なIOレジスタ番地配置は異なるが、ビットフィールド定義はほぼ同じである。

有効ならAVR_MODERNAVR_LIKE_MEGAAVRマクロが宣言される。

- /* megaAVR-0 original EVSYS syntax */
- EVSYS_CAHNNEL4 = EVSYS_GENERATOR_TCA0_OVF_LUNF_gc;
- EVSYS_USERTCB0 = EVSYS_CHANNEL_CHANNEL4_gc;
- EVSYS_STROBE = EVSYS_STROBE0_EV_STROBE_CH4_gc;
+ /* AVR_MODERNAVR_LIKE_MEGAAVR */
+ EVSYS_CHANNEL4 = EVSYS_CHANNEL4_TCA0_OVF_LUNF_gc;
+ EVSYS_USERTCB0CAPT = EVSYS_USER_CHANNEL4_gc;
+ EVSYS_SWEVENTA = EVSYS_SWEVENTA_CH4_gc;

なお tinyAVR-2EVSYS事象システムは 記法も機能も AVR_Dx 系統と互換で、 兄弟関係にある tinyAVR-0/1 とは 機能的にもバイナリ的にも互換性はない。 両者は大きく異なるので糖衣文も書けない。

#define _PROTECTED_WRITE(reg, value) etc...

reduceAVR<avr/io.h>に対して、 modernAVR に寄せた糖衣文を追加する。 これにより最新世代に準じた可読性に勝る記法で多くを書けるようになる。 両者が混在しても構わない。

一部重複するマクロには独自の別名を与えられる。PORTB→IOPORTBなど。

有効ならAVR_MODERNAVR_LIKE_REDUCEAVRマクロが宣言される。

  /* for ATtiny10 */
  /* Master Clock control */

- /* original */
- CCP = 0xD8; CLKMSR = 0;  // select OSC8M
- CCP = 0xD8; CLKPSR = 3;  // select prescale division 8X
+ /* AVR_MODERNAVR_LIKE_REDUCEAVR */
+ _PROTECTED_WRITE(CLKCTRL_MCLKCTRLA, CLKCTRL_CLKSEL_OSC8M_gc);
+ _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, CLKCTRL_PDIV_8X_gc);

  /* GPIO */

- /* original */
- DDRB = (1 << DDB1);      // PB1 (PWM OC0B) direction output
+ /* AVR_MODERNAVR_LIKE_REDUCEAVR */
+ PORTB_DIR |= PIN1_bm;
+ // pinMode(PIN_PB1, OUTPUT); /* macro_api enable */

  /* Timer Control */

- /* original */
- TCCR0A = (0 << WGM00) | (1 << COM0B0);  // Wave Generate CTC, Compare OC0B Toggle
- TCCR0B = (1 << WGM02) | (3 << CS00);    // CTC mode; use OCR0A; Clock Prescale division 64
- OCR0A = 15624;                          // 1 second; ie 0.5Hz (== 1000000L / 64 - 1)
+ /* AVR_MODERNAVR_LIKE_REDUCEAVR */
+ TIM0_CTRLA = TIM_WGMODE_CTC_CMPA_L_gc | TIM_CPMODE_OC0B_TOGGLE_gc;
+ TIM0_CTRLB = TIM_WGMODE_CTC_CMPA_H_gc | TIM_CLKSEL_CLKDIV64_gc;
+ TIM0_CMPA = 1000000L / 64 - 1;

LINKS

multix.jp/てくにかるむ(休眠中)
Multix Zinnia Product SDK [*AVR]
AVR.JP(日本語訳)
AVR-LIBC(日本語訳)

Clone this wiki locally