asknのアイコン画像
askn 2026年09月01日作成 © MIT
セットアップや使用方法 セットアップや使用方法 閲覧数 35
askn 2026年09月01日作成 © MIT セットアップや使用方法 セットアップや使用方法 閲覧数 35

[modernAVR] 簡易ロジックアナライザーを雑に作る

[modernAVR] 簡易ロジックアナライザーを雑に作る

GPIOの通信状態を可視化する

I2C や SPI の絡む低レベルな通信階層の虫取りなどをやっていると、GPIOの変化を時系列で追いたいということはよくある。そういう時にはロジックアナライザーを持ち出すわけだが、ちゃんとしたのはそれなりに高価だし、USBドングル型の廉価品も専用アプリや各OS向けドライバーを準備するのは面倒だし、だったらその辺にある適当なマイコンで GPIOキャプチャして、シリアルコンソール表示できるだけでも用が足りるのではないか?と考えてサクッと書いてみたスケッチがこれだ。250kbps程度まで追えて、8KiBの SRAMで 1400ポイント程度のキャプチャができ、1/32 usec精度の表示ができるだけ、という原始的なものだが、それでも一応モノの役に立つ。

仕組みは単純。特定のポートグループを読み、時間情報と一緒にキャプチャテーブルへ格納するだけ。トリガーとキャプチャには BOTHEDGES 割込を用い、それにタイムアウト停止用のタイマーを加えている。

F_CPUをオーバークロック32MhzにセットしたAVR64DD32を観測器として、ISP書込器から ATtiny13A のシグニチャー(型番情報)を 125kbps で読み出す様子を可視化すると以下の通り。

<startup> F_CPU=32000000 _AVR_IOXXX_H_=ioavr64dd32.h CONSOLE_BAUD=500000 CAPTURE_MAX=1488 <capture wait> <stop> 0: 0.000 0.000 00001111 1: 0.000 0.000 00000101 2: 1115.029 1115.029 00000001 3: 21144.013 20028.016 00001011 4: 21148.014 4.001 00000001 5: 21152.005 3.023 00000011 6: 21156.006 4.001 00001001 7: 21160.011 4.005 00001011 8: 21164.002 3.023 00000001 9: 21168.003 4.001 00000011 10: 21172.004 4.001 00001001 11: 21176.000 3.028 00001011 12: 21180.001 4.001 00001001 13: 21184.006 4.005 00001011 14: 21187.029 3.023 00000001 15: 21191.030 4.001 00000011 16: 21195.031 4.001 00000001 17: 21199.031 4.000 00000011 18: 21204.000 4.001 00000001 19: 21207.030 3.030 00000011 20: 21211.030 4.000 00001001 21: 21215.026 3.028 00001011 22: 21219.027 4.001 00000001 23: 21223.028 4.001 00000011 24: 21227.029 4.001 00001001 25: 21231.025 3.028 00001011 26: 21235.025 4.000 00000001 27: 21239.026 4.001 00000011 28: 21243.017 3.023 00000001 29: 21247.018 4.001 00000011 30: 21251.018 4.000 00001001 31: 21255.015 3.029 00001011 32: 21259.015 4.000 00001001 33: 21263.021 4.006 00001010 34: 21267.012 3.023 00001000 35: 21271.019 4.007 00000010 36: 21275.010 3.023 00000001 37: 21279.011 4.001 00000011 38: 21283.012 4.001 00000000 39: 21287.013 4.001 00000010 40: 21291.013 4.000 00000001 41: 21295.014 4.001 00000011 42: 21299.005 3.023 00000000 43: 21303.006 4.001 00000010 44: 21307.007 4.001 00000000 45: 21311.007 4.000 00000010 46: 21315.008 4.001 00000001 47: 21319.009 4.001 00000011 48: 21323.000 3.023 00000001 49: 21327.001 4.001 00000011 50: 21331.001 4.000 00000000 51: 21334.031 3.030 00000010 52: 21339.000 4.001 00000000 53: 21343.000 4.000 00000010 54: 21347.001 4.001 00000000 55: 21351.002 4.001 00000010 56: 21354.025 3.023 00000000 57: 21358.026 4.001 00000010 58: 21362.026 4.000 00000000 59: 21366.027 4.001 00000010 60: 21370.028 4.001 00000000 61: 21374.029 4.001 00000010 62: 21378.020 3.023 00000000 63: 21382.021 4.001 00000010 64: 21386.021 4.000 00000000 65: 21390.022 4.001 00000010 66: 21394.023 4.001 00000000 67: 38643.012 17248.021 00000010 68: 38647.013 4.001 00000000 69: 38651.004 3.023 00000010 70: 38655.004 4.000 00001000 71: 38659.010 4.006 00001010 72: 38663.001 3.023 00001000 73: 38667.007 4.006 00001010 74: 38671.007 4.000 00000000 75: 38674.030 3.023 00000010 76: 38678.031 4.001 00000000 77: 38683.000 4.001 00000010 78: 38687.001 4.001 00000000 79: 38691.001 4.000 00000010 80: 38695.002 4.001 00000000 81: 38698.025 3.023 00000010 82: 38702.026 4.001 00000000 83: 38706.023 3.029 00000010 84: 38710.024 4.001 00000000 85: 38714.025 4.001 00000010 86: 38718.025 4.000 00000001 87: 38722.026 4.001 00000011 88: 38726.027 4.001 00000001 89: 38730.018 3.023 00000011 90: 38734.019 4.001 00000000 91: 38738.019 4.000 00000010 92: 38742.020 4.001 00000000 93: 38746.021 4.001 00000010 94: 38750.022 4.001 00000000 95: 38754.013 3.023 00000010 96: 38758.013 4.000 00000000 97: 38762.014 4.001 00000010 98: 38766.015 4.001 00000000 99: 38770.012 3.029 00000010 100: 38774.013 4.001 00000000 101: 38778.014 4.001 00000010 102: 38782.014 4.000 00000000 103: 38786.006 3.024 00000010 104: 38790.006 4.000 00000000 105: 38794.007 4.001 00000010 106: 38798.008 4.001 00000000 107: 38802.008 4.000 00000010 108: 38806.009 4.001 00000000 109: 38810.000 3.023 00000010 110: 38814.001 4.001 00000000 111: 38818.002 4.001 00000010 112: 38822.002 4.000 00000000 113: 38826.003 4.001 00000010 114: 38830.004 4.001 00000000 115: 38834.001 3.029 00000010 116: 38838.002 4.001 00000000 117: 38841.025 3.023 00000010 118: 38845.026 4.001 00000000 119: 38849.027 4.001 00000010 120: 38853.027 4.000 00000001 121: 38857.028 4.001 00000011 122: 38861.029 4.001 00000001 123: 38865.020 3.023 00000011 124: 38869.020 4.000 00000001 125: 38873.021 4.001 00000011 126: 38877.022 4.001 00000001 127: 38881.023 4.001 00000011 128: 38885.023 4.000 00000000 129: 38889.014 3.023 00000010 130: 38893.015 4.001 00000000 131: 42653.028 3760.013 00000010 132: 42657.028 4.000 00000000 133: 42661.029 4.001 00000010 134: 42665.030 4.001 00001000 135: 42669.026 3.028 00001010 136: 42673.026 4.000 00001000 137: 42677.022 3.028 00001010 138: 42681.023 4.001 00000000 139: 42685.023 4.000 00000010 140: 42689.024 4.001 00000000 141: 42693.025 4.001 00000010 142: 42697.025 4.000 00000000 143: 42701.017 3.024 00000010 144: 42705.017 4.000 00000000 145: 42709.018 4.001 00000010 146: 42713.019 4.001 00000000 147: 42717.016 3.029 00000010 148: 42721.017 4.001 00000000 149: 42725.018 4.001 00000010 150: 42729.018 4.000 00000001 151: 42733.009 3.023 00000011 152: 42737.010 4.001 00000001 153: 42741.011 4.001 00000011 154: 42745.011 4.000 00000000 155: 42749.012 4.001 00000010 156: 42753.013 4.001 00000000 157: 42757.004 3.023 00000010 158: 42761.005 4.001 00000000 159: 42765.005 4.000 00000010 160: 42769.006 4.001 00000000 161: 42773.007 4.001 00000010 162: 42777.007 4.000 00000000 163: 42781.005 3.030 00000010 164: 42785.005 4.000 00000000 165: 42788.029 3.024 00000010 166: 42792.029 4.000 00000000 167: 42796.030 4.001 00000010 168: 42800.031 4.001 00000000 169: 42804.031 4.000 00000010 170: 42809.000 4.001 00000000 171: 42812.023 3.023 00000010 172: 42816.024 4.001 00000000 173: 42820.025 4.001 00000010 174: 42824.025 4.000 00000000 175: 42828.026 4.001 00000010 176: 42832.027 4.001 00001000 177: 42836.022 3.027 00001010 178: 42840.023 4.001 00001001 179: 42844.021 3.030 00000011 180: 42848.021 4.000 00000000 181: 42852.022 4.001 00000010 182: 42856.013 3.023 00000000 183: 42860.014 4.001 00000010 184: 42864.014 4.000 00000001 185: 42868.015 4.001 00000011 186: 42872.016 4.001 00000000 187: 42876.016 4.000 00000010 188: 42880.007 3.023 00000000 189: 42884.008 4.001 00000010 190: 42888.009 4.001 00000000 191: 42892.010 4.001 00000010 192: 42896.010 4.000 00000000 193: 42900.011 4.001 00000010 194: 42904.002 3.023 00000000 195: 46660.017 3756.015 00000010 196: 46664.017 4.000 00000000 197: 46668.018 4.001 00000010 198: 46672.019 4.001 00001000 199: 46676.015 3.028 00001010 200: 46680.015 4.000 00001000 201: 46684.011 3.028 00001010 202: 46688.012 4.001 00000000 203: 46692.013 4.001 00000010 204: 46696.013 4.000 00000000 205: 46700.014 4.001 00000010 206: 46704.005 3.023 00000000 207: 46708.006 4.001 00000010 208: 46712.007 4.001 00000000 209: 46716.007 4.000 00000010 210: 46720.008 4.001 00000000 211: 46724.006 3.030 00000010 212: 46728.006 4.000 00000000 213: 46732.007 4.001 00000010 214: 46735.030 3.023 00000001 215: 46739.031 4.001 00000011 216: 46743.031 4.000 00000001 217: 46748.000 4.001 00000011 218: 46752.001 4.001 00000000 219: 46756.001 4.000 00000010 220: 46759.025 3.024 00000000 221: 46763.025 4.000 00000010 222: 46767.026 4.001 00000000 223: 46771.027 4.001 00000010 224: 46775.027 4.000 00000000 225: 46779.028 4.001 00000010 226: 46783.019 3.023 00000000 227: 46787.026 4.007 00000010 228: 46791.017 3.023 00000000 229: 46795.018 4.001 00000010 230: 46799.019 4.001 00000000 231: 46803.020 4.001 00000010 232: 46807.020 4.000 00000000 233: 46811.021 4.001 00000010 234: 46815.012 3.023 00000000 235: 46819.013 4.001 00000010 236: 46823.014 4.001 00000000 237: 46827.014 4.000 00000010 238: 46831.015 4.001 00001000 239: 46835.011 3.028 00001010 240: 46839.012 4.001 00000000 241: 46843.012 4.000 00000010 242: 46847.013 4.001 00000000 243: 46851.011 3.030 00000010 244: 46855.011 4.000 00000000 245: 46859.003 3.024 00000010 246: 46863.003 4.000 00000000 247: 46867.004 4.001 00000010 248: 46871.005 4.001 00000000 249: 46875.005 4.000 00000010 250: 46879.006 4.001 00000000 251: 46882.029 3.023 00000010 252: 46886.030 4.001 00000001 253: 46890.031 4.001 00000011 254: 46894.031 4.000 00000001 255: 46899.000 4.001 00000011 256: 46903.001 4.001 00000001 257: 46906.024 3.023 00000011 258: 46910.025 4.001 00000000 259: 50333.001 3422.008 00001110 <Press the Enter key to the next capture>

ISP制御の実態は低電圧SPI通信で、キャプチャされた8ポート表示の左端4ビットが、MOSI、RESET(nSS)、CLK、MISO だ。うち RESET とCLKをトリガーに設定している。項番3から49の、SCK=1(昇端)に着目して読むと、MOSIにMLB先行でAC:53:00:00を送信していることがわかる。そして同時に MISOにはFF:FE:53:00が受信されている。この53の SPIエコーバックが、Attiny13Aが ISPプログラミング許可要求に対して承認を返した証跡だ。その後は黙々と ISPコマンドを送信し、応答を読み取り、最後は RESET=1 で終了(キャプチャタイムアウト)している。

観測器は 32MHzで動作させているが、32Mhz動作の32bitカウンターをSRAMのキャプチャテーブルに保存する割込ベクターが最大120クロック(約4us弱。レジスタページングやコンテキストスイッチ機構のない割込の重さは AVR最大の弱点)ほどかかるので、各項番間に1usのジッターが現れている。だが平均すれば4usなので、125kbps x 2倍のサンプリング周波数は一応確保されている。

tinyAVR-2以降の modernAVR世代では、2個の16bitカウンター、TCB0とTCB1を連結して、32bitのイベントキャプチャータイマーにする機能がある。このロジックアナライザー・スケッチはそれをそのまま使っている。当然普通の Arduino API互換 SDKではそういうことはできない(できなくはないが既定で有効になっている様々なAPI機能を殺しまくらないとならない)ので、素の avr-libcや XC8に対応した MPLAB Xなどの SDKが必要になる。しかし今時の モダンAVR は<avr/io.h>ヘッダーファイルがクラシック/レジェンドAVR世代より遥かに良くできているので、生のマシン語と変わらない可読性劣悪の呪文を唱える必要はない。肝心のペリフェラル・セットアップコードはこれだけだ。

/* TCB0の捕獲事象に接続 */ /* TCB0とTCB1の捕獲事象に接続 */ EVSYS_CHANNEL4 = EVSYS_CHANNEL_OFF_gc; EVSYS_USERTCB0CAPT = EVSYS_USER_CHANNEL4_gc; EVSYS_USERTCB1CAPT = EVSYS_USER_CHANNEL4_gc; /* ch5=TCB0溢れ*/ /* TCB1の計数事象に接続 */ EVSYS_CHANNEL5 = EVSYS_CHANNEL_TCB0_OVF_gc; EVSYS_USERTCB1COUNT = EVSYS_USER_CHANNEL5_gc; /* TCB1は計数捕獲周波数測定動作かつ連結上位 */ TCB1_EVCTRL = TCB_CAPTEI_bm; TCB1_CTRLB = TCB_CNTMODE_FRQ_gc; TCB1_CTRLA = TCB_CASCADE_bm | TCB_CLKSEL_EVENT_gc | TCB_ENABLE_bm; /* TCB0は計数捕獲周波数測定動作かつ連結下位 */ /* CLK元は主クロック(F_CPU)*/ TCB0_EVCTRL = TCB_CAPTEI_bm; TCB0_CTRLB = TCB_CNTMODE_FRQ_gc; TCB0_CTRLA = TCB_CLKSEL_DIV1_gc | TCB_ENABLE_bm; /* キャプチャ実行方法;前回のキャプチャからの経過クロック数が読み出せる */ /* 上位カウンタを読むことで、下位ともども自動リセットされる */ EVSYS_SWEVENTA = EVSYS_SWEVENTA_4_bm; uint32_t _timetick = TCB0_CCMP; _timetick += TCB1_CCMP << 16;

まとめ

まあ所詮は 8-bit CPU の AVRであることに変わりはないので、出来たモノもこんなモンかなーというところ。本気出すなら動作周波数がもっと高くて、ネイティブな 32bitあるいは 64bitタイマー/カウンターを普通に備えている今時の RISC-Vや、ARM64チップなら 1us以下の分解能を持つロジックアナライザーは容易く作れるだろう。とはいえ思いついたものを雑に作れて、キャッシュせずともビルドが早くて、1分かからずアップロードできて、トライ&エラーサイクルが早いってのが AVR の利点、というか魅力だからね。それにしても、ESP32とかなんであんなにビルドもアップロードも珈琲沸かせるくらいに退屈なんでしょ…?

関連リンク

asknのアイコン画像
朝日薫(通名)◆KEEP TRYING, THE GOD SAVE YOU!◆悩んでる暇があったら手を動かせ◆本質的にはデバグ解析修理屋◆ソフトもハードも全部やる◆開発言語だけなら数十種は読み書き可◆最初に覚えた言語はZ80ニモニックの手書き◆主力はPerl◆
  • askn さんが 前の火曜日の22:33 に 編集 をしました。 (メッセージ: 初版)
ログインしてコメントを投稿する