組み込みシステムラボ:シミュレートしたチップでレジスタ、ピン、PWM、割り込みを学ぶ

このラボでは、生徒ひとりひとりに専用の JupyterLab を渡します。中には、1行1行読めるように素直な Python で書いた、小さな架空の 8 ビットチップが入っています。チップには、レジスタが7つ、ティックで進むクロック、PWM のピンを動かすタイマー、割り込みを起こすボタンがあります。作業フォルダーには、チップの mcu.py、最初のノートブック、ひとつの考え方ずつを見せる短いスクリプトが入っています。

これは、実在しないチップのシミュレーターで、本物のボードではありません。本物のチップはレジスタの数も名前もきまりもずっと多いので、本物を使うときはデータシートを読みます。攻撃用のラボでもありません。どのコピーも、インターネットにも、ほかの生徒にもつながっていません。

生徒が学ぶこと

レジスタは、ビットのひとつひとつに意味がある1バイトであること。それを2進数、16進数、ふつうの数で表示します。次に、マスクでビットをひとつだけ立てる、下ろす、反転させること、データ方向レジスタでピンを出力にして、出力して、読み戻すこと、8ティックのあいだの点滅のパターン。さらに、タイマーと比較値で PWM の信号を作ること:周期16ティックで比較値が4、8、12なら、デューティ比は25、50、75パーセントです。最後は、バウンスするボタンです。ポーリングのループは1回の押下を2回と数え、割り込みは同じ2つのエッジでハンドラーを呼びます。ハンドラーがバウンスのおさまるのを待つようにすると、1回になります。組み込みシステム、コンピューターの構成、電子工作の入門に向いています。

ブラウザーで動かす

ラボはサービスをひとつ、jupyter だけ起動します。チップとノートブックと短いスクリプトを作業フォルダーに書き出し、数秒で使えるようになります。メモリはサービスに許された 512 MB の中です。JupyterLab はトークンを求めません。プラットフォームの入口が、誰が開いているかをすでに知っているからです。ラボの横のターミナルには Python がないので、docker exec jupyter のあとに実行したいコマンドを続けて、ラボの Python を使います。どのスクリプトも、毎回同じ結果を表示します。

  1. コンテナーのページを開く. バーの「つくる」を開き、「コンテナーを実行」を選びます。ページは誰でも開けて、Git ラボと SQL ラボはアカウントなしで起動できます。ほかのラボには無料アカウントが必要です。アカウントを作成してサインインし、「起動」を押します。
  2. ラボを探す. 「サンプルラボ」のカードにすべてのサンプルが並んでいます。JupyterLab:シミュレートしたチップで組み込みシステムを探します。
  3. 「起動」を押す. 「起動」はそのまま1回の操作で実行します。「先にファイルを編集」は compose ファイルを開くので、起動する前に変更できます。
  4. 開く. ラボのページのバーに JupyterLab というリンクがあります。押すとブラウザーで JupyterLab が開くので、start.ipynb をダブルクリックします。次に「ターミナルを開く」を押して docker exec jupyter python3 steps/registers.py と入力すると、7つのレジスタが表示されます。リセット後は、どれも 0b00000000 です。

生徒に提出させるもの

mcu.py を使った、自分の短いスクリプトかノートブックです。たとえば、8ティックの自分で考えた点滅のパターンや、自分で選んで計算したデューティ比の PWM 信号を、JupyterLab の File、Download でダウンロードして出します。そこに、レジスタが何を示したかを自分の言葉で一、二文添えます。自動採点はありません。その文で、理解できたかどうかがわかります。さらに力をつけたい生徒には、1回の押下を1回と数えるボタンのハンドラーを求め、シミュレーターが本物のチップとどこで違うかを書かせてください。

このラボで進める基本のレッスン

Embedded Systems Basics は、このラボで進める小さなレッスンです。生徒は、作業フォルダーを一覧し、レジスタを表示し、ビットを立てる、下ろす、反転させ、ピンを動かして点滅させ、3つのデューティ比の PWM 信号を作り、バウンスするボタンでポーリングと割り込みを比べます。そのあと、同じ作業を最初のノートブックで開きます。

意図的に小さく作ってあります。ラボで進めるレッスンがどういうものかを先生に見せるためで、あとはラボが担います。変更したいときは、ご自分のモジュールにコピーしてください。

GitHub のコード

compose ファイルには Dockerfile がありません。Jupyter Docker Stacks の scipy-notebook という、公開されている標準のイメージをひとつ、日付つきのタグに固定して使います。専用の権限のないアカウントで、メモリは 512 MB です。イメージのライセンスは BSD-3-Clause で、私たちは配布していません。ファイルは起動時にチップとスクリプトを書き出すので、どのコピーも同じ結果になり、何もダウンロードしません。限界もはっきりしています。架空のチップがひとつだけで、本物のタイミングも電子回路もなく、インターネットから何かをインストールすることもできず、本物のボードには学ぶことがもっとあります。ラボを止めると何も残らないので、生徒は先に作業をダウンロードします。

課題として出す

課題には、何を提出するかを書いておきます。

  1. ラボを作る. モジュールで課題を追加し、「コンテナーラボ」のカードを選んでから「GitHub リポジトリ」を選びます。https://github.com/mitsurutech/lab-embedded-sim とブランチ main を指定します。compose ファイルは既定の compose.yaml です。変更したい場合は、たとえばチップにレジスタを足したいときは、先にリポジトリをフォークしてください。
  2. 公開して試す. 「公開」すると、確認したコミットに固定されるので、あとでリポジトリを変更しても、すでに出したラボは変わりません。まず自分のコピーを起動してください。
  3. 配布する. ほかの課題と同じように配布します。期限を付けることもでき、課題には何をするか、何を提出するかを書いておきます。
  4. 提出物を採点する. 生徒のコピーを開いて提出された内容を確認し、採点します。足りない場合は理由を書いて差し戻します。

このラボを試す、そして費用

無料の個人アカウントで、このラボの基本レッスンに取り組めます。毎月、ほとんどのレッスンに足りる無料クレジットがあり、カードは要りません。クラスで使う場合、学校は最初の365日間、生徒50人まで無料で、その後は生徒1人あたりの年額です。すべてのラボが含まれ、教職員は無料です。

よくある質問

トークンやパスワードを入力しないのはなぜですか。
ラボのウェブページには、プラットフォームの入口を通ってしか行けません。入口は誰が開いているかをすでに知っていて、あなたと、あなたのモジュールの先生しか通しません。そのため JupyterLab はトークンなしで起動します。ほかの人が届く場所のコンピューターでは、このように動かさないでください。
ターミナルで docker exec jupyter を使うのはなぜですか。
ラボのターミナルには curl や psql などのクライアントはありますが、Python はありません。docker exec jupyter は、Python のあるラボのコンテナーの中でコマンドを実行します。JupyterLab にも、File、New、Terminal から開く自分のターミナルがあります。
これは本物のチップですか。
いいえ。本物のチップに共通する考え方、つまりレジスタ、ビット、ピン、タイマー、割り込みを、読んで動かせるように Python で書いた、小さな架空のチップです。本物のチップは、レジスタの名前もビットの位置も違い、電気的な動きや本物のタイミングがありますが、ここではそのどれもシミュレートしていません。
生徒はチップを変えてもよいですか。
はい。mcu.py は作業フォルダーにあり、短くコメントがついているので、レジスタを足したり、タイマーの周期を変えたりして、スクリプトをもう一度動かせます。変更はラボを止めるまでしか残りません。クラス全体で別のチップを使いたいときは、リポジトリをフォークし、compose ファイルが書き出すファイルを変えて、そのフォークをラボに指定してください。