« LPC2888(続) | メイン | PCの使い方と作業効率 »
2007年10月30日
LPC2888(続続)
今日も合間をみて、LPC2888。
I/Oポートの1ビットを変えるだけで1us近くかかる件。でてくるアセンブルコードは、EWBのProjectのOption内の、C/C++ Compiler→Listの、Output list fileをチェックすればOK。
MODE0_2_bit.P2_1 = 0; という1行が、次のようなアセンブルコードになっていた。
----
MOV R0,#-2147483632
ORR R0,R0,#0x3080
MOV R1,#-2147483632
ORR R1,R1,#0x3080
LDR R1,[R1, #+0]
BICS R1,R1,#0x2
STR R1,[R0, #+0]
----
これはすごい。ありえないぐらい冗長。と思ったけど、asm()で直接アセンブルコードを書こうと思っても、なぜかMOVでは、即値で0x80003090などを代入できない(out of rangeと出る)ようだ。なんでだ?
それはともかく、LPC2888のIOポートは、特定ビットだけをset/resetするためだけのレジスタというのがある、不思議な構成になっているので、そいつを使ってみる。
MODE0S_2 = 0x02; としたら、次のようになった。
----
MOV R0,#-2147483628
ORR R0,R0,#0x3080
MOV R1,#+2
STR R1,[R0, #+0]
----
さっきのよりはまし。これで500nsぐらい。それでもやっぱり1命令あたり100ns以上かかっている。なんでだろう?cacheをonにしてないから、こんなものなのか?
次。UART。こんな関数を書いてみる。
----
void UARTinit()
{
LCR = 0x83; // enable access to Divisor
DLL = 78; DLM = 0x00; // (12MHz/16) / 78 = 9600bps
LCR = 0x03; // N81
MODE0_6 = 0x0f;
MODE1_6 = 0x0c; // TXD(P6.1) & RXD(P6.0) enabled
}
void UARTputc(unsigned char d)
{
while(_LSR_bit.THRE == 0); // wait for transmission ready
THR = d; // transmit data
}
unsigned char UARTgetc()
{
unsigned char d;
while(_LSR_bit.RDR == 0); // wait for data receive
d = RBR;
return(d);
}
----
ポーリングだし、ブロッキングだし、あまりスマートではないが、とりあえず動くようだ。
次。内蔵RAMからの起動。LPC2880/2888 Product datasheet Rev.3(概要っぽやつ)の6.1.4 On-chip ROMの記述によれば、
----
6.1.4On-chip ROM
The LPC2880/2888 includes an on-chip ROM that contains boot code. Execution begins in on-chip ROM after a Reset.
The boot code in this ROM reads the state of the mode inputs and accordingly does one of the following:
1.Starts execution in internal flash
2.Starts execution in external memory
3.Performs a hardware self-test, or
4.Downloads code from the USB interface into on-chip RAM and transfers control to the downloaded code
----
とある。USBからのDL、というのは、この4.のことで、いったん内蔵RAMにDL後、それを実行(きっとここに内蔵Flashへの転送が書いてあるのが*.ebnなんだろう)、とある。ならば、例のflash書き込みツール(MassDFU)というのは、実は内蔵RAMへの転送ツールなんだろうか?
淡い期待を持ってiRAMでつくったやつをそのままMassDFUで書き込んでみるが、もちろん動作せず。がっくし。ここは、しばらくあきらめるか。
次。外付けDRAM。案の定、こいつも含めて、もろもろ初期化がlow_level_init()に書いてあり、それがcstartup.sから、mainの前に実行されている。
たしかに、unsigned char *p = (unsigned char *)0x30000000;みたいにポインタを宣言しておくと、p[0]や*pなどでアクセスできようだ。めでたい。
投稿者 akita : 2007年10月30日 16:19