FRDM-KL25Z その7
スタートアップコードについて、前回少しさがしてみたが、いったん
仕切りなおそう。
まず、IAR向けのnxpサンプルアプリをDLすると、アプリ内にそもそも
スタートアップアセンブリが含まれている。
C:\FRDM-KL25Z\SDK_2.2_FRDM-KL25Z\devices\MKL25Z4\iar\startup_MKL25Z4.s
つまりこういうことではないか。
IARは自身の製品でcortex-M向けのスタートアップアセンブリを公開している。
これをnxpがFRDM向けにカスタムしてアプリサンプルコードに含めている
のではないか。つまりIAR側のスタートアップアセンブリで動作している
わけではない。
そこで、これ、startup_MKL25Z4.sだ。先頭を見ると、
MODULE ?cstartup
とある。モジュール名 cstartupだ。
そこで、IARワークベンチのインストールフォルダ下を "*.s"ファイル、
文字列"MODULE"でグレップしてみると、
以下の4種類しかないことがわかる。
cstartup, cp15, vector_table_vorago, vector_table
flashloaderフォルダ下と、lib下の両方に転がっているので悩むが、まずはlib側
だとしよう。lib/armと、lib/thumbとあり、cortex-Mなのでtumb側だとしよう。
C:\Program Files (x86)\IAR Systems\Embedded Workbench 8.0\arm\src\lib\thumb\cstartup_M.s
さて、両者の違いはどこにあるのか。
1.PUBLIC __iar_program_start / EXTERN __iar_program_start
なるほどこれはわかる気がする。iarのスタートアップモジュールなので、
nxpのサンプルコードにはない、という意味でnxp側がEXTERNなわけだ。
ちなみに、
を参照すると以下のように説明がある。IMPORT
シンボルを無条件にインポートします。EXTERN
シンボルが現在のアセンブリで参照される場合にのみ、インポートします。
なるほど、IMPORTは使わなくってもモジュール定義するし、EXTERNは使う場合
のみ、という事か。別のオブジェクトファイルを参照する、とあるので、その
モジュールがc言語で定義されていようとアセンブリで定義されていようと、
どちらでもよい、という事か。
ちなみに、EXTERNのようなディレクトリの一覧はここ
なぜかここにPUBLICの説明はない。
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.kui0005a/a51_st_public.htm
ここの説明をざっと解釈するとEXTERNと同じだが、別のモジュールで
使用されるのがEXTERNとの違いか?
とはいえ、PUBLICも、同じアセンブリの中で FUNCALL __iar_program_start
している。
ちなみに同ファイルで BL __iar_init_coreとある。FUNCALLとBLの違いは何か?
というか、FUNCALLって何? → 疑似命令らしい。
この記述は、アセンブラの CFI FUNCALL と同じ意味で、マニュアルからは削除されておりますが、
互換性のため残されている記述です。
うむ、しかし、そのCFIって何? IAR ワークベンチのヘルプ→アセンブラ
リファレンスガイド で確認してみると、
CFI => コールフレーム情報、とある。
コールフレームは関数呼び出しのスタックに関するものであり、
「リターンアドレス、局所データ、引数」をひっくるんでコールフレームと
呼ぶらしい。よくわかってないが・・
まぁ、いいや、IARのアーキテクチャではそっちを使うらしい。
nxpのサンプルでは以下なのであまり追及しない。
LDR R0, =__iar_program_start
BX R0
素直にBXで分岐(ブランチ)している。
まぁ、いいや。なんにせよその、__iar_program_startが、iar側のどこにあるのか。
MODULE + "*.s"でサーチして見つからないので、c言語で定義されているのだろう。
C:\Program Files (x86)\IAR Systems\Embedded Workbench 8.0\arm\src\lib\thumb\cstartup_M.c
たくさんヒットするが、どうも↑らしい。前述の cstartup_M.sと同じ場所である。
とはいえ、nxpのサンプルは直接iarのコードを取り込んでいるわけではない。
(ビルドメッセージにこのファイルは出てこない)
なのでたぶん、ライブラリをリンクしているのだろう。
nxpはiarの機能を取り込むため、EXTERN __iar_program_startしているのだろう。
以上!!
なんにせよ、このC:\FRDM-KL25Z\SDK_2.2_FRDM-KL25Z\devices\MKL25Z4\iar\startup_MKL25Z4.s
をいじれば好きなことができるはずだ!!
一旦すべて削除し、わけわかってないが以下のようにしてみた。
MODULE ?cstartup
;; Forward declaration of sections.
SECTION CSTACK:DATA:NOROOT(3)
EXTERN SystemInit
DATA
__vector_table
DCD sfe(CSTACK)
DCD Reset_Handler
__Vectors_End
THUMB
PUBWEAK Reset_Handler
;SECTION .text:CODE:REORDER:NOROOT(2)
Reset_Handler
CPSID I ; Mask interrupts
LDR R0, =0xE000ED08
LDR R1, =__vector_table
STR R1, [R0]
LDR R2, [R1]
MSR MSP, R2
LDR R0, =SystemInit
BLX R0
CPSIE I ; Unmask interrupts
;LDR R0, =__iar_program_start
;BX R0
さて、この実験から何がわかるのか。
(ちなみにMODULEとENDしかないコードだと、*.oが作れないらしく怒られた)
1. main関数はちゃんと呼ばれる。
なぜだろう? __iar_program_startにブランチしていないのに。
2.main関数が無限ループして呼ばれる。
リセットハンドラで__iar_program_startにブランチしないからか、
main関数のPRINTF("xxxxhello world---.\r\n");が繰り返し実行される。
ちなみにサンプルコードは以下。
char ch;
/* Init board hardware. */
BOARD_InitPins();
BOARD_BootClockRUN();
BOARD_InitDebugConsole();
PRINTF("xxxxhello world---.\r\n");
while (1)
{
ch = GETCHAR();
PUTCHAR(ch);
}
GETCHAR/PUTCHARはちゃんと動作していて、ターミナルでキー入力
するとちゃんとエコーバックされる。
どういうことかしら・・・
ちゅーか、だれがmain関数をコールしているのかしら・・
SystemInitを呼ばなくするとどうなるかしら。ウォッチドッグタイマの
制御しかしてなさそうなんだけど・・
うむ、やはり同じ結果になる・・