ARM(LPC1114)をUbuntu12.04で使う(その2)

.24 2012 ARM-setup comment(-) trackback(0)

このDVD、うちのPCだとなぜか読み込めないんだけど…
必要かと言われれば全くそんなことはないので問題ないか。

今回はLinuxでの場合に限った話ではなく、出来損ない合いのライブラリを使わずにリセット周りを書く方法をまとめた。

詳細はトラ技10月号に書いてあるしCMSIS(ライブラリ)のリセットベクタを見ればだいたい書いてある。
CMSISってのはレジスタの名前や基本的な関数などを提供するライブラリで、基本的にすべてのARMデバイスにそれぞれに用意されているもののようだ。
しかしながらLPC1114のCMSISは巷での評判は最悪。うちの環境ではそもそもインストール出来なかったと記憶している。
ARMのコア部分のCMSISは本家ARMが管理しているのでドキュメントも充実しているし問題はないのだがNXPが提供する部分にはドキュメントがなく、いろいろ躓くポイントがあるらしい。

しかたないのでデータシートのメモリマップを参考にひたすら#defineを並べる仕事をしようかと思ったがすでにやっている方がいたのでありがたく使わせていただく。
今回はELM by ChaN氏のページのライブラリ(基本的にレジスタの定義がしてあるだけなので躓きようがない)を使うことにした。

ちなみにデータシート(メモリマップ)はこちら。

UM10398: LPC111x/LPC11Cxx User manual


割り込みベクタの定義部分とか_end_of_sramとかの定義もライブラリに移したほうがよい気はするが今回はとりあえずこのままで。
リセットベクタですべきことは次の通り。
  1. SRAMの初期化
  2. CPUやペリフェラルのクロックの設定
    1. システムクロックやシステムPLLを起動する(今回は内蔵RC発振を使うのでシステムクロックは起動しなくて良い)
    2. システムPLLの入力に入れるクロックを指定する(システム発振器(=外付け発振器) or 内蔵RC発振(12MHz))
    3. PLLで周波数を指定する(入力を何逓倍して何分周するか)
    4. メインクロックの選択(内蔵RC発振器 or ウォッチドッグ発振器 or PLLの入力をそのまま使う or PLLの出力)
    5. システムクロックの設定、どこのモジュールにクロックを供給するかを設定

用語
システム発振器:外付けの発振器のことっぽい。
メインクロック:MAINCLKSELで選択されたクロック。
システムクロック:ARMコアやペリフェラルに供給するクロック。メインクロックを1〜128?分周したもの。

文章で書くとわかりづらいがトラ技に図があるのでそれみれば一目瞭然。

このあたりをデータシート見ながら必要なレジスタに値を設定すれば初期化は終わり。

#define raise_bit(sfr, bit) \
	do {	\
		sfr |= _BV(bit);	\
		sfr &= ~_BV(bit);	\
		sfr |= _BV(bit);	\
		while (!(sfr & _BV(bit)));	\
	} while(0)

int init()
{
	long *s, *d;
	/* step 4: init SRAM */
	for (s = _sidata, d = _sdata; d < _edata; *d++ = *s++);
	for (d = _sbss; d < _ebss; *d++ = 0);

	/* step 4': set flush access rate (周波数を高く設定する場合にはフラッシュメモリのアクセスサイクル数が増える) */
	FLASHCFG = (FLASHCFG & 0xFFFFFFFC) | 2;	/* Set wait state for flash memory (1WS) */
	
	/* step 5: init CLK */
	/*  a. Power on sys PLL (今回はsysclk用RC発振を元にclkを作るのでPLLのみ有効) */
	PDRUNCFG &= ~(_BV(7));
	/*  b. PLLの入力CLKの選択 */
	SYSPLLCLKSEL = 0;
	/*   PLLCLKUEN(0)の立ち上がりでSYSPLLCLKSELの値が反映される */
	raise_bit(SYSPLLCLKUEN, 0);
	/*  c. PLL設定 */
	SYSPLLCTRL = (4 - 1) | (1 << 5);
	while ((SYSPLLSTAT & 1) == 0) ;			/* Wait for PLL locked */
	/*  d. MAINCLKの選択 */
	MAINCLKSEL = 3; // PLL出力
	/*   MAINCLKUEN(0)の立ち上がりでMAINCLKSELの値が反映される */
	raise_bit(MAINCLKUEN, 0);
	/*  e. Peripheral Clkなどの設定 */
	SYSAHBCLKDIV = 1;
	SYSAHBCLKCTRL = 0x0001005f;
	
	return main();
}
あと重要なのが周波数を高く設定するときはFLASHCFGの値も書き換える必要があるということ。
フラッシュメモリは遅いのでシステムクロックの周波数が高い場合1clkで読み出しが終わらない。
〜20MHzなら1cycle, 〜40MHzなら2cycle, 〜50MHzなら3cycleに設定する。

# パイプライン化して3clkって意味だと思う。そうじゃないとコアの周波数だけ上げてもほとんど意味ないし。

あ、NXPのCMSISだとこのFLASHCFGの設定が抜けてるらしくそれでハマった人もいるようですね。

今回のファイルは ここ に置いておきます。

あくまで「こうやったら動いたよ」くらいのものとして使ってください。

諸事情によりコメント受付を拒否しています。
関連記事

trackbackURL:http://yuranos.blog11.fc2.com/tb.php/225-a6cecfaa