Lisp Meet Up #25, 8-bit PIC マイコン用ネイティブコンパイラの作成
-
Upload
masayukitakagi -
Category
Technology
-
view
898 -
download
1
Transcript of Lisp Meet Up #25, 8-bit PIC マイコン用ネイティブコンパイラの作成
8-bit PIC マイコン用ネイティブコンパイラの作成
2015.2.25 Masayuki Takagi
Lisp Meet Up presented by Shibuya.lisp #25
© 2015 Masayuki Takagi-2-
自己紹介
高木 雅之
cl-cuda : a library to use NVIDIA CUDA in Common LispCommon Lisp から CUDA を使うライブラリ。半年ほどまえに、ここで紹介しました。
仕事は?先月に会社を設立。売上はまだないです >_<
Common Lisp
© 2015 Masayuki Takagi-3-
8-bit PICマイコン向けネイティブコンパイラ:動機
これまで、まともにアセンブラを書いたことがなかったのです。
1月下旬:はじめての PIC マイコン
2月上旬:はじめてのアセンブラ
PIC マイコンをはじめて触りました。
PIC で何作ろう?PIC用のコンパイラ作ろう。
2月中旬:PIC 用のコンパイラ
© 2015 Masayuki Takagi-4-
今日の話の流れ
そのあと、今回作った、PIC マイコン用のコンパイラについて説明します。
PIC マイコンについて
PIC マイコン用コンパイラについて
最初に、PIC マイコン自体について説明します。
© 2015 Masayuki Takagi-5-
PIC マイコンとは?
いまだと Arduino とかありますが、PIC はそれより昔からよく使われています。
マイクロコントローラ
マイクロチップ・テクノロジー社
演算器、メモリ、発振回路、割り込み、タイマ、リセット、スリープなど各種回路が1チップに。
今回使ったのは、一番小さな 8 ビット PIC。PIC12F683 や PIC16F630。
8ビット、16ビット、32ビット
© 2015 Masayuki Takagi-6-
ピン
PIC12F683(8ピン) PIC16F630(14ピン)
VDD
上2本(VDD, VSS)を電源に接続
残り6本を IO に使用可能(HI/LOW)
ただし、4番ピンは入力のみ
GP5
GP4
GP3
VSS
GP0
GP1
GP2
VDD VSS
RA5RA4RA3RC5RC4RC3
RA0RA1RA2RC0RC1RC2
上2本(VDD, VSS)を電源に接続
残り12本を IO に使用可能(HI/LOW)
ただし、4番ピンは入力のみ
© 2015 Masayuki Takagi-7-
PIC12F683
プログラムメモリは、2K ワード
SRAM は、128 バイト
DDPROM は、256 バイト
© 2015 Masayuki Takagi-8-
PIC12F683 デバイス概観
ALU
乗算器、FPU、16ビット演算器はない
プログラムメモリとデータメモリ
ハードウェアスタック
© 2015 Masayuki Takagi-9-
メモリアーキテクチャ
プログラムメモリとデータメモリが分離(ハーバード・アークテクチャ)
プログラムメモリには、専用の機器でプログラムを書き込む
プログラムからプログラムメモリを操作することはできない
データメモリプログラムメモリ
© 2015 Masayuki Takagi-10-
プログラムメモリ
プログラムメモリは 2048 ワード(000h-07FFh)
プログラムは 0 番地から始まる
4 番地は割り込み発生時にここにジャンプ
ハードウェアスタックを持つ
CALL 命令などで、戻り値アドレスが積まれる
© 2015 Masayuki Takagi-11-
データメモリ
データメモリは、SFR と GPR からなる
SFR は、Special Function Registers
GPR は、General Purpose Registers
SFR は、CPU やその他機能の制御に使う
残念なことに、番地により「バンク」を切り替えなければならない
SFR
汎用レジスタ
SFR
汎用レジスタ
バンク0 バンク1
00h
20h
80h
A0h
BFh
7Fh
© 2015 Masayuki Takagi-12-
スペシャル・ファンクション・レジスタ
SFR は、CPU やその他機能の制御に使う
STATUS は、バンク切替(RP0)、ゼロビット(Z)、キャリービット(DC,C)など
GPIOは、ピンの状態(High/Low)
TRISIOは、ピンの入出力モード
PCL と PCLATH は、プログラムカウンタ
INTCON と IOC は、割り込みの有効/無効
© 2015 Masayuki Takagi-13-
W レジスタ
ALU は、W レジスタとデータメモリから入力を受け付ける
通常の CPU の「レジスタ」に相当
ただし、1つしかない
W レジスタ レジスタ
データメモリ メモリ
EEPROM ストレージ
PIC マイコン 通常のCPU
記憶装置の対応
© 2015 Masayuki Takagi-14-
内蔵発振回路
発振回路を内蔵
デフォルトの周波数は、4MHz ±1%
1命令サイクル = 4クロック = 1μsec
© 2015 Masayuki Takagi-15-
命令セット
ADDWF ANDWF CLRF CLRW COMF DECF
DECFSZ INCF INCFSZ IORWF MOVF MOVWF
NOP RLF RRF SUBWF SWAPF XORWF
BCF BSF BTFSC BTFSS ADDLW ANDLW
CALL CLRWDT GOTO IORLW MOVLW RETFIE
RETLW RETURN SLEEP SUBLW XORLW
命令は35種類のみ。非常に簡単
要する命令サイクルは、1サイクル(=1μsec@4MHz)
ただし、CALLや条件分岐などは、2サイクル
© 2015 Masayuki Takagi-16-
ちょっと面倒
何をするにも、単一の W レジスタを要するので、ちょっと面倒
データのムーブ(R0番地からR1番地へデータをコピー)
MOVF R0,W
MOVWF R1
END
整数の加算(R0番地に 42 を加算)
MOVLW 42
ADDWF R0,F
END
© 2015 Masayuki Takagi-17-
コンパイラの概要
ホスト言語は、ML 系言語の本当に小さなサブセット
ターゲット言語は、8-bit PIC マイコンのアセンブリ
コンパイラ言語は、Common Lisp
コンパイラの設計は、MinCaml を参考にした(MinCaml ですみません…)
© 2015 Masayuki Takagi-18-
MinCaml とは?
http://esumii.github.io/min-caml/
© 2015 Masayuki Takagi-19-
構文
今回のコンパイラ MinCaml
定数
プリミティブ演算(+,-,*,/ など)
条件分岐 if e1 then e2 else e3
変数定義 let
変数の読み出し x
再帰関数定義 let rec
関数呼び出し e e1, …, en
組の作成 (e1, …, en)
配列の作成 Array.create e1 e2
組の読み出し let
配列の読み出し e1.(e2)
配列への書き込み e1.(e2) ← e3
定数
プリミティブ演算
条件分岐
変数定義
変数の読み出し
再帰関数定義(クロージャ不採用)
関数呼び出し
組は不採用
配列は不採用
SFRへの書き込み setreg
© 2015 Masayuki Takagi-20-
コンパイルステージ
今回のコンパイラ MinCaml
字句解析
構文解析
型推論
K正規化
α変換
β簡約
ネストした let の簡約
インライン展開
不要定義削除
定数畳み込み
クロージャ変換
仮想マシンコード生成
即値最適化
レジスタ割当て
アセンブリ生成
(CommonLisp のリーダを使用)
(型は 8 ビット整数のみ)
K正規化
α変換
β簡約
ネストした let の簡約
(最適化はあとで)
クロージャ変換
仮想マシンコード生成
レジスタ割当て
アセンブリ生成
(最適化はあとで)
© 2015 Masayuki Takagi-21-
呼び出し規約
当初、ソフトウェアスタックに積んで渡していた
間接アドレッシングが煩雑なため、方針変更
入力用疑似レジスタ(I0-I7)、ローカル用疑似レジスタ(L0-L7)
引数は、入力用レジスタに格納して、呼び出される関数に渡す
関数は、ローカル用レジスタを自由に使える
戻り値は、W レジスタに格納して返す
関数呼び出し時に、「生きているレジスタ」をスタックに退避する
© 2015 Masayuki Takagi-22-
クロージャを不採用とした理由
クロージャには、間接アドレスへのジャンプが必要
CALL 命令は、オペランドに即値のみ受け付ける
間接アドレスへのジャンプは、プログラムカウンタへの書き込みで可能
しかし、いろいろ面倒
PCL と PCLATH
戻りアドレスの計算
戻りアドレスの管理(ハードウェアスタックを使えない)
PCL の桁上がりの考慮
© 2015 Masayuki Takagi-23-
API
defpic
defpicmacro
pic-compile
pic-disassemble
© 2015 Masayuki Takagi-24-
サンプル - LED
(defpic init ()
(progn
(setreg :gpio #x0)
(setreg :cmcon0 #b00000111)
(setbank1)
(setreg :trisio #b00001000)
(setreg :ansel #x0)
(setreg :ioc #x0)
(setbank0)
(setreg :intcon #b00000000)))
(defpic main ()
(progn
(setreg :gpio #b00100000)
(mdelay 50)
(setreg :gpio #b00000000)
(mdelay 950)
(main)))
(defpic mdelay1 ()
(loop 52
0))
(defpicmacro mdelay (n)
(unless (<= 0 n 65535)
(error "The value ~S is invalid." n))
(multiple-value-bind (q r) (truncate n 256)
(if (= q 0)
`(loop ,r (mdelay1))
`(loop ,q (loop ,r (mdelay1))))))