So-net無料ブログ作成
検索選択

楽してユーザ・ドライバを開発する方法の探求 [ColdFire V2]このエントリーを含むはてなブックマーク#

2047506

前回の記事で、ユーザ・ドライバのためのベクタ・テーブルを書き込みました。 しかし、肝心のプログラム本体を書き込んでいないので、使えるのはヘルプ表示だけです。 どうやったら、楽してユーザ・ドライバが書けるかな?

CodeWarriorをインストールするの?

MCF52233などの"ColdFire V2"には、Interface誌に付いてきた「CodeWarrior for ColdFire」が使えることは想像に難くないと思います。 でも、あの巨大な"CodeWarrior"をもうひとつインストールするのは、気が引けます。

その理由は、HCS08を使った事があれば、"ColdeFire V1"の開発環境が含まれた「CodeWarrior for Microcontrollers」がインストールされているからです。 こいつが、 "ColdFire V2" のコンパイルぐらいはやってくれないかなと画策しました。 ところが、致命的な問題が判明しました。

ColdFire V1 の CPU は、 ColdFire V2 の CPU のスーパー・セットである。

MCF52233 の命令セットは、 ISA (Instruction Set Architecture) Rev.A と呼ばれています。 一方、 MCF51QE128 の命令セットは、 ISA Rev.C という MCF52233 よりも新しいものです。 つまり、「CodeWarrior for Microcontrollers」でコンパイルしたプログラムは、 MCF52233 ではサポートしていない命令セットを生成してくれるので、使用することが出来ません。 反対に MCF52233 のプログラムを 「CodeWarrior for Microcontrollers」 のデバッガなどで扱うことは可能です。 MCF51QE128 のコンパイル結果の方が洗練されているように見えたのは、こういう理由があったのか。

と、いう訳で、不本意ながら「CodeWarrior for ColdFire」をインストールしました。

必要の無いものは、削除、削除

まずは、MCF52233 をターゲットとして、新規プロジェクトを作成します。

項目設定
DeviceMCF52233 を選びます。
Connectionどれも使うつもりはないのだけど、P&E USB BDM Multilinkでも選んでおきますか。
Processor ExpertSilentC を使うのであれば、 Processor Expert を使える環境ではないので、 None を選びます。
Hardware Supportコンソールもシミュレーションも使う予定が無いので、 Minimal を選びます。
Compiler Optimization今は、がんばって最適化する必要も無いので Easy Debug を選びます。デバッガは使わないんだけどね。

新規プロジェクトには、三つのターゲットが定義されています。 このうち二つは必要ないので削除してしまいます。

ターゲット解説
CONSOLE_INTERNAL_RAMこれは、プログラムをRAM上において実行させる設定で、デバッグ用にコンソールも利用します。ユーザ・ドライバ向きではないので、削除してしまいます。
INTERNAL_RAMこれも、プログラムをRAM上において実行させる設定ですが、コンソールは使用しません。ユーザ・ドライバ向きではないので、削除してしまいます。
INTERNAL_FLASHプログラムをFLASHに置く、通常の組み込みプログラムを開発する設定です。ユーザ・ドライバの条件に最も近いので、これを使います。
WS000161.png

不要なターゲットは、"Targets"タブから右クリックで"Delete"を選び削除します。


新規プロジェクトには、ユーザ・ドライバの作成には必要の無いファイルがたくさん出てきてしまいます。 これも、不要なものは削除してしまいます。

不要ファイル解説
Sources/ board_sysinit.cパワーON時の初期設定ルーチンが含まれています。初期設定は、SilentCがやってくれるので、このファイルは不要です。
Sources/ uart_support.cUARTの最下層ルーチンが記述されています。使えるのかも知れませんが、今は使わないので削除してしまいます。
Sources/ exceptions.c例外ベクタ・テーブルと標準的な割り込みハンドラが定義されています。どちらもSilentCが提供してくれていますので、削除してしまいます。
Project Settings/ Startup Code/ startcf.cリセット後の初期設定を行うルーチンが記述されています。これもSilentCが提供してくれるので、削除します。
Project Settings/ Startup Code/ cfm.cプロテクション・キーなどが入ったFLASHのconfiguration領域の値が定義されています。ここは、ユーザ・ドライバが書くべき領域ではないので、ファイルも削除します。
WS000162.png

不要なファイルは、 "Files" タブから右クリックで "Remove" を選び削除します。 これらのファイルは、 IDE の表示からは消えてしまいますが、ファイルそのものは削除されないので、後で回復させることも出来ます。

とりあえず、Make

WS000163.png

ファイルを削除したら、とりあえず Make ボタンを押してみます。 すると、リンカ・エラーが発生します。

Link Error   : Linker command file error at line 45
File not found: exceptions.c

リンカ命令ファイル(Linker command file)が、削除してしまった "exceptions.c" ファイルを参照していたようです。 リンカ命令ファイルは、 "Project Settings/ Linker Files/ MCF52233_INTERNAL_FLASH.lcf" にあります。

WS000164.png

このファイルの45行目に問題の箇所がありました。

#	.vectors :
#	{
#		exceptions.c(.vectortable)
#		. = ALIGN (0x4); 
#	} > vectorrom

これは、一括してコメント・アウトしてしまいます。

Link Error   : Undefined : "_startup"

このエラーは、リセット後のプログラムカウンタの値として指定された"_startup"が見つからないというものです。

WS000166.png

これは、メニューの "Edit → INTERNAL_FLASH Settings..." ダイアログの "Linker → ColdFilre Linker" の "Entry Point" に書いてあります。 この項目は、削除してしまうと別のエラーが発生するので、とりあえず"_main"と入れておきます。

同じ場所にある "Force Active Symbols" に入っている "__vect,__cfm" も不要なので、削除します。

これで、エラー無く "Make" が出来るようになりました。

最初のユーザ・ドライバ

ここで、 "Make" していたのは、デフォルトの main 関数です。 このままでは、仕事をしてくれないので、ここで最初のユーザ・ドライバを "main.c" ファイルに書いてみます。

#include "support_common.h" /* include peripheral declarations and more */

uint32 main(uint32 arg);

asm void jump_table(void) {
  jmp main      // Driver #0   
}

uint32 main(uint32 arg) {
  char *msg;
  switch (arg) {
    case 0:
      msg = "HELLO WORLD!!\r\n";
      break;
    case 1:
      msg = "Nice to meet you.\r\n";
      break;
    default:
      msg = "Good bye.\r\n";
  }
  return (uint32)msg;
}

コメントは省いてあります。 また、条件付きでヘッダファイル stdio.h をインクルードする部分も削除してしまいました。

ユーザ・ドライバ0番は、与えられた引数に対応するメッセージ文字列を返す関数です。 "uint32" という型は、プログラムのどこにも宣言されていませんが、これは、インクルード・ファイル "support_common.h" のなかで宣言されています。 ユーザ・ドライバの規約では、 "uint32" 型の引数をひとつ受け取り、 "uint32" 型の値を返すことになっています。 このプログラムも無事に "Make" することが出来ます。

Sレコードを見てみよう

コンパイル後のコードは、プロジェクト・ディレクトリの "bin/ MCF52233_INTERNAL_FLASH.elf.S19" というファイルにSレコード形式で書き込まれます。

S0030000FC
S321000005004E560000202E00084A80670A0C8000000001670A601041F900000534C3
S3210000051C600E41F900000544600641F90000055820084E5E4E7551FC48454C4CC6
S321000005384F20574F524C4421210D0A004E69636520746F206D65657420796F7587
S315000005542E0D0A00476F6F64206279652E0D0A001E
S30900000564000000008D
S31D00000568000005642000040000000004000000000000000000000000E4
S70500000500F5

コンパイル後のコードは、0x00000500から書き込まれています。 本来は、0x00020000から書き込みたいので、後で修正します。 6行にわたる"S3"レコードのうち、最初の4行はプログラムと文字定数です。 残りの2行は、さて、何でしょう。

リンカ命令ファイルの修正

WS000164.png

プログラムの開始番地を変更するためには、リンカ命令ファイル(Linker command file)を変更します。 具体的には、 "Project Settings/ Linker Files/ MCF52233_INTERNAL_FLASH.lcf" を開いて、 "MEMORY" の宣言を変更します。

MEMORY {
   vectorrom   (RX)  : ORIGIN = 0x00000000, LENGTH = 0x00000400
   cfmprotrom  (RX)  : ORIGIN = 0x00000400, LENGTH = 0x00000020   
   code        (RX)  : ORIGIN = 0x00020000, LENGTH = 0x00020000
   vectorram   (RWX) : ORIGIN = 0x20000000, LENGTH = 0x00000400
   userram     (RWX) : ORIGIN = 0x20007F80, LENGTH = 0x00000080
}

変更箇所は、 "code" と "userram" の二つです。 これで、プログラムを配置すべき場所と作業領域が指定されます。

"code" のサイズを 64k バイトから 128kバイトに変更しました。 (2008-10-23 06:34)

次に以下の箇所をコメント・アウトまたは削除します。

#	.data : AT(___ROM_AT) 
#	{  
#		___DATA_RAM = .;
#		. = ALIGN(0x4);
#		*(.exception)	
#		. = ALIGN(0x4);	
#		__exception_table_start__ = .;
#		EXCEPTION
#		__exception_table_end__ = .;
#		
#		___sinit__ = .;
#	    STATICINIT
#		__START_DATA = .;
#
#		*(.data)
#		. = ALIGN (0x4);
#		__END_DATA = .;
#
#		__START_SDATA = .;
#		*(.sdata)
#		. = ALIGN (0x4);
#		__END_SDATA = .;
#
#		___DATA_END = .;
#		__SDA_BASE = .;
#		. = ALIGN (0x4);
#	} >> userram

これは、静的変数領域の初期状態を格納する場所の宣言です。 最後から2行目の"S3"レコードがこれに相当します。 さらに以下の箇所もコメント・アウトまたは削除します。

#	_romp_at = ___ROM_AT + SIZEOF(.data);
#	.romp : AT(_romp_at)
#	{
#		__S_romp = _romp_at;
#		WRITEW(___ROM_AT);
#		WRITEW(ADDR(.data));
#		WRITEW(SIZEOF(.data));
#		WRITEW(0);
#		WRITEW(0);
#		WRITEW(0);
#	}

これは、静的変数領域の場所と長さとその初期値を格納する場所の宣言です。 最後の"S3"レコードに相当します。

これらの静的変数領域の初期値情報を出さないようにしてしまうということは、静的変数は初期化されないということを示します。 通常のCのプログラムには、静的変数が初期化されていることを期待するプログラムもあるのですが、SilentCのユーザ・ドライバに限って言えば、静的変数は全く初期化されませんので、ユーザのプログラム内で明示的にクリアする必要があります。

リンカ命令ファイルには、他にも不要な記述があるのですが、今のところ、ワルサをする様子も無いので、そのままにしておきます。 ここまでの変更で、Sレコードファイルは、こうなりました。

S0030000FC
S321000200004E560000202E00084A80670A0C8000000001670A601041F900020034C9
S3210002001C600E41F900020044600641F90002005820084E5E4E7551FC48454C4CCF
S321000200384F20574F524C4421210D0A004E69636520746F206D65657420796F758A
S315000200542E0D0A00476F6F64206279652E0D0A0021
S70500020000F8

開始アドレスも 0x00020000 からに変更されて、純粋なプログラムだけのスリムな姿になりました。

ジャンプ・テーブルが無い

次にシンボル・ファイルを確認してみます。 シンボル・ファイルは、 "bin/ MCF52233_INTERNAL_FLASH.elf.xMAP" にあります。 FLASHへのプログラムの配置を見てみると、ジャンプ・テーブル(jump_table)がありません。

# .text
  00020000 00000034 .text   main	(main.c)
  00020034 00000010 .rodata @15	(main.c)
  00020044 00000014 .rodata @16	(main.c)
  00020058 0000000C .rodata @17	(main.c)
#>00020064          ___ROM_AT (linker command file)
#>00020064          ___DATA_ROM (linker command file)
WS000166.png

これは、メニューの "Edit → INTERNAL_FLASH Settings..." ダイアログの "Linker → ColdFilre Linker" の "Entry Point" を"_main"に書き換えてしまったのが原因です。 ここには、全てのプログラムをたどることが出来るシンボルを入れる必要があります。 このユーザ・ドライバの場合には、 "_main" に代えて "_jump_table" と入れます。 "Make" しなおすと、

# .text
  00020000 00000008 .text   jump_table	(main.c)
  00020008 00000034 .text   main	(main.c)
  0002003C 00000010 .rodata @15	(main.c)
  0002004C 00000014 .rodata @16	(main.c)
  00020060 0000000C .rodata @17	(main.c)
#>0002006C          ___ROM_AT (linker command file)
#>0002006C          ___DATA_ROM (linker command file)

"jump_table" が並びました。

この後、「引数の渡し方を変更する」という項目がありましたが、不必要かつ有害なステップであることが判明しました。 謹んで訂正いたします。

Sレコードをバイナリ・ファイルに変換するには?

あとは、Sレコードファイルをバイナリ・ファイル "COLDFIRE.BIN" に変換して、 tftp で送り込むだけです。 ところで、バイナリ・ファイルへの変換って、どうやってやるの?

乞うご期待。

参考文献

Interface (インターフェース) 2008年 09月号 [雑誌]

Interface (インターフェース) 2008年 09月号 [雑誌]

  • 作者:
  • 出版社/メーカー: CQ出版
  • 発売日: 2008/07/25
  • メディア: 雑誌

nice!(0)  コメント(8)  トラックバック(0)  このエントリーを含むはてなブックマーク#

nice! 0

コメント 8

hamayan

> 「でも、あの巨大な"CodeWarrior"をもうひとつインストールするのは、気が引けます。」

それをnoritanさんが言ったら、開発の人、涙目。
by hamayan (2008-10-23 09:45) 

noritan

既に目的別に CodeWarrior for MCU V6.0 V6.1 V6.2 と三本もインストールしているので、できたらコレで何とかしたいなと。

事実、勤め先のPCは、内蔵ディスクの容量が足りないので、どの CodeWarrior も入れていないのです。今度 CodeWarrior を入れる必要ができたら、代わりに何をアンインストールしようかな。

また、複数の CodeWarrior 間の干渉で手間取るのもイヤなので。すでに、 CodeWarrior for ColdFire のヘルプが使えない現象を確認していますが、原因追求をするヒマもありません。

3分でインストール・アンインストールが可能だったら、必要なときだけインストールしちゃうんだけどな。

by noritan (2008-10-23 10:01) 

masato

タイムリな記事で助かります。

ところが CW7.1.1a だとリンカ命令ファイル(.lcf)が無くてどうしたらいいか困ってます。
by masato (2008-10-23 21:47) 

noritan

えっ? lcf 無いんですか?
マイナー・チェンジで、劇的に変えるのは勘弁して欲しいなあ。
また、 CW 7.1.1a をインストールしないと、確認もできないのだな。
ふぅ~

by noritan (2008-10-23 23:08) 

masato

IF 付録 CD-ROM 版をろくに使わないうちにバージョンアップしてしまったし、何か設定を間違えているだけかも知れないですから手元で更に確認してみます。すみません。
by masato (2008-10-23 23:35) 

masato

CW7.0 (Build 15, PE V1.0.1, Service Pack, build 080512) でも同じく .lcf がありませんでした。どーしてー?
by masato (2008-10-24 09:33) 

hamayan

手持ちのv7.0もv7.1もlcfは出来ていますよ。

by hamayan (2008-10-24 09:54) 

masato

お騒がせしました。

新規プロジェクト作成時に "Create main.c/main.asm file" のチェックを外すと .lcf が出来ないことが判りました。
by masato (2008-10-24 10:28) 

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

トラックバックの受付は締め切りました

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。