AVR のヒューズ設定を hex ファイルに入れる方法 (Microchip Studio)

ATtiny202 は使いやすいマイコンで、8 ピンでやりたいようなことはだいたい何でもできるので、他の8ピンマイコンは不要と言っても過言ではないというのはやはり言い過ぎでしょうか(?)。
8ピンに 32bit マイコンなんて初期化が面倒なだけで、そんなものは 8bit で十分なんです。クロックも 20MHz, 20MIPS で動けば十分です。そう思います。まあもうちょっとアナログ系が充実したら言うことないのですが。

ところで、プロジェクトジェネレータの Atmel Start を使うために Microchip Studio でプロジェクトを作っているわけですが、
* Microchip は Studio の開発凍結と MPLAB X IDE への統一を明言していますが、MPLAB はいろいろダメなので、Studio が使えるうちは Studio で開発する所存です。
ヒューズ設定は自動で作ってくれないため、デフォルト値から変える場合は
ユーザが指定する必要があります。

Microchip 製のデバッガを使う場合、メニューの Tools -> Device Programming で
ヒューズを手動で書き換えることができます。
しかし、頒布や量産を考えると、プログラムファイルにヒューズ設定を入れることが望ましいです。
pymcuprog なんかでも、hex ファイルの中で指定しないとヒューズが書き換えられなさそうです。

tiny202 のヒューズ設定が必要になるとき

tiny202/402 のヒューズ設定が必要になるときは、例えば
– CPU クロックを 16MHz に設定する
(これは Start から設定できますが、そのままではクロックのキャリブレーション設定が 20MHz のままなので、正確な周波数にするためには Fuse の FREQSEL 設定が必要)
– BOD, WDT の初期設定を変える
– UPDI のプログラム書き換えで EEPROM の内容を書き換えないようにする
– スタートアップ時間を変える(出荷時は最大値 64ms)
などが挙げられます。

ヒューズ設定をプログラム中に書く

avr/io.h をインクルードして、avr/fuse.h (これは io.h からインクルードされる) の説明に従って
ヒューズの設定値をソースコード中に記述します。tiny202 なら、たとえば下記のように。
使わないヒューズ部分は _DEFAULT を指定しないと、0x00 になってしまいます。
avr/io.h をインクルードしないと、fuse なしの .elf が出来上がります。

#include <avr/io.h>
FUSES =
{
.WDTCFG = FUSE_WDTCFG_DEFAULT,
.BODCFG = FUSE_BODCFG_DEFAULT,
.OSCCFG = FUSE_OSCCFG_DEFAULT,
.TCD0CFG = FUSE_TCD0CFG_DEFAULT,
.SYSCFG0 = FUSE_SYSCFG0_DEFAULT,
.SYSCFG1 = 0x01, // SUT = 1ms
.APPEND = FUSE_APPEND_DEFAULT,
.BOOTEND = FUSE_BOOTEND_DEFAULT,
};

FUSES の中身はデバイスごとに異なるため、デバイス定義 (iotn202.h)ファイルを参照します。(tiny202 ならば下記のような感じ)

/* Fuses */
typedef struct FUSE_struct
{
register8_t WDTCFG; /* Watchdog Configuration */
register8_t BODCFG; /* BOD Configuration */
register8_t OSCCFG; /* Oscillator Configuration */
register8_t reserved_1[1];
register8_t TCD0CFG; /* TCD0 Configuration */
register8_t SYSCFG0; /* System Configuration 0 */
register8_t SYSCFG1; /* System Configuration 1 */
register8_t APPEND; /* Application Code Section End */
register8_t BOOTEND; /* Boot Section End */
} FUSE_t;

これでビルドすると、コンパイル結果の .elf ファイル中に fuse セクションが入るようになります。
たとえば

avr-objdump --section-headers ~~~.elf

で確認できます。

hex ファイルにヒューズ設定を入れる

AVR マイコンのプログラマには .hex ファイルでバイナリを渡すことが一般的ですが、まだ .hex ファイル中にヒューズビットは入っていません。

Makefile から実行される objcopy で、fuse や lockbit などを無視して hex ファイルを作るオプションが指定されています。
これはプロジェクトのビルド設定で変更できないので、(参考資料) のようにプロジェクトの Post-build event で下記のように指定して、hex ファイルを作成します。この場合、(プロジェクト名)_with_fuse.hex というファイルが生成されます。

"$(ToolchainDir)\avr-objcopy.exe" -O ihex -R .eeprom -R .lock -R .signature -R user_signatures "$(OutputDirectory)\$(OutDir)\$(OutputFileName)$(OutputFileExtension)" "$(OutputDirectory)\$(OutputFileName)_with_fuse.hex"

これで、pymcuprog でもヒューズビットが書けるようになりました。

参考資料

https://microchipdeveloper.com/8avr:avrfuses

UPDI Programmer を作る

今更も今更ですが、現在の 8bit AVR シリーズのプログラミング方法は 3線式 ISP から 1線式の UPDI へと切り替わっています。かつて AT90S 時代からお世話になった ISP プログラマでは書きこめず、1万円近くする PICkit 4 のようなデバッガが必要な気がして、最初は敷居が高く感じました。

実際には、UPDI プログラマは USB-シリアル IC を使って非常に簡単に作成できます。pyupdi がそのようなプログラマの例です。ISP プログラマの作成は一般的にマイコンが必要だったため、”卵と鶏の問題”がありましたが、その意味でも UPDI の方が敷居は低くなっていると言えます。私はいろいろあって普段は PICkit 4 を使っているのですが、安価なプログラマがあると活用の幅が広がります。


今回製作した UPDI プログラマ
の写真は上記です。特に意図はなかったのですが、ケースに UPDI と書くのは既存のケースと似てしまいました。

複数電圧に対応する回路を追加する

USB シリアル IC の CH340N を使用して作成します。オリジナルの回路では、USB-シリアル側の IO 電圧と AVR の電源電圧を合わせなければいけません。AVR はトレラント IO (VDD より高い入力電圧の対応) ではないので、広い電圧範囲に対応するためには、中間にレベルコンバータを入れる必要があります。

ちょうどいいレベルコンバータが手元になかったので、4-Input AND の日立 HD74LV21A をレベルコンバータのように使いました。CH340 を VCC = 5V で動かす場合、VOH = 5V, VIH = 2.3V となっています。HD74LV-A は 2-5.5V 動作、入力 5V トレラントなので、これを AVR 側の電源で動かすことで、2.3-5V 程度の電源範囲に対応します。(VBUS の誤差を許容する場合は、およそ 2.5V – 5.5V になるでしょう。

ついでに、プログラマとして使わないときは UART モニタとして使えるよう、スイッチでプログラマ、モニタを切り替えられるようにしました。ただしこの機能は今のところあまり使っていません。頻繁にプログラム書き換えを行うとき、PC 側のターミナルの接続、切断操作が煩わしいことが理由です。

作成した回路図を下記に示します。D1 はシリコンダイオードではだめで、小信号用 SBD を使用します。D2は直接 VTG で駆動せず、Tr で受けて 5V 側で駆動した方がよかったですね。

ロジックは 74LV21 でなくても、論理が反転しなければ何でもいいです。接続が少し妙ですが TSSOP をユニバーサル基板に手配線する都合でこのようになっています。


UPDI_schematics_PDF

実際に動かした限りでは、AVR の VDD = 1.8V 付近でも動作するようです。一応、USB 未接続の状態で VTG を入れることはできません。直ちに壊れることはないでしょうが。いろいろ考えると、レベルコンバータとして設計された IC を使用する方がよいかもしれません。私の使用状態ではこの回路で十分です。

回路の実装

マイコンの書き込み

プログラマは Python ベースの pymcuprog を使用します。python がインストールされている環境で、

pip install pymcuprog

とやればインストールできます。実行には Windows 7 以降が必要で、試した限り Windows XP 環境では動かないようです。

マイコンの接続チェックは、プログラマを接続して電源が入った状態で

pymcuprog ping -t uart -u com7 -d attiny202

のようにすれば、正しく動作しているかどうかわかります。-u で USB-シリアルに割り当てられた COM ポートを指定します。-d のデバイス指定はどうも必須のようです。

書き込みは、-f オプションで hex ファイルを指定して

pymcuprog write -t uart -u com7 -d attiny202 -f UPDI_Test.hex --erase --verify

のようにすれば OK です。

Microchip Studio から使う

Microchip Studio の場合、Project Property の Tool で Custom Programming Tool を選択してコマンドを入れれば、IDE から書き込みができると思います。

pymcuprog write -t uart -u com7 -d attiny202 -f "$(OutputDirectory)\$(OutputFileName).hex" --erase --verify

(実行結果)

LibreOfficeのデフォルトフォントを変更する

いつからか LibreOffice の日本語デフォルトフォントが 游ゴシックになっていますが
游ゴシックのフォントがあまり好きじゃないので、新規セットアップの度に変更しています。

Calc の場合

新規ドキュ メントを作成して、F11 を押してスタイルを出し、「標準」を右クリック->編集

フォントタブから、好きなフォントに変更します。

セルのフォントしか変わらないので、ついでに図形描画の既定のスタイルも変更したいのですが、Calc だと手順がないです。
Excel だとスタイルの編集で一気にできたと思います。

Calc とか Excel のような表計算ソフトの図形描画で図表を描くのはどうかと思うので、
(Excel で巨大なセルに文章を書いたり、図形描画でフローチャートを描くのは読みづらいのでやめてほしいと思っています)
図形を描くときは Draw や Impress を使ってということでしょう。
実際、図形描画のバーも標準で非表示になっています。

これでそのドキュメントのセルの標準フォントは変更できたので、このファイルをデフォルトのテンプレートに設定します。
メニューからファイル->テンプレート->テンプレートとして保存をクリック

テンプレート名を入力して、「既定のテンプレートにする」にチェックを入れて保存します。

次回新規作成から、そのテンプレートが適用されます。

ファイルは %APPDATA%/LibreOffice/4/user/template に保存されます。

Writer の場合

同じように、スタイルからフォントなどを変更して、テンプレートとして保存します。

注意しないといけないのは、LibreOffice のバグのように見えるのですが、
Calc, Writer, Impress などでテンプレートを作成する際は、別々の名前を指定しないと
すでに保存したテンプレートが消えてしまいます。
ここでは、Calc のテンプレートに「Default」という名前をつけたので、Writer では「Default_Writer」という名前にしておきます。

Impress の場合

Impress の場合、スタイルの「標準図形スタイル」で図形描画のフォントや色(OpenOffice, LibreOffice のデフォルトは変な色になっている)を変えられます。
スライドのデフォルトフォントやそのサイズは、スタイルもしくはスライドマスターで設定します。

PowerPoint ではスライドマスターのフォントを変更するだけでよいのですが、
Libreoffice 7.5 の時点では、スライドマスターのフォントなどを変更してもスタイルに反映されず、直接スタイルを変更するしかないようです。

これまでと同じように、テンプレートとして保存すれば次回からの新規作成でも反映されます。

そのへんにある部品で非接触給電(1)

コネクタや端子で接続することなく電源供給する非接触(ワイヤレス)給電が普及してきています。
非接触給電にはスマートフォンの充電ができる Qi などの規格がありますが、
そこまでの電力でなくても、LED やマイコンが動く mW レベルの
給電で十分なアプリケーションは考えられます。

そのへんにある部品で実現できないでしょうか。実験してみます。

NE555 で適当な発振器を作って、直接磁気シールドのないコイルを駆動します。
2つの D は NE555 の Tr の電流バイパス用ですが、SBD の方がよさそうです。
電源は 5V から 15V までテストできます。電圧を上げると送電電力も大きくなりますが、 9V 以上にすると発熱が気になりました。

ふつうワイヤレス給電では、磁束を確保するため送電側に空芯コイルをつかいますが
安く手に入るフェライトコアを使ったインダクタで実験してみます。
今回は小型に作りたかったのと、ちょうどたくさんあった NEC の SSB44-680 という型番のチップインダクタを使用しました。
その分送受信コイルの位置はずれが許されなくなります。
インダクタンスは大きい方が良いのか小さい方が良いのかよくわかりません。

送電側は LC で直列共振回路を構成します。
発振周波数と共振回路の fC と合わせることで、コイルに大きな電圧が発生します。
Qi が 100-200kHz らしいので、それにあわせて発振周波数は 160kHz としました。

受電側はラジオと同じ LC 並列回路を構成します。
給電状態を確認するため、負荷として LED を接続しました。
ダイオードで半波整流していますが、平滑する場合は D の後に C を追加できます。

L=0mm /  L=10mmL=20mm

VCC=5V では、写真のように 10mm 離しても LED が点灯しています。
20mm 離すと LED は消えます。
10mm 間隔で数mW 給電できるのであれば、プラスチックケースに入れた状態のマイコンを動作させることができそうです。


インダクタの波形は正弦波になるはずですが、ピーク部分がいびつな形になっています。
これは D の trr の影響だと思います。
NE555 ドライバ段の BJT の逆耐圧 (5V) を超えてしまうと故障に繋がるので、このままでは問題かもしれません。

インダクタに加わる電圧は VCC=5V のとき 26V p-p となっています。送電側の消費電流は 60mA 程度です。


VCC=9V まで上げると、インダクタの電流は 62Vp-p まで増加します。

保管用のICレールの止め具を作る

いまどきの製品で DIP IC を使うことは少ないでしょうが、
DIP IC はレール(あるいはマガジンと呼ばれる)に入ってメーカから出荷されていました。

IC レール

レールの両端はプラスチック製の止め具(エンドピンと呼ばれる)や、上の写真のような塩化ビニルやシリコンゴム製の止め具(エンドプラグと呼ばれる)で固定されます。
東芝とか沖電気は黄色、三菱やTI はグレーと、メーカによって色はさまざまでした。

IC レールのいろいろな止め具

私はレールのまま IC をたくさん保管していますが、
日本の高温多湿の環境では、レールを長期保管するとエンドプラグの劣化が問題になります。

劣化したストッパの例

製造から 10年、20年経過すると、エンドプラグは硬い樹脂と液体に分解してしまいます。
液体は油分なので、水分のように金属をさびさせることはありませんが、
もちろん蒸発することもなく、IC は油でべたべたになってしまい、
止め具としての機能もなくなってしまいます。

そこで、軟質のエンドプラグをプラスチックのエンドピンに置き換えるべく、
3D プリンタで止め具を作ることにしました。
φ3.2 の穴にはまるような形状で止め具を作成します。

止め具を3Dプリンタで作る

たくさんプリントアウト

作成した止め具に変えたICレール

IC レールにドリルで穴を開け、もとの止め具の代わりに作成した止め具を差し込みます。
PLA が何年持つかわかりませんが、20年もののエンドプラグよりは安心して保管できますね。
通常の止め具と違い、薄いので裏から差し込むこともできます。

モデルデータ

 

静音マウスを普通のマウスにする

Logicool の M650L というマウスを買ったのですが・・・
静音マウスなのはいいとして、
・左右クリックの作動力が小さすぎて、ちょっとマウスが何かにぶつかっただけで誤クリックする
・中央クリックと左右クリックの作動力がアンバランスで操作しづらい
という点が不満です。

それでも、以前に買った他社マウスよりは作りが良いので
スイッチを取り替えてしまいましょう。

ねじ止めされています。分解は星型ドライバが必要です。

タクトスイッチは一般的な 5.08mm 2P タイプなので、
適当なものに付け替えます。
もちろん普通のタクトスイッチだと耐久性が足りないので、
マウス用の Panasonic EVQ-P0E07K を使いました。

実装しなおして、静音ではなくなりましたが、これで快適になりました。

STM32G071のADC Calibration

最近は STM32G071 をいじっていて、USB-PD デバイスを作っています。

STM32 は 12bit ADC を搭載しているのですが、
変換値が実際の値からかなりずれてしまい、しばらく困りました。

ADC の初期化後、変換前に ADC のオフセットの Calibration が必要です。
STM32G071 の ADC モジュールは ハードウェアによるキャリブレーションが実装されていて、完了後に ADC_CALFACT レジスタに値が書き込まれます。
次回変換から、CALFACT で補正された変換値が ADC_DR レジスタによって取得されます。

HAL では HAL_ADCEx_Calibration_Start という関数を呼べば、キャリブレーションを実行してくれます。
STM32CubeMX のコードでは以下のように書けばよいですね。

MX_ADC1_Init();
// 中略
// call before ADC conversion has started
HAL_ADCEx_Calibration_Start(&hadc1);
// HAL_ADC_Start(); を呼び出し可能

注意点は、ADC 初期化した後、ADC 変換停止状態で Calibration_Start 関数を呼ばなければいけないということで、作成したコードではタイマ割り込みから ADC_Start() していたので、タイミングによってはその制約が守られていませんでした。
Calibration に失敗すると、CALFACT は更新されず、0 のままになります。

HAL_ADCEx_Calibration_Start のコードにもその注意が書いてあるので、まあちゃんとコメントを読めばこんなところで引っかからないはずですね。

さて、実際に Calibration させてみると、CALFACT = 69 という値が読めます。
VREF = 3.3V, 12bit なのでオフセット電圧は 69×3.3/4096 = 55mV という計算になります。ちょっと大きいですね。CALFACT は 7bit なので、最上位 bit まで使っています。
(QFP32 パッケージだと VREF = VDD)
STM32G071 のデータシートによるとオフセット誤差 EO = 4.5LSB (max) ですが、これはキャリブレーション実行後の測定値と書かれています。

実際エラッタシートを見ると、VREF が 3V 以下のとき、個体によってはオフセット誤差がキャリブレーションの CALFACT (0-127) を上回ってしまうようです。VREF = 1.65 – 3V のとき、ワーストケースの EO = 50LSB となっています。ちょっとだめですね。

何にしても、Calibration は必須であり、ADC 停止中に行う必要があり、また、Calibration_Start は手動でコードを挿入する必要があるということに注意すればよいでしょう。

AVR-DA の内蔵プルアップ特性

AVR-DA シリーズのデータシートには、IO ポート内蔵のプルアップ抵抗の電気的特性はあまり詳しい記述がありません。代表特性として VDD=3V, VIN = 0V のとき 150uA(typ) 200uA (max) を保証しています。

また、VDD と Weak Pull-Up 電流のグラフ (Fig 38-82) が掲載されています。電流は VDD 電圧に依存するように書かれていますが、測定条件が明確ではありません。


– ここまで図表は AVR64DA28-32-48-64 DS Rev.B より引用

マイコンの内部回路によりますが、
1. PU 抵抗の形成に MOSFET を使っている場合
2. PU 抵抗のイネーブルを FET SW で切り替えている場合
などの条件では、抵抗値が非線形となることが考えられます。たとえば AT90S シリーズはかなり非線形な特性でした。

内蔵プルアップを積極的に使う応用を作るうえでこのあたりが気になったので、実測してみました。

VDD=2.5, 3.3, 5V で、プルアップに設定した PE2 ピンに対して VIN を0-5V, ±0.6mA 制限でスイープして、グラフにプロットした入力電流 Iin を青線で示しています。0<VIN<VDD の範囲でほぼ線形とみなすことができます。R=20kΩ の破線とよく一致します。
なお、VIN>VDD では寄生ダイオードが導通するので大きな逆電流が流れます。数十mA を超えると IC によってはラッチアップしてしまいます。

一応、ポートを変えて PD5, PF0 ピンでも同様に確認してみましたが、ほとんど同一の特性でした。常温では プルアップ抵抗 R_PU=20kΩとみなして問題なさそうです。

VIN = 0V の電流値は先ほど示した FIg.28-82 のグラフと一致します。しかし、FIg.28-82 から、パッシブな抵抗に比べて相当大きい温度係数 (~2000ppm/K = 0.2%/K) をもつことに注意が必要です。

シフトレジスタによるノイズジェネレータのフィードバックと周期

デジタル回路の簡単なノイズジェネレータとして、シフトレジスタを使ったいわゆる Shift Register Generator Counter が使われます。シフトレジスタの出力を XOR を通して入力にフィードバックすることで、長い周期のカウンタが得られます。カウンタ周期 N が大きいとき、シフトレジスタの出力は (入力周波数 / N) より高い周波数成分をもつホワイトノイズに近づくので、サウンドジェネレータのノイズ音発生器によく使われます。

2入力の XORを使ったフィードバック回路では、SREG 出力が 0x00 のとき入力も 0 になってしまうため、この状態を避ける必要があります。一般的にはリセット後の初期値を適当な値に設定します。

74164 などの SIPO シフトレジスタは、出力 0x00 にするリセット入力しかありません。出力が 0x00 を有効なステートとするためには、上図のように XNOR を使えば OK です。これは、出力 0xFF から XOR によるフィードバックで動作させたときと等価になります。

2入力 XNOR の入力元 bit の接続先を M,N として、得られるカウンタの周期を下表に示します。N bit のシフトレジスタのとりうる状態は 2^N で、全 bit が 1 のときは無効な状態なので、周期 2^N-1 が N bit SREG の最大周期となります。この最大周期となるカウンタを Maximum Length Counter と呼びます。Maximum Length Counter となるフィードバック接続は、表中で太字で示しています。

M
N/M 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
N 0
1 3
2 7 7
3 15 6 15
4 21 31 31 21
5 63 14 9 14 63
6 127 93 127 127 93 127
7 63 30 217 12 217 30 63
8 73 465 21 511 511 21 465 73
9 889 42 1023 62 15 62 1023 42 889
10 1533 2047 1953 1533 595 595 1533 1953 2047 1533
11 3255 126 45 28 819 18 819 28 45 126 3255
12 7905 1785 8001 7161 6141 7665 7665 6141 7161 8001 1785 7905
13 11811 254 5115 186 5461 254 21 254 5461 186 5115 254 11811
14 32767 4599 63 32767 35 93 32767 32767 93 35 32767 63 4599 32767
15 255 126 57337 60 16383 434 63457 24 63457 434 16383 60 57337 126 255