873 Views
July 23, 22
スライド概要
MikanOSに搭載したUSB CDCドライバを用いて、自作CPUに機械語を送信する方法を説明します。
サイボウズ・ラボ株式会社で教育向けのOSやCPU、コンパイラなどの研究開発をしています。
MikanOSと自作CPUを USBで接続する 2022年7月23日 自作OSもくもく会 @uchan_nos 1 /15
もくじ ⚫発表のコンセプト: 自作CPUのアーキテクチャ、MikanOSとの接続部分、CDCドライ バの詳細を、ソフト・ハード両面から伝える ⚫自作CPUをMikanOSにつなげたい! ⚫自作CPUのアーキテクチャ ⚫自作CPUに機械語を送る ⚫USB CDCクラスドライバを作る ⚫CDC ACMのボーレート設定 ⚫今後MikanOSに搭載したい機能 2 /15
自作CPUをMikanOSにつなげたい! ⚫「自作CPU」 ◼ ComProc(Compiler+Processor自作)プロジェクトで 作ってるCPU ◼ 独自の命令体系、アーキテクチャを持つ ◼ UART(シリアル通信)にて機械語プログラムを受信し て実行できる ⚫MikanOS ◼ 「ゼロからのOS自作入門」で作るOS ◼ USBマウスとキーボードのドライバを搭載 ⚫USBシリアル変換で両者を接続できるのでは?! 3 /15
自作CPUのアーキテクチャ CPUコア insn[15:0] RX 演算用スタック (16ビット幅) UART 送受信 TX 0 1 機械語 書き込み ALU 15 メインメモリ (FPGA内蔵BRAM) 0x000 0x200 0x3ff コール スタック 機械語 プログラム … PC BP FP アドレス 読み出しデータ 書き込みデータ 4 /15
命令体系 C言語 アセンブラ 機械語 1+2; PUSH 1 PUSH 2 ADD 0001 0002 B002 演算用スタックの変化 x 1 2 3 x x 1 x x x x x x x x x PUSH 1 機械語パターン 命令 0iii iiii iiii iiii imm15のPUSH 1011 0000 iiii iiii 2項演算命令、imm8はALU機能選択 PUSH 2 ADD 5 /15
命令デコードと信号線 ニーモニック 機械語 PUSH imm15 ADD LD imm8 ST imm8 STA JMP imm8 xxxx B002 90xx 94xx 9500 A0xx 機械語上位8ビットのデコード後信号 1_10_00_01_00_0_00_00 0_10_00_10_00_0_00_00 1_11_10_01_00_0_00_00 1_01_01_10_00_0_00_00 0_00_01_10_00_0_00_00 1_00_00_00_01_0_00_00 addr addr data a a b b x Load=0 & Pop=1 Imm Load R W Pop Push Jmp 1=即値命令 0=stack[0] 1=stack[1]、 2=ALU出力 3=メモリ 1=メモリ読込 1=メモリ書込 1=演算用スタックからポップ 1=演算用スタックにプッシュ 0=ジャンプしない、1=無条件 6 /15
自作CPUに機械語を送る ⚫自作CPUはUARTで機械語を受け取る パソコン USBホスト ⚫自分のパソコンにはシリアル端子が無い ⚫→USBシリアル変換をかませよう ⚫MikanOSにはUSBバスドライバが搭載済み USBシリアル 変換機器 ⚫USBシリアル変換機器用のCDC ACMクラスドラ イバを作ればOK クラスドライバ 自作CPU UART端末 USBバスドライバ xHCIドライバ PCIバスドライバ 機器固有の処理を担当 USB仕様に則ったAPIを上位側に提供 ホストコントローラの初期化や駆動 PCIバスの制御を担当 7 /15
接続対象のUSBシリアル変換機器 ⚫AE-PIC18F14K50 ⚫USB機能が搭載されたPICマイコンボード ⚫ここにUSBシリアル変換プログラムを書き 込んで使う ⚫TX端子電圧=5V 5V Start 0xA2 Stop 0V ⚫FT231XS搭載USBシリアル変換アダプタ ⚫USBシリアル変換の専用機器 ⚫TX端子電圧=3.3V 3.3V Start 0xA2 Stop 0V 8 /15
ちょっと脱線:レベル変換 ⚫AE-PIC18F14K50のTX端子電圧=5V ⚫Tang Nano 9KのIO端子(Bank 1,2)の入力 電圧範囲は-0.3V~3.6V ⚫直接繋ぐとTang Nano 9Kが壊れる ⚫→レベル変換回路を間に挟む TX端子の出力電圧=5V RX端子の許容電圧=3.6V 自作CPU UART端末 AE-PIC18F14K50 Nch MOSFETを用いた 双方向レベル変換回路 9 /15
USB CDCクラスドライバを作る ⚫CDC: Communication Device Class ◼ 電話回線やイーサネットなどでの通信を行うデバイ クラスドライバ USBバスドライバ スを包括するクラス xHCIドライバ ⚫ACM: Abstract Control Model subclass PCIバスドライバ ◼ ATコマンド(電話をかけたり切ったりするコマン ド)で制御できる機器 Communication Class interface: 機器の管理と発信(call)の管理 Endpoint 0 USB ホスト Endpoint x USB デバイス Endpoint y Data Class interface: データの送受信 10 /15
CDCドライバの実装(簡易版)
Error CDCDriver::SendSerial(const void* buf, int len) {
uint8_t* buf_out = new uint8_t[len];
memcpy(buf_out, buf, len);
ParentDevice()->NormalOut(ep_bulk_out_, buf_out, len);
uint8_t* buf_in = new uint8_t[8];
ParentDevice()->NormalIn(ep_bulk_in_, buf_in, 8);
return MAKE_ERROR(Error::kSuccess);
}
int CDCDriver::ReceiveSerial(void* buf, int len) {
const auto recv_len =
std::min(len, static_cast<int>(receive_buf_.size()));
auto buf8 = reinterpret_cast<uint8_t*>(buf);
for (int i = 0; i < recv_len; ++i) {
buf8[i] = receive_buf_.front();
receive_buf_.pop_front();
}
return recv_len;
}
Out方向のエンドポイント
でデータを送信する
In方向のエンドポイント
に対し受信をかけておく
デバイスからデータが
受信されていれば
receive_buf_に
データが書かれている
11 /15
クラスドライバの動作の様子 QEMU on WSL2 でMikanOSを起動 QEMUにCDC ACM 機器を接続してある ⚫2つのインターフェースが認識されている ◼ Communication/Data Class interface ⚫Data Class interface用に2つのエンドポイント ◼ ep_idの最下位ビットは入出力の向きを表す ◼ 0がOut(Host→Device)、1がIn(Device→Host) 12 /15
CDC ACMのボーレート設定 ⚫自作CPUは機械語プログラムを115.2kbpsで受信する ⚫Linuxが勝手にCDC ACM機器を9600bpsに設定してしまう ◼ QEMU起動前に sudo stty -F /dev/ttyACM0 115200 すれば解決 ⚫CDC ACM機器のボーレートを変更するのはSetLineCoding要求 LineCoding構造体 オフセット フィールド バイト数 説明 0 dwDTERate 4 ボーレート 4 bCharFormat 1 ストップビット数 0→1 bit, 1→1.5 bits, 2→2 bits 5 bParityType 1 パリティ設定 0→None, 1→Odd, 2→Even 6 bDataBits 1 データ幅 5, 6, 7, 8, 16 13 /15
setbaudコマンド ボーレートをsetbaud (動画中撮影時はsetcdc) によって設定してから comprocコマンドで 機械語を送信し、 結果を受け取っている 14 /15
今後MikanOSに搭載したい機能 ⚫hex2bin: 16進数テキストをバイナリデータに変換するコマンド ◼ ハンドアセンブルでの実験用 ⚫ucc, uasm: ComProc用コンパイラ、アセンブラ ◼ echo/catと組み合わせて自作CPUのプログラミングが可能 ⚫FTDIドライバ ◼ 市販のUSBシリアル変換はFTDIチップを使っていることが多い ◼ FTDIはCDC ACM仕様ではない、独自仕様 ⚫複数のUSBシリアル変換機器の識別と選択機能 ◼ 現状、1つのデバイスしか使えない 15 /15