zOS (Z-オペレーティングシステム)

zOS

zOS は、ZPU Evo および SoC の動作を検証するために作成された ZPUTA テストアプリケーションから派生したものです。ZPUTA は、さまざまな FPGA が ZPU Evo のスコープに含まれるにつれて進化し、限られたリソースのためにより高度な機能が必要であることが明らかになりました。ZPUTA が OS に匹敵する水準の洗練度にまで発展したとき、それは分割され、zOS が誕生しました。

当初、ZPUTA/zOS の開発は ZPU アーキテクチャのみを対象とし、2 つの主要な実行方式がありました:
  • IOCP によってブートされるアプリケーションとして、
  • ZPU Evo のスタートアップファームウェアとしてスタンドアロンブート。
スタートアップモードは設定で選択し、機能は同一です。IOCP によってアプリケーションとしてブートされる場合、zOS は SD カードに保存され、ブート時にロードされます。「スタンドアロン」の場合、zOS はオンボード Flash(または ROM として機能するよう事前設定された BRAM)に保存されます。

最近では、zOS は tranZPUterSW プロジェクトで Freescale K64F と共に使用するため、ARM Cortex-M4 アーキテクチャに移植されました。K64F は固定アーキテクチャの CPU/SoC であるため、実行方式は「スタンドアロン」の 1 つのみであり、オンボード Flash に保存され、CPU 電源投入時に起動します。

zOS では、OS 以外の機能はすべて SD カード上のアプリケーションとして保存されます。SD カードが存在しない場合は、ZPUTA を使用する方が適しています。ZPUTA はプライマリロードイメージ内で全機能を有効/無効にできるため、限られた FPGA BRAM リソースに対応できます。

当初 zOS はシリアルライン経由のターミナルエミュレータのみで動作していましたが、tranZPUter SW-700 の登場により、zOS は動作するためにシリアル接続(物理または USB 仮想)と、できれば ANSI/VT100 ターミナルエミュレータパッケージが接続されている必要があります。ANSI/VT100 ターミナルエミュレーションパッケージの要件は、エディタや readline などのコマンドが正しく機能するためです。ダムシリアルターミナルでも動作しますが、アプリケーション機能は制限されます。シリアル接続が使用できない場合、またはインタラクティブな OS が不要で電源投入時にアプリケーションを起動する能力だけが必要な場合は、IOCP の方が適しています(ただし、K64F にはまだ移植されていません)。

最近のハードウェア開発である tranZPUter SW-700 v1.3 では、zOS はキーボードとディスプレイを直接制御するホスト OS として動作します。シリアルベースのアプリケーションとの後方互換性を維持するために、ANSI ターミナルエミュレータが開発され、組み込まれています。

OS の使い方

私のキャリアを通じて、市場変化に応じてロジックフローを監視・変更したり、問題をリアルタイムで修正したりするために最終製品とライブインタラクションを行うシステムを使用または設計してきました。これは通常、TCP クライアントサーバー接続を使用した組み込みコマンドプロセッサを通じて行われてきました。このアプローチの利点は非常に大きく、正しく実装すればセキュリティリスクを軽減できます。Reuters や TibCO などの企業はこの技術(つまり「Hawk」製品)を使用しており、私も Morgan Stanley で書いたトレード実行・価格設定モジュールや Chase Manhattan のオプション取引システムなど、自分の開発に取り入れて大きな効果を上げてきました。

このリポジトリのプロジェクトに取り組む際、限られたリソースの組み込みシステムであっても、その場で監視・変更・修正できる同様の環境が欲しいという思いが常に念頭にありました。この要件は、基本的な監視、アップロード、実行機能を持つ IOCP から始まり、強化された機能と外部アプリケーションを持つ ZPUTA の作成時にさらに拡張されました。

少なくとも基本レベルのタイムスケジューリングが間もなく実装される予定です。これにより、ハードウェアを駆動する組み込みアプリケーションが必要に応じて実行されながら、OS を実行して接続されたユーザー/開発者にサービスを提供するための処理リソースを確保できます。K64F 版の zOS は tranZPUter ボード制御にスレッドを使用していますが、これは定義された API にカプセル化され、ZPU および NIOS II アーキテクチャで利用可能にする必要があります。

私が使用してきた開発ボードのほとんどにイーサネットがないため、プロジェクトにはネットワークスタックがなく、接続性はシリアルラインに限定されます。将来の tranZPUter カードに ESP32 モジュールの追加を検討しており、この追加が実現するまでネットワーキングは引き続き検討課題です。

非同期シリアル通信の利点は、シンプルで USB アダプター経由の直接接続または RS-232 経由でほぼすべての PC のターミナルに接続できることです。SLIP を実装することもできますが、このレベルではシンプルに保つことが私の好む選択肢です。開発ボードと PC の間でシリアルラインを接続できれば、その機能を使用できます。

OS インターフェースは、シリアルテキストベースのターミナルのみが使用可能であることを念頭に置いて作成されています。エディタなどの一部のコンポーネントはより高度な機能を必要とし、そのために由緒ある VT100/ANSI エミュレーションが適切な候補として選ばれました(つまり、エディタを使用するにはシリアルラインの前に VT100/ANSI エミュレータが必要です)。インタラクションはキーボードとテキストベースです(凝った GUI インターフェースはありません!)。以下のセクションでインターフェースの使用方法についての情報を提供します。

コマンドライン

OS への最初の導入は、CPU、バージョンなどを詳述するサインオンメッセージで、コマンド入力のプロンプトが表示されます:

zOS 起動画面

OS とのインタラクションは MSDOS と変わりません。コマンドを入力して応答を得るだけです。唯一の違いは、元々フルスペックの PC ではなく組み込みシステム内にあったことです。現在、ZPU/NIOSII プロセッサ上の Sharp MZ-700 でユーザー OS として動作するよう zOS が進化しているため、これは変わりつつあります。

zOS コマンドラインはシェルインタープリターではなく、組み込みコマンドまたは SD カードに保存されたコマンドを発行するための基本的なテキストインターフェースです。コマンドの入力と取得を支援するための履歴付きの縮小 readline 機能が含まれており、概ね GNU readline の機能に従っています。コマンドラインで認識されるキーは次のとおりです:


キー 動作
CTRL-A 行頭に移動。
CTRL-B カーソルを左に 1 つ移動。
CTRL-C 現在の行を中断し、呼び出し元アプリケーションに CTRL-C を返す。
CTRL-D シェルでは未定義、実行中のアプリケーションに渡される。
CTRL-E 行末に移動。
CTRL-F カーソルを右に 1 つ移動。
CTRL-K 行をクリア。
CTRL-N 次の履歴コマンドを呼び出す。
CTRL-P 前の履歴コマンドを呼び出す。
HOME 行頭に移動。
END 行末に移動。
INSERT まだ未定義。
DEL カーソル下の文字を削除。
BACKSPACE カーソルの左の文字を削除。
PGUP シェルでは未定義、実行中のアプリケーションに渡される。
PGDOWN シェルでは未定義、実行中のアプリケーションに渡される。
ARROW UP 前の履歴コマンドを呼び出す。
ARROW DOWN 次の履歴コマンドを呼び出す。
ARROW RIGHT カーソルを右に 1 つ移動。
ARROW LEFT カーソルを左に 1 つ移動。

readline メカニズムはいくつかの内部コマンドも認識します:

コマンド 動作
!<number> <number> で識別された履歴コマンドを呼び出して実行する。
hist[ory] 履歴バッファを一覧表示する。

アプリケーション

zOS が現在提供しているアプリケーションは SD カードに保存されており、以下に概要を示します。詳細については、 アプリケーションセクション(左のナビゲーションバー)またはアプリケーション README ファイルを参照してください。
  • ディスク IO コマンド

    コマンド パラメーター 説明
    ddump [<pd#> <sect>] セクターをダンプ
    dinit* <pd#> [<card type>] ディスクを初期化
    dstat* <pd#> ディスクステータスを表示
    dioctl* <pd#> ioctl(CTRL_SYNC)
  • ディスクバッファコマンド

    コマンド パラメーター 説明
    bdump <ofs> バッファをダンプ
    bedit <ofs> [<data>] … バッファを編集
    bfill <val> バッファを埋める
    blen <len> fread/fwrite コマンドの読み書き長を設定
    bread <pd#> <sect> [<num>] バッファに読み込む
    bwrite <pd#> <sect> [<num>] バッファをディスクに書き込む
  • ファイルシステムコマンド

    コマンド パラメーター 説明
    falloc <fsz> <opt> 連続ブロックをファイルに割り当て
    fattr <atrr> <mask> <name> オブジェクト属性を変更
    fcat <name> ファイル内容を出力
    fcd <path> カレントディレクトリを変更
    fclose   開いているファイルを閉じる
    fconcat <src fn1> <src fn2> <dst fn> 2 つのファイルを連結
    fcp <src file> <dst file> ファイルをコピー
    fdel <obj name> オブジェクトを削除
    fdir [<path>] ディレクトリを表示
    fdrive <path> カレントドライブを変更
    fdump <name> [<width>] ファイル内容を 16 進数でダンプ
    fexec* <name> <ldAddr> <xAddr> <mode> ファイルをロードして実行
    finit* <ld#> [<mount>] ボリュームを強制初期化
    finspect <len> ファイルの一部を読んで検査
    flabel <label> ボリュームラベルを設定
    fload* <name> [<addr>] ファイルをメモリにロード
    fmkdir <dir name> ディレクトリを作成
    fmkfs <ld#> <type> <au> FAT ボリュームを作成
    fopen <mode> <file> ファイルを開く
    fread <len> ファイルの一部をバッファに読み込む
    frename <org name> <new name> オブジェクトの名前を変更
    fsave <name> <addr> <len> メモリ範囲をファイルに保存
    fseek <ofs> 通常シーク内で fp を移動
    fshowdir   カレントディレクトリを表示
    fstat [<path>] ボリュームステータスを表示
    ftime オブジェクトのタイムスタンプを変更
    ftrunc   現在の fp でファイルを切り捨て
    fwrite <len> <val> バッファの一部をファイルに書き込む
    fxtract <src> <dst> <start pos> <len> ファイルの一部を抽出
  • メモリコマンド

    コマンド パラメーター 説明
    mclear <start> <end> [<word>]  メモリをクリア
    mcopy <start> <end> <dst addr> メモリをコピー
    mdiff <start> <end> <cmp addr> メモリを比較
    mdump [<start> [<end>] [<size>]] メモリをダンプ
    mperf <start> <end> [<width>] [<size>] メモリ性能をテスト。
    この値は CPU <-> メモリの値であり、実際のメモリ性能ではありません。ZPU はスタックベースのため、メモリ操作にメモリを使用するので、LDIR などの拡張命令の必要性がここにあります。
    msrch <start> <end> <value> メモリを検索。
    mtest [<start> [<end>] [iter] [test mask] メモリをテスト
    meb <addr> <byte> […] メモリを編集(バイト)
    meh <addr> <h-word> […] メモリを編集(ハーフワード)
    mew <addr> <word> […] メモリを編集(ワード)
  • ハードウェアコマンド

    コマンド パラメーター 説明
    hr   レジスタ情報を表示
    ht   マイクロ秒タイマーをテスト
  • 性能テストコマンド

    コマンド パラメーター 説明
    dhry   Dhrystone テスト v2.1
    coremark   CoreMark テスト v1.0
  • プログラム実行コマンド

    コマンド パラメーター 説明
    call” <addr> <addr> の関数を呼び出す
    jmp” <addr> <addr> のコードを実行
  • その他のコマンド

    コマンド パラメーター 説明
    restart   アプリケーションを再起動
    reset   システムをリセット
    help [<cmd %>|<group %>] このスクリーンを表示
    info   設定情報
    time [<y> <m> <d> <h> <M> <s>] 現在時刻を設定/表示
  • アプリケーション

    コマンド パラメーター 説明
    ed <file> 基本 WYSIWYG VT100 ファイルエディタ
    kilo <file> WYSIWYG VT100 ファイルエディタ
    mbasic [<file>] インタラクティブなミニ BASIC インタープリター。
    tbasic   インタラクティブな tiny BASIC インタープリター。
  • tranZPUter コマンド

    コマンド パラメーター 説明
    tzload アプリセクションで全リストを参照。 tranZPUter メモリへのファイルのアップロード・ダウンロード、ビデオフレームのキャプチャまたは新しいフレームの設定。
    tzdump アプリセクションで全リストを参照。 tranZPUter メモリをスクリーンにダンプ。
    tzclear アプリセクションで全リストを参照。 tranZPUter メモリをクリア。
    tzclk アプリセクションで全リストを参照。 Z80 の代替 CPU 周波数を設定。
    tzreset アプリセクションで全リストを参照。 tranZPUter をリセット。
    tzio アプリセクションで全リストを参照。 Z80 I/O ポートの読み書きツール。
    tzflupd アプリセクションで全リストを参照。 K64F FlashRAM 更新ツール。実行中の zOS/ZPUTA カーネルを新しいバージョンに更新。

(*)の付いたすべてのコマンドは zOS に組み込まれています。

autoexec.bat

MSDOS と同様に、SD ファイルシステムのルートディレクトリ(最上位レベル)に「AUTOEXEC.BAT」という名前のファイルが作成されると、その内容がブート/リセット時に zOS によって実行されます。このファイルを使用して、意図したアプリケーションのセットアップと起動を自動化してください。現在、組み込み言語はなく、コマンドの発行のみです。

技術的詳細

このセクションでは、現時点でのオペレーティングシステムの内部詳細の一部を提供することを目的としています。この情報の多くは ZPUTA と同じですが、zOS が成熟するにつれて大きな違いが生じ始めるでしょう。

メモリ構成

IOCP メモリマップ
zOS は通常「スタンドアロン」形式で使用されます。つまり、OS がプライマリファームウェアとして起動します。後方互換性のため、または ZPU 上での zOS の開発を迅速化するために、IOCP を SD カードから zOS イメージをブートストラップするブートローダーとして使用できます。必要なメモリモデルに応じて、IOCP は以下の定義済みメモリマップで使用できます:

IOCP メモリマップ

これらすべてのモデルにおいて、zOS は IOCP によって SD カードからロードされ、zOS がブートファームウェアである場合と比較して、通常 0x1000〜0x3000 バイト先のメモリに配置されます。執筆時点では、IOCP は K64F アーキテクチャに移植されていないため、ZPU でのみ使用できます。
zOS メモリマップ
ZPU 上で動作する zOS のメモリ使用マップは以下の図のとおりです。zOS はブートファームウェアとして下位 BRAM に配置され、スタック/ヒープは使用可能な BRAM(または RAM/SDRAM)の上部にあります。アプリケーションは、ビルドスクリプトで定義されたアドレスにロードされます。通常は RAM/SDRAM の先頭、または FPGA が十分に大きい場合は BRAM の先頭です。

ZPU 用 zOS メモリマップ

K64F プロセッサのメモリ使用マップは同様ですが、Flash RAM と RAM は ZPU のように可変ではなく明確に定義されています。

K64F 用 zOS メモリマップ


アプリケーションインターフェース

ほとんどのオペレーティングシステムと同様に、zOS は適切にコンパイルされたアプリケーションがそのサイズと複雑さを削減し、シリアルライン接続などの OS 内の機能を再利用できる API を提供します。

カスタム API メソッドセットを設計するのではなく、zOS 内のメソッドをアプリケーションに公開する方が理にかなっていました。例えば printf などです。ターミナルに出力を表示するために printf を呼び出すアプリケーションは、実際には zOS 内の printf を呼び出します。これは、zOS 内の固定ベクター位置にジャンプテーブルを作成することで実現されます。アプリケーションは、printf の呼び出しを zOS ベクターテーブルへのジャンプに変換するマクロセットでコンパイルされます。

現在、以下の API メソッドが公開されています:

ベクター番号 メソッド プロトタイプ 説明
000 _break ブレークハンドラー。 ブレークポイント命令に遭遇したときに処理するメソッド。
001 _putchar void putchar(char c) 最低レベルでシリアル出力デバイスに 1 文字を送信。
002 putc void putc (char c) 出力ストリームに 1 文字を書き込む通常のメソッド。
003 fputc void fputc (void (*func)(unsigned char), char c) 指定された出力デバイスまたはストリームに文字を書き込む。
004 puts void puts (const char* str) 出力ストリームに文字列を書き出す。
005 gets int gets (char* buff, int len) 入力ストリームから文字列を取得。
006 fgets int fgets (unsigned char (func)(void), char buff, int len) 指定された入力デバイスまたはストリームから文字列を取得。
007 fputs void fputs (void (func)(unsigned char), const char str) 指定された出力デバイスまたはストリームに文字列を書き出す。
008 xatoi int xatoi (char** str, long* res) 文字列を long に変換。文字列は任意の形式またはベースが可能。
009 uxatoi int uxatoi(char **, uint32_t *) 文字列を符号なし 32 ビットに変換。文字列は任意の形式またはベースが可能。
010 printf void printf (const char* fmt, …) 書式付き文字列を出力ストリームに出力。浮動小数点はサポートされていません。
011 vprintf void vprintf (const char*, va_list ) 可変引数の書式付き文字列を出力ストリームに出力。浮動小数点はサポートされていません。
012 sprintf void sprintf (char* buff, const char* fmt, …) 書式付き文字列を文字列に出力。浮動小数点はサポートされていません。
013 fprintf void fprintf (void (func)(unsigned char), const char fmt, …) 書式付き文字列を指定された出力デバイスまたはストリームに出力。
014 getScreenWidth uint8_t getScreenWidth(void) 現在のスクリーン幅を返す。主に zOS がユーザー OS として動作するときに使用され、スクリーン幅が動的です。組み込み使用では固定定数を返します。
015 getKey int8_t getKey(uint8_t mode) キーボード(シリアルまたは物理)から最低レベルで 1 文字を取得。mode = 0 - ホスト未マップキーボード非ブロッキング、1 - ホスト未マップキーボードブロッキング、2 - ansi 非ブロッキング、3 - ansi ブロッキング。未マップはシリアルキーボードの ANSI またはホストハードウェア値(例: Sharp MZ-700 キースキャンコード)を返す。
016 crc32_init unsigned int crc32_init(void) CRC32 ジェネレーターを初期化。
017 crc32_addword unsigned int crc32_addword(unsigned int crc_in, unsigned int word) 生成された CRC32 にワードを追加し、追加後の現在の CRC32 値を返す。
018 get_dword unsigned int get_dword(void) シリアル入力デバイスから符号なし 32 ビットワード(バイナリ形式、ビッグエンディアン)を取得。
019 rtcSet uint8_t rtcSet(RTC *time) オンボードリアルタイムクロックを指定された日時に設定。
020 rtcGet void rtcGet(RTC *time) オンボードリアルタイムクロックから現在の日時を取得。
021 f_open FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode) ファイルを開くまたは作成する
022 f_close FRESULT f_close (FIL* fp) 開いているファイルオブジェクトを閉じる
023 f_read FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br) ファイルからデータを読み込む
024 f_write FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw) ファイルにデータを書き込む
025 f_lseek FRESULT f_lseek (FIL* fp, FSIZE_t ofs) ファイルオブジェクトのファイルポインターを移動
026 f_truncate FRESULT f_truncate (FIL* fp) ファイルを切り捨てる
027 f_sync FRESULT f_sync (FIL* fp) 書き込みファイルのキャッシュデータをフラッシュ
028 f_opendir FRESULT f_opendir (DIR* dp, const TCHAR* path) ディレクトリを開く
029 f_closedir FRESULT f_closedir (DIR* dp) 開いているディレクトリを閉じる
030 f_readdir FRESULT f_readdir (DIR* dp, FILINFO* fno) ディレクトリアイテムを読み込む
031 f_mkdir FRESULT f_mkdir (const TCHAR* path) サブディレクトリを作成する
032 f_unlink FRESULT f_unlink (const TCHAR* path) 既存のファイルまたはディレクトリを削除する
033 f_rename FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new) ファイルまたはディレクトリの名前変更/移動
034 f_stat FRESULT f_stat (const TCHAR* path, FILINFO* fno) ファイルステータスを取得
035 f_chmod FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask) ファイル/ディレクトリの属性を変更
036 f_utime FRESULT f_utime (const TCHAR* path, const FILINFO* fno) ファイル/ディレクトリのタイムスタンプを変更
037 f_chdir FRESULT f_chdir (const TCHAR* path) カレントディレクトリを変更
038 f_chdrive FRESULT f_chdrive (const TCHAR* path) カレントドライブを変更
039 f_getcwd FRESULT f_getcwd (TCHAR* buff, UINT len) カレントディレクトリを取得
040 f_getfree FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs) ドライブの空きクラスター数を取得
041 f_getlabel FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn) ボリュームラベルを取得
042 f_setlabel FRESULT f_setlabel (const TCHAR* label) ボリュームラベルを設定
043 f_expand FRESULT f_expand (FIL* fp, FSIZE_t szf, BYTE opt) ファイルに連続ブロックを割り当てる
044 f_mount FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt) 論理ドライブをマウント/アンマウント
045 f_mkfs FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len) FAT ボリュームを作成
046 f_putc FRESULT f_putc (TCHAR c, FIL* fp) ファイルに文字を書き込む
047 f_gets FRESULT f_gets (TCHAR* buff, int len, FIL* fp) ファイルから文字列を取得
048 disk_read DRESULT disk_read ( BYTE drv, BYTE *buff, DWORD sector, UINT count ) SD カードから完全または部分的なセクターを直接読み込む
049 disk_write DRESULT disk_write ( BYTE drv, const BYTE *buff, DWORD sector, UINT count ) SD カードに完全または部分的なセクターを直接書き込む
050 disk_ioctl DRESULT disk_ioctl ( BYTE drv, BYTE ctrl, void *buff ) SD カードに直接制御コマンドを発行。
051 getStrParam char *getStrParam(char **ptr) 文字列パラメーターリスト内の次の文字列パラメーターへのポインターを取得。文字列パラメーターリストへのポインターは次の +1 パラメーターを指すように更新される。
052 getUintParam uint32_t getUintParam(char **ptr) 文字列パラメーターリストから次の 32 ビット符号なし整数を取得。ポインターは次の +1 パラメーターを指すように更新される。
053 set_serial_output void set_serial_output(uint8_t c) 複数のシリアルポートを持つボードで、指定されたデバイスをプライマリ出力ストリームデバイスとして割り当てる。
054 printFSCode void printFSCode(FRESULT result) Fat FS 呼び出しの結果コードをテキストとして出力。
055 malloc void *malloc(size_t __size) ヒープにメモリブロックを割り当てる。
056 realloc void *realloc(void *__ptr, size_t __size) メモリブロックのサイズを変更し、新しいブロックが必要な場合はデータをコピーする。
057 calloc void *calloc(size_t __size) ヒープにゼロ初期化されたメモリブロックを割り当てる。
058 free void free(void *__ptr) メモリブロックをヒープに解放する。
059 setupZ80Pins void setupZ80Pins(uint8_t, volatile uint32_t *) Z80 機能に従ってすべてのピンを初期化する。ハードウェアから論理マッピングテーブルを設定。
060 resetZ80 void resetZ80(uint8_t) Z80 の物理 RESET を実行。
061 reqZ80Bus uint8_t reqZ80Bus(uint32_t) Z80 バスの制御を要求。
062 reqMainboardBus uint8_t reqMainboardBus(uint32_t) ホストマザーボードのリソースにアクセスするために Z80 バスの制御を要求。
063 reqTranZPUterBus uint8_t reqTranZPUterBus(uint32_t, enum TARGETS) tranZPUter のリソースにアクセスするために Z80 バスの制御を要求。
064 setupSignalsForZ80Access void setupSignalsForZ80Access(enum BUS_DIRECTION) Z80 アクセスの方向(読み取りまたは書き込み)を設定。
065 releaseZ80 void releaseZ80(void) 以前に付与された Z80 バスを解放。
066 writeZ80Memory uint8_t writeZ80Memory(uint32_t, uint8_t, enum TARGETS) Z80 ホストメモリに 1 バイトを書き込む。
067 readZ80Memory uint8_t readZ80Memory(uint32_t) Z80 ホストメモリから 1 バイトを読み込む。
068 writeZ80IO uint8_t writeZ80IO(uint32_t, uint8_t, enum TARGETS) Z80 I/O 領域に 1 バイトを書き込む。
069 readZ80IO uint8_t readZ80IO(uint32_t, enum TARGETS) Z80 I/O 領域から 1 バイトを読み込む。
070 refreshZ80 void refreshZ80(void) 次の RAS リフレッシュを実行(ホスト DRAM のリフレッシュ用)。
071 refreshZ80AllRows void refreshZ80AllRows(void) ホスト DRAM の完全リフレッシュ(全行)を実行。
072 setCtrlLatch void setCtrlLatch(uint8_t) 異なるメモリプロファイルに影響を与えるメモリモードラッチを設定。
073 setZ80CPUFrequency uint32_t setZ80CPUFrequency(float, uint8_t) Z80 CPU の周波数を 1Hz〜24MHz の範囲で設定。
074 copyFromZ80 uint8_t copyFromZ80(uint8_t *, uint32_t, uint32_t, enum TARGETS) Z80 ホストから K64F RAM にメモリブロックをコピー。
075 copyToZ80 int8_t copyToZ80(uint32_t, uint8_t *, uint32_t, enum TARGETS) K64F RAM/FlashRAM から Z80 ホストメモリにメモリブロックをコピー。
076 fillZ80Memory void fillZ80Memory(uint32_t, uint32_t, uint8_t, enum TARGETS) ホストにあるメモリブロックを指定した値で埋める。
077 captureVideoFrame void captureVideoFrame(enum VIDEO_FRAMES, uint8_t) スクリーンビデオバッファの内容をキャプチャしてローカル RAM に保存。
078 refreshVideoFrame void refreshVideoFrame(enum VIDEO_FRAMES, uint8_t, uint8_t) ローカル RAM ベースのビデオバッファからホストビデオバッファにリフレッシュまたは書き込み。
079 loadVideoFrameBuffer FRESULT loadVideoFrameBuffer(char *, enum VIDEO_FRAMES) ファイルの内容でローカル RAM ベースのビデオバッファをロード。
080 saveVideoFrameBuffer FRESULT saveVideoFrameBuffer(char *, enum VIDEO_FRAMES) ローカル RAM ベースのビデオバッファをファイルに保存。
081 getVideoFrame char *getVideoFrame(enum VIDEO_FRAMES) ローカル RAM ベースのビデオフレームのアドレスを取得。
082 getAttributeFrame char *getAttributeFrame(enum VIDEO_FRAMES) ローカル RAM ベースのビデオ属性フレームのアドレスを取得。
083 loadZ80Memory FRESULT loadZ80Memory(const char *, uint32_t, uint32_t, uint32_t, uint32_t *, enum TARGETS, uint8_t) ファイルの内容から Z80 ホストメモリをロード。
084 loadMZFZ80Memory FRESULT loadMZFZ80Memory(const char *, uint32_t, uint32_t *, enum TARGETS, uint8_t) Sharp MZF 形式のファイル内容を Z80 メモリにロード。
085 saveZ80Memory FRESULT saveZ80Memory(const char *, uint32_t, uint32_t, t_svcDirEnt *, enum TARGETS) Z80 ホストメモリの内容をファイルに保存。
086 memoryDumpZ80 int memoryDumpZ80(uint32_t, uint32_t, uint32_t, uint8_t, enum TARGETS) Z80 ホストメモリの内容を現在の出力デバイスに書式付き 16 進数形式でダンプ。
087 isZ80Reset uint8_t isZ80Reset(void) 外部ホスト RESET が発生したかどうかをテスト。
088 isZ80MemorySwapped uint8_t isZ80MemorySwapped(void) Sharp MZ-80A で 0000 からのメモリが C000 に入れ替わったかどうかをテスト。
089 getZ80IO uint8_t getZ80IO(uint8_t *) 前回のポーリング以降に Z80 I/O イベントが発生した場合に取得するメソッド。tranZPUter SW ボード v2.x 以降のバージョンでは Z80 I/O イベントのトラップが不要になったため、このメソッドは非推奨。
090 clearZ80Reset void clearZ80Reset(void) 外部 RESET イベントをクリアするメソッド。
091 hardResetTranZPUter void hardResetTranZPUter(void) tranZPUter ボードのハードリセットを強制するメソッド。
092 convertSharpFilenameToAscii void convertSharpFilenameToAscii(char *, char *, uint8_t) Sharp MZF のファイル名を ASCII 形式に変換するメソッド。
ベクター番号は参照用のみです。アプリケーションはコード内で実際のメソッドを使用し、マクロが正しいベクター呼び出しを設定します。

上記のメソッドに加えて、アプリケーションに公開され自由に使用できる 2 つのグローバルパラメーターブロックがあります:

変数 G でアクセスするグローバルパラメーターブロック:

// アプリケーションからアクセス可能なグローバルパラメーター。
typedef struct {
    uint8_t                  fileInUse;                                // file[0] が使用中かどうかを示すフラグ。
    FIL                      File[MAX_FILE_HANDLE];                    // 最大オープンファイルオブジェクト数
    FATFS                    FatFs[FF_VOLUMES];                        // 各論理ドライブのファイルシステムオブジェクト
    BYTE                     Buff[512];                                // 作業用ディスクバッファ
    DWORD                    Sector;                                   // 読み込むセクター
  #if defined __K64F__
    uint32_t volatile        *millis;                                  // K64F ミリ秒ティックへのポインター
  #endif
  #if defined __TRANZPUTER__
    int                      ctrlThreadId;                             // tranZPUter 制御スレッドの ID。
    uint8_t                  ctrlThreadBusy;                           // 制御スレッドが中断できない状態を示すフラグ。
  #endif
} GLOBALS;

プログラム内での使用例:

 printf("Sector:%d\n", G->Sector);

変数 cfgSoC でアクセスする設定ブロック:

// 設定値。
typedef struct
{
    uint32_t                           addrInsnBRAM;
    uint32_t                           sizeInsnBRAM;
    uint32_t                           addrBRAM;
    uint32_t                           sizeBRAM;
    uint32_t                           addrRAM;
    uint32_t                           sizeRAM;
    uint32_t                           addrSDRAM;
    uint32_t                           sizeSDRAM;
    uint32_t                           addrWBSDRAM;
    uint32_t                           sizeWBSDRAM;
    uint32_t                           resetVector;
    uint32_t                           cpuMemBaseAddr;
    uint32_t                           stackStartAddr;
    uint16_t                           zpuId;
    uint32_t                           sysFreq;
    uint32_t                           memFreq;
    uint32_t                           wbMemFreq;
    uint8_t                            implSoCCFG;
    uint8_t                            implWB;
    uint8_t                            implWBSDRAM;
    uint8_t                            implWBI2C;
    uint8_t                            implInsnBRAM;
    uint8_t                            implBRAM;
    uint8_t                            implRAM;
    uint8_t                            implSDRAM;
    uint8_t                            implIOCTL;
    uint8_t                            implPS2;
    uint8_t                            implSPI;
    uint8_t                            implSD;
    uint8_t                            sdCardNo;
    uint8_t                            implIntrCtl;
    uint8_t                            intrChannels;
    uint8_t                            implTimer1;
    uint8_t                            timer1No;
} SOC_CONFIG;

プログラム内での使用例:

if(cfgSoC->implSDRAM) { ... }
アプリケーションをビルドするには、通常の C プログラム(C++ は後日対応予定)を作成する場合と同じですが、引数リスト付きの標準の「main」エントリポイントを使用する代わりに、「app」という新しいメソッドが提供されています。

このプロトタイプは次のとおりです:

 uint32_t app(uint32_t param1, uint32_t param2)
param1 と param2 は、zOS 内で fileExec が呼び出されたときに渡される任意の 32 ビット値です。標準の動作条件下では、zOS はアプリケーションを 1 つのパラメーターのみで呼び出します。param1 はアプリケーションを起動したコマンドラインパラメーターへの (char *) ポインターです。

アプリケーションから zOS への戻りコードは 32 ビット符号なし整数です。0 はアプリケーションが正常に実行されたことを意味し、0xFFFFFFFF は失敗を示します。その間の値は、より詳細な失敗情報、参照、または将来のコマンドによる条件処理に使用されます。

app() の標準テンプレートは以下のとおりです:

// zOS/ZPUTA アプリケーションのメインエントリおよび開始ポイント。2 つのパラメーターと 32 ビットの戻りコードのみ対応。
// 追加パラメーターは appcrt0.s のスタートアップコードを変更して app() 呼び出し前にスタックに追加することで対応可能。
//
// ZPU の戻りコードは C コンパイラーにより _memreg に保存され、返却前に appcrt0.s で zOS/ZPUTA の _memreg に転送される。
// K64F ARM プロセッサは標準のレジスタ渡し規約を使用し、戻りコードは R0 に保存される。
//
uint32_t app(uint32_t param1, uint32_t param2)
{
    // 初期化。
    //
    char      *ptr = (char *)param1;
    long      startAddr;
    long      endAddr;
    long      bitWidth;
    long      xferSize;
  #if defined __K64F__
    uint32_t  perfTime;
  #endif
    uint32_t  retCode = 0;

    if (!xatoi(&ptr, &startAddr))
    {
        printf("Illegal <start addr> value.\n");
        retCode = 0xFFFFFFFF;
    } else if (!xatoi(&ptr, &endAddr))
    {
        printf("Illegal <end addr> value.\n");
        retCode = 0xFFFFFFFF;
    } else
    {
        xatoi(&ptr,  &bitWidth);
        if(bitWidth != 8 && bitWidth != 16 && bitWidth != 32)
        {
            bitWidth = 32;
        }
        if(!xatoi(&ptr,  &xferSize))
        {
            xferSize = 10;
        }
    }

    ... アプリケーションロジック

    return(retCode);
}

ソフトウェアビルド

このセクションでは、基本的な zOS カーネルの作成方法を示します。zOS のビルドの開始点は、必要なすべてのロジックを含む「build.sh」スクリプトです。このプログラムは当初、知識のダンプとして始まり、ソフトウェアの進歩とともに拡張されてきました。このスクリプトは最終的には Python や Java でコーディングされるべきものを BASH シェル言語に押し込んでいるため、再設計できると良いのですが、現時点ではこのソフトウェアのビルドに機能しています。

パス

読みやすさのため、以下の短縮名はこの章の対応するパスを指します。

短縮名 パス 説明
[<ABS PATH>] このリポジトリがシステム上で展開されたパス。  
<apps> [<ABS PATH>]/zsoft/apps アプリケーションディレクトリ。すべての zOS/ZPUTA アプリケーションとその Makefile がここに格納されています。
<build> [<ABS PATH>]/zsoft/build コンパイルされたソフトウェアのターゲット出力ディレクトリ。例: <z-build>/SD には SD カードに書き込むすべてのファイルが含まれています。
<common> [<ABS PATH>]/zsoft/common ライブラリに組み込まれない共通の C/C++ メソッド。
<libraries> [<ABS PATH>]/zsoft/libraries C/C++ ライブラリ。通常は C/C++ インストールの一部ですが、組み込み作業(特に ZPU)では個別に作成する必要があります。
<teensy3> [<ABS PATH>]/zsoft/teensy3 K64F ベースの Teensy 3.5 ソフトウェア。一部は K64F 版 zOS で使用されます。豊富なライブラリを持ち、K64F プログラムに容易に追加できます。
<include> [<ABS PATH>]/zsoft/include 共通インクルードヘッダーファイル。
<startup> [<ABS PATH>]/zsoft/startup 組み込みプロセッサのスタートアップファイル(主にアセンブラー)。テンプレートとマクロを使用して正しいターゲットメモリモデルのスタートアップコードを生成します。
<iocp> [<ABS PATH>]/zsoft/iocp IO 制御プログラム。ZPU 上でアプリケーションをブートストラップするための初期ブートローダー。
<zOS> [<ABS PATH>]/zsoft/zOS zOS のソースコード。異なるターゲット CPU 向けにパラメーター化されています。
<zputa> [<ABS PATH>]/zsoft/zputa ZPUTA のソースコード。異なるターゲット CPU 向けにパラメーター化されています。
<rtl> [<ABS PATH>]/zsoft/rtl レジスタ転送レベルファイル。ZPU ターゲットプロジェクトのビルドに必要な生成されたメモリ定義および初期化ファイル。
<docs> [<ABS PATH>]/zsoft/docs ソフトウェアに関連するドキュメント。
<tools> [<ABS PATH>]/zsoft/tools コンパイルとターゲットファイル作成を支援するツール。

ツール

すべての開発は Linux(特に Debian/Ubuntu)環境で行われています。標準の Linux ビルドチェーンに加えて、以下のソフトウェアが必要です。

   
ZPU GCC ToolChain ZPU 開発用の GCC ツールチェーン。/opt または同様の共通領域にインストールしてください。
Arduino Arduino 開発環境。広範な Arduino ライブラリから K64F 版 zOS に機能を追加しない限り実際には不要。参照用として利用可能。
Teensyduino Arduino レベルで Teensy3.5 ボードを扱うための Teensy3 Arduino 拡張機能。実際には不要、参照用として利用可能。

Teensy3.5/K64F の場合、ARM 互換ツールチェーンはビルドツリー内のリポジトリに保存されています。

ビルドツリー

ソフトウェアは以下のツリー/フォルダー構造で整理されています:

フォルダー ソースファイル 説明
apps   zOS/ZPUTA アプリケーションアプレットツリー。これらは zOS/ZPUTA の下で実行されるディスクベースのスタンドアロンアプレットです。
zOS/ZPUTA のすべてのアプレットはこのフォルダー内に保存されています。
build   SD カードに直接コピーするのに適したビルドツリー出力。
選択した初期ブートローダーおよび/またはアプリケーションは、devices/sysbus/BRAM フォルダーの BRAM に事前ロードするために VHDL ファイルに直接コンパイルされます。
common   Elm Chan の優れた Fat ファイルシステムなどの共通 C モジュール。
docs   このプロジェクトに関連するすべてのドキュメント。
libraries   コードライブラリ。umlibc と FreeRTOS がまもなく追加される予定。
rtl   レジスタ転送レベルテンプレートと生成されたファイル。これらのファイルには、ZPU と共に使用される BRAM ベースの RAM/ROM の事前ロード済み VHDL 定義が含まれています。
teensy3   K64F プロセッサターゲットのビルドに必要な Teensy 3.5 ファイル。
include   C インクルードヘッダーファイル。
iocp   ZPU の初期化用の小さなブートローダー/モニターアプリケーション。設定に応じて SD カードまたはシリアルラインからアプリケーションをブートしたり、メモリ検査などの基本ツールを提供したりできます。
startup   ZPU アプリケーション生成用のアセンブラーおよびリンカーファイル。GCC がバイナリイメージを作成してリンクする方法を定義し、ハードウェアに実装されていない ZPU 命令のマイクロコードを提供するために重要なファイルです。
tools   バイナリイメージを VHDL 初期化データに変換するための小さなツール。
zputa   ZPU テストアプリケーション。ZPU と SoC コンポーネントをテストするためのアプリケーションです。VHDL 経由で BRAM に事前ロードするための単一イメージとして、または IOCP ブートローダーによって SD カードからロードされるスタンドアロンアプリケーションとして構築できます。提供するサービスはメモリ制限に応じて組み込みまたは SD カード上のアプレットとして利用可能です。
zOS   z オペレーティングシステム。ZPUTA から派生した軽量 OS で、ZPU または K64F プロジェクト内でアプリケーションビルドとランタイム制御の両方のフレームワークを提供することを目的としています。OS はディスクベースのサービス、共通ハードウェアアクセス API、およびこの環境用にビルドされたアプリケーションを実行・サービスするための追加機能を提供します。アプリケーションはシリアルベースの VT100 コンソールを介して自律的またはインタラクティブに起動できます。
  build.sh IOCP、zOS、ZPUTA、および特定のデザイン向けアプリをビルドする Unix シェルスクリプト。
build.sh
  buildall tranZPUter SW-700 v1.3 ボードのすべての依存関係(K64F 用組み込み zOS+アプリケーションと ZPU 用ホスト zOS+アプリケーション)をビルドする Unix シェルスクリプト。

Build.sh

zOS は「build.sh」スクリプトを使用してビルドします。このスクリプトは、多数のフラグとオプションを持つ Makefile システムをカプセル化します。スクリプトの概要は以下のとおりです:

NAME
    build.sh -  ZPU/K64F プログラムまたは OS をビルドするシェルスクリプト。

SYNOPSIS
    build.sh [-CIOoMBAsTZdxh]

DESCRIPTION

OPTIONS
    -C <CPU>      = Small, Medium, Flex, Evo, EvoMin, K64F - デフォルトは Evo。
    -I <iocp ver> = 0 - フル、1 - ミディアム、2 - 最小、3 - タイニー(ブートストラップのみ)
    -O <os>       = zputa, zos
    -o <os ver>   = 0 - スタンドアロン、1 - IOCP ブートローダー付きアプリとして、
                    2 - タイニー IOCP ブートローダー付きアプリとして、3 - RAM 内アプリとして
    -M <size>     = ブート ROM/BRAM の最大サイズ(スタック設定に必要)。
    -B <addr>     = <os> のベースアドレス、デフォルト -o == 0 : 0x00000 それ以外 0x01000
    -A <addr>     = <os> のアプリアドレス、デフォルト 0x0C000
    -N <size>     = 必要なヒープサイズ
    -n <size>     = 必要なアプリケーションヒープサイズ
    -S <size>     = 必要なスタックサイズ
    -s <size>     = 必要なアプリケーションスタックサイズ
    -a <size>     = アプリの最大サイズ。デフォルトは、アプリ開始が BRAM 内にある場合
                    (BRAM SIZE - アプリ開始アドレス - スタックサイズ)、それ以外は 0x10000。
    -T            = tranZPUter 固有ビルド、初期化とセットアップコードを追加。
    -Z            = Sharp MZ シリーズ ZPU ビルド、zOS が Sharp MZ ハードウェア上でホスト OS として動作。
    -d            = デバッグモード。
    -x            = シェルトレースモード。
    -h            = このヘルプ画面。

EXAMPLES
    build.sh -O zputa -B 0x00000 -A 0x50000

EXIT STATUS
     0    コマンドが正常に実行された

     >0    エラーが発生した。

スクリプトには適切なデフォルト値が設定されています。オーバーライドフラグの説明は以下のとおりです。

フラグ            説明
-C <CPU> 完成したイメージのターゲット CPU。各 ZPU は異なる設定を持ち、基盤となる Make のスタートアップコードと設定の選択を誘導する必要があるため、このフラグは必須です。ARM ベースの K64F の追加により、このフラグはさらに意味を持ちます。

選択肢:
Small - ほとんどの命令がマイクロコードで実装された最小限の ZPU ハードウェア設計。
Medium - より多くのハードウェアと優れた性能を使用した中間的な ZPU 設計。大部分の命令がハードウェアに組み込まれています。
Flex - 多くの拡張機能を持つ ZPU Small ベースの設計。大部分の命令がハードウェアに組み込まれています。
Evo - ZPU の最新の進化版。すべての命令がハードウェアに組み込まれ、拡張命令を追加するフレームワークと性能向上のための 2 段階キャッシュを持ちます。
K64F - Freescale の ARM Cortex-M4 ベースプロセッサ。
デフォルトは Evo。
-I <iocp ver> ビルドのメモリモデルを設定。メモリモデルは上述のとおりです。

選択肢:
0 - フル
1 - ミディアム
2 - 最小
3 - タイニー(ブートストラップのみ)。
デフォルトは 3。
-O <os> ターゲットオペレーティングシステムを設定。

選択肢:
zputa - K64F でも動作する ZPU テストアプリケーション。
zos - zOS オペレーティングシステム。
デフォルトはありません。OS をビルドする場合はこのフラグが必須です。
-o <os ver> オペレーティングシステムのターゲットモデルを設定。

選択肢:
0 - スタンドアロン、OS がスタートアップファームウェアです。
1 - IOCP ブートローダー付きアプリとして、OS は SD カードから IOCP によってブートされ、IOCP はメモリ常駐します。
2 - タイニー IOCP ブートローダー付きアプリとして、OS は可能な限り最小の IOCP によって SD カードからブートされ、IOCP はメモリ常駐します。
3 - RAM 内アプリとして、OS は FPGA 外部の(静的または動的)RAM にロードされるよう設定され、IOCP は BRAM に常駐します。
デフォルトは 2。
このフラグは K64F ターゲットには意味がありません。
-M <size> ブート ROM/BRAM の最大サイズを指定(スタック設定に必要)。
このフラグは K64F ターゲットには意味がありません。
-B <addr> <os> のベースアドレス。
デフォルト: -o == 0 の場合 0x00000、それ以外 0x01000
このフラグは K64F ターゲットには意味がありません。
-A <addr> 指定された <os> のアプリ開始/ロードアドレス。
ZPU のデフォルトは 0x0C000、K64F は 0x1FFF0000
-N <size> <os> ヒープの必要サイズ。OS とアプリケーションのヒープは現在別々です。RTOS が zOS に統合される場合は変更される予定です。
-n <size> アプリケーションヒープの必要サイズ。アプリケーションには別途ヒープが割り当てられ、アプリケーションによって管理されます。
-S <size> スタックの必要サイズ。通常、<os> はアプリケーションでも使用されるスタックを管理します。アプリケーションが危険と見なされる場合はローカルスタックを割り当てる必要があります。
-s <size> アプリケーションスタックの必要サイズ。通常、アプリケーションは <os> のスタックを共有するため不要です。アプリケーションが危険な場合はこの値を設定してローカルスタックを割り当てます。
-a <size> アプリケーションの最大サイズ。
ZPU では、アプリ開始が BRAM 内にある場合 (BRAM SIZE - アプリ開始アドレス - スタックサイズ)、それ以外は 0x10000 がデフォルト。K64F では 0x20030000 - スタックサイズ - ヒープサイズ - 0x4000。アプリ開始が BRAM 内にある場合、それ以外は 0x10000。
-T tranZPUter 固有ビルド。初期化とセットアップコードを追加。tranZPUter ボード用の組み込み OS としてビルド。
-Z Sharp MZ シリーズ ZPU ビルド。zOS が Sharp MZ ハードウェア上でホスト OS として動作。ZPU/NIOSII をホストプロセッサとして実行する Sharp MZ シリーズコンピューター用のホスト OS としてビルド。
-d デバッグモード。スクリプトが行う状態と判断のより詳細な出力を有効化。
-x シェルトレースモード。シェル実行の非常に低レベルな行ごとのトレース。デバッグ中のみ使用。
-h このヘルプ画面。


Freescale K64F プロセッサ上で実行する標準 zOS をビルドするには、以下のコマンドを発行します:

<ABS PATH>/build.sh -C K64F -O zos -B 0x00000000 -N 0x00002000 -S 0x00001000 -A 0x1FFF0000 -n 0x00020000 -s 0x00000000

これは以下を指定します:

  • ターゲット CPU は K64F プロセッサ (-C K64F)、
  • ターゲット OS は zOS (-O zos)、
  • 生成されるファームウェアのベースまたは開始アドレスは 0x00000000 (-B 0x00000000)、
  • zOS のヒープサイズは 0x00002000 バイト (-N 0x00002000)、
  • zOS のスタックサイズは 0x000010000 バイト (-S 0x000010000)、
  • アプリケーションの開始アドレスは RAM のベース 0x1FFF0000 (-A 0x1FFF0000)、
  • アプリケーションヒープサイズは 0x00020000 (-n 0x00020000)、
  • アプリケーションにはローカルスタックがない (-s 0x00000000)。

完了すると、出力は 2 つの場所に保存されます:

<zOS>/main.(hex | bin | srec) - 0x00000000 の K64F FlashRAM に直接フラッシュできる 3 つの標準形式の主要 zOS ファームウェア。<br>
<build>/SD - FAT32 フォーマットの SD カードに直接コピーできるアプリケーション(および ZPU プロセッサと IOCP を使用する場合はカーネル)。<br>

CI/CDパイプライン

zOSは、サポートされているすべてのプロセッサターゲットに対して自動コンパイルとリリース管理を行うJenkins CI/CDパイプラインを使用しています。パイプラインは3つのバリアント(tranZPUterボード上のFPGA用ZPU EVO、および2つの異なるSharp MZマシンファミリー用のK64F(ARM Cortex-M4)ファームウェア)をビルドします。ビルドはGiteaウェブフックによって自動的にトリガーされ、配布用のバージョン管理されたリリース成果物を生成します。

Jenkinsパイプライン概要

zOS CI/CDパイプラインは、EaW VPS上のDockerコンテナ内で動作するJenkinsインスタンス上で実行されます。mainまたはmasterブランチにコミットがプッシュされると、Giteaウェブフックによって自動的にトリガーされます。パイプラインのステージは以下の通りです:
  1. チェックアウト — ワークスペースをクリーンにし、GiteaからzOSリポジトリをクローンします。
  2. バージョン決定 — リポジトリルートからVERSIONを読み取ります。前回のコミットからバージョンが変更されていない場合、最新のGiteaリリースタグからバージョン番号を自動インクリメントします。
  3. Sharp MZ用ZPU EVOビルド — ZPU Evoプロセッサ用にIOCPブートローダー、zOSカーネル、60以上のアプリケーションをコンパイルします。SDカードイメージとFPGA用VHDL BRAMテンプレートを生成します。
  4. MZ-700用K64Fビルド — MZ-700上のK64F(Teensy 3.5)用にzOSをコンパイルします。MZ-700のメモリ構成に合わせてヒープサイズ0x18000を使用します。
  5. MZ-80A/MZ-2000用K64Fビルド — MZ-80AおよびMZ-2000上のK64F用にzOSをコンパイルします。これらのマシンに適した小さいヒープサイズ0x10000を使用します。
  6. リリースパッケージ作成 — 各ビルドバリアント用にgzip圧縮されたリリースアーカイブを作成します。
  7. Giteaリリース作成 — リリース成果物をバージョン番号でタグ付けされた新しいGiteaリリースにアップロードします。

Dockerビルド環境

zOSのビルドには2つのクロスコンパイルツールチェーンが必要です:ZPU EVOプロセッサ用のzpu-elf-gccとK64F(ARM Cortex-M4)用のarm-none-eabi-gccです。これらはdebian:bookworm-slimをベースにしたカスタムDockerイメージ(zos-builder:latest)にパッケージされています。このイメージにはdcbuild.shが16進数演算に使用するデスクカリキュレータ)、gawk/nawk、および標準ビルドツールも含まれています。
Jenkins自体がDockerコンテナ内で実行されるため、zOSビルドはサイドカーコンテナパターンを使用します — 両方のコンテナがホスト上のDockerデーモンを共有します。ワークスペースパスをJenkinsコンテナパスからDockerホストパスにマッピングする必要があります。
デュアルボリュームマウントは、いくつかのMakefile(特にiocp/MakefilezOS/Makefile.zpu)がBASEDIR = ../..SWDIR = $(BASEDIR)/softwareを使用しているため必要です。これはzOSがより大きなtranZPUterリポジトリの一部であった時代のレガシーです。2つ目のマウントにより、これらのMakefileが期待する../softwareパスでワークスペースにアクセスできるようになります。

Webhook設定

パイプラインは、Jenkins Generic Webhook TriggerプラグインへのPOSTリクエストを送信するGiteaウェブフックによってトリガーされます。設定は以下の通りです:
  • Webhook URLhttp://<jenkins-container-ip>:8080/generic-webhook-trigger/invoke?token=zos-build-trigger
  • トークンzos-build-trigger
  • コンテンツタイプapplication/json
  • ブランチフィルターrefs/heads/mainまたはrefs/heads/masterへのプッシュのみでトリガーされます。

バージョン管理

ビルドバージョンはリポジトリルートのVERSIONファイルにMAJOR.MINOR形式(例:"1.05")で格納されます。バージョン管理は以下のルールに従います:
  • トリガーコミットでVERSIONが変更された場合、ファイルに指定されたバージョンがそのままリリースに使用されます。
  • VERSIONが変更されていない場合、パイプラインはGitea APIで最新のリリースタグを照会し、マイナーバージョン番号を自動インクリメントします。
  • マイナーバージョンは100でロールオーバーします:バージョン1.99は2.00にインクリメントされます。
  • VERSIONファイルが存在せず、以前のリリースも見つからない場合、バージョンはデフォルトで1.00になります。

ビルドステージ

パイプラインは、異なるプロセッサとSharp MZマシンファミリーをターゲットとする3つの異なるファームウェアバリアントをビルドします:
Sharp MZ用ZPU EVO — このステージでは、tranZPUterボード上のFPGA内で動作するZPU Evoソフトプロセッサ用にzOSをビルドします。ビルドはbuild.shによってオーケストレーションされ、3つのコンポーネントを順番にコンパイルします:
  1. IOCPブートローダー — メインOSを起動する最小限のZPUファームウェア。iocp/からzpu-elf-gccを使用してビルドされます。
  2. zOSカーネルzOS/からコンパイルされるメインオペレーティングシステム。BRAMサイズとメモリレイアウトパラメータに基づいて動的に生成されるリンカスクリプトに対してリンクされます。
  3. アプリケーションapps/からコンパイルされる60以上のユーザーアプリケーション(ファイルマネージャー、テキストエディタ、BASICインタープリター、ベンチマーク、メモリツールなど)。
MZ-700用K64F — MZ-700固有のパラメータでK64F(Teensy 3.5上のARM Cortex-M4)用にzOSをビルドします。MZ-700は利用可能なSRAMが多いため、より大きなヒープ(0x18000)を使用します。
MZ-80A/MZ-2000用K64F — MZ-80AおよびMZ-2000をターゲットにK64F用zOSをビルドします。これらのマシンはより小さなヒープ(0x10000)を使用します。

リリース成果物

各パイプライン実行で最大3つのgzip圧縮リリースアーカイブが生成されます:
成果物 内容 用途
zOS-SharpMZ-ZPU-vX.XX.tar.gz ZPU EVO SDカードイメージ + VHDL BRAMテンプレート Sharp MZシリーズ用tranZPUter FPGAファームウェア更新
zOS-K64F-MZ700-vX.XX.tar.gz K64Fファームウェア + SDカードアプリ MZ-700上のtranZPUter用Teensy 3.5更新
zOS-K64F-MZ80A-vX.XX.tar.gz K64Fファームウェア + SDカードアプリ MZ-80A/MZ-2000上のtranZPUter用Teensy 3.5更新

パイプライン設定

Jenkinsパイプラインは、Jenkinsコンテナ内の/var/jenkins_home/pipeline-scripts/zos-build.groovyに格納されたGroovyスクリプトとして定義されています。初期化スクリプト(08-zos-pipeline.groovy)がJenkins起動時にこのパイプライン定義をロードします。
変数 目的
GITEA_URL Giteaインスタンスのベース URL (https://git.eaw.app)
REPO_URL zOSリポジトリの完全なクローン URL
GITEA_TOKEN リリース作成とアセットアップロード用APIトークン
GITEA_OWNER リポジトリオーナー (“eaw”)
GITEA_REPO リポジトリ名 (“zOS”)
ZOS_DOCKER ビルド用Dockerイメージ名 (“zos-builder:latest”)

手動ビルドトリガー

リポジトリにプッシュせずにビルドを手動でトリガーするには、ウェブフックエンドポイントにPOSTリクエストを送信します:
curl -X POST \
    -H "Content-Type: application/json" \
    -d '{"ref": "refs/heads/main"}' \
    "http://<jenkins-ip>:8080/generic-webhook-trigger/invoke?token=zos-build-trigger"

メール通知

パイプラインはビルド完了時にメール通知を送信します:
  • 成功 — 件名:"zOS Build vX.XX - SUCCESS"、ビルドバージョン、ジョブ名、ビルド番号、URLを含みます。
  • 失敗 — 件名:"zOS Build - FAILED"、ジョブURLと詳細についてコンソール出力を確認するよう記載されます。
メールはJenkins初期化スクリプト05-email-config.groovyを介して設定され、support@net2net-ips.comに送信されます。

クレジット

サードパーティの設計を使用または参考にした場合は、ヘッダーに元の著者の著作権表示を含めるか、適切なクレジットを記載しています。すべてのサードパーティソフトウェアは、私の知識と調査の限りにおいてオープンソースであり自由に使用可能です。ライセンス制限のあるコンポーネントが見つかった場合は、このリポジトリから削除し、適切なリンク/設定を提供します。

ライセンス

オリジナルの ZPU は FreeBSD ライセンスを使用しており、Evo も FreeBSD の下でリリースされています。私が作成した SoC コンポーネントとその他の開発物は現在 GPL でライセンスされています。サードパーティのコンポーネントは元の著作権表示を維持します。

FreeBSD ライセンス

ソースコード形式またはバイナリ形式での再配布および使用は、変更の有無にかかわらず、以下の条件が満たされる場合に許可されます:

  1. ソースコードの再配布には、上記の著作権表示、この条件リスト、および以下の免責事項を保持する必要があります。
  2. バイナリ形式の再配布には、上記の著作権表示、この条件リスト、および以下の免責事項を、配布物に付属するドキュメントおよび/またはその他の資料に再現する必要があります。

本ソフトウェアは「現状のまま」提供され、商品性および特定目的への適合性を含む(ただしこれに限らない)いかなる明示的または黙示的な保証も否認されます。ZPU プロジェクトまたは貢献者は、直接的、間接的、偶発的、特別、懲罰的、または結果的損害(代替品またはサービスの調達、使用、データ、または利益の喪失、または事業の中断を含むがこれに限らない)について、いかなる責任理論に基づいても(契約、厳格責任、または不法行為(過失その他を含む)を問わず)、そのような損害の可能性について通知されていた場合でも、本ソフトウェアの使用から何らかの方法で生じる損害について責任を負いません。

ソフトウェアおよびドキュメントに含まれる見解と結論は著者のものであり、このプロジェクトの公式ポリシーを(明示的または黙示的に)表すものとして解釈されるべきではありません。

GNU 一般公衆ライセンス v3

GPL v3 としてマークされたこのプロジェクトのソースファイルとバイナリファイルはフリーソフトウェアです: フリーソフトウェア財団が公表した GNU 一般公衆ライセンスのバージョン 3、またはそれ以降のバージョンの条件の下で再配布および/または変更することができます。

ソースファイルは有用であることを期待して配布されていますが、いかなる保証もありません。商品性や特定目的への適合性の黙示的な保証さえも含みません。詳細については GNU 一般公衆ライセンスをご覧ください。

このプログラムとともに GNU 一般公衆ライセンスのコピーを受け取っているはずです。受け取っていない場合は http://www.gnu.org/licenses/ をご参照ください。