2022年4月9日土曜日

カーミット

Kermit(カーミット)といえば、Sesame street のキャラクタを思い出す人も多いだろう。
やたらと早口で喋るカエル(びっき)のKermit だ。時々リポーターの仕事をする。
かく言う私も、Kermitは大好きなキャラクタだ。

プログラマ、特に組み込み系の人にとって、Kermitと言えば、もう一つある。
通信ソフトウエアパッケージの Kermit だ。
私はLinux上での組み込みマイコン開発時、シリアルポートの操作のために使っている。
Kermitは膨大な機能があるため、man-pageを見ても、便利なヘルプ機能を使っても、どこに何が書いてあるかわからない。私も全てを使ったことがあるわけではない。
そのせいで敷居が高いと感じる人も少なくはないだろう。
しかし、シリアルポートでの最低限の使用に限れば、けっして難しくはない。
今回は、UbuntuでのKermitでのシリアルポートの操作について書く。

インストールしよう

UbuntuでKermitを使うなら、aptでckermitパッケージをインストールするのが手っ取り早い。
こんな感じ:
$ apt-get install ckermit

起動しよう

インストールができたら、起動しよう。
シリアルポート使うなら、起動オプションでポートのスペシャルファイルを指定して起動するのが良い。
$ kermit -l /dev/ttyUSB0
上記は、USBシリアルデバイスの0番を指定している。レガシーポートのあるPCなら、COM1は"/dev/ttyS0"、COM2は"/dev/ttyS1"を指定する。
起動後のコマンドモードでも指定できるのだが、コマンドオプションの方が短く済むし、後で示す.kermrcを使った設定のためにも、起動時に指定したほうが良い。

通信設定しよう

Kermitは起動直後、インタラクティブコマンドモードになる。
起動時に、ポートを指定していないなら、"set line"コマンドで指定する。
(/home/foo/) C-Kermit>set line /dev/ttyUSB0
起動時に入力したほうが多少短い。起動時に'-l'で指定したほうが、楽だろう。

起動時にポートを指定していれば、必要な設定は、
  • フォーマット(キャラクタ長、パリティ、ストップビット長)
  • ボーレート
  • フロー制御
  • キャリア監視
キャラクチャ長、パリティ、ストップビット長をまとめて、フォーマットと書いているが、これらをまとめてセットするのが便利なためだ。
これらは、"set serial"でまとめてセットする。
たとえば、よく使われる(であろう)「キャラクタ8bit, パリティなし、1ストップビット」なら、以下のように指定する。
(/home/foo/) C-Kermit>set serial 8n1
"8n1"の3文字のそれぞれが、キャラクタ長('8'=8bit)、パリティビット('n'=none parity)、ストップビット長('1'=1stop)を示している。
使える組み合わせは、"set serial"と入力後に'?'を打つとダダっと表示される。
このコマンドに限らず、いろいろな場面で'?'を打つと、インタラクティブなヘルプが表示される。憶えておくといい。
キャラクタ長は 7, 8 が使える。
パリティは、キャラクタ長が8bitの場合、'n'=なし、'e'=偶数パリティ、'o'=奇数パリティから選べる。7bitの場合、それに加えて、'm'=マーク、's'=スペースも選べる。
ストップビット長は、1, 2 が使える。
それぞれ個別に指定もできるのだが、この1発入力表現がとにかく便利だ。

ボーレートは、"set speed"で指定する。
115.2Kbpsなら、
(/home/foo/) C-Kermit>set speed 115200
原因不明ながら、フォーマット指定後にボーレートを指定しないと、フォーマットが無視されることがある。
そのため、後からボーレートをセットしたほうが良い。

フロー制御は、"set flow-control"で指定する。
フロー制御無しなら、
(/home/foo/) C-Kermit>set flow-control none
俗に言うハードウエアフロー制御(RTS/CTS)なら"rts/cts"を、ソフトウエアフロー制御(XON/XOFF)なら"xon/xoff"を指定する。
ここでも忘れてしまった時は'?'だ。

最後の「キャリア監視」は、ピンとこないだろう。
KermitはシリアルポートのCD(Carrier Detect)をデフォルトで監視しており、これが落ちていると接続状態にならない。
使用するクロスケーブルや、開発機のハードウエア構成にもよるのだが、CDがオープンの場合も多いだろう。
そういう時は、"set carrier-watch"を使って、
(/home/foo/) C-Kermit>set carrier-watch off
として、監視を止める。

接続・切断しよう

これで設定ができたので、接続してみよう。
接続には、"connect"コマンドを使うのだが、これは短縮形の"c"でいい。
(/home/foo/) C-Kermit>c
接続すると、以下のようになる。
(/home/foo/) C-Kermit>c
Connecting to /dev/ttyUSB0, speed 57600
 Escape character: Ctrl-\ (ASCII 28, FS): enabled
Type the escape character followed by C to get back,
or followed by ? to see other options.
----------------------------------------------------

英語が読める人はもうおわかりと思うが、インタラクティブコマンドモードに戻るには、CTRL-\押下後、'C'を入力する。
'C'の代わりに'?'を入力すると、ヘルプが表示される。
'C'の他によく使うものは、'U'と'Q'かな。
'U'は接続を切断し、コマンドモードに戻る。
'Q'は切断して、Kermitも終了する。

CTRL-\ + 'C'で戻っても、シリアルデバイスはopen状態にある。
設定を変えて接続し直す場合、'U'で終えるか、'C'で戻った後で明示的に'close'コマンドを引数無しで使う。

ファイルを垂れ流し送信しよう

マイコンでの開発をしていると、まとまったデータをマイコン側へ送りたいときがある。
Motorola-SやIntel-hex形式のファイルをROMライタへ送りたい時(いつの時代だよ!)などだ。
ROMライタに限らず、マイコン内蔵Flashの内容を書き換えるコード(ローダ)をマイコンに用意しておいて、JTAGなしでプログラムを書き換える機能を用意することもあるだろう(最近は無いのかな…)。
その場合は、インタラクティブコマンドモードで、"transmit"コマンドを使う。
(/home/foo/) C-Kermit>transmit ファイル名
これで送信できるのだが…。やってみればわかるけど、とても遅い。
実は、kermitは、行毎に待ちを挟む。
受信側に配慮したやさしい動作であるが、大量のデータをやり取りすることを目的としている場合、受信側もバリバリにチューンしているだろう。最近のRISCマイコンなら、十数MHzのマイコンでも、115.2kbpsを取りこぼすのは稀だ。
Flash消去・書き換えにはさすがに時間がかかるが、それは毎行に待ちを挟むと言うよりも、消去ブロック単位や書き込み単位で待ちを挟むべきであり、その場合はフロー制御を使うべきだ。

ちょっと脱線したけど、transmitの際に、'/NOWAIT'オプションを指定すると、待ちを除去できる。
(/home/foo/) C-Kermit>transmit /NOWAIT ファイル名
ボーレートが高いほど、待ちの影響も大きい。
バリバリチューンを無駄にしないためにも、憶えておこう。
その他にも、transmitコマンドのオプションがある。'?'で表示されるので見ておくと良い。

受信内容を記録しよう

マイコンの動作確認やDebugの際に、シリアルポートを使うことも多い。
この場合、行った作業を記録しておきたい。
インタラクティブコマンドモードで、"log session"を使う。
(/home/foo/) C-Kermit>log session ログファイル名
ログファイル記録されるのは、プレーンテキストであり、エスケープシーケンスは記録されない事に注意せよ。

BSキーとDELキーの扱い

TeraTermを使っていると、BSキーを押した時、0x08(CTRL-H)が送信される。
BSのコードは0x08なので、この動作は正しい。

しかし、Linuxの端末では、BSキーを押すとDEL(0x7F)が押されたものとして動作する。
Kermitは、通信アプリであり厳密には端末エミュレータではない。端末としての振る舞いは、それを起動した端末に依存する。
そのため、KermitもBSキーが押された場合、DEL(0x7F)を送信することになる。
すなわち、TeraTermと違う動作になる。

このねじれ現象は歴史的な経緯により生じたものだ。
そもそもDELキーはBSキーの動作をしていた時期があり、その後現在と同じような動作になるのだがBSとは違うので、0x7Fなどというコード(それ以外の制御文字はすべて0x20未満)を持つ。
この件、かなり古いもので、知る人ぞ知る情報だったのだが、最近はネット上に転がっているので検索して読んでみるのもいいだろう。
2022年4月15日 追記: DELが0x7Fなのは、紙テープを使っていた頃の影響

改めて、Wikipediaの「削除文字」の部分を読むと、全ビット穴が空いている(7bit文字なら0x7F)部分を読み飛ばすという動作になっており、それを使って修正液のように文字を消すので、0x7Fだそうだ。
それとは別に、BSとDELの混乱も書かれている。とにかく、ごちゃごちゃしている。

そして、Linuxではこのねじれに対して、VT100のキー配列とLinus氏の判断により、BSキーはDEL(0x7F)を発行する。
詳しくは、Linuxの文書、"The Linux Keyboard and console HOWTO"の、"5.2 How to tell Linux what code to generate when a key is pressed"のあたりにチラッと書いてある。

色々対処方法はあるが、私はKermitでコードを変換するようにしている。
以下のようにすると、BSキーがBS(0x08)を送信するようになる。
(/home/foo/) C-Kermit>set key \127 \8
これで、他のアプリに影響を与えず、TeraTermと相互運用しやすくなる。

自動設定しよう

Kermitのインタラクティブコマンドモードのコマンドを、${HOME}/.kermrcに書いておくこと、起動時にそれが実行され、設定される。
私の.kermrcは以下のようになっている。
$ cat .kermrc 
set line /dev/ttyUSB0
set speed 57600
set serial 8N1
set flow-control none
set carrier-watch off
set key \127 \8
ボーレートが57.6kbpsになっているのは、例のマイコンボードを使ってるためだ。
こうしておけば起動すればすぐに使えるし、コマンドを忘れたとしてもこの.kermrcを見れば思い出すだろう。

エスケープシーケンスとキー入力

ここからは、kermitと言うよりもマイコン側の話だ。
エスケープシーケンスは、端末ごとに微妙に違っており、マイコン側で全てに対応するのは無駄だろう。
基本的にはANSIエスケープシーケンスに対応すればいい。
しかしながら、PC-98(だから、いつの時代だよ!)で、デバッグしていたコードを移植する場合、カーソルON/OFFのコードが違う。
意味PC-98ANSI
カーソルON ESC [>5lESC [?25h
カーソルOFFESC [>5hESC [?25l
また、LinuxではDELキーは(0x7FがBSなので)、エスケープシーケンスで表現される。
さらにこのへんにも書いてあるが、 キー入力のスキームはいくつも存在し、残念なことに多くの端末は異なるスキームのシーケンスを混ぜているので、ホストソフトウエアはあらゆるスキームを使った入力シーケンスが扱えなければならないのだ。
すなわち、DELキーは、0x7Fのみならず、エスケープシーケンス表現でも扱えるように実装しておくべきだ。

一通り使えるであろう方法を示した。

kermitは、Windows以前の'80年代から存在しているので、「あー、あれね。」と思う人もいるだろう。
昔からパソコンをいじっている人の中には特に。

厳密には端末エミュレータではないが、端末上で動作し、その端末の機能を利用することで、端末エミュレータのように使うこともできる。

しかしながら、日本ではPC-9801のDOS上で、CCT-98など高速動作する端末エミュレータが使われることが増え、さらにWindows後ではTeraTermに移行していった。

私は、'90年代末頃からPC Linuxを使うようになった。
そのころからGCCが日立SuperHを扱えるようになったので、それを使うようになった。
端末エミュレータとしては、当初はWindowsのTeraTermを使っていたものの、「今でもKermitがあるんじゃね?」と思って探すとすぐに見つかった。
そのため、またLinux上でKermitを使うようになった。
使わなくなってから数年経過していたため、使い方をかなり忘れていたが、使い始めればすぐに思い出していった。

Kermitをまた使うようになってから20年ぐらいになるだろう。途中、使わなかった時期があったことも最近では忘れていた。

ずっと使っているし、昔から存在しているので誰でも知っていると思っていた。
若手はKermitを知らない場合もあるが、若者は経験がまだ少ないのだからそういう事もあると、思っていた。
最近になって、色々見てみると意外にみんなKermitを知らないようだ。

考えてみれば'80年代では広く使われていたが、現在と比べ'80年代は、PCを使う人そのものが少なかっただろう。
Windows以降、大量の人の流入により、Kermitを知っている人は少数派になっているようだ。

いつの間にやら、世界は変わっていた。

0 件のコメント:

コメントを投稿