組み込みシステムラボ:シミュレートしたチップでレジスタ、ピン、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 を使います。どのスクリプトも、毎回同じ結果を表示します。
- コンテナーのページを開く. バーの「つくる」を開き、「コンテナーを実行」を選びます。ページは誰でも開けて、Git ラボと SQL ラボはアカウントなしで起動できます。ほかのラボには無料アカウントが必要です。アカウントを作成してサインインし、「起動」を押します。
- ラボを探す. 「サンプルラボ」のカードにすべてのサンプルが並んでいます。JupyterLab:シミュレートしたチップで組み込みシステムを探します。
- 「起動」を押す. 「起動」はそのまま1回の操作で実行します。「先にファイルを編集」は compose ファイルを開くので、起動する前に変更できます。
- 開く. ラボのページのバーに 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 で、私たちは配布していません。ファイルは起動時にチップとスクリプトを書き出すので、どのコピーも同じ結果になり、何もダウンロードしません。限界もはっきりしています。架空のチップがひとつだけで、本物のタイミングも電子回路もなく、インターネットから何かをインストールすることもできず、本物のボードには学ぶことがもっとあります。ラボを止めると何も残らないので、生徒は先に作業をダウンロードします。
課題として出す
課題には、何を提出するかを書いておきます。
- ラボを作る. モジュールで課題を追加し、「コンテナーラボ」のカードを選んでから「GitHub リポジトリ」を選びます。https://github.com/mitsurutech/lab-embedded-sim とブランチ main を指定します。compose ファイルは既定の compose.yaml です。変更したい場合は、たとえばチップにレジスタを足したいときは、先にリポジトリをフォークしてください。
- 公開して試す. 「公開」すると、確認したコミットに固定されるので、あとでリポジトリを変更しても、すでに出したラボは変わりません。まず自分のコピーを起動してください。
- 配布する. ほかの課題と同じように配布します。期限を付けることもでき、課題には何をするか、何を提出するかを書いておきます。
- 提出物を採点する. 生徒のコピーを開いて提出された内容を確認し、採点します。足りない場合は理由を書いて差し戻します。
このラボを試す、そして費用
無料の個人アカウントで、このラボの基本レッスンに取り組めます。毎月、ほとんどのレッスンに足りる無料クレジットがあり、カードは要りません。クラスで使う場合、学校は最初の365日間、生徒50人まで無料で、その後は生徒1人あたりの年額です。すべてのラボが含まれ、教職員は無料です。
よくある質問
- トークンやパスワードを入力しないのはなぜですか。
- ラボのウェブページには、プラットフォームの入口を通ってしか行けません。入口は誰が開いているかをすでに知っていて、あなたと、あなたのモジュールの先生しか通しません。そのため JupyterLab はトークンなしで起動します。ほかの人が届く場所のコンピューターでは、このように動かさないでください。
- ターミナルで docker exec jupyter を使うのはなぜですか。
- ラボのターミナルには curl や psql などのクライアントはありますが、Python はありません。docker exec jupyter は、Python のあるラボのコンテナーの中でコマンドを実行します。JupyterLab にも、File、New、Terminal から開く自分のターミナルがあります。
- これは本物のチップですか。
- いいえ。本物のチップに共通する考え方、つまりレジスタ、ビット、ピン、タイマー、割り込みを、読んで動かせるように Python で書いた、小さな架空のチップです。本物のチップは、レジスタの名前もビットの位置も違い、電気的な動きや本物のタイミングがありますが、ここではそのどれもシミュレートしていません。
- 生徒はチップを変えてもよいですか。
- はい。mcu.py は作業フォルダーにあり、短くコメントがついているので、レジスタを足したり、タイマーの周期を変えたりして、スクリプトをもう一度動かせます。変更はラボを止めるまでしか残りません。クラス全体で別のチップを使いたいときは、リポジトリをフォークし、compose ファイルが書き出すファイルを変えて、そのフォークをラボに指定してください。