アプリケーションノート 179 - ARM Information Center

アプリケーションノート 179
Cortex™-M3 組み込みソフトウェア開発
発行日:2007 年 3 月
Copyright © 2007. All rights reserved.
ARM DAI0179B
Application Note 179
アプリケーションノート 179
Cortex-M3 組み込みソフトウェア開発
Copyright © 2007. All rights reserved.
リリース情報
表 1 改訂履歴
日付
発行
変更内容
2007 年 1 月
A
初版(廃版)
2007 年 3 月
B
第2版
著作権
®または™と記されている語やロゴは、EU および他国における ARM 社の登録商標または商標です。ただ
し、著作権に関して下記に別途定められている場合を除きます。本書に記載されている他の製品名は、各
社の所有する商標です。
本書に記載されている情報の全部または一部、ならびに本書で紹介する製品は、著作権所有者の文書によ
る事前の許可を得ない限り、転用・複製することを禁じます。
本書に記載されている製品は、今後も継続的に開発・改良の対象となります。本書に含まれる製品および
その利用方法についての情報は、ARM が利用者の利益のために提供するものです。したがって当社では、
製品の商品性または目的への適用性を含め、暗黙的・明示的に関係なく一切の責任を負いません。
本書は、本製品の利用者をサポートすることだけを目的としています。本書に記載されている情報の使用、
情報の誤りまたは省略、あるいは本製品の誤使用によって発生したいかなる損失・損害についても、ARM
社は一切責任を負いません。
ARM という語は、適宜「ARM またはその子会社」の意味で使用されます。
守秘義務
このドキュメントは公開文書です。このドキュメントを使用、コピー、公開する権利は、ARM と本書を配
布する他社の結んだ契約条件に基づき、ライセンス制限の対象となる場合があります。
製品状態
本ドキュメントの情報は、開発済みの製品に関する確定情報です。
ホームページ
http://www.arm.com
2
Copyright © 2007. All rights reserved.
ARM DAI0179B
Application Note 179
1
ARM Cortex™-M3
本アプリケーションノートでは、ARM Cortex™-M3 プロセッサの主な特長を紹介し、対応ソフ
トウェア開発のさまざまな側面を解説します。既存の ARM プロジェクトから Cortex-M3 プラ
ットフォームへの移行についても述べます。
ARM Cortex-M3 は、
高性能、低コスト、低消費電力の 32 ビット RISC プロセッサです。Cortex-M3
プロセッサは、Thumb-2 命令のみ実行します。ARM 命令セットはサポートしません。Cortex-M3
プロセッサは、ARM アーキテクチャ v7-M をベースとし、効率性に優れたハーバード 3 段パイ
プラインコアを採用しています。ハードウェア除算、低レイテンシの割り込みサービスルーチ
ン(ISR)開始/終了機能も備えています。
CPU コアに加え、Cortex-M3 プロセッサには多数のコンポーネントがあります。ネスト型ベク
タ割り込みコントローラ(NVIC)、オプションのメモリ保護ユニット(MPU)、タイマ、デバ
ッグアクセスポート(DAP)、オプションのエンベデッドトレースマクロセル(ETM)などで
す。また Cortex-M3 は、固定メモリマップを持ちます。
1.1
ネスト型ベクタ割り込みコントローラ(NVIC)
NVIC は、シリコンメーカの使用する実装に応じ、最大 240 本の外部割り込みに対応します。
割り込みレベルは 256 種類あり、動的な再優先度付けも可能です。また、レベル割り込みソー
ス、パルス割り込みソースの両方をサポートします。プロセッサ状態は、割り込み開始時にハ
ードウェアで自動的に保存され、割り込み終了時に復元されます。割り込みのテールチェイン
機能も備えています。
NVIC の使用により、Cortex-M3 のベクタテーブルは従来の ARM コアと大きく異なります。
Cortex-M3 のベクタテーブルは、他のほとんどの ARM コアのように命令ではなく、例外ハン
ドラと ISR のアドレスを格納します。初期スタックポインタは 0x0、リセットハンドラのアド
レスは 0x4 に置く必要があります。これらの値は、リセット時に適切な CPU レジスタにロー
ドされます。
1.2
メモリ保護ユニット(MPU)
MPU は、Cortex-M3 のオプションコンポーネントです。MPU は、特権とアクセス規則を適用
することにより、メモリの領域を保護します。保護する領域は 8 つまでで、各領域はさらに 8
つの下位領域に等分割できます。
1.3
デバッグアクセスポート(DAP)
DAP は、AHB-AP インタフェースを使ってプロセッサおよび他のペリフェラルと通信します。
サポートされているデバッグポートの実装には、シリアルワイヤ JTAG デバッグポート
(SWJ-DP)、シリアルワイヤデバッグポート(SW-DP)の 2 種類があります。Cortex-M3 実装
は、シリコンメーカの使用する実装に応じ、これらのいずれを装備することもあります。
1.4
メモリマップ
従来のほとんどの ARM コアと異なり、Cortex-M3 搭載デバイスのメモリマップの全体的なレ
イアウトは固定されています。これにより、Cortex-M3 を搭載した異なるシステム間のソフト
ウェア移植が容易となります。アドレス空間は、多数のセクションに分割されています。これ
については、4 ページの図 1、表 2 に示します。
ARM DAI0179B
Copyright © 2007. All rights reserved.
3
Application Note 179
ROM table
External PPB
ETM
TPIU
Vendor-specific
Private peripheral bus-external
Private peripheral bus-internal
Reserved
System control space
Reserved
FPB
DWT
ITM
External device
External RAM
Bit band alias
Bit banding
Peripheral
Bit band alias
SRAM
Code
Bit banding
図1
表2
4
Cortex のメモリマップ
Cortex-M3 メモリマップの詳細
メモリ領域
説明
アクセスに使用
するバス
コード
コードメモリ用(フラッシュ、ROM、リマップさ
れた RAM)。
ICode および
DCode
SRAM
ビットバンディング機能を備えたオンチップ
SRAM 用。
システム
ペリフェラル
ビットバンディング機能を備えたノーマルペリフ
ェラル用。
システム
外部 RAM
外部メモリ用。
システム
Copyright © 2007. All rights reserved.
ARM DAI0179B
Application Note 179
表2
ARM DAI0179B
Cortex-M3 メモリマップの詳細(続き)
アクセスに使用
するバス
メモリ領域
説明
外部デバイス
外部ペリフェラルまたは共有メモリ用のメモリ空
間。
システム
プライベートペリ
フェラル
MPU、NVIC、DAP、その他の CoreSight デバイス
など、システムデバイス用のアドレス空間。
システム
ベンダ固有
ベンダが指定するその他の用途向け。
.
Copyright © 2007. All rights reserved.
5
Application Note 179
2
Cortex-M3 用ソフトウェアの開発
このセクションでは、Cortex-M3 向けソフトウェア開発のさまざまな側面について説明し、コア
の主要機能を設定、使用するコードの書き方を紹介します。このセクションのサンプルコード
は、RealView コード生成ツール(RVCT)3.0 以上の使用を前提としています。
2.1
例外処理
例外テーブルの記述
ベクタテーブルを埋める最も簡単な方法は、スキャッタファイルを使ってメモリアドレス 0x0
に C 言語の関数ポインタの配列を置くことです。C の配列は、初期スタックポインタ、イメー
ジエントリポイント、外部ハンドラのアドレスの設定に使用されます。
例1
外部ハンドラ用の C の構造体の例
/* Filename: exceptions.c */
typedef void(* const ExecFuncPtr)(void) __irq;
/* Place table in separate section */
#pragma arm section rodata="exceptions_area"
ExecFuncPtr exception_table[ ] = {
(ExecFuncPtr)&Image$$ARM_LIB_STACKHEAP$$ZI$$Limit,
(ExecFuncPtr)__main, /* Initial PC, set to entry point */
NMIException,
HardFaultException,
MemManageException,
BusFaultException,
UsageFaultException,
0, 0, 0, 0, /* Reserved */
SVCHandler,
DebugMonitor,
0, /* Reserved */
PendSVC,SysTickHandler,
/* Configurable interrupts start here...*/
InterruptHandler0,
InterruptHandler1,
InterruptHandler2
/*
...
*/
};
#pragma arm section
注
この構造体の最初の 2 つのアイテムは、初期スタックポインタとイメージのエントリポイント
です。初期スタックポインタは、リンカ定義のシンボルを使って生成されます。詳細は、11 ペ
ージの「スタックとヒープの設定」をご参照ください。例 1 は、イメージのエントリポイント
として C ライブラリのエントリポイント(__main)を使用しています。
6
Copyright © 2007. All rights reserved.
ARM DAI0179B
Application Note 179
例外テーブルも、専用のセクションに配置されています。これは、#pragma arm section
このディレクティブは、#pragma arm section
rodata="exceptions_area"を使って行われます。
rodata="exceptions_area"と#pragma arm sectioninto の間にあるすべての RO(読み出し
専用)データを exceptions_area と呼ばれる専用セクションに配置するようコンパイラに指示
します。そして、このセクションがスキャッタファイルから参照されます。最後に例外テーブ
ルは、メモリマップの正しい位置、アドレス 0x0 に配置されます。
例外ハンドラの記述
コアは、例外が発生するとシステム状態を保存し、復帰時に復元します。したがって例外ハン
ドラはシステム状態を保存、復元する必要がなく、通常の ABI 準拠 C 関数として記述できます。
しかし、ARM では__irq 修飾子を使ってコードを明確にすることを推奨します。キーワードは、
コンパイラが必要に応じてスタックの 8 バイトのアライメントを維持する際にも使用されます。
詳細は、13 ページの「8 バイトのスタックアライメント」をご参照ください。
例2
シンプルな C の例外ハンドラ
__irq void SysTickHandler(void)
{
printf("----- SysTick Interrupt -----");
}
注
割り込みソースのクリアは、ISR で処理する必要があります。
Cortex-M3 では、例外の優先度付け、例外のネスト化、破壊可能レジスタの保存は、すべてコア
によって効率的に処理されます。すなわち、例外ハンドラ開始時には常に、コアによって割り
込みのイネーブルが継続されるということです。
例外テーブルの配置
例外テーブルは、オブジェクト内の専用セクションに配置されているため、例 3 のようにスキ
ャッタファイルを使って簡単に 0x0 に配置することができます。
例3
スキャッタファイルにおける例外テーブルの配置
LOAD_REGION 0x00000000 0x00200000
{
;; Maximum of 256 exceptions (256*4 bytes == 0x400)
VECTORS 0x0 0x400
{
exceptions.o (exceptions_area, +FIRST)
}
}
注
exceptions_area が必ず領域の最初に配置されるよう、+FIRST を使用します。これにより、リ
ンカの未使用セクション削除機能によってベクタテーブルが削除されることも防ぎます。
ARM DAI0179B
Copyright © 2007. All rights reserved.
7
Application Note 179
システム制御空間(SCS)レジスタの設定
SCS レジスタは 0xE000E000 にあります。個別のレジスタは多数にのぼるため、SCS レジスタ
を示すには構造体を使用します。例外テーブルと同様、この構造体をスキャッタファイルに追
加することにより、SCS レジスタは正しいメモリ位置に配置されます。例 4 は、SCS レジスタ
のサンプル構造体を示しています。
例4
SCS レジスタ構造体
typedef
int
int
int
volatile struct {
MasterCtrl;
IntCtrlType;
zReserved008_00c[2];
/* Reserved space */
struct {
int Ctrl;
int Reload;
int Value;
int Calibration;
} SysTick;
int zReserved020_0fc[(0x100-0x20)/4];
/* Reserved space */
/* Offset 0x0100 */
struct {
int Enable[32];
int Disable[32];
int Set[32];
int Clear[32];
int Active[64];
int Priority[64];
} NVIC;
int zReserved0x500_0xcfc[(0xd00-0x500)/4];
/* Reserved space */
/* Offset 0x0d00 */
int CPUID;
int IRQcontrolState;
int ExceptionTableOffset;
int AIRC;
int SysCtrl;
int ConfigCtrl;
int SystemPriority[3];
int SystemHandlerCtrlAndState;
int ConfigurableFaultStatus;
int HardFaultStatus;
int DebugFaultStatus;
int MemManageAddress;
int BusFaultAddress;
int AuxFaultStatus;
int zReserved0xd40_0xd90[(0xd90-0xd40)/4];
/* Reserved space */
/* Offset 0x0d90 */
struct {
int Type;
int Ctrl;
int RegionNumber;
int RegionBaseAddr;
8
Copyright © 2007. All rights reserved.
ARM DAI0179B
Application Note 179
int RegionAttrSize;
} MPU;
} SCS_t;
注
このレジスタ構造体は、デバイスのすべての SCS レジスタを含んでいないことがあります。シ
リコンメーカが提供するデバイスのリファレンスマニュアルをご参照ください。
個別の IRQ の設定
各 IRQ には、NVIC レジスタの一環である割り込みセットイネーブルレジスタ内にイネーブルビ
ットがあります。割り込みをイネーブルするには、割り込みセットイネーブルレジスタ内の対
応ビットをセットする必要があります。割り込みセットイネーブルレジスタの具体的な詳細は、
お使いのデバイスについてシリコンメーカが提供するリファレンスマニュアルをご参照くださ
い。
例 5 は、8 ページの例 4 に示した SCS 構造体の割り込みイネーブルコードを示しています。
例5
IRQ イネーブル関数
void NVIC_enableISR(unsigned isr)
{
/* The isr argument is the number of the interrupt to enable. */
SCS.NVIC.Enable[ (isr/32) ] = 1<<(isr % 32);
}
注
SCS 領域の一部のレジスタは、特権モードからしかアクセスできません。IRQ は、割り込みク
リアイネーブルレジスタの対応ビットを設定することで個別に禁止できます。
割り込みの優先度
各割り込みには、割り込み優先度レジスタによって優先度が指定されています。実装に応じ、
各割り込みに最大で 256 の優先度を指定することができます。優先度は最大 8 ビットを使って
表示されます。メモリの各ワードには 4 つで 1 グループになった割り込み優先度がストアされ
ています。
指定された優先度の数が小さければ小さいほど、割り込みの優先度は高くなります。したがっ
て優先度 0 が最高、255 が最低です。
2.2
メモリ保護ユニット(MPU)
Cortex-M3 は、オプションで MPU を搭載しています。MPU が搭載されているかどうかは、シリ
コンメーカのデータシート、その他の資料をご参照ください。
ARM DAI0179B
Copyright © 2007. All rights reserved.
9
Application Note 179
MPU レジスタの位置
MPU レジスタは 0xE000ED90 にあります。基本的な MPU レジスタが 5 つ、それに各領域の
エイリアスレジスタが多数あります。表 3 は、MPU レジスタの概要を示したものです。詳
細は、Cortex-M3 テクニカルリファレンスマニュアルをご参照ください。
表3
MPU レジスタ
名称
アドレス
説明
MPU タイプ
0xE000ED90
領域の番号をビット[15:8]に含み、MPU が
ない場合は 0 です。
制御レジスタ
0xE000ED94
MPU のイネーブル/ディセーブル、特権ア
クセス用のデフォルトメモリマップの使
用、ハードフォールト、NMI、フォールト
マスクハンドラ中に MPU を許可するかど
うかを制御します。
領域番号
0xE000ED98
設定したい領域を選択します。
領域ベースアドレス
0xE000ED9C
領域のベースアドレスの設定または読み
出しを行います。
領域属性/サイズ
0xE000EDA0
領域のサイズと許可の設定または読み出
しを行います。
各領域について領域ベースアドレスレジスタ、領域属性/サイズレジスタのエイリアスもあり
ます。これらは、領域属性/サイズレジスタの直後に続きます。場所は 0xE000EDA4 で、メモ
リの上位へ連続していきます。これらは、STM 命令を使ってエイリアスアドレスに書き込む
ことで起動時に短時間で MPU を設定できるため、非常に便利です。
MPU 領域の設定
MPU 領域を設定するには、まず設定したい領域を選びます。これには以下の 2 つのうち、
いずれかの方法を使用します。1 つは、領域番号レジスタに適切な値を書き込むことです。
もう 1 つの方法は、領域ベースアドレスレジスタのビット 0~3 を使用し、VALID ビットを
セットすることです。この 2 番目の方法では、領域を選択すると同時に、領域ベースアドレ
スレジスタに領域ベースアドレスをプログラムできます。
領域を選択後、領域のベースアドレスをプログラムする必要があります。ベースアドレスの
値は、領域サイズの複数倍にアラインしていることが必要です。したがって 64KB 領域は、
64KB の複数倍、例えば 0x00010000、0x00020000 などにアラインしていなければなりませ
ん。
最後に許可を設定し、サイズを決め、領域属性/サイズレジスタを使って領域をイネーブルす
る必要があります。レジスタレイアウトの詳細は、Cortex-M3 テクニカルリファレンスマニ
ュアルをご参照ください。
——— 注 ——————
領域をアクティブにするには、必ず MPU 制御レジスタのビット 0 をセットして MPU をイネ
ーブルする必要があります。
———————————
10
Copyright © 2007. All rights reserved.
ARM DAI0179B
Application Note 179
メモリ領域属性/サイズ(タイプとアクセス許可)
MPU は、さまざまなメモリタイプ、拡張、属性をサポートします。これらは、領域属性/サイ
ズレジスタの各領域について設定します。表 4 は、領域属性/サイズレジスタの詳細を示して
います。
表4
領域属性/サイズレジスタ
フィールド
名称
説明
[28]
XN
[26:24]
AP
[21:19]
TEX
[18]
S
共有可能。
[17]
C
キャッシュ可能。
[16]
B
バッファ可能。
[15:8]
SRD
サブ領域ディセーブルフィールド(サブ領域参照)
[5:1]
REGION SIZE
領域の領域サイズは、4K、8K などのように設定できます。
[0]
SZENABLE
領域イネーブルビット。
命令アクセスディセーブルビット。1 のとき命令フェッチ
をディセーブルします。
データアクセス許可。ユーザ/特権モードでの読み出し/書き
込みアクセスを設定します。
タイプ拡張フィールド。ストロングリオーダ、ペリフェラ
ルなど、メモリアクセスタイプを設定します。
各種フィールドについての詳細は、Cortex-M3 テクニカルリファレンスマニュアルをご参照く
ださい。
サブ領域
各メモリ領域は、8 つのサブ領域に分割されます。サブ領域は、それぞれ他のサブ領域に影響
を与えることなくディセーブルすることができます。メイン領域の 8 分の 1 となる各サブ領域
は、領域属性/サイズレジスタの SRD フィールドを使ってディセーブルします。SRD フィール
ドの最下位ビットは、最下位アドレスのサブ領域をディセーブルします。
大きな領域があり、その一部分には別の属性を持たせたい場合など、メモリ領域をオーバラッ
プさせる際にサブ領域は便利です。すなわち、大きな領域のあるサブ領域をディセーブルし、
2 番目の MPU 領域を使ってそのサブ領域に必要な属性を持たせます。
——— 注 ——————
サブ領域は、32 バイト、64 バイト、128 バイトのサイズの領域には使用できません。
———————————
2.3
スタックとヒープの設定
スタックとヒープの設定
RealView コード生成ツール(RVCT)では、多くの方法でスタックとヒープの位置を設定でき
ます。主な 2 つの方法は、__user_initial_stackheap()関数を再実装することと、特定の領
域名を使ってスタックとヒープをスキャッタファイルに配置することです。
ARM DAI0179B
Copyright © 2007. All rights reserved.
11
Application Note 179
RealView コード生成ツールは、スタックとヒープの実装の 2 つの主要タイプ、すなわち 1 領域
モデル、2 領域モデルもサポートしています。1 領域モデルでは、スタックとヒープが 1 つのメ
モリ領域を共有します。ヒープはメモリ領域の低位から高位に伸び、スタックは高位から低位
に伸びます。
2 領域モデルでは、ヒープとスタックがそれぞれ専用のメモリ領域を持ちます。それでもやはり
ヒープはメモリの低位から高位へ、スタックは高位から低位へ伸びます。詳細は、RVCT ディベ
ロッパーガイド、RVCT コンパイラおよびライブラリガイドをご参照ください。
——— 注 ——————
MPU を使用し、オーバフローを検出するよう領域を配置してもかまいません。
———————————
1 領域モデル
1 領域モデルを使用する場合、スタック/ヒープ領域をメモリに配置する最も簡単な方法は、ス
キャッタファイルに配置することです。このためには、スキャッタファイル内で専用の領域名
である ARM_LIB_STACKHEAP を使用し、スタック/ヒープ領域のアドレスとサイズを指定しま
す。例 6 を参照してください。
例6
1 領域モデルのスキャッタファイルから抽出した例
;; Heap and stack share 1MB
ARM_LIB_STACKHEAP 0x20100000 EMPTY 0x100000
{
}
——— 注 ——————
リンク時に領域を意図的に入力していないことを示すため、EMPTY を使用しています。
———————————
この後、リンカ定義のシンボル Image$$ARM_LIB_STACK$$ZI$$Limit を使い、ベクタテーブルの
0x0 にある最初のエントリに初期スタックポインタ値を配置します。
専用の領域名の代わりに、__user_initial_stackheap()関数を再実装してもかまいません。し
かし、初期 SP 値は必ずベクタテーブルに正しく指定してください。
__user_initial_stackheap()の詳細は、RVCT ディベロッパーガイド、RVCT コンパイラおよ
びライブラリガイドをご参照ください。
2 領域モデル
2 領域モデルを使用するには、スキャッタファイルにヒープ用、スタック用の 2 つの領域を、
ARM_LIB_HEAP、ARM_LIB_STACK という専用の領域名で指定する必要があります。アセンブリ言
語では IMPORT __use_two_region_memory、C 言語では#pragma
import(__use_two_region_memory)も加える必要があります。これらは、
(デフォルトの)1 領域
モデルではなく、2 領域モデルを使用することを示します。例 7 を参照してください。
例7
2 領域モデルのスキャッタファイルから抽出した例
; Heap starts at 1MB and grows upwards
ARM_LIB_HEAP 0x20100000 EMPTY 0x100000-0x8000
{
12
Copyright © 2007. All rights reserved.
ARM DAI0179B
Application Note 179
}
; Stack space starts at the end of the 2MB of RAM
; and grows downwards for 32KB (indicated by the negative length)
ARM_LIB_STACK 0x20200000 EMPTY -0x8000
{
}
この後、リンカ定義のシンボル Image$$ARM_LIB_STACK$$ZI$$Limit を使い、ベクタテーブル
の 0x0 にある最初のエントリに初期スタックポインタ値を配置します。
ここでも、専用領域を使用する代わりに__user_initial_stackheap()を再実装してスタックと
ヒープを配置してもかまいません。しかし、初期スタックポインタは必ずベクタテーブルに追
加する必要があります。
8 バイトのスタックアライメント
ARM アーキテクチャ向けのアプリケーションバイナリインタフェース(ABI)では、異なるソ
ースファイル間での関数の呼び出しなど、すべての外部インタフェースにおいてスタックを 8
バイト境界でアラインする必要があります。しかし、リーフ関数などのように、内部的には 8
バイトのスタックアライメントを維持する必要はありません。
つまり、割り込みや例外の発生時、スタックが正しく 8 バイト境界でアラインしていないかも
しれないということです。Cortex-M3 シリコンのリビジョン 1 以降は、例外が発生すると自動的
にスタックポインタをアラインできます。この動作は、0xE000ED14 にあるコンフィギュレーシ
ョン制御レジスタの STKALIGN(ビット 9)をセットすることでイネーブルできます。
Cortex-M3 のリビジョン 0 を使用している場合、この調整はハードウェアで実行できません。ス
タックを正しくアラインするコードを IRQ ハンドラの中にコンパイラで生成します。これには、
IRQ ハンドラの最初に__irq を付け、--cpu=Cortex-M3 ではなく、--cpu=Cortex-M3-rev0 コ
ンパイラスイッチを使用します。
——— 注 ——————
--cpu=Cortex-M3-rev0 コンパイラスイッチは、RVCT 3.0 SP1(ビルド 586)以降のバージョン
でのみサポートされています。
———————————
2.4
命令セットのサポート
Cortex-M3 がサポートする命令の中に、通常、特定の用法や機能を C 言語で表現することが難し
く、コンパイラ自体は生成できない命令が数多くあります。これらの命令は、アセンブラ、コ
ンパイライントリンシック、組み込みアセンブリのいずれかを使用して使用することができま
す。
——— 注 ——————
以下の命令の詳細および命令セット全体の説明は、RVCT アセンブラガイドまたは ARM アーキ
テクチャリファレンスマニュアルをご参照ください。
———————————
メモリアクセス命令
コンパイラが C コードから直接生成しないメインメモリ命令は、排他ロード命令の LDREX と排
他ストア命令の STREX です。これらは、異なるスレッド間のミューテックスなど、排他的なメ
モリアクセスの実行に使用されます。
ARM DAI0179B
Copyright © 2007. All rights reserved.
13
Application Note 179
バリア命令
Cortex-M3 は、多数のバリア命令をサポートします。これらは、特定イベントを確実に完了させ
てから次の命令やイベントを開始させます。
命令同期バリア(ISB)は、プロセッサのパイプラインをフラッシュすることで、ISB の完了後、
すべての命令がキャッシュまたはメモリからフェッチされるようにします。これにより、シス
テム、例えば MPU への変更が、ただちに有効となります。
データ同期バリア(DSB)は、特殊なメモリバリアとして作用します。DSB 命令は、明示的な
メモリアクセスをすべて完了させた後に完了します。DSB 命令が完了するまで、すなわち保留
中のアクセスがすべて完了するまで、以降の命令は一切実行されません。
データメモリバリア(DMB)は、メモリバリアとして作用します。DMB の動作は DSB とやや
異なります。DMB 命令は、必ず DMB 命令の前のメモリアクセスをすべて完了させた後に、DMB
命令の後の命令のメモリアクセスを実行させます。
例 8 は、典型的な MPU コードの断片でこれらのバリア命令の用法を示しています。ここでは、
組み込みアセンブラを使い、1 つのバリア命令を含む小さな関数をいくつか作成します。これら
の関数は後でリンカを使ってインライン化します。
例8
疑似イントリンシックを使用したバリア命令のデモンストレーション
/* pseudo_intrinsics.c */
/* Small embedded assembly functions for barrier instructions*/
/* Link with armlink --inline ... */
__asm void __ISB(void)
{
ISB
BX lr
}
__asm void __DSB(void)
{
DSB
BX lr
}
/* scs.c - Initialize System Control Space registers */
void SCS_init(void)
{
/* Code to configure the MPU regions inserted here
…
*/
/* Enable the MPU */
SCS.MPU.Ctrl |= 1;
/* Force Memory Writes before continuing */
__DSB();
/* Flush and refill pipline with updated permissions */
__ISB();
}
14
Copyright © 2007. All rights reserved.
ARM DAI0179B
Application Note 179
条件付き実行
ARM 命令と異なり、Thumb 命令は無条件です。Thumb-2 は、Thumb-1 命令セットに含まれる 16
ビットの条件付き分岐に、3 つの条件付き命令を追加しています。これらを以下に挙げます。
•
32 ビットの条件付き分岐。分岐範囲が+/- 1MB 拡大されています。
•
16 ビットのゼロ比較分岐(CBZ)および非ゼロ比較分岐(CBNZ)命令。分岐範囲は+4~
+130 バイトです。例えば、これにより 0 までカウントダウンするとループの外へ分岐す
る C コードを生成することができます。
•
16 ビットの if-then(IT)命令。IT 命令は、最大で後続の 4 つの命令を条件付きにすること
ができます。これは、短い if 文の中などで、条件付き実行の代わりとして最もよく使用さ
れます。
アセンブラは、条件付きで実行された命令の代わりとして適切な IT 命令を自動的に生成できま
す。ARM ベースのレガシーコードを Cortex-M3 に移植する場合に、これは非常に便利です。
システム「ヒント」
実装でサポートされていれば、コアに演算を実行するよう指示する「ヒント」命令は数多くあり
ます。このような命令は、コアに指示を出すだけで、実行を強制することはありません。デバイ
スにサポートされていない場合、ヒント命令の一部あるいはすべてが NOP として実行されます。
表 5 は、Cortex-M3 で使用されるヒント命令をまとめたものです。
表5
2.5
ヒント命令
命令
演算
説明
WFE
Wait For Event
低消費電力モードを開始し、イベントを待ってからウェ
イクアップするようプロセッサに指示します。ウェイク
アップにソフトウェアの介入は不要です。
WFI
Wait For Interrupt
低消費電力モードを開始し、割り込みを待ってからウェ
イクアップするようプロセッサに指示します。ウェイク
アップにソフトウェアの介入は不要です。
SEV
Send Event
マルチプロセッサシステムのすべてのプロセッサにイ
ベントを送信します。
ビットバンディング
ビットバンディングは、メモリの完全な 1 ワードをビットバンド領域の 1 ビットに対応させます。
例えば、エイリアスワードの 1 つに書き込むと、ビットバンド領域の対応ビットがセットまたは
クリアされます。
これにより、1 つの LDR 命令で、ワードアラインドアドレスからビットバンディング領域の各ビ
ットに直接アクセス可能となります。また、リード・モディファイ・ライト命令シーケンスを実
行することなく、C から各ビットをトグルすることも可能となります。
アドレス変換
Cortex-M3 には、2 つの 32MB 領域があり、それぞれ 1MB のビットバンド領域にマッピングして
います。2 つの領域は独立していて、1 つは SRAM 領域、1 つはペリフェラル領域にあります。
ARM DAI0179B
Copyright © 2007. All rights reserved.
15
Application Note 179
ビットバンド領域の各ビットは、32MB のエイリアス領域内で連続してアドレス指定されていま
す。例えば、ビットバンド領域の 8 番目のビットは、32MB のエイリアス領域の 8 番目のワード
を使ってアクセスされます。
ビットバンド領域の読み出しと書き込み
エイリアス領域に書き込む場合、32 ビットワードのビット 0 を使用してビットバンド領域に値
がセットされます。エイリアスアドレスから読み出す場合、ビットバンド領域の値がビット 0
に戻され、他のビットはクリアされます。
ワード、ハーフワード、バイトアクセスを使用し、通常のメモリと同様にベースビットバンド
領域自体にアクセスすることもできます。
C コードによるビットバンディングの使用
プリプロセッサマクロを使って C コードからビットバンディングを使用し、アクセスを実行す
ることもできます。例 9 は、この方法を示しています。
例9
プリプロセッサマクロを使用して C コードからビットバンディングを使用する方法
#define BITBAND_SRAM_REF 0x20000000
#define BITBAND_SRAM_BASE 0x22000000
#define BITBAND_SRAM(a,b) ((BITBAND_SRAM_BASE + (a-BITBAND_SRAM_REF)*32 \
+ (b*4))) // Convert SRAM address
#define BITBAND_PERI_REF 0x40000000
#define BITBAND_PERI_BASE 0x42000000
#define BITBAND_PERI(a,b) ((BITBAND_PERI_BASE + (a-BITBAND_PERI_REF)*32 \
+ (b*4))) // Convert PERI address
#define MAILBOX 0x20004000
#define TIMER 0x40004000
// Mailbox bit 0
#define MBX_B0 *((volatile unsigned int *)(BITBAND_SRAM(MAILBOX,0)))
// Mailbox bit 7
#define MBX_B7 *((volatile unsigned int *)(BITBAND_SRAM(MAILBOX,7)))
// Timer bit 0
#define TIMER_B0 *((volatile unsigned char *)(BITBAND_PERI(TIMER,0)))
// Timer bit 7
#define TIMER_B7 *((volatile unsigned char *)(BITBAND_PERI(TIMER,7)))
int main(void)
{
unsigned int temp = 0;
MBX_B0 = 1; // Word write
temp = MBX_B7; // Word read
TIMER_B0 = temp; // Byte write
return TIMER_B7; // Byte read
}
2.6
16
実行モード
Copyright © 2007. All rights reserved.
ARM DAI0179B
Application Note 179
動作モード
Cortex-M3 は、特権実行とユーザ(非特権)実行をサポートします。特権として実行されるコ
ードは完全なアクセス権を持ち、ユーザとして実行されるコードはアクセス権が制限されます。
この制限には、MSR フィールドなどの命令の使用制限、システム設計に基づくメモリおよび
ペリフェラルへのアクセスに関する制限、MPU コンフィギュレーションによって課される制
限があります。
プロセッサは、スレッドモードとハンドラモードの 2 つの動作モードをサポートします。スレ
ッドモードは、リセット時、および通常は例外からの復帰時に開始されます。スレッドモード
の場合、コードは特権または非特権のいずれかで実行されます。
ハンドラモードは、例外の結果として開始されます。ハンドラモードの場合、コードは常に特
権として実行されるため、例外が発生するとコアは自動的に特権モードに切り替わります。
そしてリンカレジスタ(R14)の EXC_RETURN の値を変更すれば、例外からの復帰時に特権ス
レッドモードとユーザスレッドモードを切り替えることができます。MSR 命令を使って
CONTROL[0]をクリアすれば、
特権スレッドモードからユーザスレッドモードに切り替えること
も可能です。しかし、SVC などの例外を介さずに、非特権モードから特権モードへ直接変更す
ることはできません。
メインスタックとプロセススタック
Cortex-M3 は、
メインスタックとプロセススタックという 2 種類のスタックをサポートします。
このため、Cortex-M3 には 2 つのスタックポインタ(R13)があります。このうち 1 つは、使用
するスタックによってバンクに読み込まれます。つまり、スタックポインタは常に 1 つだけが
R13 として認識されます。しかし、MRS 命令と MSR 命令を使用すれば、両方のスタックポイ
ンタにアクセス可能です。
メインスタックはリセット時に使用され、ハンドラモード(例外ハンドラ開始時)で常に使用
されます。プロセススタックポインタは、スレッドモードでのみ、カレントスタックポインタ
として使用可能です。スレッドモードでどのスタックポインタ(メインまたはプロセス)を使
用するかは、2 つの方法のいずれかで選択できます。すなわち、ハンドラモード終了時に
EXC_RETURN 値を使用するか、スレッドモード中に MSR 命令を使って CONTROL[1]に書き込む
かです。
——— 注 ——————
プロセススタックポインタは、コンテキストスイッチコードまたは初期化コードで初期化する
必要があります。
———————————
2.7
スーパバイザコール(SVC)
従来の ARM コアと同様、スーパバイザコールを生成するのは SVC(旧 SWI)です。スーパバ
イザコールは、通常、特権動作を要求したり、オペレーティングシステムからシステムリソー
スにアクセスしたりする場合に使用されます。
SVC 命令には、一般に SVC 番号と呼ばれる数字が組み込まれています。これは、呼び出し元
の要求内容を示すために使用される場合があります。従来の ARM コアでは、リンクレジスタ
の復帰アドレスを使って SVC 番号を命令から抽出する必要がありました。そして他の SVC 引
数は既に R0~R3 にありました。
Cortex-M3 では、最初の例外開始時にコアが引数レジスタをスタックに保存します。SVC ハンド
ラの最初の命令の実行の前に受け付けられた、後から到着する例外によって、まだ R0~R3 に保
持されている引数のコピーを破壊する可能性があります。つまり、SVC ハンドラは引数のスタ
ックコピーを使用する必要があります。復帰値も、スタックに保存されたレジスタ値を修正する
ことで呼び出し元に受け渡されねばなりません。これを行うためには、SVC ハンドラの最初に少
量のアセンブリコードを実装する必要があります。これが、レジスタが保存されているスタック
を識別し、命令から SVC 番号を抽出し、その番号と引数へのポインタを C 言語で書かれたハン
ドラの本体に渡します。
ARM DAI0179B
Copyright © 2007. All rights reserved.
17
Application Note 179
例 10 は、SVC ハンドラのサンプルです。このコードは、プロセッサがセットした EXC_RETURN
をテストすることで、SVC が呼び出された時にどのスタックポインタが使用されていたかを
判断します。標準的なシステム設計では、スーパバイザコールがプロセススタックを使用す
るユーザコードからしか実行されないため、これはほとんどのシステムで不要です。この場
合、アセンブリコードは 1 つの MSR 命令と、ハンドラの C 本体へのテールコール分岐(B
命令)で構成されます。
例 10
SVC ハンドラのサンプル
__asm void SVCHandler(void)
{
IMPORT SVCHandler_main
TST lr, #4
MRSEQ r0, MSP
MRSNE r0, PSP
B SVCHandler_main
}
void SVCHandler_main(unsigned int * svc_args)
{
unsigned int svc_number;
/*
* Stack contains:
* r0, r1, r2, r3, r12, r14, the return address and xPSR
* First argument (r0) is svc_args[0]
*/
svc_number = ((char *)svc_args[6])[-2];
switch(svc_number)
{
case SVC_00:
/* Handle SVC 00 */
break;
case SVC_01:
/* Handle SVC 01 */
break;
default:
/* Unknown SVC */
break;
}
}
例 11 は、SVC 番号にさまざまな宣言を使えることを示しています。__svc は、指定された番
号を含む SVC 命令と関数呼び出しを置き換えるコンパイラキーワードです。
例 11
C コードから SVC を呼び出すサンプル
#define SVC_00 0x00
#define SVC_01 0x01
void __svc(SVC_00) svc_zero(const char *string);
void __svc(SVC_01) svc_one(const char *string);
int call_system_func(void)
{
svc_zero("String to pass to SVC handler zero");
svc_one("String to pass to a different OS function");
}
18
Copyright © 2007. All rights reserved.
ARM DAI0179B
Application Note 179
2.8
システムタイマ(SysTick)
SysTick の概要
SCS には、別のプラットフォームからの移植を容易にするためにオペレーティングシステムが
使用するシステムタイマ(SysTick)も含まれます。SysTick は、ソフトウェアからポーリングし
たり、割り込みを生成するよう設定したりすることができます。SysTick 割り込みは、ベクタテ
ーブルに専用のエントリを持つため、専用のハンドラを持つことも可能です。
SysTick は表 6 に挙げる 4 つのレジスタを使って設定できます。
表6
SysTick レジスタ
名称
アドレス
説明
SysTick Control and
Status
0xE000E010
イネーブル、クロックソース、割り込み、ポーリングなど、
SysTick の基本的な制御
SysTick Reload
Value
0xE000E014
0 に達するとカレントバリューレジスタにロードする値
SysTick Current
Value
0xE000E018
カウントダウンの現在の値
SysTick Calibration
Value
0xE000E01C
実装により、10ms のインターバルを生成するティック数や
その他の情報を含むことがある
SysTick の設定
SysTick を設定するには、SysTick リロードバリューレジスタに、SysTick イベント間に必要なイ
ンターバルをロードする必要があります。タイマ割り込み、すなわち COUNTFLAG ビット(SysTick
制御/ステータスレジスタ内)は 1 から 0 への遷移時にアクティブになるため、SysTick はクロッ
クティック n+1 回ごとにアクティブになります。インターバルを 100 にしたい場合は、SysTick
リロードバリューレジスタに 99 を書き込みます。SysTick リロードバリューレジスタは、1~
0x00FFFFFF の値に対応します。
1ms など、インターバルを時間で設定してイベントを生成したい場合は、SysTick キャリブレーシ
ョンバリューレジスタでリロードレジスタの値を調節します。SysTick キャリブレーションバリュ
ーレジスタは、TENMS フィールド(0~23)に 10ms のパルス数を含む読み出し専用レジスタです。
このレジスタには、クロック周波数の小さな変動により、TENMS セクションの 10ms のキャリブレ
ーションが正確な 10ms ではないことを示す SKEW ビット(30)もあります。ビット 31 は、リファ
レンスクロックがあるかどうかを示します。
制御/ステータスレジスタでは、COUNTFLAG(ビット 16)の読み出し、SysTick の割り込み生成の
いずれでタイマをポーリングするかを選択できます。
デフォルトで SysTick はポーリングモードに設定されています。このモードでは、ユーザコード
が COUNTFLAG を読み出して、SysTick イベントが発生したことを確認する必要があります。イベ
ントの発生は COUNTFLAG のセットで表示されます。制御/ステータスレジスタを読み出すと
COUNTFLAG ビットはクリアされます。SysTick が割り込みを生成するよう設定するには、TICKINT
(SysTick 制御/ステータスレジスタのビット 1)を HIGH にセットします。また、NVIC で適切
な割り込みをイネーブルする必要があります。コアクロックを選択するには CLKSOURCE(ビッ
ト 2)を 1 に、外部リファレンスクロックを選択するには 0 にセットします。
タイマは、SysTick 制御/ステータスレジスタのビット 0 をセットすることでイネーブルされます。
2.9
RVCT 3.0 のオプション
ARM DAI0179B
Copyright © 2007. All rights reserved.
19
Application Note 179
コンパイラとアセンブラのオプション
コードをビルドする際には、コンパイラとアセンブラのコマンドラインに正しい CPU を指定す
る必要があります。
RVCT 3.0 ツールはデフォルトで ARMv4T コア用のコードをビルドします。
CPU を指定するには、コマンドラインに--cpu name を追加します。name は Cortex-M3 また
は Cortex-M3-rev0 のいずれかです。コマンドラインに--thumb を追加する必要はありませ
ん。Cortex-M3 は Thumb-2 専用コアだからです。コンパイラは自動的に Thumb-2 命令を生成
し、アセンブラは有効な Thumb-2 命令しか受け付けません。
リンカオプション
Cortex-M3 に適したイメージを生成するために、リンカに特定のオプションを指定する必要は
ありません。リンカは、必要な情報をリンカのコマンドラインに指定されているオブジェク
トファイルから取得します。
しかし、ARM ではスキャッタファイル(--scatter filename)の使用を推奨します。Cortex-M3
のメモリマップは、リンカで使用できるコマンドラインオプションを使って表現することが
難しいからです。--entry スイッチを使用してイメージのエントリポイントも指定する必要
があります。通常、これは例外テーブルにリセットハンドラとして指定したのと同じエント
リポイントです。
20
Copyright © 2007. All rights reserved.
ARM DAI0179B
Application Note 179
3
既存の ARM プロジェクトから Cortex-M3 への移行
このセクションでは、既存の ARM プロジェクトを新しい Cortex-M3 プラットフォームに移行
させる方法を説明します。例えば、ARM7TDMI ベースのアプリケーションを Cortex-M3 プラ
ットフォームに移行させるような場合です。
プロジェクトの最小限のバージョンから始め、機能性を徐々に充実させるのが一般に最善の
方法です。これは、コメントやプリプロセッサマクロを使ってその機能のセクションを除外
していくことで容易にできます。除外した機能を移行プロセスで 1 つずつ再導入し、プラッ
トフォームに依存する機能を綿密にテストすることも可能となります。
3.1
一般的なコードの修正
プラットフォームに依存しないコードセクションのほとんどは、通常、Cortex-M3 でも修正な
しで正常に動作します。しかし、新しいターゲット用に修正、更新が必要なコードの部分も
あります。
C コードの修正
プロジェクトを ARM7 コアから Cortex-M3 に移行させるには、20 ページの「コンパイラとア
センブラのオプション」に記載されているように、適切な--cpu オプションを設定し、C コ
ードすべてを Thumb-2 用にリコンパイルする必要があります。これには、サードパーティの
ライブラリも含まれます。
Thumb-1 のレガシーコードは Cortex-M3 とバイナリ互換なので、新しいプロセッサでも実行
することができます。しかし RVCT 3.0 では、リンカが ARM 命令を含むオブジェクトファイ
ルとライブラリを誤ってリンクしてしまうケースに対処できません。できる限り、すべての
コードを Thumb-2 用にリコンパイルすることをお勧めします。レガシーオブジェクトやレガ
シーライブラリを使用する必要がある場合は、リンクされるイメージに ARM 命令が含まれ
ていないことを手作業で確認してください。ARM7 をターゲットとするサードパーティのラ
イブラリがある場合は、ライブラリの Thumb-2 バージョンがないかサプライヤに問い合わせ
ることをお勧めします。
ソースコード自体にも、多少の変更が必要となることがあります。特に、状態を変更するプ
ラグマディレクティブ(#pragma arm と#pragma thumb)はもはや適用できないので削除す
る必要があります。インラインアセンブリコードは、Thumb-2 向けのコード生成をサポート
していないため、C、C++、エンベデッドアセンブリのいずれかのコードで書き直す必要があ
ります。
アセンブリコードの修正
アセンブリコードの移植には特に注意が必要です。
いかなる場合にも、ARM 命令のアセンブリを引き起こすディレクティブ
(ARM または CODE32)
があれば削除または変更してください。正しい--cpu オプションをアセンブラコマンドライ
ンに指定すれば、それで既存コードのほとんどは問題なくアセンブルできます。しかし、ARM
命令セットでサポートされ、Thumb-2 命令セットでサポートされていない一部の稀な命令に
は、修正が必要となることがあります。
CODE16 ディレクティブが存在する場合には、THUMB に変更されたときに動作に微妙な違いがある
にもかかわらず、警告なしでアセンブルされることを認識しておいてください。これは、CODE16
がレガシーの Thumb-1 構文規則に基づいてアセンブルされるためです。例えば、CODE16 構文規
則では、S の接尾辞を持たない多くの命令が、フラグをセットするバリアントにエンコードされ
ます。THUMB ディレクティブの構文規則では、S の接尾辞は常に明示的に指定する必要がありま
す。
アセンブラは、条件付きで実行する命令に IT 命令を適宜挿入します。例えば、1 つの ADDSNE
r0, r0, r1 命令(後に無条件命令が続く)は、IT NE の後に ADDS r0, r0, r1 となります。
ARM DAI0179B
Copyright © 2007. All rights reserved.
21
Application Note 179
特定コア向け、特定アーキテクチャ向けの命令には注意してください。以下に例を挙げます。
•
コプロセッサ命令
•
状態またはモードの変更、その他の PSR へのアクセス
•
LDREX および STREX に置き換えられた SWP 命令
•
LDM 命令と STM 命令にサポートされない一部のアドレシングモード
•
レジスタオフセットとイミディエートシフトを持つ LDR、STR 命令など、Thumb-2 で制
約が追加されるその他の命令
このようなコードは、Cortex-M3 のプログラマモデルに応じて書き直す必要がある場合があり
ます。アセンブラは、コードに矛盾を発見すると警告またはエラーを生成します。ステータ
ス/制御レジスタのほとんどは Cortex-M3 にメモリマップされており、サポートされているモ
ードは ARM7TDMI と大きく異なることに注意してください。状態やモードを変更するコー
ドはすべて、適切に修正または削除が必要です。同様に、ハンドラがエミュレートして用法
フォールト例外を引き起こす場合を除き、コプロセッサにアクセスするコードも削除する必
要があります。
PC の値をアドレス計算に使用するコードにも注意してください。Thumb-2 は 16 ビット命令
と 32 ビット命令の混合を使用するため、PC の値は、データ処理演算で使用される場合、常
に現在の命令のアドレス足す 4 になります。
3.2
スタートアップコードの変更
スタートアップコードは、アプリケーションのリセットハンドラに加え、アプリケーション
が本体を実行する前に環境とペリフェラルをセットアップする初期化関数で構成されます。
スタートアップコードは、コアやターゲットに固有のものです。
シンプルなシステムの場合は、C ライブラリエントリポイント(__main()関数)をリセット
ハンドラとしてベクタテーブルに指定し、自分のコードの main()から他の初期化を実行する
だけで済むかもしれません。しかし、クリティカルな初期化を必要とするペリフェラルがあ
る場合は、__main()に分岐する前に初期リセットハンドラとして作用する短いアセンブリコ
ード関数を書く必要があります。また、MPU など一部のデバイスにアクセスするコードには、
レジスタへの書き込み後、変更がただちに有効となるよう 1 つ以上のメモリバリア命令が必
要な場合もあります。プロジェクトが以前、MPU や MMU をサポートするプラットフォーム
をターゲットとしていた場合には、関連コードを修正する必要があります。
Cortex-M3 プロジェクトの場合は常に、6 ページの「例外処理」に記載されているとおり、新
しいベクタテーブルを作成し、初期スタックポインタを 0x0、リセットハンドラを 0x4 に追
加する必要があります。
3.3
例外処理の変更
例外ハンドラは、Cortex-M3 に適合させる必要があります。
コアがリエントラントに処理するため、通常、アセンブリ言語の低レベルのハンドラは必要
ありません。低レベルのハンドラが他の機能も果たしている場合は、その一部を新しいハン
ドラから呼び出される独立した関数に分割する必要があるかもしれません。
明確性を持たせ、コンパイラが Cortex-M3 revision 0 ハードウェアに対応するスタックアライ
メントを維持できるよう、__irq キーワードを使って IRQ ハンドラをマークするのを忘れな
いようにしてください。
Cortex-M3 に FIQ 入力はありません。ARM7TDMI プロジェクトで FIQ 信号を生成していたペ
リフェラルはすべて、高優先度のベクタ割り込み、または Cortex-M3 の NMI 信号に移行させ
る必要があります。この種の割り込み用のハンドラが、バンク FIQ レジスタを使用しないこ
とを確認したほうが良いかもしれません。なぜなら、通常の IRQ ハンドラと同様に、これら
のレジスタをスタックに積む必要があるからです。
22
Copyright © 2007. All rights reserved.
ARM DAI0179B
Application Note 179
最後に、新しい初期化関数を記述し、割り込み優先度を含めて、NVIC を設定します。これで、
メインのアプリケーションコードを開始する前に割り込みをイネーブルすることができます。
クリティカルセクションと例外動作
Cortex-M3 では、例外の優先度付け、例外のネスト化、破壊可能レジスタの保存は、すべてコ
アによって処理されるため、非常に効率的で割り込みレイテンシも短くなります。すなわち、
例外ハンドラ開始時には常に、コアによって割り込みのイネーブルが継続されるということ
です。また、例外から復帰したときに割り込みがディセーブルされている場合、割り込みが
プロセッサによって自動的に再イネーブルされることはありません。割り込みをアトミック
にイネーブルし、例外から復帰することは不可能です。ハンドラで一時的に割り込みをディ
セーブルした場合は、まず再イネーブルしてから、別の命令を使って復帰する必要がありま
す。したがって例外が例外復帰の直前に発生する場合もあります。
例外モデルのこのような特長は、システム設計により、コードのクリティカルセクションに
影響を与えることがあります。クリティカルセクションとは、実行中に割り込みをディセー
ブルすることにより、オペレーティングシステムのコンテキストスイッチを行うコードのよ
うに、割り込み不可のブロックとして実行する必要のあるコードの部分です。一部のレガシ
ーコードでは、例外ハンドラ開始時に割り込みをディセーブルし、クリティカルセクション
が完了して初めてコードで明示的に割り込みをイネーブルすることを前提しています。
Cortex-M3 の新しい例外モデルにこのような前提はないため、これを考慮に入れてコードを書
き直す必要がある場合があります。
3.4
新しいデバイスへのリターゲット
Cortex-M3 にビルドをリターゲットするには、スキャッタファイルに新しいメモリマップを定
義するなど、他の手順を実行する必要もあります。システムコントロール空間に対応するレ
ジスタへの構造体配置、ライブラリスタックおよびヒープ領域の追加なども、このような手
順に含まれます。タイマを使用するプロジェクトの場合は、SCS に装備されている SysTick
機能を使うようコードを修正したほうが良いかもしれません。19 ページの「SysTick の設定」
をご参照ください。
3.5
Cortex-M3 の新機能の活用
元のプロジェクトを新しいプラットフォームにリターゲットした後で、プロジェクトを修正
して Cortex-M3 の新しい特長を活用したい場合があります。Thumb-2 向けにコードをリコン
パイルすると、ARMv7M に含まれる新しい命令のほとんどが自動的に使用されます。しかし、
Cortex-M3 の一部の機能を活用するには、手作業でのコードの変更が必要です。以下に例を挙
げます。
•
初期化コードを修正し、MPU をイネーブルする。
•
コアに装備されているスリープモードを活用し、消費電力を削減する。
•
データやペリフェラルが適切なビットバンドに位置する場合、ビットバンディングを利
用してビット変更の性能を高める。
ビットバンディング機能の使用方法については、15 ページの「ビットバンディング」をご参
照ください。MPU の設定方法は、9 ページの「メモリ保護ユニット(MPU)」をご参照くだ
さい。MPU レジスタの詳細は、Cortex-M3 テクニカルリファレンスマニュアルに記載されて
います。ここに、コアがサポートするスリープモードの詳細も記載されています。
ARM DAI0179B
Copyright © 2007. All rights reserved.
23
Application Note 179
4
Cortex-M3 を使用したデバッグ
Cortex-M3 には、高度なデバッグ機能があります。以下に例を挙げます。
•
フラッシュまたは ROM 領域にデバッガでハードウェアブレークポイントを設定できる
フラッシュパッチ/ブレークポイントユニット。
•
ウォッチポイントおよび ETM トリガをサポートするデータウォッチポイント/トレース
ユニット。
•
命令とデータをトレースするオプションの ETM。
•
オペレーティングシステムからなど、アプリケーション駆動型のイベントトレース機能
を使用して printf スタイルのデバッグを可能にする計装・トレース・マクロセル(ITM)。
また、プロセッサの構造により、デバッグアクセスはデバッグアクセスポート(DAP)を通じ
て実行されます。DAP は、バスマトリクスを介してコアなど残りのシステムに接続します。つ
まり、デバッガにサポートされていれば、所定のデバッグ演算を実行しつつ、コア自体に動作
を継続させることができます。例えば、外部メモリを読み出したり、外部メモリに書き込んだ
りするためにコアを停止する必要はありません。この機能は、ハードウェアターゲットに接続
する際、RVD 3.0 によってサポートされます。しかし、RVD 3.0 は Cortex-M3 のトレース機能
をサポートしません。
RVDS 3.0 は、Cortex-M3 の命令セットシステムモデル(ISSM)も含んでいます。これは、コ
ア、NVIC、他のプロセッサの主要機能をシミュレートします。UART ペリフェラル 1 つ、さら
にタイマペリフェラル 3 つのモデルもあります。しかし、モデルはブレークポイントとウォッ
チポイントのデバッグロジックをシミュレートするにすぎません。トレースコンポーネントの
モデルはありません。
24
Copyright © 2007. All rights reserved.
ARM DAI0179B