
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
XMC1000 ベクタ テーブルの再マップ – KBA235654
Translated by: NXTY_hayashi
Community Translation: XMC1000 Vector table remap – KBA235654
Version: **
Arm® Cortex® Coreは、NVIC(Nested vector interrrupt controller)を経由して例外割り込みを処理します。NVICは、ベクタテーブルと呼ばれるルックアップテーブルを使用し実行するコード(飛び先)を決定します。一部のCortex®アーキテクチャでは、プログラムがベクタテーブルを変更したい場合、ベクタテーブルオフセットレジスタ(VTOR)レジスタが使用されます。この仕組みは次のような場合に便利です。
・アプリケーションにブートローダがあり、ブートローダとアプリケーションがそれぞれ独自のベクタテーブルを持っている場合
・ユーザがRAMベースのベクタテーブルで動的に異なるハンドラを使用したい場合
・ユーザが外部RAMを使用している場合
ところが、XMC1000デバイス ファミリのCortex® M0コアは、この機能をサポートしていません。XMC1000デバイスでは、Daveスタートアップ コードによってこの問題を解決しています。
XMC1000デバイスのスタートアップの詳細については、アプリケーション ノートAP32326を参照してください。
ベクター テーブルのリマップについて
ベクター テーブルは、SRAM の位置にリマップされ、各ベクターには 4 バイトのサイズが割り当てられています。このサイズでは、例外や割り込みを発生させるのに十分ではありません。そのため、別の場所にある実際のハンドラにジャンプするための分岐命令が必要となる。これを実現するのが"割り込みベニア処理"であす。"割り込みベニア処理"は命令の中間ターゲットとして機能し、その後PC(プログラムカウンター)を飛び先へ設定します。以下は、"割り込みベニア処理"のコード例です。
.section “.XmcVeneerCode”,”ax”,%progbits
.align 1
.globl HardFault_Veneer
HardFault_Veneer:
LDR R0, =HardFault_Handler
MOV PC, R0
In the startup code you can see this being done by using the following Macro
.macro Insert_InterruptVeener Interrupt
.globl \Interrupt()_Veener
\Interrupt()_Veener:
LDR R0, =\Interrupt()_Handler
BX R0
.endm
これらは、コード中の以下のマクロを使用して、デフォルトハンドラにマッピングされます。
.macro Insert_InterruptHandler Interrupt
.weak \Interrupt()_Handler
#if defined(ENABLE_OWN_HANDLER)
.thumb_func
.type \Interrupt()_Handler, %function
\Interrupt()_Handler:
b .
.size \Interrupt()_Handler, . - \Interrupt()_Handler
#else
.thumb_set \Interrupt()_Handler, Default_Handler
#endif
.endm
ユーザーはこれを上書きするために独自のカスタムハンドラを定義することができます。また、リンカファイルで、"割り込みベニア処理"が最初のSRAM位置にマッピングされていることを確認することができます。
/* DSRAM layout (Lowest to highest)*/
/* Veneer <> Stack <> DATA <> BSS <> HEAP */
.VENEER_Code ABSOLUTE(0x2000000C):
{ . = ALIGN(4); /* section size must be multiply of 4. See startup.S file */ VeneerStart = .; KEEP(*(.XmcVeneerCode)); . = ALIGN(4); /* section size must be multiply of 4. See startup.S file */ VeneerEnd = .; }
> SRAM AT > FLASH
eROData = LOADADDR (.VENEER_Code);
VeneerSize = ABSOLUTE(VeneerEnd) - ABSOLUTE(VeneerStart);