Tosainu Lab

Linux環境でAssemblyLangプログラミングしたメモ

どもどもー

ここ3日、ずっとAVRマイコンをAssemblyでプログラミングしていました。(きっと)

何となくわかってきたのでとりあえずメモ。

 

 

使用しているマイコンと回路図

調べてみたところ、Arduinoに任意のHEXが書き込めるようだったので、書き込み器付きマイコンボードとしてArduino Unoを使いました。

プログラマを持っていなかったので助かりました・・・

ちなみに載っているマイコンはATmega328Pです。

 

図のようにパーツを接続しました。

 

追加するパッケージ

avra

AVRマイコン(等)のアセンブラです。これを使って書いたコードをビルドします。

 

avrdude

AVRマイコンのプログラマソフトです。これでビルドしたプログラムの書き込みを行います。

 

2013/10/6 (Sun) 21:42:56追記

また、各マイコンのIncludeFileをこのサイトからダウンロードし、使うマイコンのファイルをソースと同じフォルダに配置します。

 

プログラム

この3日で書いていたプログラムを2つ上げておきます。

1.PB0に接続されたスイッチを押す(内部プルアップなので入力はLOW)とLEDが消える、離すと(入力はHIGH)再び点灯

.include "m328pdef.inc"

; Interrupt Vectors
.ORG    0x0000
  RJMP  RESET

; Reset Pin and Timer
RESET:
  CLI                         ; Disable All Interruputs
  ; Port Config
  LDI   R25,    0b11111110    ; PB0 is Input, Others are Output
  OUT   DDRB,   R25
  LDI   R25,    0b00000001    ; Output HIGH to PORTB
  OUT   PORTB,  R25
  RJMP  MAIN

; Main Loop
MAIN:
  SBIS  PINB,   0             ; If PB0 is Low,
  RJMP  RESET                 ; LED Turn Off
  LDI   R25,    0xFF          ; Else, Led Turn On
  OUT   PORTB,  R25
  RJMP  MAIN

 

2.LED点滅(タイマ1使用)

.include "m328pdef.inc"

; Named General Purpose Register
.DEF    TMP1  = R25
.DEF    TMP2  = R24
.DEF    STACK = R23

; Interrupt Vectors
.ORG    0x0000                ; RESET
  RJMP  RESET
.ORG    0x001A                ; TIMER1 OVF
  RJMP  INT

; Interrupt Routine
INT:
  IN    STACK,  SREG          ; Backup Status Register
  LDI   TMP1,   0x00          ; Stop Timer1
  STS   TCCR1B, TMP1

  IN    TMP1,   PORTB         ; Invert the Value of PORTB
  LDI   TMP2,   0b11111110
  EOR   TMP1,   TMP2
  OUT   PORTB,  TMP1

  LDI   TMP1,   0x0000        ; Set Timer1 Counter and Restart
  STS   TCCR1A, TMP1
  LDI   TMP1,   0x05
  STS   TCCR1B, TMP1
  LDI   TMP1,   0xC2
  STS   TCNT1H, TMP1
  LDI   TMP1,   0xF7
  STS   TCNT1L, TMP1
  OUT   SREG,   STACK         ; Restore Status Register
  RETI                        ; Interrupt End

; Reset Pin and Timer
RESET:
  CLI                         ; Disable All Interruputs

  ; Port Config
  LDI   TMP1,   0b11111110    ; PB0 is Input, Others are Output
  OUT   DDRB,   TMP1
  LDI   TMP2,   0xFF          ; Output HIGH to PORTB
  OUT   PORTB,  TMP2

  ; Timer1 Config
  LDI   TMP1,   0x00          ; Nomal Mode
  STS   TCCR1A, TMP1
  LDI   TMP1,   0x05          ; Prescaler:1024
  STS   TCCR1B, TMP1
  LDI   TMP1,   0xC2          ; Interrupt Time:1sec
  STS   TCNT1H, TMP1
  LDI   TMP1,   0xF7
  STS   TCNT1L, TMP1
  LDS   TMP1,   TIMSK1        ; Enable Timer1 Overflow Interrupt
  SBR   TMP1,   (1<<TOIE1)
  STS   TIMSK1, TMP1
  SEI                         ; Enable All Interruputs
  RJMP  MAIN

; Main Loop
MAIN:
  RJMP  MAIN

 

ビルド及び書き込み

// ビルド
$ avra FileName.asm
// ArduinoにHEXを書き込み(Arduinoの接続先が/dev/ttyACM0とする)
$ avrdude -c arduino -P /dev/ttyACM0 -p m328p -b 115200 -u -e -U flash:w:"FileName.hex":a

これで書き込めます。

 

実際にLED点滅プログラムを動かしてみたところです。(何気にFullHD)

 

Arch LinuxでArduinoが認識されない時

僕の環境でもそうでしたが、一般ユーザーで/dev/ttyACM0にアクセスができませんでした。

しかし、次の方法で解決出来ました。

$ sudo gpasswd -a YourUserName uucp
$ sudo stty -F /dev/ttyACM0 cs8 9600 ignbrk -brkint -imaxbel -opost -onlcr -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke noflsh -ixon -crtscts
$ sudo chown root:wheel /run/lock
$ sudo chmod 775 /run/lock

参考

Arduino - ArchWiki

Greyed Serial Port Menu in Arduino IDE on Arch Linux | Stray Bytes

 

いやぁ〜、AVR-Assemblyヤバイです。

わかりやすいし美しい。PICとかいうクソマイコンとは大違いです。

 

これから書く予定のステッピングモータ制御プログラム、全部Assemblyで書こうかな・・・

 

ではでは〜