LoginSignup
1
0

More than 1 year has passed since last update.

ORANGE-4のI/Oの仕様を調査してみた (暴走もあるよ)

Posted at

ORANGE-4には、3本のI/Oピンを制御できる命令がある。
今回は、これらのI/Oについて挙動を調べてみた。
今回対象とするファームウェアのバージョンは1.09である。

免責

今回は、仕様に無い挙動や、仕様に反する使い方を扱う。
そのため、ファームウェアのバージョンやそれまでの操作、個体差、環境などによって挙動が変わる可能性が考えられる。
この記事の内容を参考にした、または参考にしなかった結果生じた一切の損害について、筆者は責任を負わない。

I/Oの仕様

ORANGE-4には、PORT1、PORT2、PORT3の3本のI/Oピンがある。
また、これらの操作用の以下の命令がある。
(マニュアル「必ずわかるORANGE-4機械語プログラミング」(2020/3/23版) に基づく)

機械語 ニモニック 動作 (仕様)
F70 ioctrl Aレジスタの値により、Yレジスタで指定したポートの設定を行う。
A=0 : デジタル出力
A=2 : デジタル入力
F71 out Yレジスタで指定したポートに、Aレジスタの値(0または1)を出力する。
ポートはioctrl命令でデジタル出力の設定をしておく必要がある。
F72 in Aレジスタに、Yレジスタで指定したポートの状態を読み込む。
ポートはioctrl命令でデジタル入力の設定をしておく必要がある。

調査方法

ソフトウェア

パラメータをキーを用いて自由に指定してioctrl命令、out命令、in命令を実行できる以下のプログラムを用意した。

以下のプログラムは、MikeAssemblerでアセンブルできる。
また、先頭のtarget orange4を取ればORANGE-4 IDEでもアセンブルできる。

target orange4

	; 操作方法
	; 1. コマンドを選択する (状態を2進LEDに表示する)
	;    0 : ioctrl
	;    1 : out
	;    2 : in
	;    その他 : 無効 (無視)
	; 2. ポートを選択する (0-f)
	; 3. パラメータを選択する (0-f) (ioctrl, out のとき)
	;    読み込んだ値を7セグメントLEDに表示する (in のとき)

	org 0x00

	ay
	scall 0
	ldi 0
	ldyi 0xE
	st
	ldyi 0xF
	st
main_loop:
	; 2進LEDを消灯する
	scall 0xD
	; モード選択
	call key_input
	cpi 0
	jmpf not_ioctrl
	; 0 : ioctrl
	ldyi 0
	scall 1
	; ポートを選択する
	call key_input
	outn
	ldyi 6
	scall 1
	; パラメータを選択する
	ay
	call key_input
	; コマンドを実行する
	ioctrl
	scall 0
	jmpf main_loop

	org 0x80

not_ioctrl:
	cpi 1
	jmpf not_out
	; 1 : out
	ldyi 1
	scall 1
	; ポートを選択する
	call key_input
	outn
	ldyi 6
	scall 1
	; パラメータを選択する
	ay
	call key_input
	; コマンドを実行する
	out
	scall 0
	jmpf main_loop
not_out:
	cpi 2
	jmpf main_loop
	; 2 : in
	ldyi 2
	scall 1
	; ポートを選択する
	call key_input
	outn
	ldyi 6
	scall 1
	; コマンドを実行する
	ay
	in
	outn
	jmpf main_loop

key_input:
	ink
	jmpf key_input
	; キー入力後、チャタリング対策で待つ
	abyz
	ldi 0
	scall 0xC
	abyz
key_release_wait:
	ink
	jmpf key_released
	jmpf key_release_wait
key_released:
	; キー入力後、チャタリング対策で待つ
	abyz
	ldi 0
	scall 0xC
	abyz
	ret

このプログラムの機械語のORANGE-4のモニター向け表現は、以下のようになった。

E00:3E080AE4AF4EDF60
E10:BCC0F80A0E1F60BC
E20:1A6E13F60BCF70E0
E30:F0B
E80:C1FA1A1E1F60BC1A
E90:6E13F60BCF71E0F0
EA0:BC2F0BA2E1F60BC1
EB0:A6E13F721F0B0FBC
EC0:280EC20FCDFC6280
ED0:EC2F61

ハードウェア

調査対象のポートから、GNDとVDDそれぞれに20kΩ(公称値)の抵抗を接続し、GNDからポートの電圧を測定する。

ポート状態確認用ハードウェア

測定される電圧から、ポートの状態を以下のように判定する。

電圧 状態
3.3V付近 HIGHを出力
1.65V付近より高く、3.3V付近より低い プルアップ
1.65V付近 ハイインピーダンス
0V付近より高く、1.65V付近より低い プルダウン
0V付近 LOWを出力

調査

リセット時の状態

電源投入直後は、3ポートとも「LOWを出力」となっていた。
プログラムを実行してポートの状態を変更した後、RSTボタンによりプログラムの実行を止めた時は、ポートの状態は維持された。
RESETボタンによるリセットを行うと、ポートの状態は「LOWを出力」に戻った。

ポートの選択

ioctrl命令では、Yレジスタの値によって以下のポートの状態が変わった。

Yレジスタの値 状態が変わったポート
1 PORT1
2 PORT2
3 PORT3
0,4,5,6,7,8,9,A,B,C,D,E,F なし

out命令では、Yレジスタの値によって以下のポートの状態が変わった。

Yレジスタの値 状態が変わったポート
1 PORT1
2 PORT2
3 PORT3
0,4,5,6,7,8,9,A,B,C,D,E,F なし

in命令においては、PORT1、PORT2、PORT3全てにHIGHを入力した状態で実行した結果、
Yレジスタが1,2,3の時はAレジスタの値が1となり、それ以外の時はAレジスタの値が0となった。
よって、ioctrl命令やout命令と同様に、Yレジスタの値1,2,3がそれぞれPORT1,PORT2,PORT3に対応すると推測できる。

ポートの設定

リセット後、PORT1について、ioctrl命令によるポートの設定を行った。
Aレジスタの値として0~Fを昇順に試した結果、命令実行後のポートの状態は以下のようになった。

Aレジスタの値 ポートの状態
0,1,F LOWを出力
2,3,4,5,6,7,8,9,A,B,C,D,E ハイインピーダンス

また、リセット後、Aレジスタの値として3~Fを昇順に試した結果、ポートの状態は「LOWを出力」のまま変わらなかった。
さらに、リセット後、PORT1をデジタル入力に設定(Aレジスタの値=2)した後、Aレジスタの値として1を用いると、ポートの状態は「ハイインピーダンス」のまま変わらなかった。
したがって、Aレジスタの値が0,2,F以外の場合、ポートの状態は変わらないと推測できる。

仕様にあるAレジスタの値0,2でポートの設定を行った場合、その後もioctrl命令でポートの設定を変更したり、out命令でポートの出力を設定したりできる。
一方、Aレジスタの値Fでポートの設定を行った場合、ioctrl命令やout命令を用いても反応せず、ポートの状態は「LOWを出力」のままとなった。
一旦RSTボタンでプログラムの実行を止めて再実行しても、反応は復活しなかった。
この設定を行う前のポートの状態が「デジタル入力」「デジタル出力、0を出力」「デジタル出力、1を出力」のどれであっても、この現象が見られた。
また、あるポートがこの設定により反応しなくなっても、他のポートはこの設定をしない限り反応は維持されるようだった。

したがって、ioctrl命令実行時のAレジスタの値とポートの設定は以下のようになっていると考えられる。

Aレジスタの値 ポートの設定
0 デジタル出力
2 デジタル入力 (ハイインピーダンス)
F ポートを無効化し、LOWを出力するように固定
その他 変更なし

ポートへの出力

ioctrl命令でPORT1をデジタル出力に設定した後、Aレジスタの値として0~Fを昇順に用い、out命令をPORT1について実行したところ、ポートの状態は以下のようになった。

Aレジスタの値 ポートの状態
0 LOWを出力
1~F HIGHを出力

さらに、Aレジスタの値0でout命令を実行した後、Aレジスタの値2~Fそれぞれについてout命令を実行 (それぞれの実行の前にAレジスタの値0でout命令を実行) すると、全てポートの状態は「HIGHを出力」となった。

したがって、ポートがデジタル出力に設定されている場合、out命令におけるAレジスタの値とポートの状態の関係は以下のようになっていると考えられる。

Aレジスタの値 ポートの状態
0 LOWを出力
1~F HIGHを出力

ioctrl命令でPORT1をデジタル入力に設定した後、Aレジスタの値として0~Fを昇順に用い、out命令をPORT1について実行したところ、ポートの状態は全て「ハイインピーダンス」のまま変わらなかった。

さらに、PORT1について以下のような操作を行うと、PORT1の状態は以下のようになった。

操作 操作の詳細 ポートの状態
プログラムの実行を開始 - LOWを出力
デジタル出力に設定 ioctrl, A=0 LOWを出力
0を出力 out, A=0 LOWを出力
デジタル入力に設定 ioctrl, A=2 ハイインピーダンス
1を出力 out, A=1 ハイインピーダンス
デジタル出力に設定 ioctrl, A=0 HIGHを出力
デジタル入力に設定 ioctrl, A=2 ハイインピーダンス
0を出力 out, A=0 ハイインピーダンス
デジタル出力に設定 ioctrl, A=0 LOWを出力

よって、デジタル入力に設定してある状態でのout命令による操作も保存され、デジタル出力に設定した際に反映されるようである。
さらに、デジタル出力に設定した状態で、さらにAレジスタの値0でioctrl命令を実行(デジタル出力に設定)しても、ポートの状態は変わらない(HIGHの出力も維持される)ようだった。

ポートからの入力

「ポートの選択」での実験結果より、PORT1、PORT2、PORT3をデジタル入力に設定した状態では、HIGHはAレジスタの値1として読み込まれ、無効なポートはAレジスタの値0として読み込まれることがわかっている。

また、PORT1で実験をすると、LOWはレジスタの値0として読み込まれることがわかった。

ポートをデジタル出力に設定した場合、1を出力している状態ではAレジスタの値1、0を出力している状態ではAレジスタの値0が読み込まれた。
Aレジスタの値2でout命令を実行した後でも、Aレジスタの値1が読み込まれた。
ポートを無効化(Aレジスタの値Fでioctrl命令を実行)した場合も、Aレジスタの値0が読み込まれた。

よって、in命令はポートの設定によらず、HIGHをAレジスタの値1、LOWをAレジスタの値0として読み込むようであることがわかった。

結論

ORANGE-4 (ファームウェアのバージョンは1.09) は、I/O関係について以下のような挙動をするらしいことがわかった。

ポートの選択 (共通)

Yレジスタの値 ポート
1 PORT1
2 PORT2
3 PORT3
その他 無効

ioctrl命令

ioctrl命令は、選択したポートの状態をAレジスタの値によって以下のように設定する。

Aレジスタの値 ポートの設定
0 デジタル出力
2 デジタル入力
F LOWの出力に固定し、以降のioctrl命令やout命令を無視
その他 変化なし

リセット(電源投入・RESETボタン)時は、デジタル出力に設定したような状態になっている。
RSTボタンによりプログラムの実行を止めても、状態の設定は維持される。

デジタル入力は、ハイインピーダンスのみ(プルアップ・プルダウンなし)のようである。

out命令

out命令は、選択したポートの出力をAレジスタの値によって以下のように設定する。

Aレジスタの値 出力
0 LOW
非0 HIGH

出力の設定はポートがデジタル入力に設定されている時でも有効であり、設定後ポートをデジタル出力に設定すると設定した値が出力される。

in命令

in命令は、選択したポートの状態を以下のようにAレジスタの値に反映する。

ポートの状態 Aレジスタの値
LOW 0
HIGH 1

この関係は、ポートがデジタル出力に設定されている場合でも同様である。(出力している値が読み込まれる)
無効なポートを選択した場合は、Aレジスタの値は0となる。

ポートの物理仕様

ORANGE-4のサイトに載っている回路図より、ポートとマイコンのピンの対応は以下のようになっている。

ポート ピン番号 ピン名
PORT1 10 OSC2
PORT2 14 RB5
PORT3 7 RB3

使われているマイコン PIC32MX120F032B のデータシートを参照すると、この中で5VトレラントになっているのはPORT2 (RB5) だけであることがわかる。

ORANGE-4の暴走再び

今回のプログラムによる検証中も、前回のXorshiftのプログラムの実行時に見られた暴走現象が度々発生した。

今回の暴走はキー入力時に発生することがあり、発生すると以下の症状が見られた。

  • キー操作を受け付けない (数字キーだけでなく、RSTキーも)
  • 2進LEDが通常より明るく点灯する
  • 押したキーによって2進LEDが点灯することがある (例えば、Cキーを押すとLED3が点灯する)

検証のためにプログラムを削っていったところ、以下のプログラムを実行し、RSTキーで実行を止めると、別の不都合が発生することがわかった。
(「発生することがある」ではなく、100%に近い確率で発生するようである)

target orange4

	; ORANGE-4 Ver 1.09 暴走テスト
	; 1. このプログラムをアセンブルし、モニターから入力する
	; 2. モニターを終了する (qコマンド)
	; 3. 1→RUNで実行する
	; 4. RSTで止める
	; 5. ビープ音が繰り返し鳴り、キー入力を受け付けなくなる

	; ※モニターを終了せずにgコマンドで実行した場合、RSTを押しても不都合は起きない
	; ※モニターを経由せず、キーでプログラムを打ち込んで実行しても不都合が起きる

	org 0x00

	ay
	scall 0
main_loop:
	; 2進LEDを消灯する
	ldi 0
	ldyi 0xE
	st
	ldyi 0xF
	st
	scall 0xD
	; モード選択
	ldi 1
	cpi 1
	jmpf main_loop
	; 1 : out
	ldyi 0
	scall 1
	; ポートを選択する
	ldi 1
	outn
	ldyi 1
	scall 1
	; コマンドを実行する
	scall 0
	jmpf main_loop
E00:3E080AE4AF4ED81C
E10:1F03A0E1811A1E1E
E20:0F03

このプログラムを実行し、RSTキーで実行を止めると、以下の現象が発生した。

  • 約134BPMで「ピッ」という短い音が鳴り続ける
  • キー操作を受け付けなくなる
  • 前述の暴走とは異なり、キーを押しても2進LEDは点灯しない

このような暴走現象が発生する詳しい条件は、まだよくわかっていない。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0