Kinetis Lシリーズをつかってみる3

20161123追:
FreeScaleはNxPに喰われた後さらにQualCommに喰われました



VersaloonのBBSにはすでにレポートしていますが、FreeScaleのKinetis-Lシリーズを
OpenOCDから使う際のフラッシュ書き込みのスピードを大幅に増加させることに成功
しましたのでこちらでもご報告します。


以前、私はKL25Z,KL05Z等のKintis-LシリーズのマイコンにOpenOCDからの書き込みに
対応させていました。しかしこれらのマイコンは"Program-LongWord"という4バイト単位で
フラッシュロムに書き込むコマンドしかなく、SWD接続でちまちまやり取りをしている
と1KiB/Sec程度の速度しか出ないため、役に立たない代物でした。

さらにそのときにSRAM上で動くブートローダーが必要だ…と言っていました。結局
自分で作成する羽目になりましたorz


原理はそこまで難しくは無く、上記のSRAM上で"Program-LongWord"を送り込んだワー
ド単位のデータの数だけ動作するプログラム(とデータ)を送り込んで実行するだけです。

具体的には先ずC言語で以下の関数をコンパイルして…


void kinetis_lwrite(uint32_t *pLW,uint32_t faddr,uint32_t wcount)
{
volatile uint8_t * pfstat = (uint8_t*) (0x40020000u+0);
volatile uint32_t* pfcoob3 = (uint32_t*)(0x40020000u+4);
volatile uint8_t * pfcoob0 = (uint8_t*) (0x40020000u+7);
volatile uint32_t* pfcoob7 = (uint32_t*)(0x40020000u+8);
#define FTFx_FSTAT (*(pfstat))
#define FTFx_FCCOB3 (*(pfcoob3))
#define FTFx_FCCOB0 (*(pfcoob0))
#define FTFx_FCCOB7 (*(pfcoob7))

for(register uint32_t i=0;i<wcount;i++){

/* wait till CCIF bit is set */
while((FTFx_FSTAT&FTFA_FSTAT_CCIF_MASK) != FTFA_FSTAT_CCIF_MASK){};
/* clear RDCOLERR & ACCERR & FPVIOL flag in flash status register */
FTFx_FSTAT = FTFA_FSTAT_ACCERR_MASK|FTFA_FSTAT_FPVIOL_MASK|FTFA_FSTAT_RDCOLERR_MASK;

FTFx_FCCOB3 = faddr;
FTFx_FCCOB0 = 0x06;
FTFx_FCCOB7 = *pLW;
faddr += 4;
pLW++;

/* All required FCCOBx registers are written, so launch the command */
FTFx_FSTAT = FTFA_FSTAT_CCIF_MASK;
/* Wait for the command to complete */
while((FTFx_FSTAT&FTFA_FSTAT_CCIF_MASK) != FTFA_FSTAT_CCIF_MASK){};

}
}

出てきたアセンブラリストをさらに最適化を行い今度はその最適化したアセンブラ
ファイルをコンパイルしてマシン語を得ます。
で、このマシン語をOpenOCDのおソースにデータの形で持ちます、↓こんな感じです。

/* Kinetis Program-LongWord Microcodes */
const uint8_t kinetis_flash_write_code[] = {
/* Params:
* r0 - workarea buffer
* r1 - target address
* r2 - wordcount
* Clobbered:
* r4 - tmp
* r5 - tmp
* r6 - tmp
* r7 - tmp
*/

/* .L1: */
/* for(register uint32_t i=0;i<wcount;i++){ */
0x04,0x1C, /* mov r4, r0 */
0x00,0x23, /* mov r3, #0 */
/* .L2: */
0x0E,0x1A, /* sub r6, r1, r0 */
0xA6,0x19, /* add r6, r4, r6 */
0x93,0x42, /* cmp r3, r2 */
0x16,0xD0, /* beq .L9 */
/* .L5: */
/* while((FTFx_FSTAT&FTFA_FSTAT_CCIF_MASK) != FTFA_FSTAT_CCIF_MASK){}; */
0x0B,0x4D, /* ldr r5, .L10 */
0x2F,0x78, /* ldrb r7, [r5] */
0x7F,0xB2, /* sxtb r7, r7 */
0x00,0x2F, /* cmp r7, #0 */
0xFA,0xDA, /* bge .L5 */
/* FTFx_FSTAT = FTFA_FSTAT_ACCERR_MASK|FTFA_FSTAT_FPVIOL_MASK|FTFA_FSTAT_RDCO */
0x70,0x27, /* mov r7, #112 */
0x2F,0x70, /* strb r7, [r5] */
/* FTFx_FCCOB3 = faddr; */
0x09,0x4F, /* ldr r7, .L10+4 */
0x3E,0x60, /* str r6, [r7] */
0x06,0x27, /* mov r7, #6 */
/* FTFx_FCCOB0 = 0x06; */
0x08,0x4E, /* ldr r6, .L10+8 */
0x37,0x70, /* strb r7, [r6] */
/* FTFx_FCCOB7 = *pLW; */
0x80,0xCC, /* ldmia r4!, {r7} */
0x08,0x4E, /* ldr r6, .L10+12 */
0x37,0x60, /* str r7, [r6] */
/* FTFx_FSTAT = FTFA_FSTAT_CCIF_MASK; */
0x80,0x27, /* mov r7, #128 */
0x2F,0x70, /* strb r7, [r5] */
/* .L4: */
/* while((FTFx_FSTAT&FTFA_FSTAT_CCIF_MASK) != FTFA_FSTAT_CCIF_MASK){}; */
0x2E,0x78, /* ldrb r6, [r5] */
0x77,0xB2, /* sxtb r7, r6 */
0x00,0x2F, /* cmp r7, #0 */
0xFB,0xDA, /* bge .L4 */
0x01,0x33, /* add r3, r3, #1 */
0xE4,0xE7, /* b .L2 */
/* .L9: */
0x00,0xBE, /* bkpt #0 */
/* .L10: */
0x00,0x00,0x02,0x40,/* .word 1073872896 */
0x04,0x00,0x02,0x40,/* .word 1073872900 */
0x07,0x00,0x02,0x40,/* .word 1073872903 */
0x08,0x00,0x02,0x40,/* .word 1073872904 */
};


引数に取るレジスタはARMの関数呼び出し規約に即します。ここで間違えると失敗しま
すのでご注意を。Kinetis系のマイコンの場合は最悪のケースになる場合がある(後述)
のでマジでご注意を!!

後は上のプログラムの小片を流し込んで実行させるだけです。
OpenOCDには"target_run_algorithm"という仕組みがあるので引数にとるレジスタを
正しく設定したあとこれを利用して実行するとSWDの通信を介さずターゲット上で書
き込みプログラムが実行されます。通信のオーバーヘッドが無いのでもちろん書き込
み動作はとしては非常に早くなります♥


こちらに新旧の書き込み速度を比較したlogをVersaloonとSTLink/v2で試したものを
まとめた圧縮ファイルがあるので参考にしてください。見るのがめんどくさい方の為
に下に要素だけ抽出しましたが、書き込みスピードは10倍以上改善されたのが分かる
と思います。
旧ドライバ:
wrote 36648 bytes from file main.elf in 26.328295s (1.359 KiB/s)
新ドライバ:
wrote 36648 bytes from file main.elf in 1.906275s (18.774 KiB/s)

これで市販のツールに勝るとも劣らないパフォーマンスを得ることが出来ましたので
GCC環境でもVersaloonかSTLink/V2を持っていさえすればOpenOCDでバリバリ書き込み/
デバッグが可能です!

あと、しつこいくらいに言っておきますがこちらの件だけはご注意ください。security
とmass-erase disableを同時に有効にしてしまうとMDM-APでも復帰不可能の完全な
ゴミにしてしまいます!
…ねむいさんも今回のドライバ改良の際にFRDM-KL25Zをゴミにしてしまいましたorz
簡単にゴミに出来て回復手段も全くないとか雄度高すぎですよこのマイコン…
で、仕方ないのでおなじのを買うはめになりました…


↑良く見ると基板りビジョンのほかにチップの刻印も違っていた…
ちなみにFRDM系ボードにあるOpenSDA側のK20マイコンもバッチリsecurityとmass-erase
のdisableが掛けられていやがってSTマイクロのDiscovery系の板みたいな自由度は全く
ありません!ぜんぜんFreedomぢぁない!!F**K!


…はぁはぁ…失礼、とにかくすでにバイナリには反映してますので皆さんもバリバリ使っ
てください…今のところ私以外で試された方はAlanさんただ一人のようですが‥



●おまけ
KinetisのOpenOCDのコード見ててなんとなくフラッシュドライバの追加の方法が分かって
来たのでNuvotonのNUC1xx系のマイコンのドライバの実装も試行中です。


実はすでに低速なSWD通信によるProgram-LongWordの書き込みには成功してたりします。
こちらもアトミックに書き込みできるようになったら別枠でご報告とさせていただきます。

Comments

Post a Comment








Go to top of page