pico6502 テクニカルガイド
注記: pico6502 プロジェクトは初期開発段階にあります。ハードウェア、PIO バスインターフェース、メモリモデル、ビルドシステムは完全に実装されて動作しています。マシンペルソナドライバーは初期段階にあります。このガイドは現時点のテクニカルアーキテクチャを説明します。
概要
pico6502 のテクニカルアーキテクチャは、CPU バスインターフェースを除くすべての点で picoZ80 と同一です。同じ RP2350B デュアルコアプロセッサー、PSRAM メモリモデル、フラッシュレイアウト、ESP32 コプロセッサー、ドライバーフレームワークを両製品で共有しています。このガイドは 6502 固有の違いに焦点を当て、完全に共通するトピックについては picoZ80 テクニカルガイドを参照します。
ハードウェアアーキテクチャ
ブロック図
┌─────────────────────────────────────────────────────────────────────────┐ │ pico6502 Board (v2.2) │ │ │ │ ┌───────────────┐ PIO 0: A0–A15, D0–D7 ┌───────────────────┐ │ │ │ │◄──────────────────────────►│ DIP-40 Interface │ │ │ │ RP2350B │ PIO 1: cycle/ctrl/irq │ (6502 socket) │ │ │ │ (300 MHz) │◄──────────────────────────►│ A0–A15, D0–D7 │ │ │ │ │ PIO 2: PHI1/PHI2 clock ──►│ PHI0/RNW/SYNC │ │ │ │ Core 0 │ │ IRQ/NMI/RDY/SO │ │ │ │ (USB/IO/ESP) │ └───────────────────┘ │ │ │ │◄──QSPI──►[ 8MB PSRAM ] │ │ │ Core 1 │◄──SPI───►[ 16MB Flash ] │ │ │ (6502 loop) │ │ │ │ │◄──FSPI──►┌───────────┐ │ │ │ │◄──UART──►│ ESP32 │◄──SPI──►[ SD Card ] │ │ └───────────────┘ │ (WiFi) │──────────[ Web Server ] │ │ └───────────┘ │ │ [ USB Hub ]──USB──►[ RP2350 USB Bridge ] │ └─────────────────────────────────────────────────────────────────────────┘
主要コンポーネント
| コンポーネント | 部品 | 仕様 |
|---|---|---|
| メインプロセッサー | RP2350B | デュアル Cortex-M33、最大 300 MHz、512KB SRAM、48 GPIO |
| PSRAM | SPI PSRAM | 8MB、QSPI インターフェース、最大 133 MHz |
| フラッシュ | SPI NOR Flash | 16MB、XIP(実行時実行) |
| コプロセッサー | ESP32-S3 | WiFi、SD カード、ウェブサーバー、RP2350 への 460.8kbaud UART |
| SD カード | FAT32 | ROM イメージ、ディスクイメージ、config.json、ウェブファイル |
| バスインターフェース | 抵抗ネットワーク | 5V ↔ 3.3V レベル変換用直列抵抗 |
| 電源 | TLV62590BV | 同期バック、5V(VCC ピン)→ 3.3V、全基板電源 |
| USB | オンボードハブ | ファームウェア書き込み用 RP2350 USB マスストレージブリッジ |
GPIO 割り当て
以下の GPIO 割り当ては pico6502 v2.2 基板の典型的なレイアウトを示しています。KiCad 回路図(
kicad/PICO6502/PICO6502_Schematic.pdf)が権威ある情報源です。
| GPIO | 信号 | 方向 | 備考 |
|---|---|---|---|
| 0–15 | A0–A15 | 出力 | 6502 アドレスバス — PIO 0 m6502_addr が駆動 |
| 16–23 | D0–D7 | 双方向 | 6502 データバス — PIO 0 m6502_data が駆動/サンプリング |
| 24 | PHI0 | 入力 | PIO 2 への外部クロック入力 |
| 25 | PHI1 | 出力 | フェーズ 1 クロック出力 — PIO 2 が生成 |
| 26 | PHI2 | 出力 | フェーズ 2 クロック出力 — PIO 2 が生成 |
| 27 | RNW | 入力 | リード/ノットライト — PIO 1 がサンプリング |
| 28 | SYNC | 出力 | オペコードフェッチインジケーター — PIO 1 が駆動 |
| 29 | IRQ | 入力 | マスク可能割り込み(アクティブロウ)— PIO 1 が監視 |
| 30 | NMI | 入力 | ノンマスカブル割り込み(アクティブロウ)— PIO 1 が監視 |
| 31 | RDY | 入力 | レディ信号 — PIO 1 がサンプリング |
| 32 | SO | 入力 | セットオーバーフロー — PIO 1 が監視 |
| 33 | RESET | 双方向 | システムリセット(アクティブロウ) |
| 34–39 | Flash | — | SPI NOR フラッシュ(XIP) |
| 40–45 | PSRAM | — | QSPI PSRAM |
| 46–47 | ESP32 FSPI | — | ESP32 への SCLK、CS |
| 48–49 | ESP32 UART | — | ESP32 への TX/RX 460.8kbaud |
ファームウェアアーキテクチャ
フラッシュメモリレイアウト
picoZ80 のレイアウトと同一:
| パーティション | アドレス範囲 | サイズ | 内容 |
|---|---|---|---|
| ブートローダー | 0x10000000–0x1001FFFF |
128KB | USB ブリッジ、ファームウェア更新、パーティションセレクター |
| アプリスロット 1 | 0x10020000–0x1051FFFF |
5MB | メイン 6502 ファームウェア(パーティション 1) |
| アプリスロット 2 | 0x10520000–0x10A1FFFF |
5MB | メイン 6502 ファームウェア(パーティション 2) |
| アプリ設定 1 | 0x10A20000–0x10C9FFFF |
2.5MB | ROM イメージ + 最小化された設定 JSON(スロット 1) |
| アプリ設定 2 | 0x10CA0000–0x10F1FFFF |
2.5MB | ROM イメージ + 最小化された設定 JSON(スロット 2) |
| 汎用設定 | 0x10F20000–0x10FFEFFF |
892KB | コア設定、スクラッチスペース |
| パーティションテーブル | 0x10FFF000–0x11000000 |
4KB | アクティブスロット、チェックサム、メタデータ |
デュアルコア設計
| コア | 担当 |
|---|---|
| コア 0 | USB マスストレージブリッジ;ファームウェアパーティション管理;ESP32 へのファイル I/O リレー;ESP32 UART コマンドディスパッチ;コア間キューサービス |
| コア 1 | 6502 バスエミュレーションホットループ — すべてのバスサイクルで PIO FIFO をサービス、メモリマップに対してアドレスを解決、PSRAM / PHYSICAL / FUNC ハンドラーにディスパッチ、ドライバーポールコールバックを呼び出し |
PIO バスインターフェース
6502 バスインターフェースは、すべての 3 つの RP2350 PIO ブロックにまたがる
M6502.pio に実装されています。Z80 インターフェースとの主な違いは、6502 の二相非重複クロックスキームです。PHI0 は外部クロック入力で、PIO 2 がそこから PHI1 と PHI2 を生成します。これにより、コア 1 のスケジューリングに依存せず正確な 6502 バスタイミングが保証されます。
PIO プログラム
| PIO ブロック | プログラム | ステートマシン | 機能 |
|---|---|---|---|
| PIO 0 | m6502_addr |
SM 0 | 16 ビットアドレス A0–A15 を出力;IRQ 0(サイクル開始)を通知 |
| PIO 0 | m6502_data |
SM 1 | D0–D7 を駆動またはサンプリング;IRQ 1(データフェーズ)を通知;RNW 経由でトライステート制御 |
| PIO 1 | m6502_cycle |
SM 0 | トップレベルバスサイクルシーケンサー;IRQ 7 = 実行ループ終了 |
| PIO 1 | m6502_fetch |
SM 1 | オペコードフェッチサイクル(SYNC アサート、PHI2 ハイ、RNW=1) |
| PIO 1 | m6502_read |
SM 1 | メモリリードサイクル |
| PIO 1 | m6502_write |
SM 2 | メモリライトサイクル |
| PIO 1 | m6502_irq |
SM 2 | IRQ ピンを監視;アサート時に PIO IRQ 5 を通知 |
| PIO 1 | m6502_nmi |
SM 3 | NMI ピンを監視;アサート時に PIO IRQ 4 を通知 |
| PIO 1 | m6502_so |
SM 3 | SO(セットオーバーフロー)ピンを監視;PIO IRQ 6 を通知 |
| PIO 2 | m6502_clock_6502 |
SM 0 | 外部 PHI0 入力から PHI1/PHI2 二相クロックを生成 |
IRQ 信号の規約
| PIO IRQ フラグ | 信号 | トリガー元 | 消費元 |
|---|---|---|---|
| IRQ 0 | サイクル開始 | m6502_addr — PHI1 でアドレス有効 |
コア 1 ディスパッチループ |
| IRQ 1 | データフェーズ | m6502_data — データバスアクティブ |
コア 1 ディスパッチループ |
| IRQ 4 | NMI | m6502_nmi — NMI ピンロウ |
コア 1 NMI ハンドラー |
| IRQ 5 | IRQ | m6502_irq — IRQ ピンロウ |
コア 1 IRQ ハンドラー |
| IRQ 6 | SO | m6502_so — SO ピンハイ |
コア 1 SO ハンドラー |
| IRQ 7 | ループ終了 | ソフトウェアリクエスト | m6502_cycle — 実行ループ終了 |
PHI1/PHI2 クロック生成
6502 は二つの非重複クロックフェーズを必要とします。PIO 2 は専用の GPIO で外部 PHI0 入力を受け取り、正確な非重複タイミングで PHI1 と PHI2 を生成する
m6502_clock_6502 プログラムを実行します。クロック生成専用に PIO ブロック全体を割り当てることで、6502 バスタイミングがコア 1 のアクティビティや FIFO のストールに影響されないことが保証されます。
ウェイトステートと RDY
6502 の
RDY 信号はウェイトステートの挿入に使用できます。リードサイクル中に RDY をローにホールドすることで、RDY がハイになるまでプロセッサーが停止します。pico6502 はコア 1 からプログラムで RDY をアサートし、低速な仮想デバイス(例:フロッピーディスクエミュレーション)にアクセスする際にウェイトステートを挿入できます。メモリマップ JSON エントリーの tcycwait パラメーターは、特定のメモリ領域に挿入するウェイトステートの数を指定します。
PIO アーキテクチャ — 6502 バスサイクルの再現方法
RP2350 のプログラマブル I/O(PIO)サブシステムは、3 つの PIO ブロックにまたがる 10 個のステートマシンを使用して、サイクル精度の 6502 バスタイミングを再現します。picoZ80 PIO との根本的な違いは 2 点です:6502 は単一クロックではなく二相非オーバーラップクロック方式(PHI1/PHI2)を使用すること、そして別々の
二相クロック生成
/RD と /WR 信号の代わりに単一の R/W̄(リード/ノットライト)信号を使用することです。
6502 には非オーバーラップの 2 つのクロック — PHI1 と PHI2 — が必要です。外部 PHI0 信号がリファレンスを提供し、PIO 2 がそこから PHI1 と PHI2 を生成します。
m6502_clock_6502 ステートマシン(PIO 2 SM 0)はこれを以下のように実装します:
PHI0(入力): ──┐ ┌──┐ ┌──
│ │ │ │
└────────┘ └────────┘
PHI1(出力): ┌──────┐ ┌──────┐
│ │ │ │
───┘ └──────────────┘ └───
PHI2(出力): ───┐ ┌──────┐ ┌──
│ │ │ │
└──────────────┘ └──────────────┘
↑ ↑ ↑
│ │ │
PHI0 立ち下がり PHI0 立ち上がり PHI0 立ち下がり
→ 短いギャップ → 短いギャップ → 短いギャップ
→ PHI1 立ち上がり → PHI1 立ち下がり
→ PHI2 立ち上がり
SM は
jmp pin で PHI0 のエッジを検出し、set pins で正しい非オーバーラップギャップを持って PHI1 と PHI2 の両方を駆動します。最初の set pins 命令の [1] 遅延アノテーションが非オーバーラップ期間を作成します — 遷移中に両方のクロックが一時的にローになります。クロック生成に PIO ブロック全体を専用にすることで、6502 のバスタイミングが FIFO ストールやコア 1 のレイテンシーの影響を受けないことが保証されます。
out exec, 32 メカニズム
picoZ80 と同様に、pico6502 も
out exec による動的命令インジェクションを使用しますが、重要な違いがあります:6502 のサイクル SM は Z80 の out exec, 16(16 ビット命令)ではなく out exec, 32(32 ビット命令)を使用します。これにより、サイドセットビット、遅延値、拡張オペランドを含む完全な 32 ビット PIO 命令エンコーディングが単一の FIFO プッシュで可能になります。
m6502_cycle SM(PIO 1 SM 0)がすべてのバスサイクルをオーケストレートします:
// m6502_cycle SM プログラム(PIO 1 SM 0): // // start_cycle: // wait 0 gpio CLK2 ; PHI2 立ち下がりエッジに同期(新サイクル開始) // irq set 0 ; 「新しいサイクル準備完了」を通知 // wait 0 irq 0 ; C コードがアドレスをロードして IRQ 0 をクリアするまで待機 // cycle_exec: // out exec, 32 ; FIFO から 32 ビット命令を取得し実行 // jmp cycle_exec ; 繰り返し // cycle_end: // irq set 7 ; 実行ループ終了フラグ // cycle_exec2: // out exec, 32 ; インジェクトされた命令の実行を継続 // jmp cycle_exec2 ; JMP start_cycle が実行されるまでループ
C コードは各サイクルタイプ(フェッチ、リード、ライト)の 32 ビット命令シーケンスをプリコンパイルし、FIFO にプッシュします。サイクル SM は各命令を順に取得して実行し、アドレスおよびデータ SM と IRQ フラグを介して連携しながら
6502 バスサイクルタイプ
SYNC と R/W̄ 信号を制御します。
6502 には 3 つのバスサイクルタイプがあり、すべて
R/W̄ と SYNC の状態で制御されます:
オペコードフェッチ(m6502_fetch):
PHI1: ┌──────┐ ┌──
│ │ │
───┘ └──────────────┘
PHI2: ───┐ ┌──────┐
│ │ │
└──────────────┘ └───
A0–A15: ══╤═══ PC アドレス ═════════╗ (PHI1 立ち上がりで有効)
R/W̄: ──┤── ハイ(リード)────────╢
SYNC: ──┤── ハイ(フェッチ)──────╢ (SYNC ハイ = オペコードフェッチ)
D0–D7: ══════════════════╤════════╗ (PHI2 立ち下がりでサンプリング)
オペコード
メモリリード(m6502_read):
フェッチと同じタイミング、ただし SYNC = ロー。
メモリライト(m6502_write):
PHI1: ┌──────┐ ┌──
│ │ │
───┘ └──────────────┘
PHI2: ───┐ ┌──────┐
│ │ │
└──────────────┘ └───
A0–A15: ══╤═══ アドレス ════════════╗ (PHI1 立ち上がりで有効)
R/W̄: ──┤── ロー(ライト)────────╢ (R/W̄ ロー = ライト)
SYNC: ──┤── ロー ────────────────╢
D0–D7: ══════════════╤═══ データ ══╗ (PHI2 ハイ中に駆動)
Z80 PIO 実装との主な違い:
信号監視ステートマシン
- 単一 R/W̄ 信号 — Z80 の個別
/RDと/WR信号を置き換えます。m6502_fetchとm6502_readSM はR/W̄をハイに設定、m6502_writeはローに設定します。 - SYNC 信号 — 6502 はオペコードフェッチ中に
SYNCをアサートして通常のリードと区別します。m6502_fetchSM はSYNCをハイに設定、m6502_readとm6502_writeはローのままにします。 - PHI2 ベースのデータサンプリング — データバスは Z80 のように特定の T ステートクロックエッジではなく、PHI2 立ち下がりエッジ(サイクル終了時)でサンプリングされます。
m6502_dataSM はwait 0 gpio CLK2でデータキャプチャーのタイミングを計ります。 - RDY ベースのウェイトステート — Z80 の
/WAIT信号の代わりに、6502 はRDYを使用します。リードサイクル中にRDYがローの場合、プロセッサーが停止します。フェッチとリード SM は各 PHI2 立ち上がりエッジ後にjmp pinで RDY を確認します。 - リフレッシュサイクルなし — 6502 には DRAM リフレッシュサイクルがないため、フェッチサイクルがよりシンプルです(T3–T4 リフレッシュフェーズなし)。
- I/O 専用サイクルなし — 6502 には
IN/OUT命令がありません。すべてのペリフェラルアクセスはメモリマップドリードとライトを介して行われます。
3 つの専用 SM が 6502 の非同期入力信号を監視します:
m6502_irq(PIO 1 SM 2)—/IRQピンを監視。/IRQがローになると PIO IRQ 5 をセットし、ピンがハイに戻るまで保持した後フラグをクリアします。コア 1 は IRQ 5 を確認して割り込みベクターフェッチシーケンスのインジェクトが必要かを判断します。m6502_nmi(PIO 1 SM 3)—/NMIを監視し PIO IRQ 4 をセット/クリア。コア 1 の NMI ハンドラーは$FFFA/$FFFBを通じてベクタリングする適切なバスサイクルシーケンスをプッシュします。m6502_so(PIO 1 SM 3)—SO(セットオーバーフロー)ピンを監視し PIO IRQ 6 をセット/クリア。一部の 6502 システム(特に Commodore ディスクドライブ)がデータレディイベントの通知に使用します。
jmp pin でピンのアクティブ化を検出、irq set でコア 1 に通知、その後ループ内の jmp pin でピンの復帰を検出し、irq clear で完了。これにより、非同期エッジイベントが同期 IRQ フラグに変換され、コア 1 がホットループ内で効率的にポーリングできます。
メモリモデル
pico6502 のメモリモデルは picoZ80 のモデルと構造的に同一ですが、重要な違いが一つあります。6502 には独立した I/O アドレス空間がありません。
t_6502PSRAM に ioPtr[] 配列はなく、iomap の JSON セクションもありません。すべてのペリフェラルレジスターは FUNC タイプのブロックを使用して 64KB メモリアドレス空間にマップされます。
ティア 1 — RP2350 SRAM(高速ディスパッチテーブル)
_membankPtr[] に 128 × 32 ビットエントリー、64KB アドレス空間の 512 バイトブロックごとに 1 エントリー。各エントリーはブロックタイプ、PSRAM バンク番号、ブロックベースアドレスを 1 つの 32 ビットワードにエンコードし、すべてのバスサイクルで O(1) ディスパッチを実現します:
// 32ビット membankPtr エンコード // ビット 31–24: MEMBANK_TYPE_xxx 定数 // ビット 23–16: PSRAM バンク番号(0–63) // ビット 15–0: ブロックベースアドレス >> 9(16ビットアドレスの上位 7 ビット) #define MEMBANK_ENCODE(type, bank, base) (((type) << 24) | ((bank) << 16) | ((base) >> 9))
ティア 2 — PSRAM(8MB)
8MB の PSRAM は RAM/ROM 領域と関数ポインターテーブルの間で分割されます:
typedef struct {
uint8_t RAM[MAX_MEMORY_BANKS * MEMORY_PAGE_SIZE]; // 64バンク × 64KB = 4MB RAM/ROM領域
MemoryFunc memPtr[MEMORY_PAGE_SIZE]; // 64K バイト単位リードリダイレクト(PTR タイプ)
MemoryFunc memioPtr[MEMORY_PAGE_SIZE]; // 64K メモリマップハンドラー配列(FUNC タイプ)
// 注: ioPtr[] なし — 6502 には独立した I/O 空間がない
} t_6502PSRAM;
ティア 3 — フラッシュ(16MB)
16MB のフラッシュにはブートローダー、2 つの 5MB アプリケーションファームウェアスロット、ROM イメージと最小化された JSON の 2 つの設定スロット、汎用設定、パーティションテーブルが格納されます。上記「ファームウェアアーキテクチャ」セクションのフラッシュメモリレイアウト表を参照してください。
メモリブロックタイプ
| 定数 | 値 | 動作 |
|---|---|---|
MEMBANK_TYPE_PHYSICAL |
0 | 実際のホストハードウェアへのパススルー — RP2350 がバスを解放 |
MEMBANK_TYPE_PHYSICAL_VRAM |
1 | 設定可能なウェイトステートを持つホストビデオ RAM |
MEMBANK_TYPE_RAM |
2 | 読み書き — PSRAM バンクが裏付け |
MEMBANK_TYPE_ROM |
3 | 読み取り専用 — PSRAM バンクが裏付け;書き込みは無視 |
MEMBANK_TYPE_VRAM |
4 | ウェイトステート付き PSRAM ビデオ RAM ミラー |
MEMBANK_TYPE_FUNC |
5 | 仮想デバイス — すべてのアクセスで memioPtr[addr] ハンドラーを呼び出し |
MEMBANK_TYPE_PTR |
6 | バイト単位リダイレクト — リード時に memPtr[addr] ハンドラーを使用 |
設定リファレンス
pico6502 は picoZ80 と同じ JSON 設定メカニズムを使用します。トップレベルキーは
"esp32" と "rp2350" です。CPU 固有のセクションはキー "6502"("z80" ではなく)を使用します。6502 には I/O 空間がないため "io" 配列はなく、"memory" 配列のみです。
esp32.core
| キー | タイプ | 説明 |
|---|---|---|
device |
文字列 | CPU デバイスタイプ。pico6502 では "6502" でなければなりません。 |
mode |
整数 | デフォルト起動モード:0 = クライアント(ステーション)、1 = アクセスポイント。 |
esp32.wifi
| キー | タイプ | 説明 |
|---|---|---|
override |
0/1 | 1 = このブロックのすべての WiFi 設定を適用;0 = NVS の設定を使用。 |
wifimode |
文字列 | "ap" または "client"。 |
ssid |
文字列 | 作成する(AP)または参加する(クライアント)ネットワーク名。 |
password |
文字列 | WiFi パスフレーズ。 |
ip |
文字列 | 固定 IP アドレス。 |
netmask |
文字列 | サブネットマスク。 |
gateway |
文字列 | デフォルトゲートウェイ。 |
dhcp |
0/1 | クライアントモードのみ。1 = DHCP、0 = 固定 IP。 |
webfs |
文字列 | SD カード上のウェブファイルシステムのルートディレクトリ(デフォルト "webfs")。 |
persist |
0/1 | 1 = 起動のたびに解決された設定を NVS に書き戻す。 |
rp2350.core
| キー | タイプ | 説明 |
|---|---|---|
cpufreq |
整数 | RP2350 システムクロック(Hz)(例:300000000)。 |
psramfreq |
整数 | PSRAM SPI クロック(Hz)(例:133000000)。 |
voltage |
浮動小数点 | RP2350 コア電圧(例:1.10)。 |
rp2350.6502.memory[ ]
6502 メモリマップを定義します。すべてのペリフェラルは
FUNC タイプのエントリーとしてここに記述する必要があります — 独立した I/O マップはありません。
| キー | タイプ | 説明 |
|---|---|---|
enable |
0/1 | このエントリーがアクティブかどうか。 |
addr |
16 進文字列 | 6502 アドレス空間内の開始アドレス(例:"0xE000")。 |
size |
16 進文字列 | 領域サイズ(バイト)(例:"0x2000")。 |
type |
文字列 | PHYSICAL、PHYSICAL_VRAM、RAM、ROM、FUNC、または PTR。 |
bank |
整数 | RAM/ROM タイプの PSRAM バンク番号(0–63)。 |
tcycwait |
整数 | この領域に挿入するウェイトステート(RDY ストレッチング)。 |
task |
文字列 | FUNC タイプのブロック用の名前付きタスク/ドライバーハンドラー。 |
file |
文字列 | 起動時に読み込む ROM イメージの SD カードパス(ROM タイプ)。 |
rp2350.6502.drivers[ ]
6502 のドライバーエントリーは Z80 のものより単純です。各エントリーは名前付きドライバー(ファームウェアの
virtualFuncMap[] テーブルと照合)を有効化し、オプションで起動時に ROM イメージを PSRAM に読み込みます。
| キー | タイプ | 説明 |
|---|---|---|
enable |
0/1 | このドライバーエントリーがアクティブかどうか。 |
name |
文字列 | ドライバー名 — virtualFuncMap[] と大文字小文字を区別せずに照合。 |
rom[] |
配列 | 起動時に読み込む ROM イメージ。各エントリー:enable、file、loadaddr[]。 |
rom[] エントリー:
| キー | タイプ | 説明 |
|---|---|---|
enable |
0/1 | この ROM イメージを読み込むかどうか。 |
file |
文字列 | ROM バイナリへの SD カードパス。 |
loadaddr[] |
配列 | 1 つ以上のロードアドレス記述子:enable、position、addr、bank、size。 |
仮想デバイスフレームワーク
仮想デバイスフレームワークは picoZ80 テクニカルガイドで説明されている picoZ80 のフレームワークと構造的に同一です。主な違いは、すべての仮想デバイスが
memioPtr[] に登録されることです — 6502 には ioPtr[] に相当するものがありません。
ハンドラーシグネチャー
// メモリ/ペリフェラルハンドラー — memioPtr[addr] にインストール // MEMBANK_TYPE_FUNC ブロックへのすべてのアクセスで呼び出される typedef uint8_t (*MemoryFunc)(M6502CPU *cpu, bool read, uint16_t addr, uint8_t data); // ドライバー初期化関数 — virtualFuncMap[] に登録 // 2 回呼び出される:pass=0(検証)、pass=1(設定) typedef int (*VirtualFunc)(M6502CPU *cpu, t_drvConfig *drvConfig, int pass);
ペリフェラルドライバーの作成
pico6502 用の仮想ペリフェラルを追加するには:
MemoryFuncシグネチャーを持つハンドラー関数を作成します。ハンドラーは 6502 リードサイクル(RNW=1)に対してread=true、ライトサイクル(RNW=0)に対してread=falseを受け取ります。VirtualFuncシグネチャーを持つ初期化関数を作成します。設定パス(pass=1)では、ペリフェラルが占有する各アドレスのcpu->_6502PSRAM->memioPtr[addr]にハンドラーをインストールします。M6502CPU.cのvirtualFuncMap[]テーブルにドライバー名と初期化関数を登録します。config.jsonのmemory配列にアドレス範囲のFUNCタイプエントリーを追加します。- 一致する
"name"フィールドを持つドライバーエントリーをconfig.jsonに追加します。
VIA6522 ペリフェラル実装を含む完全な例については pico6502 デベロッパーズガイドを参照してください。
ESP32 コプロセッサー
ESP32 コプロセッサーは picoZ80 の ESP32 と機能および実装において同一です — SD カードインターフェース、ウェブサーバー構造、RP2350–ESP32 コマンドプロトコルの完全な説明については picoZ80 テクニカルガイド — ESP32 コプロセッサーを参照してください。
SD カード
SD カードは SPI 経由で ESP32 が排他的に管理します。RP2350 はコア間キューにメッセージを投稿してファイルの読み書きをリクエストし、コア 0 がこれらのリクエストを UART 経由で ESP32 に中継して結果を返します。pico6502 の SD カードディレクトリ構造は picoZ80 と同一です:ウェブファイル用
webfs/、ROM イメージ用 ROM/、ルートに config.json。
ウェブサーバー
同じ 7 ページの Bootstrap 4 ウェブサーバーが ESP32 上で動作します。ウェブインターフェースは
config.json の esp32.core.device フィールドから接続されているデバイスタイプを自動検出し、CSS テーマとラベルを調整します(p6502.css スタイルシートが 6502 固有のカラースキームを適用します)。
コマンドプロトコル
RP2350–ESP32 コマンドプロトコルは picoZ80 と pico6502 の両方で同一です。コマンドは 460.8kbaud UART リンク(バルクデータ転送用の 50MHz FSPI がバックアップ)で交換されます。プロトコルは
ESP.c / ESP.h で定義され、両方のファームウェアバリアント間で共有されます。
SWD デバッグ — RP2350
pico6502 の SWD デバッグセットアップは picoZ80 と同一です — ハードウェア接続、カスタム
rp2350_tzpu.cfg OpenOCD ターゲット、グローバル GDB 初期化の完全な説明については picoZ80 テクニカルガイド — SWD デバッグを参照してください。picoZ80 との違いは:
- メインファームウェアの ELF は
build/bin/model/BaseM6502/BaseM6502_0x10020000.elfです(BaseZ80ではありません)。 ~/.gdbinitのadd-auto-load-safe-pathエントリーはBaseM6502を参照しなければなりません。
OpenOCD セットアップ
sudo cp rp2350_tzpu.cfg /usr/local/share/openocd/scripts/target/ openocd -f interface/cmsis-dap.cfg -f target/rp2350_tzpu.cfg -c "adapter speed 5000"
GDB 設定
set history save on set history filename ~/.gdb_history set history size 65536 add-auto-load-safe-path build/bin/model/BaseM6502/.gdbinit:build/bin/model/Bootloader/.gdbinit
# ブートローダー — コア 0 cd build/bin/model/Bootloader cp ../../../../.gdbinit.bootloader.3333 .gdbinit gdb-multiarch Bootloader.elf # ブートローダー — コア 1(別ターミナル) cd build/bin/model/Bootloader cp ../../../../.gdbinit.bootloader.3334 .gdbinit gdb-multiarch Bootloader.elf
# メインファームウェア — コア 0 cd build/bin/model/BaseM6502 cp ../../../../.gdbinit.3333 .gdbinit gdb-multiarch BaseM6502_0x10020000.elf # メインファームウェア — コア 1(別ターミナル) cd build/bin/model/BaseM6502 cp ../../../../.gdbinit.3334 .gdbinit gdb-multiarch BaseM6502_0x10020000.elf
ESP32 — USB デバッグ
picoZ80 と同一 — USB を ESP32 USB ポートに接続し、ESP32-S3 内蔵の USB-JTAG インターフェースを使用します(外部プローブ不要)。
openocd -f board/esp32s3-builtin.cfg xtensa-esp32s3-elf-gdb esp32/build/main.elf (gdb) target extended-remote :3333
ビルドシステム
ビルドシステムは picoZ80 と同一です — RP2350 をターゲットとした Pico SDK 2.x を使用した CMake です。pico6502 は Zeta Z80 エミュレーターライブラリを必要としません。前提条件、ESP-IDF 用 Docker セットアップ、ビルドスクリプトの完全な説明については picoZ80 テクニカルガイド — ビルドシステムを参照してください。pico6502 固有の違いを以下に記します。
ビルドターゲット
| ターゲット | 出力 | 説明 |
|---|---|---|
BaseM6502 |
BaseM6502_0x10020000.uf2 |
メイン 6502 ファームウェア — スロット 1 ロードアドレス |
BaseM6502 |
BaseM6502_0x10520000.uf2 |
メイン 6502 ファームウェア — スロット 2 ロードアドレス |
Bootloader |
Bootloader.uf2 |
共有ブートローダー(picoZ80 と同一) |
| ESP32 | main.bin |
ESP32 ファームウェア(picoZ80 と共有) |
ビルドコマンド
# セットアップ(初回のみ)— プロジェクトルートから export PICO_PATH=/path/to/pico-sdk ./get_and_build_sdk.sh # 標準リリースビルド ./build_tzpuPico.sh # デバッグビルド ./build_tzpuPico.sh DEBUG # ESP32 ファームウェアを含む完全ビルド ./build_tzpuPico.sh ALL # ESP32 のみ(Docker idf54 エイリアスを使用) cd projects/tzpuPico/esp32 idf54 build # USB マスストレージ(BOOTSEL モード)で RP2350 を書き込む cp build/bin/model/Bootloader/Bootloader.uf2 /media/$USER/RPI-RP2/ cp build/bin/model/BaseM6502/BaseM6502_0x10020000.uf2 /media/$USER/RPI-RP2/ # ESP32 の初回書き込み(esptool を使用) esptool.py --chip esp32s3 --port /dev/ttyUSB0 --baud 460800 \ write_flash 0x0 esp32/build/bootloader/bootloader.bin \ 0x8000 esp32/build/partition_table/partition-table.bin \ 0x10000 esp32/build/main.bin
参考サイト
| リソース | リンク |
|---|---|
| pico6502 プロジェクトページ | /pico6502/ |
| pico6502 ユーザーマニュアル | /pico6502-usermanual/ |
| pico6502 デベロッパーズガイド | /pico6502-developersguide/ |
| picoZ80 テクニカルガイド | /picoz80-technicalguide/ |
| picoZ80 プロジェクトページ | /picoz80/ |
| RP2350 データシート | datasheets.raspberrypi.com |
| Pico SDK マルチコア API | raspberrypi.github.io/pico-sdk-doxygen |
| MOS 6502 データシート | archive.org |
| esptool ドキュメント | docs.espressif.com |
| cJSON ライブラリ | github.com/DaveGamble/cJSON |
無線規制に関する注意事項
本デバイスは 2.4 GHz ISM バンドで送信する ESP32-S3-PICO-1 無線モジュールを搭載しており、世界各国の無線周波数規制(米国の FCC Part 15 Subpart C、欧州連合の無線機器指令 2014/53/EU を含む)において意図的放射器に該当します。
ESP32-S3-PICO-1 モジュール自体は既存の規制認証(FCC、CE など)を取得していますが、そのモジュールレベルの認証は、モジュールを組み込んだ完成品に自動的に適用されるものではありません。事前認証モジュールの免除規定は、個人の趣味愛好家が個人使用、実験、または教育目的で少数のデバイスを製作する場合に、個別の機器認可を取得せずに行うことを許可するものです。
重要な制限事項
本設計に基づいて製作されたデバイスが、管轄区域内の適用されるすべての無線周波数規制に準拠することは、製作者の単独の責任です。著者は本設計を個人使用、教育、および趣味愛好家向けに提供しており、本設計から製作されたデバイスが商業的配布の規制要件を満たすことについて、いかなる表明も行いません。
- 組み立てられたデバイスは、完成品が独自にテストされ、該当する管轄区域で機器認可(例:FCC ID、認定機関による CE マーキング評価)を取得しない限り、第三者への販売、販売の申し出、贈与、またはその他の方法での配布を行ってはなりません。
- 個人使用のために少数を製作することは、趣味愛好家および実験使用の規定(例:FCC § 15.23)に基づき、デバイスが有害な干渉を引き起こさない限り、一般的に許可されています。
- 規制要件は国によって異なります。米国外の製作者は、適用される規則について自国の無線周波数当局に確認してください。
本設計に基づいて製作されたデバイスが、管轄区域内の適用されるすべての無線周波数規制に準拠することは、製作者の単独の責任です。著者は本設計を個人使用、教育、および趣味愛好家向けに提供しており、本設計から製作されたデバイスが商業的配布の規制要件を満たすことについて、いかなる表明も行いません。