背景
2020年は混沌とした年であり、また私にとってはコンピュータの本質を再考する年でもありました。この年には得意ではない分野で多くの試みをしましたが、基本的にはすべて「ローレベルの理解」をテーマにしていました。
私は高校(正確には高職)で電子科を学んでいましたが、進学が主流となっていた時代にはインターンシップの授業がありましたが、ほとんどが単なる課題の解答であり、ほとんどの時間は勉強や問題解決に費やされました。唯一の救いは、一般的な高校のように多忙な学業ではなかったことですが、そうでなければ台科に合格することもできなかったでしょう。
高校で少し残念だったのは、実際に手を動かして何かを作ることにあまり興味が持てなかったことです。そして、多くの時間がはんだ付けやブレッドボードの接続、線の重なりを避けることに費やされました。私のような不器用な人にとっては、それは本当に苦手でした。
実際、電子科を学んでいた当時は、電子にあまり興味がありませんでしたし、後にプログラムを書いて生計を立てることになるとも予想していませんでした。しかし、そのために最近、これらのよりローレベルのものに興味を持ち始めました。
この問題自体に戻ると、答えはコンピュータの理解の深さによって異なります。ダイオードやトランジスタ、レジスタ、CPUの動作、オペレーティングシステムなど、各分野の知識は一生かけても完全に理解することはできません。本当に奥深いです。
私にとって、今年はコンピュータが何であるかを理解する年です。専門的ではありませんが、私はそこで多くの楽しみを見つけ、また会社で同じようにローレベルに興味を持つ同僚を見つけました。
電子科との重なり
高校で電子科の関連知識を学んでいたとき、後にこれらの知識が非常に役立つことを予想していませんでした。例えば、ブリッジ整流、ダイオード、フィルタ、レギュレータなどは、充電器でよく使用される回路です。これらのものは試験で何度も出題され、実習の授業でブリッジ整流回路の実験を行うよう指示されました。
CPUの加算には加算器を実装する必要があり、それは半加算器と全加算器に分かれます。これらは真理値表を学び、ロジックゲートを使用してブレッドボード上に実装することで学びました(もちろんICを直接使用することもできます)。
CPUの動作にはクロックが必要であり、一般的にはクォーツ発振子を使用するか、別途クロックジェネレータを接続します。おっと、当初学んでいた謎のフリップフロップは、実際にはレジスタの実装です。より多くの基礎を理解するにつれて、これらのものが高校で既に学んだことだと気付きましたが、当時はこれらの知識を結びつけることはありませんでした。
これらのローレベルの知識には一種の神秘性があります。一方で、それは比較的高い入門障壁があるためです。毎日誰かがチップを購入してブレッドボードに差し込むわけではないでしょうし、各知識点についてある程度の理解が必要です。もう一方では、インターネット上には情報が非常に少ないため、キーワード検索にはかなりの時間がかかり、答えがフォーラムのx番目のコメントの下にあることがわかるまでにはかなりの努力が必要です。多くの場合、問題が発生した場合には自分自身で解決する方法を見つける必要があります。
基礎に回帰する
そのため、2020年にはできるだけローレベルに近づくことを目指す課題がありました。ハードウェアであっても、オペレーティングシステムの動作であっても、プログラミング言語の動作を理解することでも構いません。とにかく、ローレベルのものを理解することができれば良かったのです。
したがって、今年の初めにArduinoを購入しました。Arduinoは単なる他人が作ったものではありますが、まずはこのステップから始めることができると思いました。あるセンサーを使用する場合、他の人が書いたライブラリを使用せずに、自分でデータシートを見て使用方法を確認してみることができます。本当にうまくいかない場合は、ライブラリの実装を確認してみることもできます。
今年の7月には、ArduinoとESP32を使用して空気品質モニタリングアプリケーションを実装しました。この中でMQTT、DHT11、MH-Z14Aを使用し、データ通信にはUARTを使用しました。ライブラリを使う部分もありますが、MH-Z14Aの部分ではデータシートをしっかりと読み、実装しました。Wi-FiとMQTTの部分はライブラリを直接使用しましたが、私にとっては多くのことを学びました。
これだけでは十分ではありません。私はArduinoのケースに制約されたくありません。そこで、伝説のMOS 6502をAmazonで探しました。
MOS 6502は、非常に安価で性能も優れているため、FamicomやApple IIなどの8ビットCPUに採用されています。また、現代のCPUと比較して、命令セットや設計が比較的単純であるため、CPUの動作をより理解しやすくすることができます。
最初はワクワクして注文し、到着を待っていましたが、後で気付いたのは、MOS 6502にはEEPROMが内蔵されていないことです。プログラムをEEPROMに書き込んでMOS 6502に送る必要があります。しかし、現在私は日本にいるため、必要なEEPROMを手に入れるための良い方法がありません。したがって、この道は一時的に断念しました。
その代わりに、AVRを選びました。私が今住んでいる場所の近くには電子部品店があり、さまざまなatmegaシリーズのマイクロコントローラを取り扱っています。したがって、いくつかのもの(ATMEGA328、ちょうどArduino UNOで使用されているMCU)を選びました。
ATMEGA328を使用する利点は、まず第一にサイズがちょうどブレッドボードに収まること、そして指令セットが比較的単純であること、さらにはAVR固有の利点(x86: 8個、ARM: 16個)などです。
アセンブリ言語とハードウェアロジックの理解
ハードウェアの世界では、すべてが単純になり、同時に不便になります。例えば、特定のピンを高電圧にする場合、純粋なアセンブリ言語(AVR)では次のように書く必要があります:
ldi r16, 0x01
out DDRB, r16
out PORTB, r16
まず、0x01
をr16レジスタに入れ、次にDDRB
レジスタ(データ方向)を0x01
に設定し、PORTB
を0x01
に設定します。実際には、これはdigitalWrite
と非常に似たことをしています。
しかし、アセンブリ言語は想像していたほど難しくありませんでしたが、業界レベルのアセンブリ言語を書くのは難しいと思います。
割り込みのより深い理解
割り込み機構が具体的にどのように動作するか(ハードウェア回路を含む)はまだ完全に理解していませんが、割り込み(Interrupts)についてはより深く理解しています。
一般的に、CPU内には割り込みベクタが定義されており、割り込みが発生した場合にCPUが何をすべきかを示しています。また、割り込みの有無は通常、SREG
レジスタのGlobal Interrupt Enableビットで判断されます。レジスタの操作やビットシフトについて十分な理解が必要であり、AVRでは通常、いくつかの関数が対応しています(avr/interrupt.h)。
この部分は非常に興味深いですが、トラブルの原因にもなります。おもちゃのプロジェクトであればまだ良いですが、本番環境での割り込み機構の管理やデバッグ方法についてはわかりません。
オペレーティングシステムの理解
今年の3〜4月ごろ、Courseraでオペレーティングシステムのコースを断続的に学びました。PC(プログラムカウンタ)、IR(命令カウンタ)、カーネルモード、ユーザーモード、アトミック、スレッドからセマフォまで、何を実装するかはまだ完全には理解していませんが、少なくとも「比較的」良い理解ができました。最近、30日で自作OSという本を見つけました。見た目はかなり簡素ですし、多くの詳細が省略されていると思いますが、興味深いと思います。いつか時間があるときに試してみるかもしれません。シミュレータを実行するよりも、実機で直接テストする方が好きです!
プログラミング言語
今年の初めに、松本行弘氏の「まつもとゆきひろ 言語のしくみ」を偶然見つけました。彼はそこで、yacc/lexから始まり、プログラミング言語を一から実装し、原理と実装方法を一つずつ説明しています。彼の完成度には驚きました。単なる計算機の四則演算だけでなく、文字列、時間処理、数値、乱数、配列、アトミックなど、プログラミング言語に必要な基本的な要素がほぼ実装されています。私も同様のことをしたいと思っていますが、yacc/lexのドキュメントは本当に理解できないので、C言語により深い理解を持つまで挑戦することにします。
もう一つは、IT鉄人コンテストに参加した際に、簡単なSvelte(リアクティブ機能なし)を一から実装して、簡単なパーサーを書いてみたことです。これはプログラミング言語に少し触れたということです XD
まだ学ぶべきことはたくさんあります!みんなでこの混沌とした一年を乗り越えましょう!