LPC1114FN28/102 (8) -- IRQLATENCY レジスタ (1)

LPC1114FN28/102 で割り込みレイテンシを調べていて、LPC111x / LPC11C1x のユーザ・マニュアル (UM10398) には記載がない「IRQLATENCY」レジスタ (アドレス 0x40048170) が存在し、機能することを確認しました。
「IRQLATENCY」レジスタは、

  • LPC11Uxx のユーザ・マニュアル (UM10462)
  • LPC11Exx のユーザ・マニュアル (UM10518)

には記載されています。
LPC111x では (LPC11C1x、LPC11Uxx、LPC11Exx を含む) タイマ/カウンタのマッチ・レジスタ (MRx) にシャドウ・レジスタ (バッファ・レジスタ) がないため、マッチ・レジスタを書き換えると、即座にその値が現在のカウント値と比較されます。
したがって、もしマッチ・レジスタ (MRx) に設定すべき値が、現在のカウント値 (TC) よりも小さい場合には現在の PWM サイクル中には決してマッチが発生せず、PWM 出力としては不正な値が出力されることになります。
PWM 周期をマッチ・レジスタ 3 (MR3) で規定する場合の図を下に示します。

のこぎり波状の太い青色の線で示されているのが、タイマ/カウンタのカウント値で、システム・クロックでカウントアップされていき、MR3 の値に達するとリセットされてゼロに戻ります。
この MR3 とのマッチにより割り込みを発生させ、割り込みハンドラ内で PWM 値を更新するものとします。
当然、ハードウェアの割り込み信号が発生してから、ソフトウェアの割り込みハンドラに制御が移るまでには時間を要するわけで、これが「割り込み応答時間」(interrupt latency) となります。
Cortex-M シリーズでは、発生した割り込みに対する応答として、CPU 内部の

  • R0 〜 R3
  • PC (R15)
  • LR (R14)
  • R12
  • PSR (Program Status Register)

の計 8 ワードが自動的にスタックに退避されます。
したがって、割り込みレイテンシは必ず「8」クロック以上となります。
Cortex-M3 のテクニカル・リファレンス・マニュアルの「3.9.1 例外処理」の項には、「0 ウェイトサイクルのメモリでレイテンシは最大 12 サイクル」という趣旨の記述があります。
また、Cortex-M0+ のテクニカル・リファレンス・マニュアルでは「0 ウェイトサイクルのメモリでジッタ抑制なしでレイテンシは 15 サイクル」という趣旨の記述があります。
肝心の Cortex-M0 のテクニカル・リファレンス・マニュアルでは、「詳細については、プロセッサ実装者から提供されている説明書を参照して下さい」のような記述があり、はっきりとは述べられていません。
NXP の技術資料であるユーザ・マニュアル UM10398 の中にレイテンシの記述は見つけられませんでしたが、プレゼンテーション用の資料 (PowerPoint のスライド) には「16 サイクル」との記述がありました。
Cortex-M3 が 12 サイクルで、Cortex-M0 が 16 サイクル程度と違いがあるのは、Cortex-M3 は「ハーバード・アーキテクチャ」でレジスタをデータ・メモリのスタックに積んでいる間にコード・メモリの割り込みベクタなどを同時に読み込めるからのようです。
トランジスタ技術 2012 年 10 月号の pp.114 の「図 4 割り込みコントローラの処理の比較」では、ARM7TDMI のレイテンシ「26 サイクル」との比較で「12 サイクル」となっていますが、これは Cortex-M3 の場合で、Cortex-M0 に対しては正しくありません。
このレイテンシの数値の条件として「0 ウェイト・サイクルのメモリ」とありますが、LPC111x の場合には、20 MHz 以上のシステム・クロックを使用する場合にはフラッシュ読み出しにウェイト・サイクルを挿入する必要があります。

  • クロック 20 MHz 以下なら 0 ウェイト・サイクル
  • クロック 20 MHz 以上 40 MHz 以下なら 1 ウェイト・サイクル
  • クロック 40 MHz 以上 50 MHz 以下なら 2 ウェイト・サイクル

の設定にします。
リセット後のデフォルト値では 2 ウェイト・サイクルが選ばれています。
クロック 48 MHz とか 50 MHz に設定する場合には、デフォルト値の 2 のままで変更する必要はありません。
クロック周波数を低くして、ウェイト・サイクルを減らすためには、LPC_FLASHCTRL->FLASHCFG レジスタをいじる必要があります。
フラッシュの構成としては、データ 128 ビット (16 バイト) + ECC 8 ビット (1 バイト) のブロックを一度に読み出しており、この時にウェイト・サイクルが必要となります。
決して 1 ワード (4 バイト) 読み出しごとにウェイト・サイクルが必要なわけではなく、新たな 16 バイト・ブロックを読み出すごとにウェイト・サイクルが必要とされるだけです。
割り込みレイテンシを実測するのに、当初は上の図のように、タイマ/カウンタ・レジスタの値を割り込みハンドラの冒頭で読み出していたのですが、期待される値よりも大きな値となりました。
具体的には、カウント・レジスタの値を読み出す部分の実行サイクル数 4 程度を含んだ値で、

  • 0 ウェイト・サイクルでレイテンシ 29 クロック
  • 1 ウェイト・サイクルでレイテンシ 32 クロック
  • 2 ウェイト・サイクルでレイテンシ 35 クロック

となりました。
タイマ/カウンタは CPU コア側とは AHB-Lite および APB を介してつながっており、その影響も考えられるので、コアと密接につながっている SysTick タイマを利用する方法に変えました。
その結果、0 ウェイト・サイクルで 26 クロックという、少しはタイトな値が得られました。
次回は、その方法などについて説明します。