スティック系ジャグラーが集まってわいわいジャグろーぜ!
なイベント、Fantastick。
年に1度関東で開催されています。
公式(?)ツイッターのアイコンになっている「犬も歩けば棒でジャグる」ですが、
結構線が荒いです。
そこでGWに入り暇ができたので、ちょっとなめらかにしてみました。
before
after
とりあえず、自分のスキルではこれが限界。
でもまあ満足です。
「つくってあそぼ」こと「つくってワクワク」が2013/3で終了するらしいです。
今でも見ている、という訳ではありませんが好きな番組でした。
ちなみに、前回のブログタイトルはこれをパクっています。
2ステップ目。いっきまーす。
今回も複数回にまたがります。ご了承ください。
■周辺ハードウェア
ベリフェラル、周辺インターフェース、周辺I/Oと呼ばれる。
CPUはCPU単体では意味をなしません。
様々な周辺ハードウェアを制御してこそ、真価を発揮します。
周辺ハードウェアといっても何のことか分かりにくいですね。
どうやら、CPUに繋げるやつは全部と考えて良さそうです。
キーボードやマウスはいかにも。
更には外部メモリ(レジスタ等は違う)なども周辺ハードウェアと呼ぶようです。
これらはI/O(input/output=入出力)の名の通り、データを転送するためにあります。
■コントローラ
データはただ転送すれば良いのではなく、転送速度や信号の電圧など、
それぞれに決まったインターフェースがあります。
更には受信可能通知を受けたらデータを送信、受信エラーが起きたら・・・等と
データ転送のための手順も存在します(プロトコル)。
これらすべてをソフトで実現するのは非常に手間ですし、処理が多い。
そこで、専用のICチップ(コントローラ)に任せてしまいます。
これにより、CPUはコントローラに対して送信要求を出す・データを受け取る
等の簡単な制御でデータのやりとりが出来ます。
teratermなんかはソフトでシリアルの送受信を実装しているのでしょうか。
ちょっと気になる。
■コントローラの制御
コントローラの制御は(コントローラの)レジスタを用いて行います。
このレジスタに対して操作(値の書き込み)をすると、
書き込んだ値が送信される、データ受信はこのレジスタのフラグを見る等。
では、どうやってレジスタにアクセスするのか。
それには、アドレスを使います。
■アドレス
メモリの位置情報のことをアドレスと呼びますね。
そこで、メモリについて考えてみます。
CPUにはデータ転送用のデータバス、アドレスを指定するためのアドレスバスがあります。
バスはCPUとメモリを繋ぐ線のことで、電圧の高低で1(High),0(Low)を表わします。
つまりバス1本につき1ビットを表わせる、ということです。
32ビットCPUの場合、バス幅は32本のことが多いようです。
0x00000000-0xffffffffまでのアドレスを表現でき、1つのアドレスには
1byteのデータが書き込まれるので、4GB程のメモリ空間にアクセスできることになります。
アクセスできるからといって、4GBのメモリ(DRAM)が繋がっているかといえば、
そうではなく、数MB単位のDRAMを複数繋げています。
この場合、下位ビットでDRAMのメモリ位置を表わし、使用していない上位ビットで
どのDRAMを使用するか指定します。
DRAM側にはチップセレクト(CS)と呼ばれる信号線を持っており、これが1となった場合に
動作する、という仕組みを持っています。
比較機を使用し、特定のアドレスでCSに信号を送るようにします。
レジスタも同様です。
DRAMと同じくCSを持ち、特定のアドレスでレジスタにアクセスするよう配置します。
そして下位ビットにより、レジスタ位置を特定します。
これでレジスタ(=コントローラ)の操作を行うことができます。
=====
以上の様に、DRAMに加え、コントローラのレジスタもアドレスに配置する(マッピング)
I/Oの操作方法を、メモリマップドI/Oと呼びます。
どのアドレスに何がマッピングされているか、どのレジスタがどういう役割か等
マニュアルとにらめっこすること必須です。
次回に続く。
前:組込みOSをつくってわくわく[1ステップ後編](Hello,World)
次:まだ
リンクは後で。
ホテルで暮らしているうちになるべく更新しようという魂胆。
間違えて書いたものを消してしまうことが多々あるので、気をつけます。
モチベーションがめっさ下がりますね。
結構書いたあとだったのに。。
***
今回はあの世界一有名なプログラムを作成するところから始まります。
…そう、ハローワールド。
printで簡単にかけてしまうプログラムですが、
今回はフルスクラッチでOSを作成することを目的としています。
つまり、printfは存在しません。
あ、フルスクラッチは1から新規で作成することを指すそうです。
さてさて。
ボードにはディスプレイが無いのでシリアルで出力します。
よって、下記が必要と考えられます。
・Hello Worldを出力するメインプログラム
・シリアルデバイスを制御するプログラム(ドライバ)
・文字の出力関数を記述するライブラリファイル
それに加えて用意するのが、以下のようです。
・スタートアップ
・割込みベクタ定義
・リンカスクリプト
・(makefile)
スタートアップはメイン関数を実行する前の準備を行うプログラムで、アセンブラで記述します。
割込みベクタ定義は、割込み関数を登録するためのファイル。
配列があり、その中に関数の実行アドレスを格納していきます。
これを割込みベクタテーブルと呼ぶことにします。
リンカスクリプトは関数やデータのメモリ配置を決めるためのファイルです。
makefileはなくても出来なくはないので()にしています。あると楽。
ファイル数だと10個。270用程度です。
今回は動くものを作る、という思想の元、とにかく写していきます。
ここ↓にソースコードが置いてあるので、コピーして使用することもできます。
http://kozos.jp/books/makeos/
まあ、コピーしたら負けだと思っていますが。
アセンブラやmakefileの書き方はわけわけめですが、気にせず写します。
細かいことは後だー!
しかし、makefileはあまり扱っていないので、後々勉強することにする。
ほぼ全部写しなのですが、makefileの一部を書き換えています。
H8writerはcygwin\tools\に入れているので、makefileのH8writeへの
パス指定を下記へ変更。
H8WRITE = = ../../../tools/h8write/
書き忘れていましたが、プログラムが置いてあるのはcygwin\home\01\bootloadです。
今後02,03とフォルダを作成し、同様の構成にしていきます。
もうひとつ、シリアルの接続先を下記に変更します。
H8WRITE_SERDEV = com4
同じwindows環境でも数字は違うと思うので、デバイスマネージャー等で確認する
必要があります(comなのは変わらない)。
準備完了。
cygwinでカレントディレクトリに移動します。
> make
> make image
このコマンドでkzload.motというファイルができます。
あとはこのファイルをROMに書き込むだけです。
makefileは本当に便利ですね。
次に、ボードのディップスイッチ(4個のスイッチが並んでいるやつ)
の3以外をすべてONに切り替えます。
この状態で電源をONにすると、書き込みモードで起動するので、
> male write
を実行します。これだけ。
makefileは本当に便利ですね。(大事なことなので(ry)
電源をオフにし、今度はスイッチの1,3のみONにします。
そしてteratermを立ち上げ、ボードに接続します。
さあ、電源ONだ!Hello world来い!
…
…
…あれ、出ない。。。
と思っていたら刺す電源アダプタを間違えていました。
PSP充電してどうすんのさ。
気を取り直して、再度電源ON。
…今度はすんなり出ました。
LEDが光ったりが無いので、電源がONになっているか不安になりますが、
間違いなくシリアル出力できているので成功です。
余談:プログラム実行のイメージ
何ステップか先まで読み進めているので、ちょっとまとめてみます。
電源が入るとCPUはアドレス0番地から実行を始めます。
0番地には、リンカスクリプトで割込みベクタテーブルを配置します。
つまり、電源が入るとテーブルの0番目の要素に登録された関数が実行されます。
ここにはスタートアップを登録しておくので、スタートアップルーチンが実行されます。
スタートアップはルーチンの最後にメイン関数を呼びます。
メイン関数が呼ばれたら、後は普段良く見る処理ですね。
今回のスタートアップはメイン関数を呼ぶだけの処理です。
割込みベクタへの登録は、特別な処理をするわけではなく、
ファイルに書いておくだけです(ソースコ-ド見ればわかりますね)。
これにて1ステップ目終了です。
1回1回が濃いので、なかなかまとめ切れませんね。。
せめて面白おかしく、と思ってもウィットにとんだことを
言えるわけもなく。しばらく模索しつつ進めていきます。
今回文字を出力したので、次回は数字出力です。
こんな感じですが、よろしくお願いいたします。
前:組込みOSをつくってわくわく[1ステップ]
(環境構築)
次:組込みOSをつくりんだりんだ[2-1]
あまり本に載っていないので書いてみます。検索すると書いている方はいるようです。
カゴテリ作ったものの他にネタがないという。
ええ、見切り発車です。
今回は
しゃーぷ、いんくるーど、すたでぃお、てん、えいち
という、おまじないのお話。
C言語というより、C言語系ですね。もっというと言語そのものではなかったと思います。
プログラムを習うと、必ずと言って良いほどハローワールドの出力から始まります。
そして必ずと言って良いほど#include~はとりあえず書いておいてね扱いされます。
そしてステップを進んでいっても説明がされません。
考えても仕方がないので、考えるのをやめます。
こんな状況を打破しましょう。分解して説明します。
■#(シャープ)
C、言、語…?となる原因。
プリプロセス命令、プリプロセッサ命令と呼ばれるものの指定に用います。
#~行末までがプリプロセス命令の範囲です。
複数行にまたがる場合は、行末に\を記述します。
プリプロセッサとは、コンパイルの前に動作するプログラムのことを指します。
ヘッダを読み込んだり、条件付きコンパイルをしたり。
#includeのほかにも#define、#if、#ifdef等の命令があります。
とてもお世話になっています。
■include
ヘッダファイルを読み込むプリプロセス命令です。
ヘッダファイルには関数の宣言や構造体の定義がされており、
.ファイルを読み込んだCファイルは自ファイル内で定義していなくとも
その関数や構造体を利用することができます。
逆にいえば、読み込んでいないと関数、構造体は自ファイルに定義されていない限り
利用できないことになります。
■<stdio.h>
<>の中に読み込みたいヘッダファイルを指定します。
自分でヘッダファイルを作成する段階になればわかりますが、
#include "hedder.h"
と書くこともあります。
何が違うのかというと、ファイルを探す順番です。
<>は環境変数INCLUDEとして定義されている、ディレクトリを優先して検索します。
ここに標準て用意されている関数のヘッダ等が置いてあるはずです。
""はコンパイル対象となるCファイルの置いてあるディレクトリを優先して検索します。
stdio.hは標準の入出力関数ライブラリで、printf等が定義されています。
ちなみに、standard input/output の略です。スタジオは一切関係ありません。
プラットフォームが提供している機能なので、ないときはない。
検索をかけたところ、下記に存在していました(Visual Studioインストールしてて良かった)。
C:\Program Files\Microsoft Visual Studio 8\VC\include
最後に、よく使うプリプロセス命令を書いておきます。
#include
#define
#ifdef, #ifndef
#typedef
(#if, #elseif, #endif)
まあまあ使うけれどよくわかっていないのが、#pragma。
コンパイラによって処理が違うらしいです。
そもそも使用せず無視するものもあるそうで。
毎回何だこれ?って思ってしまいます。
プリプロセス命令は使い方を覚えておくと非常に便利です。
私自身は知っている方ではないので、説得力に欠けてしまいますが。
本文以上。
分かりやすく書くのは難しいですね。
上手い文章を書ける方々を尊敬します。
ここわかりにくい、間違っている、等ありましたらコメントを頂けると幸いです。
こんばんは。
更新速度の遅さに定評があるとらです。
今回はソフトウェア関係。
組込みOS自作入門の続きです。
まずは、定番の開発環境構築からです。
正直ここで時間を使いたくないので、全て本に載っているバージョンを使います。
筆者は専用PCを用意するのを進めていますが、お手軽にWindows+cygwinでいきます。
Cygwinはボード付属のCD-ROMからインストール。
次へ次へで良かったはず。
でもgccにチェックが入っているのは確認しましょう。
バージョンが古いのですが、以前ネット経由でインストールした時、
やたら時間がかかった印象があったのでまあいいや、と。
開発用のPCが用意できたら、コンパイラの準備に取りかかります。
まずはセルフコンパイラをインストールします。
セルフコンパイラとは、
今回のボード向けにコンパイルするためのコンパイラをコンパイルするためのコンパイラのことです。
アセンブリをアセンブルするのがアセンブラ、と似たような響きがしますね。
こちらはgccを使います。
使います、と言ってもcygwinインストール時に一緒に入れているので特に何もしません。
cygwinというフォルダがC:直下に作成されます。
cygwin起動時のルートディレクトリはc:\cygwinになるみたいです。
あ、書き忘れていましたが。
今回の開発はC言語がメインです。
次!クロスコンパイラ。
クロスコンパイラとは、開発対象CPU向けにコンパイルしてくれるコンパイラのことです。
い、今起こったことをありのまま話すぜ!
コンパイラをインストールしたと思ったらまたコンパイラのインストールが始まった...。
何を(ry
という方の為に(自分です)説明します。
違いは、対象となるCPUです。
プログラムをコンパイルすると、機械語命令に変換されます。
この機械語は、CPUによって異なります。
例えば、0100で加算命令のCPUがあれば、0011で加算命令になるCPUもあると言うことです。
同じ命令があるとも限りません。
ところがコンパイラは特定のCPUに対する変換しか行うことが出来ないのです。
と、言うわけで。
CPU毎に異なるコンパイラが必要になります。
今回はx86(windows)とH8(ボード)の2つですね。
もちろん、同じ命令をもつなら同じコンパイラで問題ありません。
ちなみに、ここで言う命令は機械語命令ないしはアセンブリ命令のことで
printf等の標準ライブラリに入っている命令ではないのでご注意ください。
ここでH8用のコンパイラだけあれば良いのでは?という疑問が浮かびます。
まあ、そうはいかないから2つ入れるのですが。
これからDLするファイルは、H8用のコンパイラとして動作・使用できるものではありません。
コンパイラのソースコードです。
これをH8用に動くようコンパイルしてください、とwindows用コンパイラにお願いするのです。
つまり、セルフコンパイラは環境構築が終わったら使用しません。
ここまで書いておいて間違っていたら泣く。
インストールに戻ります。
クロスコンパイラですが、こちらもgccを使います。
以下から2点、DLします。
・binutils-2.19.1.tar.tar
・gcc-3.4.6.tar.tar
http://www.gnu.org/home.ja.html
下記の様に配置しました。
C:
+--cygwin
+--なんやかんや
+--tools
+--binutils-2.19.1.tar.tar
+--gcc-3.4.6.tar.tar
まずはbinutilsをインストールします。
こちらは、コンパイラを動作させるのに必要な基本ツールだそうです。
まずはDLしたファイルの置いてあるフォルダに移動。
binutils-2.19.1.tar.gzを解凍します。
> cd /tools
> tar xvzf binutils-2.19.1.tar.tar
するとカレントフォルダにbinutils-2.19.1フォルダが作成されます。
cdコマンドでそこへ移動します。
移動したら、下記コマンドを実行し、H8用binutilsをビルドします。
> ./configure --target=h8300-elf --disable-nls --disable-werror
> make
ビルドができたら、インストールして完了です。
> make install
次にgccをインストールします。
binutils同様なのでコマンドだけ載せます。
> tar xvzf gcc-3.4.6.tar.tar
> cd gcc-3.4.6
> ./configure --target=h8300-elf --disable-nls --disable-werror
> make
> make install
インストールが終わったら、次で最後だ!
フラッシュROM書き込みツール。
平たくいうと、作成したプログラムをボードに覚えさせるためのツールです。
Open SH/H8 writer(以後h8wite)というものを使用します。
以下からインストーール!
windows用の実行ファイルが既にあります。
やった!文章を書く手間が省けるぞ!
http://mes.sourceforge.jp/h98/writer-j.html
以上で環境構築は終了です。
お疲れ様でした!
1ステップ1記事と見込んでいましたが、甘かった。。
ハローワールドは次回です。
始まらなかった世界。完。
次:組込みOSをつくってわくわく[1ステップ後編] (Hello,World.)