Help us understand the problem. What is going on with this article?

Raspberry PiのGPIOからAVRマイコンに書き込む方法

はじめに

Arduinoなどでよく使われているAVRマイコンにRaspberry PiのGPIOからプログラムを書き込む方法です。
AVRマイコンへの書き込みは専用の書き込み機を使用したり、Arduinoでライターをエミュレートしたりといった方法がありますが、Raspberry PiがあればGPIOから安価に書き込みを行うことが可能です。

書き込みソフトの準備

書き込みにはavrdudeを使用します。
Arduinoの開発環境でも使われているAVR開発ではメジャーなツールで、
パッケージでも配布されていますが、GPIOを使用するにはビルドが必要です。

環境

Raspberry Pi 3 model b+

Raspberry Pi 4 model bでも動作します。その他のSBCでも動作するかもしれません。
今回はdockerでubuntuコンテナをたてて作業しました。

avrdudeのビルド

avrdudeのビルドを行っていきます。
ほとんどのディストリビューションにgccなどの開発ツールがインストールされていますが、なければインストールしておきます。

# apt install build-essential autoconf wget

続いてflex bisonのインストール

# apt install flex bison

次にavrdudeのビルドですが、バージョンには注意が必要です。
現在最新のv6.3にはバグがあり、Raspberry PiでGPIOが利用できません。
ですので今回はv6.2を使用します。

公式リポジトリからダウンロードして展開

# wget http://download.savannah.gnu.org/releases/avrdude/avrdude-6.2.tar.gz
# tar -zxf avrdude-6.2.tar.gz

ビルドとインストール
configureに--lenable-linuxgpioオプションを渡すのを忘れずに

# cd avrdude-6.2
# ./configure --enable-linuxgpio
# make
# make install

avrdude.confにデバイスの定義を追加します。
以下のファイルを適当なエディタで編集します。
/usr/local/etc/avrdude.conf
エディタ上で"linuxgpio"を検索すると次のセクションが見つかるはずです。

/usr/local/etc/avrdude.conf
#programmer
#  id    = "linuxgpio";
#  desc  = "Use the Linux sysfs interface to bitbang GPIO lines";
#  type  = "linuxgpio";
#  reset = ?;
#  sck   = ?;
#  mosi  = ?;
#  miso  = ?;
#;

コメントアウトを外して適当なピンをアサインします。

/usr/local/etc/avrdude.conf
programmer
  id    = "linuxgpio";
  desc  = "Use the Linux sysfs interface to bitbang GPIO lines";
  type  = "linuxgpio";
  reset = 4;
  sck   = 16;
  mosi  = 20;
  miso  = 21;
;

avrdudeはGPIOで書き込みプロトコルをソフトウェアエミュレートで行います。いわゆるbit bangingです。
ですのでハードウェアリソースによらず空いてるピンなら何でも構いません。

次のコマンドでlinuxgpioが追加されていることを確認します。

# avrdude -c?

以上でavrdudeのセットアップは終了です。

書き込み

準備ができたらいよいよ書き込みを行っていきます。
プログラムを書き込むマイコンはatmega328pを想定していますが、ISP(SPI programming protocol)が使用できるAVRマイコンならほとんど対応しています。

ヒューズビット

atmega328pには豊富な動作モードが用意されており、ヒューズビットと呼ばれている特殊な領域に設定値を書き込むことでsystem clockなどの変更が行えます。
avrdudeはヒューズビットの書き込みにも対応しているのですが、設定を間違えるとISPでの書き込みが行えなくなったりするので、今回は初期値のままにしておきます。

書き込み回路

ヒューズビットが初期値の場合、clock sourceは内部RC発振8Mhzで分周が8なので1Mhz動作です。これは3.3vの給電でも動作に十分な電力を確保できますし、外部クリスタルも必要ないので先ほどアサインした各ピンをatmega328pのreset,clk,mosi,misoに接続して電源を接続するだけで動作します。

rpi_avr_writer.png

コンデンサを持っていればVCCとGNDの間にパスコンを挿したほうがいいかもしれません。
以下のコマンドで正常に接続できているか確認します。

# avrdude -c linuxgpio -p m328p

問題なければデバイスシグネチャとヒューズビットの値が取得できます。

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e950f (probably m328p)

avrdude: safemode: Fuses OK (E:FF, H:D9, L:62)

avrdude done.  Thank you.

以下のようなメッセージがでるようなら配線に間違いがあります。
電源を切り、配線を確認しましょう。

avrdude: AVR device not responding
avrdude: initialization failed, rc=-1
         Double check connections and try again, or use -F to override
         this check.


avrdude done.  Thank you.

プログラムのビルド

ビルド作業とプログラムの詳説は省略します。
普通のLチカです。
Arduinoのプロジェクトをビルドするコマンドラインツールもあるようですが、私はavr-gccで直接コンパイルしています。

# apt install gcc-avr avr-libc
blink.c
#define F_CPU 1000000
#include <avr/io.h>
#include <util/delay.h>

int main(void) {
        DDRB  = DDRB  | 0b00001111;
        PORTB = PORTB | 0b00001111;

        while(1) {
                PORTB |= 0b00000001;
                _delay_ms(1000);
                PORTB &= 0b11111110;
                _delay_ms(1000);
        }
        return 0;
}
# avr-gcc -Os -mmcu=atmega328p blink.c -o blink.out
# avr-objcopy -F ihex blink.out blink.hex

以下のhexファイルができます。

blink.hex
:100000000C9434000C943E000C943E000C943E0082
:100010000C943E000C943E000C943E000C943E0068
:100020000C943E000C943E000C943E000C943E0058
:100030000C943E000C943E000C943E000C943E0048
:100040000C943E000C943E000C943E000C943E0038
:100050000C943E000C943E000C943E000C943E0028
:100060000C943E000C943E0011241FBECFEFD8E04C
:10007000DEBFCDBF0E9440000C945B000C940000DA
:1000800084B18F6084B985B18F6085B9289A2FE3D8
:100090008DE093E0215080409040E1F700C00000E7
:1000A00028982FE38DE093E0215080409040E1F7C5
:0A00B00000C00000EBCFF894FFCF72
:00000001FF

アップロード

先ほどのhexファイルをavrdudeでatmega328pにアップロードします。
avrdudeはUオプションの後にメモリタイプ、操作、ファイル、フォーマットを:で区切って指定します。
フォーマットは指定しなくても自動で判別できます。

# avrdude -c linuxgpio -p m328p -U flash:w:blink.hex:i

特にエラーとかが出なければ書き込みは成功です。
以下のようにPB0からledを接続するとおよそ1秒おきに点滅するはずです。

led4.png

以上でraspberry piからavrマイコンにファームをアップロードできるようになりました。
avr単体で使用する以外にもUSBのついてないarduino pro miniなどに書き込んだり、arduinoにブートローダーを書き込んだりも可能です。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした