yskwiki
CMSIS日本語訳
最終更新:
yskwiki
-
view
Cortex Microcontroller Software Interface Standard
原文Version: 1.30 - 30. October 2009
今後のために日本語訳を残してみます。まだ内容を理解してないので、おそらく変な訳があるかと思いますが、お許しください。
今後のために日本語訳を残してみます。まだ内容を理解してないので、おそらく変な訳があるかと思いますが、お許しください。
2012.09.06 | SDK-NUC120の場合のCMSISファイルの場所を追記(個人用メモ#20120906) |
2012.09.05 | 初版 |
2012.09.04 | 新規作成 |
About
Cortex Microcontroller Software Interface Standard (CMSIS)はソフトウェアコンポーネントをCortex-M0もしくはCortexM3プロセッサベースのマイクロコントローラへ展開する際に直面する試みに答えます。CMSISもまたは将来のCortex-Mプロセッサコア("Cortex-M"はそれを示すのに用いられます)へ拡張されるでしょう。CMSISは様々な半導体・ソフトウェアベンダーとの密接な協力で定義されており、周辺機器、リアルタイムOS、ミドルウェアコンポーネントにI/Fへの共通のアプローチを提供します。
ARMはCMSISの一部として以下に示す様々なコンパイラ実装に対して使用可能なソフトウェアレイヤーを提供します。
- Core Peripheral Access Layer:名前定義、アドレス定義、コアレジスタやペリフェラルへアクセスするヘルパー関数を含む。また、デバッグチャンネル定義を含むRTOSカーネル用のデバイス非依存インターフェースも定義されている。
以下のソフトウェアレイヤーは半導体パートナーによって拡張されています。
- Device Peripheral Access Layer:全てのデバイスペリフェラル用の定義を提供。
- Access Functions for Peripherals(optional):ペリフェラル用の追加ヘルパー関数を提供。
CMSISはCortex-M Microcontroller Systemのために定義されています。
- ペリフェラルレジスタにアクセスするための共通の方法および例外ベクタを定義するための共通の方法
- コアペリフェラルのレジスタ名やコア例外ベクタの名前
- デバッグチャンネルを含むRTOSカーネル用のデバイス非依存インターフェース
CMSIS準拠ソフトウェアコンポーネントを使うことで、ユーザーはテンプレートコードを容易に再利用できます。CMSISは複数のミドルウェアベンダーからのソフトウェアコンポーネントの組み合わせを可能にすることを目的としています。
コーディング規約・記法(Coding Rules and Conventions)
このセクションはCMSIS実装において利用されているコーディング規約・記法について記述します。またデータ型やバージョン番号についての情報も含みます。
必須項目(Essentials)
- CMSIS CコードはMISRA 2004規則に従う。MISRA違反がある場合、PC-LINTのための挿入されるdisable/enableシーケンスがある。(どうしてもルール違反を回避できない場合は、目視で問題が無いことを確認してdisableでリントチェックから除外するってこと?)
- 原文)The CMSIS C code conforms to MISRA 2004 rules. In case of MISRA violations, there are disable and enable sequences for PC-LINT inserted.
- ANSI Cヘッダファイル<stdint.h>で定義されているANSI標準データ型を使用する。
- 式を含む#define定数は括弧で括らなければならない。
- 変数やパラメータは完全なデータ型を持っていなければならない。
- Core Peripheral Access Layer内の全ての関数は再入可能(繰り返し実行可能)である。
- Core Peripheral Access Layerはブロッキングコードを持たない。(wait/queryループは他のソフトウェアレイヤーで実行される)
- 各例外/割込については以下の定義がある
- 例外/割込ハンドラには接尾辞_Handler (for exceptions)/_IRQHandler (for interrupts)が付く
- デフォルトの例外/割込ハンドラ(弱い定義)は無限ループを含む
- 割込番号の定義(#define)には接尾辞_IRQnが付く
推奨項目(Recommendations)
CMSISは識別子についての以下の記法を推奨しています。
- CAPITAL名はコアレジスタ、ペリフェラルレジスタ、CPU命令とする
- CamelCase名はペリフェラルアクセス関数や割り込みとする
- PERIPHERAL_ 接頭辞は特定のペリフェラルに属する関数とする
- 全ての関数においてDoxygenコメントは下記の関数コメントの下に記載された例のように含まれる
- 原文)Doxygen comments for all functions are included as described under Function Comments below.
Comments
- コメントにはANSI C90形式(/*コメント*/)もしくはC++形式(// コメント)を用いる。これはプログラミングツールがC++コメント形式をしっかりとサポートすることを仮定している。
- 関数コメントは各関数に対して下記の情報を提供する
- 1行の簡単な関数の要約
- 詳細なパラメータ説明
- 戻り値に関する詳細な情報
- 実際の関数についての詳細な記述
Doxygen記述例:
/** * @brief Enable Interrupt in NVIC Interrupt Controller * @param IRQn interrupt number that specifies the interrupt * @return none. * Enable the specified interrupt in the NVIC Interrupt Controller. * Other settings of the interrupt such as priority are not affected. */
データ型・IO型修飾子(Data Types and IO Type Qualifiers)
Cortex-M HALは標準ANSI Cヘッダファイル<stdint.h>の標準型を使用しています。IO型修飾子はペリフェラル変数へのアクセスを指定するために使用されています。IO型修飾子はペリフェラルレジスタのデバッグ情報の自動生成のために用いられる事を目的としています。
IO型修飾子 | #define | 説明 |
__I | volatile const | Read access only |
__O | volatile | Write access only |
__IO | volatile | Read and write access |
CMSIS Version Number
ファイルcore_cm3.hは以下の定義でCMSISのバージョン番号を含んでいます。
#define __CM3_CMSIS_VERSION_MAIN (0x01) /* [31:16] main version */ #define __CM3_CMSIS_VERSION_SUB (0x30) /* [15:0] sub version */ #define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16) | __CM3_CMSIS_VERSION_SUB)
ファイルcore_cm0.hは以下の定義でCMSISのバージョン番号を含んでいます。
#define __CM0_CMSIS_VERSION_MAIN (0x01) /* [31:16] main version */ #define __CM0_CMSIS_VERSION_SUB (0x30) /* [15:0] sub version */ #define __CM0_CMSIS_VERSION ((__CM0_CMSIS_VERSION_MAIN << 16) | __CM0_CMSIS_VERSION_SUB)
CMSIS Cortex Core
ファイルcore_cm3.hは以下のようにCMSIS Cortex-Mの型を定義しています。
#define __CORTEX_M (0x03)
ファイルcore_cm0.hは以下のようにCMSIS Cortex-Mの型を定義しています。
#define __CORTEX_M (0x00)
CMSIS Files
このセクションではCortex-MハードウェアとペリフェラルへアクセスするためにCMSISとともにコンテキスト内で提供されているファイルについて記述します。
ファイル | 提供者 | 説明 |
device.h | デバイス固有(半導体パートナーにより提供) | 実デバイスのためのペリフェラルを定義。実デバイスのペリフェラルを定義するために他のインクルードファイルをいくつか使用する場合があります。 |
core_cm0.h | ARM (for RealView ARMCC, IAR, and GNU GCC) | Cortex-M0のCPUとコアペリフェラル用のコアペリフェラルを定義。 |
core_cm3.h | ARM (for RealView ARMCC, IAR, and GNU GCC) | Cortex-M3のCPUとコアペリフェラル用のコアペリフェラルを定義。 |
core_cm0.c | ARM (for RealView ARMCC, IAR, and GNU GCC) | コアレジスタへアクセスするヘルパー関数を提供。 |
core_cm3.c | ARM (for RealView ARMCC, IAR, and GNU GCC) | コアレジスタへアクセスするヘルパー関数を提供。 |
startup_device | ARM (コンパイラ/半導体パートナーにより適合) | Cortex-Mスタートアップコードと完全な(デバイス固有の)割り込みベクタテーブルを提供。 |
system_device | ARM (半導体パートナーにより適合) | デバイス用のデバイス固有の設定ファイルを提供。これはマイクロコントローラデバイスの一部である典型的なオシレータ(PLL)を初期化するデバイスを設定します。 |
個人用メモ#20120906:SDK-NUC120の場合の上記ファイルの場所
ファイル | 場所 |
NUC1xx.h(device.h) | C:\Nuvoton\BSP Library\NUC100SeriesBSP_v1.04.004\CMSIS\CM0\DeviceSupport\Nuvoton\NUC1xx |
core_cm0.h | C:\Nuvoton\BSP Library\NUC100SeriesBSP_v1.04.004\CMSIS\CM0\CoreSupport |
core_cm0.c | C:\Nuvoton\BSP Library\NUC100SeriesBSP_v1.04.004\CMSIS\CM0\CoreSupport |
startup_NUC1xx(startup_device) | C:\Nuvoton\BSP Library\NUC100SeriesBSP_v1.04.004\CMSIS\CM0\DeviceSupport\Nuvoton\NUC1xx\startup (arm/iarの2種類がある) |
system_NUC1xx(system_device) | C:\Nuvoton\BSP Library\NUC100SeriesBSP_v1.04.004\CMSIS\CM0\DeviceSupport\Nuvoton\NUC1xx |
device.h
device.hは半導体ベンダーにより提供され、アプリケーションプログラマがCソースコードで使用している中心的なインクルードファイルです。このファイルは以下の内容を含んでいます。
- 割込番号定義:全てのコアおよびデバイス固有の例外/割込用の割込番号(IRQn)を提供。
- core_cm0.h / core_cm3.h用の設定:実デバイスの一部であるCoretex-Mプロセッサの実設定を反映。core_cm0.h / core_cm3.hのようなファイルはプロセッサレジスタやコアペリフェラルにアクセスするための実装に含まれている。
- Device Peripheral Access Layer:全てのデバイスペリフェラル用の定義を提供。これはデバイス固有のペリフェラルのために全てのデータ型やアドレスマッピングを含む。
- ペリフェラル用アクセス関数(optional):これらのペリフェラルのプログラミングで便利な、ペリフェラル用の追加ヘルパー関数を提供。アクセス関数はインライン関数として提供されたり、半導体ベンダーより提供されるデバイス固有のライブラリへの外部参照である場合もある。
割込番号定義(Interrupt Number Definition)
デバイス固有の割込へアクセスするために、device.hファイルは以下に示すようなenum typedefを用いた、完全なデバイス用のIRQn番号を定義します。
デバイス固有の割込へアクセスするために、device.hファイルは以下に示すようなenum typedefを用いた、完全なデバイス用のIRQn番号を定義します。
typedef enum IRQn { /****** Cortex-M3 Processor Exceptions/Interrupt Numbers ************************************************/ NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ HardFault_IRQn = -13, /*!< 3 Cortex-M3 Hard Fault Interrupt */ MemoryManagement_IRQn = -12, /*!< 4 Cortex-M3 Memory Management Interrupt */ BusFault_IRQn = -11, /*!< 5 Cortex-M3 Bus Fault Interrupt */ UsageFault_IRQn = -10, /*!< 6 Cortex-M3 Usage Fault Interrupt */ SVCall_IRQn = -5, /*!< 11 Cortex-M3 SV Call Interrupt */ DebugMonitor_IRQn = -4, /*!< 12 Cortex-M3 Debug Monitor Interrupt */ PendSV_IRQn = -2, /*!< 14 Cortex-M3 Pend SV Interrupt */ SysTick_IRQn = -1, /*!< 15 Cortex-M3 System Tick Interrupt */ /****** STM32 specific Interrupt Numbers ****************************************************************/ WWDG_STM_IRQn = 0, /*!< Window WatchDog Interrupt */ PVD_STM_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */ : : } IRQn_Type;
core_cm0.h / core_cm3.h用の設定(Configuration for core_cm0.h / core_cm3.h)
各デバイス実装用に定義されているCoretex-Mコア設定オプション。いくつかの設定オプションは以下に記述されている#define設定を使ったCMSISレイヤーに反映されます。
コアペリフェラルへのアクセスのために、ファイルdevice.hはファイルcore_cm0.h / core_cm3.hを含んでいます。core_cm0.h / core_cm3.h内の数々の特徴は以下の定義によって設定されており、プリプロセッサ命令#include <core_cm0.h> / #include <core_cm3.h>の前で定義されなければなりません。
各デバイス実装用に定義されているCoretex-Mコア設定オプション。いくつかの設定オプションは以下に記述されている#define設定を使ったCMSISレイヤーに反映されます。
コアペリフェラルへのアクセスのために、ファイルdevice.hはファイルcore_cm0.h / core_cm3.hを含んでいます。core_cm0.h / core_cm3.h内の数々の特徴は以下の定義によって設定されており、プリプロセッサ命令#include <core_cm0.h> / #include <core_cm3.h>の前で定義されなければなりません。
#define | ファイル | 値 | 説明 |
NVIC_PRIO_BITS | core_cm0.h | (2) | NVIC内で実装されている優先度ビットの数(デバイス固有) |
NVIC_PRIO_BITS | core_cm3.h | (2 ... 8) | NVIC内で実装されている優先度ビットの数(デバイス固有) |
MPU_PRESENT | core_cm0.h, core_cm3.h | (0, 1) | MPUが存在するかどうかを定義。 |
Vendor_SysTickConfig | core_cm0.h, core_cm3.h | (1) | この定義が1にセットされていると、core_cm3.h内のSysTickConfig関数は除外される。この場合、device.hファイルはこの関数のベンダー固有の実装を含まなければならない。 |
Device Peripheral Access Layer
各ペリフェラルは、この固有のペリフェラルにアクセスするペリフェラルレジスタを識別するために、接頭辞<デバイス略称>_および<ペリフェラル名>_を用います。
これは短縮名に起因する名前衝突を避けるためです。もし1つ以上の同じ型のペリフェラルが存在すれば、識別子は以下の例のように接頭辞(数字/文字)を持ちます。
各ペリフェラルは、この固有のペリフェラルにアクセスするペリフェラルレジスタを識別するために、接頭辞<デバイス略称>_および<ペリフェラル名>_を用います。
これは短縮名に起因する名前衝突を避けるためです。もし1つ以上の同じ型のペリフェラルが存在すれば、識別子は以下の例のように接頭辞(数字/文字)を持ちます。
- <デバイス略称>_UART_Type:デバイス内の全UARTチャンネル用汎用レジスタ配置を定義。
typedef struct { union { __I uint8_t RBR; /*!< Offset: 0x000 Receiver Buffer Register */ __O uint8_t THR; /*!< Offset: 0x000 Transmit Holding Register */ __IO uint8_t DLL; /*!< Offset: 0x000 Divisor Latch LSB */ uint32_t RESERVED0; }; union { __IO uint8_t DLM; /*!< Offset: 0x004 Divisor Latch MSB */ __IO uint32_t IER; /*!< Offset: 0x004 Interrupt Enable Register */ }; union { __I uint32_t IIR; /*!< Offset: 0x008 Interrupt ID Register */ __O uint8_t FCR; /*!< Offset: 0x008 FIFO Control Register */ }; __IO uint8_t LCR; /*!< Offset: 0x00C Line Control Register */ uint8_t RESERVED1[7]; __I uint8_t LSR; /*!< Offset: 0x014 Line Status Register */ uint8_t RESERVED2[7]; __IO uint8_t SCR; /*!< Offset: 0x01C Scratch Pad Register */ uint8_t RESERVED3[3]; __IO uint32_t ACR; /*!< Offset: 0x020 Autobaud Control Register */ __IO uint8_t ICR; /*!< Offset: 0x024 IrDA Control Register */ uint8_t RESERVED4[3]; __IO uint8_t FDR; /*!< Offset: 0x028 Fractional Divider Register */ uint8_t RESERVED5[7]; __IO uint8_t TER; /*!< Offset: 0x030 Transmit Enable Register */ uint8_t RESERVED6[39]; __I uint8_t FIFOLVL; /*!< Offset: 0x058 FIFO Level Register */ } LPC_UART_TypeDef;
- <デバイス略称>_UART1: これは固有のUARTへの参照のレジスタ構造体へのポインタとなります。例えば、UART1->DRはUART1のデータレジスタとなります。
#define LPC_UART2 ((LPC_UART_TypeDef *) LPC_UART2_BASE ) #define LPC_UART3 ((LPC_UART_TypeDef *) LPC_UART3_BASE )
最小必要条件(Minimal Requiements)
デバイス内のペリフェラルレジスタと関連する関数へアクセスするために、device.h、core_cm0.h / core_cm3.hは最低限として定義します。
デバイス内のペリフェラルレジスタと関連する関数へアクセスするために、device.h、core_cm0.h / core_cm3.hは最低限として定義します。
- 全レジスタ名を定義する各ペリフェラル用のレジスタ配置Typedef。RESERVEで始まる名前は、ペリフェラルレジスタのアドレスを調整するため、構造体へ空間を空けるために使われています。
typedef struct { __IO uint32_t CTRL; /* SysTick Control and Status Register */ __IO uint32_t LOAD; /* SysTick Reload Value Register */ __IO uint32_t VAL; /* SysTick Current Value Register */ __I uint32_t CALIB; /* SysTick Calibration Register */ } SysTick_Type;
- ペリフェラルごとのベースアドレス(同じレジスタ配置typedefを使用するマルチペリフェラルの場合、複数のベースアドレスが定義される)
#define SysTick_BASE (SCS_BASE + 0x0010) /* SysTick Base Address */
- ペリフェラルごとのアクセス定義(同じレジスタ配置typedefを用いるマルチペリフェラルの場合、LPC_UART0, LPC_UART2のようなマルチアクセス定義が存在します。
#define SysTick ((SysTick_Type *) SysTick_BASE) /* SysTick access definition */
これらの定義は以下のような単純代入を伴うユーザーコードからペリフェラルレジスタへアクセスすることを許可します。
SysTick->CTRL = 0;
オプション機能(Optional Features)
さらにdevice.hでは以下を定義する場合があります。
さらにdevice.hでは以下を定義する場合があります。
- ペリフェラルレジスタへのアクセスを容易にする#define定数。これらの定数は、ペリフェラルレジスタのプログラミングに必要とされているビット位置もしくは他の固有のパターンを定義する。利用される識別子は<デバイス略称>_や<ペリフェラル名>_で始まる。これは大文字をそのような#define定数のために使用することを推奨している。
- ペリフェラルと共により複雑な機能を実行する関数(例えば送信中レジスタがアクセスされる前のステータスの問い合わせ)。これらの関数は<デバイス略称>_や<ペリフェラル名>_で始まる。
core_cm0.h and core_cm0.c
ファイルcore_cm0.hはCortex-M0コアペリフェラル用のデータ構造体を記述し、この構造体のアドレスマッピングを行います。また、これは効果的な関数(static inlineとして定義されている)でCortex-M0のコアレジスタやコアペリフェラルへの基本アクセスを提供します。
ファイルcore_cm0.cはプロセッサレジスタへアクセスする数々のヘルパー関数を定義します。
これらのファイルを組み合わせてCortex-M0用のCore Peripheral Access Layerを実装します。
ファイルcore_cm0.cはプロセッサレジスタへアクセスする数々のヘルパー関数を定義します。
これらのファイルを組み合わせてCortex-M0用のCore Peripheral Access Layerを実装します。
core_cm3.h and core_cm3.c
ファイルcore_cm3.hはCortex-M3のコアペリフェラル用データ構造体を記述し、この構造体のアドレスマッピングを行います。また、効果的な関数(static inlineとして定義されている)でCortex-M3のコアレジスタやコアペリフェラルへの基本アクセスを提供します。
ファイルcore_cm3.cはプロセッサレジスタへアクセスする数々のヘルパー関数を定義します。
これらのファイルを組み合わせてCortex-M3用のCore Peripheral Access Layerを実装します。
ファイルcore_cm3.cはプロセッサレジスタへアクセスする数々のヘルパー関数を定義します。
これらのファイルを組み合わせてCortex-M3用のCore Peripheral Access Layerを実装します。
startup_device
startup_device用のテンプレートファイルはARMにより各サポートコンパイラ向けに提供されています。これは半導体ベンダーによって全てのデバイス固有の割込ハンドラ用の割込ベクタを含むよう適合されます。それぞれの割込ハンドラはダミーハンドラへの弱い関数として定義されています。したがって割込ハンドラはstartup_deviceファイルに対応するためのいかなる条件もなしにアプリケーションソフトウェア内で直接利用できます。
次に示す例外名は固定であり、Cortex-M0用のベクタテーブルの始まりを定義します。
次に示す例外名は固定であり、Cortex-M0用のベクタテーブルの始まりを定義します。
__Vectors DCD __initial_sp ; Top of Stack DCD Reset_Handler ; Reset Handler DCD NMI_Handler ; NMI Handler DCD HardFault_Handler ; Hard Fault Handler DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD SVC_Handler ; SVCall Handler DCD 0 ; Reserved DCD 0 ; Reserved DCD PendSV_Handler ; PendSV Handler DCD SysTick_Handler ; SysTick Handler
次に示す例外名は固定であり、Cortex-M3用のベクタテーブルの始まりを定義します。
__Vectors DCD __initial_sp ; Top of Stack DCD Reset_Handler ; Reset Handler DCD NMI_Handler ; NMI Handler DCD HardFault_Handler ; Hard Fault Handler DCD MemManage_Handler ; MPU Fault Handler DCD BusFault_Handler ; Bus Fault Handler DCD UsageFault_Handler ; Usage Fault Handler DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD SVC_Handler ; SVCall Handler DCD DebugMon_Handler ; Debug Monitor Handler DCD 0 ; Reserved DCD PendSV_Handler ; PendSV Handler DCD SysTick_Handler ; SysTick Handler
以下にデバイス固有の割込用の例題を示します。
; External Interrupts DCD WWDG_IRQHandler ; Window Watchdog DCD PVD_IRQHandler ; PVD through EXTI Line detect DCD TAMPER_IRQHandler ; Tamper
デバイス固有の割込はユーザーコード内で上書きできるダミー関数を持たなければなりません。下記はこのダミー関数の例です。
Default_Handler PROC EXPORT WWDG_IRQHandler [WEAK] EXPORT PVD_IRQHandler [WEAK] EXPORT TAMPER_IRQHandler [WEAK] : : WWDG_IRQHandler PVD_IRQHandler TAMPER_IRQHandler : : B . ENDP
ユーザーアプリケーションは、以下に示すようなハンドラ名を使うことによって単に割込ハンドラ関数を定義するだけの場合があります。
void WWDG_IRQHandler(void) { : : }
system_device.c
system_device.c用のテンプレートファイルはARMによって提供されますが、半導体ベンダによって実デバイスに合うように適合されます。最低限必要な条件として、このファイルはデバイス固有のシステム設定関数やシステム周波数を含むグローバル変数を提供しなければなりません。これはデバイスを設定し、マイクロコントローラデバイスの一部である典型的なオシレータ(PLL)を初期化します。
ファイルsystem_device.cは最低限必要な条件として、以下に示すようなSystemInit関数を提供しなければなりません。
ファイルsystem_device.cは最低限必要な条件として、以下に示すようなSystemInit関数を提供しなければなりません。
関数定義 | 説明 |
void SystemInit (void) | マイクロコントローラシステムをセットアップする。一般的にこの関数はマイクロコントローラデバイスの一部であるオシレータ(PLL)を設定する。可変クロック速度をもつシステムでは、変数SystemCoreClockも更新する。 SystemInitはstartup_deviceファイルから呼び出される。 |
void SystemCoreClockUpdate (void) | 変数SystemCoreClockを更新する。これはコアクロックがプログラム実行中に変更された時は必ず呼ばれなければならない。SystemCoreClockUpdate()はクロックレジスタ設定を評価し、現在のコアクロックを計算する。 |
ファイルsystem_device.cの一部は以下に示す現在のCPUクロック速度を含むSystemCoreClock変数である。
変数定義 | 説明 |
uint32_t SystemCoreClock | システムコアクロックを含む(これはSysTickタイマーとプロセッサコアクロックへ供給されるシステムコアクロックを含む)。この変数はユーザーアプリケーションから、SysTickタイマーのセットアップもしくは他のパラメータの設定をするために使用することができる。これはデバッグタイマーの周波数の問い合わせもしくはトレースクロック速度の設定のために使用される場合もある。 SystemCoreClockは正しい定義済み変数で初期化される。 コンパイラは、アプリケーションプログラムによって使用されていない場合に、この変数が除去されるのを避けるために設定されなければならない。これは変数がメモリ内に物理的に存在するデバッグシステムでは重要であるため、デバッガを設定することを調べる事ができます。 |
Note
- 上記の定義はsystem_device.cファイルのための最低必要条件です。このファイルはさらにマイクロコントローラシステムのより柔軟な設定を提供をする関数もしくは変数exportする場合があります。
Core Peripheral Access Layer
Cortex-Mコアレジスタアクセス(Cortex-M Core Register Access)
以下に示す関数はcore_cm0.h / core_cm3.hで定義され、Cortex-Mコアレジスタへのアクセスを提供します。
関数定義 | コア | コアレジスタ | 説明 |
void __enable_irq (void) | M0, M3 | PRIMASK = 0 | Global Interrupt enable (using the instruction CPSIE i) |
void __disable_irq (void) | M0, M3 | PRIMASK = 1 | Global Interrupt disable (using the instruction CPSID i) |
void __set_PRIMASK (uint32_t value) | M0, M3 | PRIMASK = value | Assign value to Priority Mask Register (using the instruction MSR) |
uint32_t __get_PRIMASK (void) | M0, M3 | return PRIMASK | Return Priority Mask Register (using the instruction MRS) |
void __enable_fault_irq (void) | M3 | FAULTMASK = 0 | Global Fault exception and Interrupt enable (using the instruction CPSIE f) |
void __disable_fault_irq (void) | M3 | FAULTMASK = 1 | Global Fault exception and Interrupt disable (using the instruction CPSID f) |
void __set_FAULTMASK (uint32_t value) | M3 | FAULTMASK = value | Assign value to Fault Mask Register (using the instruction MSR) |
uint32_t __get_FAULTMASK (void) | M3 | return FAULTMASK | Return Fault Mask Register (using the instruction MRS) |
void __set_BASEPRI (uint32_t value) | M3 | BASEPRI = value | Set Base Priority (using the instruction MSR) |
uiuint32_t __get_BASEPRI (void) | M3 | return BASEPRI | Return Base Priority (using the instruction MRS) |
void __set_CONTROL (uint32_t value) | M0, M3 | CONTROL = value | Set CONTROL register value (using the instruction MSR) |
uint32_t __get_CONTROL (void) | M0, M3 | return CONTROL | Return Control Register Value (using the instruction MRS) |
void __set_PSP (uint32_t TopOfProcStack) | M0, M3 | PSP = TopOfProcStack | Set Process Stack Pointer value (using the instruction MSR) |
uint32_t __get_PSP (void) | M0, M3 | return PSP | Return Process Stack Pointer (using the instruction MRS) |
void __set_MSP (uint32_t TopOfMainStack) | M0, M3 | MSP = TopOfMainStack | Set Main Stack Pointer (using the instruction MSR) |
uint32_t __get_MSP (void) | M0, M3 | return MSP | Return Main Stack Pointer (using the instruction MRS) |
Cortex-M命令アクセス(Cortex-M Instruction Access)
次の関数はcore_cm0.h / core_cm3.hで定義され、固有のCortex-M命令を生成します。関数はファイルcore_cm0.c / core_cm3.c内で実装されています。
名前 | コア | 生成される命令 | 説明 |
void __NOP (void) | M0, M3 | NOP | No Operation |
void __WFI (void) | M0, M3 | WFI | 割込待機(Wait for Interrupt) |
void __WFE (void) | M0, M3 | WFE | イベント待機(Wait for Event) |
void __SEV (void) | M0, M3 | SEV | イベントセット(Set Event) |
void __ISB (void) | M0, M3 | ISB | 命令同期バリア(Instruction Synchronization Barrier) |
void __DSB (void) | M0, M3 | DSB | データ同期バリア(Data Synchronization Barrier) |
void __DMB (void) | M0, M3 | DMB | データメモリバリア(Data Memory Barrier) |
uint32_t __REV (uint32_t value) | M0, M3 | REV | integer値内のバイト並びの反転(Reverse byte order in integer value.) |
uint32_t __REV16 (uint16_t value) | M0, M3 | REV16 | unsigned short値内のバイト並びの反転(Reverse byte order in unsigned short value.) |
sint32_t __REVSH (sint16_t value) | M0, M3 | REVSH | integerへの符号拡張を伴うsigned short値内のバイト並びの反転(Reverse byte order in signed short value with sign extension to integer.) |
uint32_t __RBIT (uint32_t value) | M3 | RBIT | 値のbit並びの反転(Reverse bit order of value) |
uint8_t __LDREXB (uint8_t *addr) | M3 | LDREXB | 排他的?バイトの読み込み(Load exclusive byte) |
uint16_t __LDREXH (uint16_t *addr) | M3 | LDREXH | 排他的ハーフワードの読み込み(Load exclusive half-word) |
uint32_t __LDREXW (uint32_t *addr) | M3 | LDREXW | 排他的ワードの読み込み(Load exclusive word) |
uint32_t __STREXB (uint8_t value, uint8_t *addr) | M3 | STREXB | 排他的バイトを格納(Store exclusive byte) |
uint32_t __STREXB (uint16_t value, uint16_t *addr) | M3 | STREXH | 排他的ハーフワードを格納(Store exclusive half-word) |
uint32_t __STREXB (uint32_t value, uint32_t *addr) | M3 | STREXW | 排他的ワードを格納(Store exclusive word) |
void __CLREX (void) | M3 | CLREX | __LDREXB, __LDREXH, __LDREXWによる排他的ロックの解除 |
NVICアクセス関数(NVIC Access Functions)
CMSISはレジスタインターフェース構造体経由でのNVICへのアクセスとNVICのセットアップを単純化するいくつかのヘルパー関数を提供します。CMSIS HALは割込を識別するためにIRQ番号(IRQn)を使用します。一番目のデバイス割込はIRQn値0を持ちます。したがって、負のIRQn値はプロセッサコア例外用に使用されます。
コア例外のIRQn値については、ファイルdevice.hで次に占めるenum名のように提供されます。
コア例外のIRQn値については、ファイルdevice.hで次に占めるenum名のように提供されます。
コア例外enum値 | コア | IRQn | 説明 |
NonMaskableInt_IRQn | M0, M3 | -14 | Cortex-M Non Maskable Interrupt |
HardFault_IRQn | M0, M3 | -13 | Cortex-M Hard Fault Interrupt |
MemoryManagement_IRQn | M3 | -12 | Cortex-M Memory Management Interrupt |
BusFault_IRQn | M3 | -11 | Cortex-M Bus Fault Interrupt |
UsageFault_IRQn | M3 | -10 | Cortex-M Usage Fault Interrupt |
SVCall_IRQn | M0, M3 | -5 | Cortex-M SV Call Interrupt |
DebugMonitor_IRQn | M3 | -4 | Cortex-M Debug Monitor Interrupt |
PendSV_IRQn | M0, M3 | -2 | Cortex-M Pend SV Interrupt |
SysTick_IRQn | M0, M3 | -1 | Cortex-M System Tick Interrupt |
次の関数はNVICのセットアップを簡単化します。関数はstatic inlineで定義されています。
名前 | コア | パラメータ | 説明 |
void NVIC_SetPriorityGrouping (uint32_t PriorityGroup) | M3 | Priority Grouping Value | 優先度分類をセット(Groups . Subgroups) |
uint32_t NVIC_GetPriorityGrouping (void) | M3 | (void) | 優先度分類を取得(Groups . Subgroups) |
void NVIC_EnableIRQ (IRQn_Type IRQn) | M0, M3 | IRQ Number | IRQnを有効化 |
void NVIC_DisableIRQ (IRQn_Type IRQn) | M0, M3 | IRQ Number | IRQnを無効化 |
uint32_t NVIC_GetPendingIRQ (IRQn_Type IRQn) | M0, M3 | IRQ Number | IRQnが保留であれば1、そうでなければ0を返す |
void NVIC_SetPendingIRQ (IRQn_Type IRQn) | M0, M3 | IRQ Number | IRQnを保留にする |
void NVIC_ClearPendingIRQ (IRQn_Type IRQn) | M0, M3 | IRQ Number | IRQn保留状態を解除する |
uint32_t NVIC_GetActive (IRQn_Type IRQn) | M3 | IRQ Number | IRQnがアクティブであれば1、そうでなければ0を返す |
void NVIC_SetPriority (IRQn_Type IRQn, uint32_t priority) | M0, M3 | IRQ Number, Priority | IRQnの優先度をセットする (Cortex-M0ではスレッドセーフではない) |
uint32_t NVIC_GetPriority (IRQn_Type IRQn) | M0, M3 | IRQ Number | IRQnの優先度を取得 |
uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) | M3 | IRQ Number, Priority Group, Preemptive Priority, Sub Priority | 与えられたグループ、先制優先度および下位優先度で優先度をエンコードする |
NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* pPreemptPriority, uint32_t* pSubPriority) | M3 | IRQ Number, Priority, pointer to Priority Group, pointer to Preemptive Priority, pointer to Sub Priority | 与えられたグループ、先制優先度、下位優先度をデコードする |
void NVIC_SystemReset (void) | M0, M3 | (void) | システムをリセットする |
Note
- プロセッサ例外は負のenum値を持ちます。デバイス固有の割込は正のenum値を持ち、0から使われます。その値はdevice.hで定義されています。
- PreemptPriorityおよびSubPriority用の値は、NVIC内で実装されている利用可能な__NVIC_PRIO_BITSに依存する関数NVIC_EncodePriorityやNVIC_DecodePriority内で使用されます。
SysTick設定関数(SysTick Configuration Function)
次に示す関数はSysTickタイマーの設定やSysTick割込の開始に使用されます。
名前 | パラメータ | 説明 |
uint32_t SysTickConfig (uint32_t ticks) | ticks is SysTick counter reload value | SysTickタイマーをセットアップし、SysTick割込を有効にする。この呼び出しの後、SysTickは指定された時間間隔で割込を生成する。 戻り値: 0(成功時), 1(失敗時) |
Cortex-M3 ITMデバッグアクセス(Cortex-M3 ITM Debug Access)
Cortex-M3は搭載されたTrace Macrocell(ITM)(これはマイクロコントローラシステム用Serial Viewer Outputトレース機能を合わせて提供)を組み込みます。ITMは32の通信チャンネルを持ちます。2つのITM通信チャンネルは次に示す情報を出力するためにCMSISにより利用されます。
- ITM Channel 0: デバッグインターフェースを経由したprint-style出力に使われるITM_SendChar関数を実装
- ITM Channel 31: これはRTOSカーネル用に確保され、カーネル認知デバッギング(kernel awareness debugging)のために利用される
Note
- ITMチャンネル31はRTOSカーネル用に選択されています。いくつかのカーネルが特権レベルをプログラム実行に利用する場合があります。ITMチャンネルは8チャンネルごとに4つグループを持ち、それにより各グループが非特権レベルで権利にアクセスするために設定されることができます。それゆえに、ITMチャンネル31がRTOSカーネル自身からの特権レベルでのみアクセス可能である場合があるのに反して、ITMチャンネル0はユーザータスク用に有効化されることができます。ITM_SendCharルーチンのプロトタイプを以下の表に示します。
名前 | パラメータ | 説明 |
void uint32_t ITM_SendChar(uint32_t chr) | character to output | ITMチャンネル0を経由し、関数は文字を出力する。出力を予約しているデバッガが何も接続されていない時、関数は戻る。これはデバッガが接続されている時はブロックするが、前の文字送信は転送されない。 戻り値: 入力文字'chr' |
RTOSカーネル用のITMチャンネル31の使用例:
// デバッガが接続されているか、ITMチャンネルがトレースを有効化されているかをチェックする if ((CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA) && (ITM->TCR & ITM_TCR_ITMENA) && (ITM->TER & (1UL << 31))) { // transmit trace data while (ITM->PORT31_U32 == 0); ITM->PORT[31].u8 = task_id; // id of next task while (ITM->PORT[31].u32 == 0); ITM->PORT[31].u32 = task_status; // status information }
Cortex-M3追加的デバッグアクセス(Cortex-M3 additional Debug Access)
CMSISはCortex-M3デバッグアクセスを拡張するための追加デバッグ関数を提供します。データは信頼できるグローバルバッファ変数経由でターゲットシステム側へ転送されることができる。
バッファ変数と追加関数のプロトタイプを以下の表に示します。
バッファ変数と追加関数のプロトタイプを以下の表に示します。
名前 | パラメータ | 説明 |
extern volatile int ITM_RxBuffer | デバッグシステム側への転送データへのバッファ。 値0x5AA55AA5はバッファが空であることを表す。 | |
int ITM_ReceiveChar (void) | none | ノンブロッキング関数はITM_RxBufferへ格納された文字を返す。 戻り値: -1(文字が受信されていない) |
int ITM_CheckChar (void) | none | この関数は文字がITM_RxBuffer内で利用可能かどうかチェックする。 戻り値: 1(文字が利用可能), 0(文字が利用不可能) |
CMSIS Example
このセクションではユーザーアプリケーションでCMSISを利用するための一般的な例を示します。この例はSTM32F10xデバイスに基づいています。
#include "stm32f10x.h" volatile uint32_t msTicks; /* timeTicks counter */ void SysTick_Handler(void) { msTicks++; /* increment timeTicks counter */ } __INLINE static void Delay (uint32_t dlyTicks) { uint32_t curTicks = msTicks; while ((msTicks - curTicks) < dlyTicks); } __INLINE static void LED_Config(void) { ; /* Configure the LEDs */ } __INLINE static void LED_On (uint32_t led) { ; /* Turn On LED */ } __INLINE static void LED_Off (uint32_t led) { ; /* Turn Off LED */ } int main (void) { if (SysTick_Config (SystemCoreClock / 1000)) { /* Setup SysTick for 1 msec interrupts */ ; /* Handle Error */ while (1); } LED_Config(); /* configure the LEDs */ while(1) { LED_On (0x100); /* Turn on the LED */ Delay (100); /* delay 100 Msec */ LED_Off (0x100); /* Turn off the LED */ Delay (100); /* delay 100 Msec */ } }