EWARMで開発するCortex-M プログラミングガイド April 2015 IAR Systems K.K. FAE Team 本ドキュメントについて 目的 Cortex-Mプロセッサファミリの特徴を理解し、ソフトウェア開発をする上 での注意事項を学ぶ。ARM用統合開発環境、ARM用IAR Embedded Workbench(EWARM)を用いて、実際の開発を理解する。 内容 ARM Cortex-Mの概要 Cortex-Mの命令セット Cortex-Mのレジスタ Cortex-Mの割込みハンドリング スタートアップ処理 リンカ設定でメモリ配置コントロール Cortex-Mへの移行時の注意点 解析ツールを使用して、品質向上 ※本ドキュメントは、2015年4月現在のIARシステムズWebサイト、ST社Webサイト、 およびEWARMバージョン7.40.2を元に作成しています。 2 IAR SYSTEMS— A LEADING GLOBAL VENDOR 168 Employees with HQ in Uppsala, Sweden Listed in Stockholm/Nasdaq R&D investment 32% of revenue 32 years in the industry 24 hour technical support in 13 languages Uppsala Munich Sao Paulo Tokyo Seoul Shanghai London Paris San Francisco Dallas Boston Los Angeles +Distributor representation in 43 countries Stability and growth Licenses # (000’s) 2010 - 2013 Operating Margin % 20 20 15 15 10 10 5 5 0 0 2010 2011 License # 2012 2013 Operating Margin ARM Cortex-Mの概要 Cortex-Mベースのマイコンとは 英ARM Limitedの設計・開発するARM プロセッサを採用したマイコン ARMはCPUコア(など)のIP(設計図)を販売 ARM チップベンダが周辺機能(ペリフェラル)や メモリを追加実装 周辺機能 周辺機能 周辺機能 周辺機能 メモリ メモリ メモリ メモリ ARM コア ARM コア ARM コア ARM コア A社 B社 C社 D社 5 クラシックARMとARM Cortexプロセッサファミリ ARMマイコンの進化の過程 ARM11 Cortex-Ax Application Processors Cortex-Rx Real Time Processors ARM9 ARM7 CortexM0 V4 Microcontrollers Cortex-Mx V5 クラシックARM V6 V7 “基本的に” xが 大きいほど処理能力大 ARM Cortex 6 クラシックARMとARM Cortex-M ARM7(v4)とCortex-M3/4(v7-M)の主要な違い ARM7 Cortex-M3/M4 アーキテクチャ ARM v4 ARM v7-M 命令セット ARM / Thumb Thumb2 DMIPS / MHz 0.93 1.25 割込みコントローラ 外部 ネスト型ベクタ割込みコントローラ(NVIC) ベクタテーブル方式 命令方式 アドレス方式 アセンブラ要不要 要 不要 タイマー 外付け Systickタイマー内蔵 モード User FIQ IRQ SuperViser Monitor Abort Undef System User(Thread) System (Handler) メモリマップ 未規定 定義済み Flash 基本外付け 基本内蔵 割り切り! 簡単! 高性能! 7 STM32シリーズラインナップ 各種コアとシリーズの対応 M3 M4 M0 M3 M4 M0+ M3 M4 http://www.st.com/web/en/catalog/mmc /FM141/SC1169 M7 2015年4月1日 ST社Webサイトより抜粋 8 Cortex-Mのラインナップ比較 システム機能概要 M0 M0+ M3/M4 M7 スリープモード Yes Yes Yes Yes WIC Yes Yes Yes Yes SVC、PendSV Yes Yes Yes Yes - 0 or 8 0 or 8 0 or 8 or 16 HardFault HardFault HardFault +3設定 HardFault +3設定 フォールトステータスレジスタ - - Yes Yes ビットバンド - - オプション オプション L1キャッシュ - - - 最大64KB(I&D) TCM(密結合メモリ) - - - 最大1MB(I&D) MPU(オプション) フォールト/例外ハンドラ http://www.arm.com/ja/products/processors/cortex-m/cortex-m0.php http://www.arm.com/ja/products/processors/cortex-m/cortex-m0plus.php http://www.arm.com/ja/products/processors/cortex-m/cortex-m3.php http://www.arm.com/ja/products/processors/cortex-m/cortex-m4-processor.php http://www.arm.com/ja/products/processors/cortex-m/cortex-m7-processor.php 2015年4月1日 ARM社Webサイトより抜粋 9 Cortex-Mのラインナップ比較 最大パフォーマンス比較 1MHzあたりの処理量(CoreMark値) http://www.eembc.org/coremark/index.php 2015年4月1日 EEMBC Webサイトより抜粋 10 Cortex-Mの命令セット 命令セット:Cortex-Mの命令セットThumb-2 Cortex-MではThumb-2命令をサポート • ARM命令セット Thumb命令セット • Thumb-2命令セット 16ビット+32ビット命令混在 • 32ビット命令 16ビット命令 ARM7からの伝統的な命令セット • よく使う命令は16 bit、複雑な命令は32bitで高効率を実現 • Cortex-Mのラインナップごとにサポート命令セットは異なる 12 命令セット:Cortex-Mの命令セットThumb-2 同じコードをコンパイルして結果を比較 int gcd(int a, int b) { while (a != b) { if (a > b) a = a - b; else b = b - a; } return a; } 最大公約数を求める関数 ARM、Thumb、Thumb2でビルド 13 命令セット:Cortex-Mの命令セットThumb-2 同じコード(最大公約数を求める関数)をコンパイルして結果を比較 Thumb命令セット ARM命令セット gcd: gcd: ??gcd_0: 0x148: 0x14c: 0x150: 0x154: 0xe1500001 0x0a000003 0xe1510000 0xa0411000 CMP BEQ CMP SUBGE R0, R1 ??gcd_1 R1, R0 R1, R1, 0x158: 0xb0400001 SUBLT R0, R0, 0x15c: 0xeafffff9 B gcd 0x160: 0xe12fff1e BX LR R1 Thumb-2命令セット 0x4288 0xd004 0x4281 0xbfac 0x1a09 CMP BEQ.N CMP ITE SUBGE R0, R1 ??gcd_1 R1, R0 GE R1, R1, 0x92: 0x1a40 SUBLT R0, R0, 0x94: 0xe7f8 B.N ??gcd_0 0x96: 0x4770 BX LR ??gcd_0 0x14a: 0x1a40 SUBS R0, R0, 0x14c: 0x14e: 0x150: 0x152: 0x154: CMP BEQ.N CMP BLT.N SUBS R0, R1 ??gcd_2 R1, R0 ??gcd_1 R1, R1, 0x156: 0xe7f9 B.N ??gcd_0 0x158: 0x4770 0x15a: 0x0000 BX MOVS LR R0, R0 0x4288 0xd003 0x4281 0xdbfa 0x1a09 R0 ??gcd_2: gcd: ??gcd_0: 0x88: 0x8a: 0x8c: 0x8e: 0x90: B.N R1 ??gcd_0: R0 ??gcd_1: 0x148: 0xe000 ??gcd_1: ARM gcd(バイト) Thumb 28 Thumb-2 20 16 R0 R1 コード効率が高い ??gcd_1: 14 Cortex-Mプロセッサファミリごとのサポート命令 Cortex-Mに続く数字が大きくなるほど、多くの命令をサポート 浮動小数点演算 DSP(SIMD,高速加算乗算) アドバンストデータ処理 ビットフィールド処理 基本データ処理 I/Oハンドリング M0/M0+ M3 M4 M7 M4 FPU M7 FPU 15 Cortex-Mプロセッサファミリの命令比較 命令セット概要 M0/M0+ シングルサイクル乗算 M3 M4 M7 Yes Yes Yes Yes ハードウェア除算 - Yes Yes Yes アドバンストメモリアクセス - Yes Yes Yes アドバンスト分岐サポート - Yes Yes Yes 排他アクセス - Yes Yes Yes SIMD DSP - - Yes Yes サチュレーションサポート - 一部 フル フル 浮動小数点演算(オプション) - - 単精度 単精度/倍精度 16 Cortex-Mプロセッサファミリの命令比較 浮動小数点除算の例 元のCコード M4F:8命令 M3:44命令 M0:171命令 コンパイラが自動的にコア搭載する命令を有効活用 17 Cortex-Mのレジスタ Cortex-Mのレジスタ構成 CPUレジスタ MSP PSP R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13(SP) R14(LR) R15(PC) xPSR 汎用的に使えるレジスタ R0~R12 さらに、R0~R7までを下位レジスタ R8~R12までを上位レジスタと呼ぶ。 R0~R7までが16ビット命令で 自由に使えるレジスタ R13はスタックポインタとして使用。 2つあり、切り替えて使用することができる。 R14は関数の返りアドレスを保存するリンクレジスタとして使用。 R15はプログラムの実行アドレスを示すPCに使用。 xPSRは実行状態を示す。演算結果フラグ、割り込み番号、使用す る命令セット(Thumb系か否か)。 NMIとフォルトハンドラ以外の割り込みの許可・禁止を制御する PRIMASK CONTROL FAULTMASK BASEPRI M3/M4/M7のみ 使用するスタックの指定、特権/ユーザ・レベル。 NMI以外の割り込みの許可・禁止を制御する 指定優先度以下の割り込みの許可・禁止を制御する 19 Cortex-Mのレジスタ構成 ステータスレジスタ 31 30 29 28 27 26 25 24 23 xPSR N Z C V Q APSR N Z C V Q ICI/IT T 16 15 10 9 8 7 ICI/IT IPSR EPSR • 0 Esception Number Exception Number ICI/IT T ICI/IT アプリケーションプログラムステータスレジスタ APSR – 演算結果のフラグ • 割り込みプログラムステータスレジスタ IPSR – 割り込み番号 • 実行プログラムステータスレジスタEPSR – 実行状態bit 各レジスタは個別にも、まとめても(xPSR)アクセス可能 20 Cortex-Mのレジスタ構成 コントロールレジスタ 31 CONTROL 2 1 0 Reserved • bit [0] でスレッドモード時の特権を設定 — 0: スレッドモードは特権あり — 1: スレッドモードは特権なし. • bit [1] はスタックを選択 — 0: メインスタックポインタを使用 — 1: スレッドモードのときは、プロセススタックポインタを使用。 MRS命令でREAD、MSR命令でWRITE。 特権がないとアクセスできない。 21 Cortex-Mの関数コールとレジスタ 関数のジャンプ時には、レジスタ操作が行われる • • • • 引数は R0,R1,R2,R3を利用(5つ目からスタックに) 返り値はR0を利用 ジャンプするときには、BL命令 戻る時はいろいろPC(R15)を操作する命令 • たとえば、BX命令、POP命令 R0 R1 R2 R3 R4 R5 int f1(int a ) { return a+1; } int main (void) { ・・・ t = f1(10); Cコード f1: ADDS #1 BX R6 R0, R0, LR R7 R8 R9 main: ・・・ BL R10 R11 f1 コンパイル結果 R12 R13 (SP) R14 (LR) R15 (PC) CPSR 22 Cortex-Mの関数コールとレジスタ 実際に動作を見てみる PC=0x200_01FA0 LR= 0x200_01F91 戻りアドレス=0x20001FA4 BLでジャンプ BL命令は LR(R14)レジスタに戻りアドレスを 保存し、PCを関数にセットする PC=0x20001F98 LR= 0x20001FA5 23 Cortex-Mの関数コールとレジスタ 実際に動きを見てみる:関数からの戻り PC=0x20001F9A LR= 0x20001FA5 BXでジャンプ BX命令は LR(R14)レジスタで指 定されるアドレスにジャンプ PC=0x20001FA4 LR= 0x20001FA5 *Thumb命令では、ジャンプ時にLRのアドレスのLSBが常に1にセットされる 24 ARMのレジスタとSTのレジスタ ARMマイコンはARM CPUレジスタと周辺レジスタがある ARM ST 25 Cortex-Mの割込みハンドリング NVIC(内蔵割込みコントローラ) Cortex-Mプロセッサは割込みコントローラを内蔵している • • • レジスタの退避 割込み優先度ハンドリング ネスト割込みのハンドリング Cortex-M NMI NVIC 各種割込み Core システム例外 SysTick タイマーペリフェラル 27 ベクタテーブルの記述 4バイト単位で、割込みハンドラのアドレスを記述 *先頭だけは、スタックのアドレスを指定 スタックアドレス Vector No. Vector Offset 例外& 割り込み 値(例) 00 0x00 Stack Top sfe (CSTACK) 01 0x04 Reset __iar_program_start 02 0x08 NMI Default Handler 03 0x0C Hard Fault Default Handler 04 0x10 Memory Management 05 0x14 Bus Fault Default Handler 06 0x18 Usage Fault Default Handler 07~10 0x1C~0x28 Reserved 0 11 0x2C SVCall Default Handler 12 0x30 Debug Monitor Default Handler 13 0x34 Reserved 0 14 0x38 PendSV Default Handler 15 0x3C SysTick Default Handler 16 ~ 255 0x40~0x3FC External Interrupts Interrupt Handlers RESETハンドラアドレス Default Handler 外部割込みのハンドラアドレス 28 ベクタテーブルの比較 クラシックARMおよびCortex-R/Aとの比較 ARM9 ( + Cortex-R/A) __vector: ARM LDR LDR LDR SWI/SVC) LDR LDR DCD LDR LDR PC,Reset_Addr PC,Undefined_Addr PC,SWI_Addr ; Reset ; Undefined instructions ; Software interrupt PC,Prefetch_Addr PC,Abort_Addr 0 PC,IRQ_Addr PC,FIQ_Addr ; ; ; ; ; Cortex-M #pragma location = ".intvec" const intvec_elem __vector_table[] = { { .__ptr = __sfe( "CSTACK" ) }, __iar_program_start, Prefetch abort Data abort RESERVED IRQ FIQ NMI_Handler, HardFault_Handler, MemManage_Handler, BusFault_Handler, UsageFault_Handler, 0, 0, 0, 0, SVC_Handler, DebugMon_Handler, 0, PendSV_Handler, SysTick_Handler, DATA Reset_Addr: Undefined_Addr: SWI_Addr: Prefetch_Addr: Abort_Addr: IRQ_Addr: FIQ_Addr: DCD DCD DCD DCD DCD DCD DCD __iar_program_start Undefined_Handler SWI_Handler Prefetch_Handler Abort_Handler IRQ_Handler FIQ_Handler //Device specified interrupt handler InterruptHandler0 InterruptHandler1 アセンブラ命令 (割込みハンドラにジャンプ) InterruptHandler240 }; C言語(ハンドラのアドレス指定) 29 SysTickタイマーで割込み動作確認 SysTickを有効にして確認 static int tick = 0; void SysTick_Handler(void) { 割り込みハンドラはCの関数。 tick++; ハンドラと関数に差はない } int main( void ) { SysTick->LOAD = 0x0000FFFF; //←リロードレジスタの値をセット SysTick->VAL = 0; // ←初期値をセット SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; //← コアクロックで割込み有効でスタート __enable_interrupt(); while (1) { //SysTick_Handler(); delay(); } } 30 SysTickタイマーで割込み動作確認 EWARMのデバッガ機能で確認 割り込みハンドラの先頭 LRは割込みを意味する 0xFFFF_FFxx PCはハンドラへ 31 SysTickタイマーで割込み動作確認 自動的にスタックにレジスタが退避される 0x0000_0000側 R0: R1: R2: R3: R12: LR: PC: 割込み前の LRの値 割り込み発生の アドレス CPSR 使用スタック 使用スタック 0xFFFF_FFFF側 表示-スタック-スタック1 スタックの表示可能 32 SysTickタイマーで割込み動作確認 割込みハンドラを通常の関数として呼んでみる コメントを外して メイクしてデバッグ 33 SysTickタイマーで割込み動作確認 割込みハンドラを通常の関数として呼んでみる(結果) 関数から呼んだ場合 LR = 0x080001C1 SysTick_Handler: 0x800019e: 0x4815 [0x80001f4] tick 0x80001a0: 0x6801 0x80001a2: 0x1c49 0x80001a4: 0x6001 } 0x80001a6: 0x4770 int main( void ) { main: - - - SysTick_Handler(); 0x80001bc: 0xf7ff 0xffef 0x800019e 割込みから呼ばれた場合 LR = 0xFFFFFFE9 LDR.N R0, [PC, #0x54] LDR ADDS STR R1, [R0] R1, R1, #1 R1, [R0] BX LR BL SysTick_Handler ; ; 34 SysTickタイマーで割込み動作確認 割込みハンドラでのLRの値(EXC_RETURN) 割込みを抜ける際のスタックポインタ、多重割込み、FPUなどにより異なる MSP(メイン) PSP(プロセス) 割り込み時 使用 × その他 使用可能 使用可能 • CONTROLレジスタの設定で使用スタックの変更が可能 LRの値 0xFFFF_FFF1 多重割込み 0xFFFF_FFF9 通常状態への復帰時にMSPを使用 0xFFFF_FFFD 通常状態への復帰時にPSPを使用 0xFFFF_FFE1 多重割込み(FPU状態) 0xFFFF_FFE9 通常状態への復帰時にMSPを使用(FPU状態) 0xFFFF_FFED 通常状態への復帰時にPSPを使用(FPU状態) 35 スタートアップ処理 Cortex-Mのリセット動作 Cortex-Mでは起動時にベクタテーブルの内容を元に初期化される ベクタ先頭 0x0000_0000 スタックの先頭アドレス リセットハンドラアドレス NMIハンドラアドレス リセットされるとCPUは メモリから2ワード読み出す。 最初のデータでスタックポインタをセット。 2つ目のデータにPCをセット。 リセット スタック 37 EWARM+Cortex-Mの起動動作 参照 ジャンプ Cortex-M0/M3/M4 Vector Table: IAR DLIB ランライム ライブラリの コード ただし 上書き可能 thumb¥vector_table_M.s or thumb¥cstartup_M.c デフォルトプログラムエントリ: thumb¥cstartup_M.s or thumb¥cstartup_M.c main()前の初期化: thumb¥cmain.s ユーザコード User’s Application: 例外& 割り込み 値 0x00 Stack Top sfe (CSTACK) 01 0x04 Reset __iar_program_start 02 0x08 NMI Default Handler 03 0x0C Hard Fault Default Handler 04 0x10 Memory Management Default Handler 05 0x14 Bus Fault Default Handler 06 0x18 Usage Fault Default Handler 07~10 0x1C~0x28 Reserved 0 11 0x2C SVCall Default Handler 12 0x30 Debug Monitor Default Handler 13 0x34 Reserved 0 14 0x38 PendSV Default Handler 15 16 ~ 255 0x3C 0x40~0x3FC SysTick External Interrupts Default Handler Interrupt Handlers Vector No. Vector Offset 00 __iar_program_start: bl __iar_init_core bl __iar_init_vfp bl __cmain ; optional ; optional, enable VFP, thumb¥fpinit_M.s __cmain: bl __low_level_init bl __iar_data_init3 bl main ; low_level_init.c ; initialize data sections, init¥data_init3.c int main (void) { …… } void xxx_InterruptHandler (void) { …… } 38 初期化処理のデバッグ デバッグのオプションを変更することで、main以前のデバッグ可能 チェックを外す 39 初期化処理のソースコード EWARMインストールフォルダに初期化処理のソースコードがる EWARMのインストールフォルダ #pragma location = ".intvec" const intvec_elem __vector_table[] = { { .__ptr = __sfe( "CSTACK" ) }, __iar_program_start, NMI_Handler, HardFault_Handler, }; void __cmain( void ); __weak void __iar_init_core( void ); __weak void __iar_init_vfp( void ); Reset #pragma required=__vector_table void __iar_program_start( void ) { __iar_init_core(); __iar_init_vfp(); __cmain(); } __cmain: bl cmp beq bl ?l1: MOVS BL line BL BL __low_level_init r0,#0 ?l1 __iar_data_init3 変数の初期化 r0,#0 __iar_argc_argv ; No parameters ; Maybe setup command main exit main 40 リンカ設定でメモリ配置コントロール ILINKの基本概念・キーワード EWARMのリンカはILINK 詳細使用方法はC/C++開発ガイドを参照 42 ILINKの基本概念・キーワード GUIの設定項目 プロジェクトオプション > リンカ > 設定 ベクタテーブル、ROM/RAM領域、スタックサイズの変更が可能 43 ILINKの基本概念・キーワード リンカの働き 領域(Region)を指定して、そこにセクションやブロックを配置 ROMの特定の アドレスに配置 Memory領域 Region 0x00000000-0x0000FFFF IARの標準セクション .intvec .text place in ROM に配置 .data_init .rodata .data Region 0x20000000-0x2000FFFF place in ブロック(スタック) RAM に配置 ブロック(ヒープ) 割り込みベクター コード 変数の初期化データ constデータ 変数 44 ILINKの基本概念・キーワード リンカ設定ファイルのキーワード紹介 • region メモリ上の領域を指定します。 • block サイズを指定します • section プログラムのセクション • initialize 初期化方法の指定 • do no initialize 初期化しない領域の指定 • place regionにblockやsectionを配置 • rw(readwrite), ro(readonly)の属性を指定 ILINKの基本概念・キーワード EWARMの基本セクション • .bss :0初期化する変数 • .data :0以外で初期化される変数 • .data_init • .intvec : ベクタ • .noinit :初期化しない変数 • .rodata : readonlyの変数 • .text : プログラム • .textrw : __ramfuncを使った時のコード • .textrw_init : .textrwの初期化データ : .dataセクションの初期化データ *詳細はIAR C/C++ 開発ガイドのセクションリファレンスを参照 実際に動作をみてみる(関数を配置) ファイルfunc.cのLED絡みの関数を特定領域に配置 0x00000000 IROM 0x00050000 ROMLED 0x00FFFFF void set_LED_port(void) void LED_Handler(void) 0x20000000 RAM 0x2000FFFF 47 実際に動作をみてみる(関数を配置) C言語ソースコードでの指定 pragmaでセクション定義。 EWARMではセクション定義は #pragma location=“XXXX” EWARMではセクションを参照するときに #pragma section=“XXXX” とななる。 48 実際に動作をみてみる(関数を配置) 実際にセクションを指定 #pragma location="LED" void set_LED_port(void ) { printf("initialize LED port¥n"); } #pragma location="LED" void LED_Handler(void) { Port0 != Port0; } set_LED_portがセクション”LED”に割当 LED_Handlerがセクション”LED”に割当 49 実際に動作をみてみる(関数を配置) リンカ設定ファイル(抜粋) 0x00000000から0x0004FFFFをIROM_region define region IROM_region = mem:[from __ICFEDIT_region_IROM1_start__ to 0x0004FFFF ]; define region ROMLED_region= mem:[from 0x00050000 to __ICFEDIT_region_ROM_end__]; 0x00050000から0x000FFFFFをROMLED_region place in IROM_region { readonly }except { section LED }; セクションLEDを除く、readonlyをROM_regionに配置 place in ROMLED_region { readonly section LED }; セクションLEDのreadonlyをROMLED_regionに配置 50 実際に動作をみてみる(関数を配置) ビルド結果のmapファイル プロジェクトオプション > リンカ > リスト > リンカマップファイルの表示 Outputフォルダに生成されるマップファイルをダブルクリックで表示 Codeは関数を示す 関数が奇数アドレスは、Thumb命令。 (Cortex-MはすべてThumb命令。) 51 実際に動作をみてみる(変数を配置) RAM2に図のように4つの変数を配置 0x00000000 ROM 0x000FFFFF 0x20000000 0x20004000 0x2000FFFF RAM int int int int mydat1[10]; mydat2[10]; mydat3[5]; mydat4[5]; RAM2 52 実際に動作をみてみる(変数を配置) 実際にセクションを定義 ひとつひとつ変数にセクションを割り当て #pragma location="MYDAT" __root int mydat1[10]; #pragma location="MYDAT" __root int mydat2[10]; #pragma default_variable_attributes = __root int mydat3[5]; int mydat4[5]; #pragma default_variable_attributes = @ "MYDAT" まとめて変数に属性をつける このとき__rootもpragma側でつけること 53 実際に動作をみてみる(変数を配置) リンカ設定ファイル define region RAM_region define region RAM2_region place in RAM_region = mem:[from __ICFEDIT_region_RAM_start__ = mem:[from 0x20004000 { readwrite, to 0x20003FFF]; to __ICFEDIT_region_RAM_end__]; block CSTACK, }; place in RAM2_region { readwrite section MYDAT}; RAM2_regionにセクションMYDATの readwriteデータを配置 54 実際に動作をみてみる(変数を配置) MAPファイルを確認 #pragma location="MYDAT" __root int mydat1[10]; #pragma location="MYDAT" __root int mydat2[10]; #pragma default_variable_attributes = __root int mydat3[5]; int mydat4[5]; #pragma default_variable_attributes = define region RAM2_region = mem:[from 0x20004000 to _ICFEDIT_region_IRAM1_end__]; place in RAM2_region { readwrite mydat1 mydat2 mydat3 mydat4 0x20004000 0x20004028 0x20004050 0x20004064 0x28 0x28 0x14 0x14 @ "MYDAT" section MYDAT}; Data Data Data Data Gb Gb Gb Gb main.o main.o main.o main.o [1] [1] [1] [1] 55 実際に動作をみてみる(変数を手動初期化) 初期化つき変数にセクション定義 初期化つき変数にセクションを割り当て #pragma location="MYDAT" __root int mydat1[10] = {0,1,2,3,4,5,6,7,8,9,}; #pragma location="MYDAT" __root int mydat2[10] = {10,11,12,13,14,16,17,18,19}; 初期化つき変数にセクションを割り当て 56 実際に動作をみてみる(変数を手動初期化) 初期化ルーチンの作成 プログラム中でセクション名を参照する場合には #pragma sectionで明示する。 #pragma section="MYDAT" #pragma section="MYDAT_init" void init_MYDAT( ) { int i; unsigned char *psrc, *pdest; 変数はMYDATというセクションになる。 初期化データはMYDAT_initというセクションにる。 pdest = __section_begin("MYDAT"); psrc = __section_begin("MYDAT_init"); for (i=0; i < __section_size("MYDAT"); i++ ) { *pdest = *psrc; pdest++; psrc++; } セクションMYDATの先頭アドレスを __section_beginで取得 セクションMYDAT_initの先頭アドレスを __section_beginで取得 } セクションMYDATのサイズを __section_sizeで取得 57 実際に動作をみてみる(変数を手動初期化) リンカ設定ファイルでの指定 この領域の初期化は自動に行う initialize by copy { readwrite } except {section MYDAT}; initialize manually with packing=none { readwrite section MYDAT}; place in RAM2_region { readwrite section MYDAT}; この領域の初期化は手動で行う + 初期化データの圧縮はしない 58 実際に動作をみてみる(変数を手動初期化) マップファイルでの確認 initialize manually { readwrite section MYDAT};の場合 ************************************ *** INIT TABLE *** initialize by copy { readwrite };の場合 ****************************************** *** INIT TABLE *** Address Size ------- ---Zero (__iar_zero_init3) 1 destination range, total size 0x54: 0x20000030 0x54 Address Size ------- ---Zero (__iar_zero_init3) 1 destination range, total size 0x54: 0x20000030 0x54 Copy (__iar_copy_init3) 1 source range, total size 0x50: 0x000019dc 0x50 1 destination range, total size 0x50: 0x20004000 0x50 Copy (__iar_copy_init3) 1 source range, total size 0x30: 0x00001be4 0x30 1 destination range, total size 0x30: 0x20000000 0x30 ない mydat1 0x20004000 0x28 Data Gb main.o [1] mydat2 0x20004028 0x28 Data Gb main.o [1] ある Copy (__iar_copy_init3) 1 source range, total size 0x30: 0x00001bf8 0x30 1 destination range, total size 0x30: 0x20000000 0x30 59 実際に動作をみてみる(変数を手動初期化) 初期化関数前後の変数の値を比較 コード for ( i=0; i< 10; i++){ printf("BEFORE No%d - %d¥n", i, mydat1[i]); } init_MYDAT( ); 初期化関数を実行 for ( i=0; i< 10; i++){ printf("AFTER No%d - %d¥n", i, mydat1[i]); } printf出力結果 表示>ターミナルI/O initialize LED port BEFORE No0 - -842150451 BEFORE No1 - -842150451 BEFORE No2 - -842150451 BEFORE No3 - -842150451 BEFORE No4 - -842150451 BEFORE No5 - -842150451 BEFORE No6 - -842150451 BEFORE No7 - -842150451 BEFORE No8 - -842150451 BEFORE No9 - -842150451 AFTER No0 - 0 AFTER No1 - 1 AFTER No2 - 2 AFTER No3 - 3 AFTER No4 - 4 AFTER No5 - 5 AFTER No6 - 6 AFTER No7 - 7 AFTER No8 - 8 AFTER No9 - 9 60 Cortex-Mへの移行時の注意点 Cortex-Mへの移行時の注意点 アーキテクチャにより、仕様が異なる項目に注意する • スタックサイズ • intデータのサイズ • 構造体のパッキング 62 スタックサイズ 8bit、16bitマイコンと比較するとスタック使用量は多い 全レジスタ汎用レジスタ+PC+STACK+CPSRを退避した際の例 Cortex-M 16bitマイコンの例 68?バイト 14?バイト EWARMでは2種類のスタック解析機能で使用量を解析可能 • 静的なスタック解析(メイク時) • 動的なスタック解析(デバッグ時) 63 スタックサイズ 静的なスタック解析(メイク時) :オプション設定 プロジェクトを選択し、✓をダブルクリック [リンカ]-[アドバンスド]-[スタックの使用量解析を有効にする] 1 2 4 3 5 64 スタックサイズ 静的なスタック解析(メイク時):マップファイルに表示 メイクでマップファイルに解析結果表示 Call Graph Root Category -----------------------interrupt Program entry Max Use ------0 232 Total Use --------0 232 Program entry "__iar_program_start": 0x0000058d Maximum call chain "__iar_program_start" "__cmain" "main" "dhry_main" "Proc_1" "Proc_6" "Func_3" 232 bytes 0 0 8 192 16 16 0 Mainの実行されるパスでの スタック使用量 interrupt "__default_handler" in vector_table_M.o [4]: 0x00000473 Maximum call chain "__default_handler" in vector_table_M.o [4] 0 bytes 0 ハンドラの実行されるパスでの スタック使用量 65 スタックサイズ 静的なスタック解析(メイク時):解析サポート機能 • 関数ポインタなどを使うと、自動では追えない • #pragma calls=XX,YY を使って手動指定 void Fun1(), Fun2(); void Caller(void (*fp)(void)) { #pragma calls = Fun1, Fun2 (*fp)(); この関数はFun1,Func2が呼ばれる } • 解析のスタート関数を個別指定したい #pragma call_graph_root void delay_time(int number){ ・・・ } 66 スタックサイズ 動的なスタック解析(デバッグ時):ツールオプション設定 [ツール]-[オプション] [スタック]-[グラフィカルスタック表示・・・]を有効 1 2 4 3 67 スタックサイズ 動的なスタック解析(デバッグ時):表示 [表示]-[スタック]-[スタック1] 1 2 3 68 スタックサイズ 動的なスタック解析(デバッグ時):実行結果表示 灰色は使用した量 緑のバーは現状値 マウスをあてると 詳細が表示 69 intデータ型のサイズ intデータ型のサイズは、マイコン・コンパイラにより異なる EWARM 16ビットマイコン signed char 8 8 unsigned char 8 8 signed short 16 16 unsigned short 16 16 signed int 32 16 unsigned int 32 16 signed long 32 32 unsigned long 32 32 signed long long 64 32 unsigned long long 64 32 70 intデータ型のサイズ マイコンにより、結果が異なる例 unsigned short c=0xFFFF; int gg(unsigned short a, unsigned short b) { if ( c == ( a | ~b) ) { return 0; } else { return 1; } } int main( void ) { int t; x =0で、yが0, c=0xFFFFの時のprintfの出力 16 bit result=0 32 bit result=1 t= gg(0, 0 ); printf("result=%d¥n", t); return 0; } 71 構造体のパッキング 構造体のパッキングによる差 struct S1 { char s1; int s2; char s3; int s4; char s5; } A[10]; struct S2 { char s1; char s3; char s5; int s2; int s4; } B[10]; Entry Address Size(hex) Size(Dec) Type Object A 0x20000000 0xc8 200 Data Gb main.o [1] B 0x200000c8 0x78 120 ▲40% Data Gb main.o [1] struct S1での状況 struct S2での状況 s1 s2 5 s5 s3 s4 s3 s2 s4 s1 3 s5 4バイト 4バイト 72 解析ツールを使用して品質向上 解析ツールを使用して品質向上 IARシステムズの提供する解析アドオン製品を使用して品質向上 • 静的解析アドオン機能 C-STAT • MISRA-C 2004/2008C++/2012のチェック • CWE / CERTルールに準拠した脆弱性のチェック • 動的解析アドオン機能 C-RUN • 実行時の数値演算エラーの検出 • 不適切なメモリ利用の検出 ※C-RUN/ C-STATはEWARM製品版に対するアドオン製品となります。 74 静的解析アドオン機能C-STAT 実動作不要の静的解析で、潜在的なコードエラーを検出 ソースコードレベルにおいて潜在的なエラーやバグを EWARM上で発見。 例えばメモリリーク・アクセス違反・算術演算の エラー・配列や文字列のオーバーランといった 潜在的なコードエラーを発見でき、 アプリケーションの誤動作を未然に防止。 主な機能 • C , C++ 言語に対応 • MISRA C:2004, MISRA C++:2008, MISRA C:2012に対応 • CWE や CERT C/C++といった基準に基づく100以上のルールに沿ったチェック • 直感的で簡単に使える設定 • 任意でコーディング規約単位または個別のルール単位でチェック • IAR Embedded Workbenchとシームレスに統合 • 短時間で解析 • ARM用IAR Embedded Workbenchバージョン7.40より利用可能 75 簡単に使える「C-STAT」 EWARMのオプションで解析したいチェックルールを選択するだけ [静的解析]を選択 [C-STAT check]をクリック プロジェクトを右クリックし [オプション…]を選択 CWE/CERTをベースに 動作時不良リスクをチェック MISRA C コーディングガイド 準拠チェック チェック項目選択画面 76 「C-STAT」の実行 EWARMのオプションメニューで選択するだけ プロジェクトを 右クリック [C-STAT]静的解析 プロジェクトを解析 数分でC-STATメッセージが表示 77 動的解析アドオン機能C-RUN デバッグ実行時に、実際に発生した潜在エラーを検出 事前に設定したチェック項目を対象にデバッグ実行中に、 リアルタイムにチェックを行い、違反した挙動を 検出し、EWARM上で通知。 実装フェーズから問題を検出することで、後段での テスト・修正工数を削減し、品質向上・納期短縮を実現 • • • • • • • • • • • • • • 主な機能 C, C++言語に対応 直感的で簡単に使える設定 包括的かつ詳細な実行時のエラー情報 エラーが見つかった場所のコールスタック情報 エディタ上でのコード位置を表示やグラフィカルな表示 自由度の高いエラー情報の管理 配列や他のオブジェクトが境界内に正しくアクセスしていることを保証する境界チェック バッファオーバーフローの検出 データのキャスト時の、値の変化を検出 算術計算時の値のチェック シフト演算のビット損失を検出 ヒープやメモリリークに関するチェック ARM用IAR Embedded Workbenchバージョン7.20以降で利用可能 78 動的解析アドオン機能C-RUN デバッグ実行時に、実際に発生した潜在エラーを検出 コンパイラ開発者による高効率 IDE tools Build tools IAR C-SPY Debugger Editor IAR C/C++ Compiler Simulator driver Project manager Assembler Hardware system drivers Library builder Linker Librarian 完全に統合された 動的解析 Power debugging RTOS plug-ins 詳細かつ柔軟な 動的エラー情報 79 簡単に使える「C-RUN」 EWARMのオプションで解析したいチェックルールを選択するだけ ※ビルド時にチェックコードが実行コードに埋め込まれる [ランタイム解析]を選択 [有効化]をチェック チェックしたい項目をチェック 80 「C-SRUN」の実行 EWARMのデバッグ実行中に自動的に検出される 発生したソース位置 発生した違反 発生したPC位置 発生したコア (マルチコア対応) データ値の表示 値0x000001f4を0xf4にした コールスタックで、mainから、convを呼んだ中で発 生したことを示す。 81 まとめ まとめ Cortex-Mの特徴を理解することで、レジスタや命令セットの読み方 を習得できる 割込みハンドラやベクタテーブルは、従来のARMコアから変更となっ ている。 初期化処理やリンカ設定はEWARM独自の記述となり、既存のものを 参考にカスタマイズしていく。 マイコンアーキテクチャごとに動作の異なるコーディングに注意する 静的解析ツール、動的解析ツールを使用することで、不具合の早期発 見、品質向上につながる 83 本資料について 本資料取り扱い上の注意 本資料は2015年4月1日時点の情報を基に作成されており、将来変更の可能性 のあるものです。あわせてご紹介する設定や機能に関連して、動作保証をお約束す るものではございませんので、ご了承ください 本資料で提供している情報は、ご利用されている方のご判断・責任においてご使用 ください。提供した情報に関連して、ご利用される方が不利益等を被る事態が生じ たとしても、弊社及び執筆者は一切の責任を負いかねますので、ご了承ください。 本資料の内容に関する弊社または各社へのお問合せはご遠慮ください。 本資料及びデータの再配布・無断転用・転載等はご遠慮ください。 85 商標について • IAR Systems, IAR Embedded Workbench, C-SPY, C-RUN, C-STAT, visualSTATE, Focus on Your Code, IAR KickStart Kit, I-jet, I-scope, IAR, お よび IAR Systems のロゴタイプはIAR Systems ABが所有する商標または登録 商標です。 • ARMおよびCortexは、ARM Limited(またはその子会社)のEUまたはその他の 国における登録商標です。 ARMおよびThumbは、ARM Limited(またはその子 会社)のEUまたはその他の国における商標です。 CoreSightは、ARM Limited (またはその子会社)のEUまたはその他の国における商標です。 All rights reserved. • STM32は、STマイクロエレクトロニクスの登録商標です。 • その他、本資料中の製品名やサービス名は全てそれぞれの所有者に属する商標ま たは登録商標です。 86
© Copyright 2025 ExpyDoc