読者です 読者をやめる 読者になる 読者になる

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なわけだ。
ちなみに、

ARM Information Center

を参照すると以下のように説明がある。
IMPORT
シンボルを無条件にインポートします。
EXTERN
シンボルが現在のアセンブリで参照される場合にのみ、インポートします。
なるほど、IMPORTは使わなくってもモジュール定義するし、EXTERNは使う場合
のみ、という事か。別のオブジェクトファイルを参照する、とあるので、その
モジュールがc言語で定義されていようとアセンブリで定義されていようと、
どちらでもよい、という事か。
ちなみに、EXTERNのようなディレクトリの一覧はここ

ARM Information Center

なぜかここに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って何? → 疑似命令らしい。

IAR【カスタマーサポート】FAQ

この記述は、アセンブラの 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を呼ばなくするとどうなるかしら。ウォッチドッグタイマの
制御しかしてなさそうなんだけど・・
うむ、やはり同じ結果になる・・
 

FRDM-KL25Z その6

さて、FRDM-KL25Zのプログラミングのために、IAR Embedded Workbench IDE
選んでるが、Eclipseベースのフリーな環境もあるらしい。
今はコード量が問題ではないので、コード制限評価版として IAR を選択した。
至れり尽くせりなのは、FRDM-KL25Zメーカ(nxp)のサイトで、各社ワークベンチ向け
のサンプルコードがダウンロードできるところ。

IAR向けのサンプルでLチカを試すことができた。

 

さて、それはさておきスタートアップはどうなってるのか。
IARのマニュアルを確認してみる。IARのFAQでスタートアップに関するものがあり、
そこからPDFがダウンロードできる。

 

PDFの中身を確認すると、
Cortex-M0/M3/M4向けのベクタテーブルが抜き出されている。
IARのインストールディレクトリを確認すると・・・あった。
C:\Program Files (x86)\IAR Systems\Embedded Workbench 8.0\arm\src\lib\thumb\vector_table_M.s

------------------------------------------------------
__vector_table

DCD sfe(CSTACK)
DCD __iar_program_start

DCD NMI_Handler
・・・
------------------------------------------------------

ふむふむ、IAR社のCortexマイコン用スタートアップだから、iar_...なるほど。
ちなみにDCD命令はARMサイトで以下のように説明されている。
DCD ディレクティブは、ワード単位でメモリを割り当てて 4 バイト境界で整列させ、実行時のメモリの初期内容を定義します。

ここでは関数アドレスを示す__jar_program_startをメモリに割り当てている感じか。

このコードの手前に

------------------------------------------------------
EXTERN __iar_program_start
PUBLIC __vector_table
------------------------------------------------------

 

とあるので、__iar_program_startは別の場所に定義されている。
同じフォルダに、cstartup_M.cがあり、内容を確認すると、あった・・
------------------------------------------------------
void __iar_program_start( void )
{
__iar_init_core();
__iar_init_vfp();
__cmain();
}
そういえばこれ、アセンブラコードとc言語コードの両方の記述が可能であり
(Cortex-Mプロセッサがそーいう風にできている)、
同じ名前のアセンブラファイル cstartup_M.sに以下のように定義されている。

__iar_program_start:
FUNCALL __iar_program_start, __iar_init_core
BL __iar_init_core
FUNCALL __iar_program_start, __iar_init_vfp
BL __iar_init_vfp
FUNCALL __iar_program_start, __cmain
BL __cmain
REQUIRE __vector_table

やってることは一緒である。さて、まず__iar_init_coreはどこで定義されているのか。

cstartup_M.cで以下のように宣言されているので
__weak void __iar_init_core( void );
乱暴に言えばなくても怒られないexternである。

C:\Program Files (x86)\IAR Systems\Embedded Workbench 8.0\arm\src\lib\arm\coreinit.s
ここに定義されているっぽい。アプリ側のフルgrepでは見つからなかったので、
唯一ここにあるだけか?__iar_init_core_v6とあるので、ARMv6アーキテクチャ向け。
MRC/MCRでステータスレジスタを初期化してる感じ。あまり踏み込まないでおこう。

__cmainはどうだろう? ここからmain関数がコールされるので
ユーザアプリは動くわけだけど、さて、pdfに書かれているようなcmain.sが
存在しない。

cライブラリを含めたIARの便利ライブラリをロードしつつ、アプリを動かす
のだとすると、その部分(おそらくCortexプロセッサをどう初期化するか含めて)
IAR資産なのかと推測。

とりあえずリセット割り込みから、Cortexプロセッサの標準的な初期化を行い、LEDチカまでの最小限の流れが追えるとよいのだが、便利なものはシステムが肥大化し、
内部は隠蔽されるの法則か・・

Cで全てを抽象化するなら、Linuxアプリコードを書くのと大して変わらず面白くない・・・

うーむ、このへんにしておこう。

FRDM-KL25Z その5

サンプルコードを確認すると以下のようになっている。

int main(void)

{

   char ch;

   BOARD_InitPins();

   BOARD_BootClockRUN();

   BOARD_InitDebugConsole(); 

   PRINTF("hello world.\r\n");

   while(1)

   {

          ch = GETCHAR();

          PUTCHAR(ch)

    }

}

ハードウェア初期化の部分はともかく・・・

おおおお、普通にC言語だww

シリアル通信でキーボード入力をエコーバックする、という話が

GETCHAR, PUTCHARで抽象化されている。おぉぉぉ。

ふつうだ、まったくもってふつうだwwww

感動ww

FRDM-KL25Zその4

お次はデバッグ。IAR Embedded Workbench IDEデバッグボタンを

押してみる。

 

おぉ・・ main関数で止まっている。すばらしい。

マイコンを初めてデバッグした・・初体験ww

 

OpenSDAプロトコルを制御するオンボードデバッガ=マイコンチップと、それ上で動作するアプリの力を借りている。

 

子のアプリがワークベンチからはデバッガとして指定するものなので、

プロジェクトのデバッガ設定でJ-Link/J-Traceを選択してある。

「表示」メニューでレジスタを出してみると

 

PC  0x0000134C

とある。ステップインしてみると

PC 0x0000134E

おお、変わった。感動wwww

アドレスが2バイト進んだ?

もう一回ステップイン(BOARD_InitPis関数に入る)

PC 0x000012E0

おぉ、110バイト番地が戻った。

つまり、BOARD_InitPins関数のアドレスはスタートアップ(main)

よりも手前なのか、当たり前なのかもだけど感動するwwww

 

 

 

FRDM-KL25Z その3

さて、実際、OpenSDA USBポートでFRDM-KL25Zに接続しているわけだが、

オープンデバッガとゆーことは、つまりシリアル通信しているわけで、

(といってもUSB自体がシリアルか?)

シリアルポートとして見えるはずなのだ。

つまり、シリアルポートを持つデバイスとしてWindowsからみえるはずなのだ。

 

バイスマネージャを開くと・・・あった。

 

ポート(COMとLPT)

     JLink CDC UART Port (COM4) 

ふむふむ、UARTなんだ。

ボード側で動作しているアプリ名が見えている。JLink。

 

なので当然シリアル接続してみる。

ボーレートは 115200らしい。

 

ボードにはhelloworldサンプルをダウンロードしてあるので

リセットキーを押すと・・・

 

でた。

 

"hello world"

 

キーボードになんか入力すると、

"hello world"

aaaabbbccc

ふむ、ふむ、キーボード入力をエコーバックしてるそうな。

なるほどなるほど。

 

FRDM-KL25Z その2

さて、OpenSDAが何かいまいちわかってないけど、フラッシュへの書き込みやデバッグをするためのオープンなプロトコル仕様だと思うことにしよう。

 

そのプロトコルを制御するためのチップというか、マイコンがターゲットボードに搭載され、そのマイコンごしに、Cortex-Mxマイコン(コアそのものでなく)と通信する。

 

Cortexマイコンのインタフェースを吸収してくれるマイコンとゆーことだろうか。

 

UARTや、SPIで、オンボードデバッガ=OpenSDAマイコンと、ターゲットボード=Cortexマイコンと繋がってるので、UART/SPIでプロトコル通信している、という事か。

 

前回OpenSDAのブートローダデバッグファームウェアを書き換えることで、

Windows10から仮想ドライブとして見えるようになった。

 

そしてOpenSDAマイコン上で動作する専用アプリを今度はダウンロードしなければいけないらしい。

 

ここでは Segger J-Linkというアプリを使う(アプリにも複数メーカ製があるらしい)

www.segger.com

↑ここから、FRDM-KL25Z用のアプリを落としてきた。それはそうか、Cortexコアは一緒でもCortex搭載マイコンは各社異なるだろうから、OpenSDAというお約束事は一緒でも、プロトコル内容は違うわけだ。

 

例によってリセット+接続でBOOTLOADERと認識されるので、上記から落としてきた

12_OpenSDA_FRDM-KL25Z.binをドロップし再起動する。

 

すると起動時のFRDM-KL25Zの内容が少し変わる。

Segger.html

↑今入れたアプリのHTMLが入っている。

 

なるほど、なるほど、こうやって入れたものによって仮想ドライブの内容が変わっていくのか。

 

FRDM-KL25Z

触り始めた。

ただ、OpenSDA用のファームウェアが古いと、

Windows10では正常に動作しない、という話があり、

ブートローダを更新してみる。

BOOTUPDATEAPP_Pemicro_v111.SDAというファイルだ。

これは、リセット状態でFRDM-KL25Zを接続(OpenSDA側)すると

中にサイトリンクがあるのでクリックすると取ってこれる。

 

Windows 8以降でFRDM-KL25Zのファームウェアアップデートができない場合の対処法 | コーヒーサーバは香炉である

↑こちらのサイトに従って、Windows10のレジスタとサービスを停止させてから

ブートローダを更新する。

 

上手くいくのだけど、FRDM-KL25Zを接続すると、「BOOTLOADER」としてしか認識されない。「FRDM-KL25Z」という名称で認識されない。

 

一方で、mbed化する記事を見ると、BOOTLOADER更新後に

mbed用のファームウェア?を放り込んでいた。

mbed FRDM KL25Z ゲッティングスターテッド | mbed

 

なるほど、もしかして・・と思い、落としてきたOpenSDAツールの中に・・・

あった。

MSD-DEBUG-FRDM-KL25Z_Pemicro_v118.SDA

これだ。これを入れて初めて、OpenSDAがxx化するのではないか。

リセット起動で「BOOTLOADER]認識させ、このファイルを放り込んで

再接続・・

 

よし、見えた!「FRDM-KL25Z】として認識されたぜぃ。