Upload
others
View
4
Download
0
Embed Size (px)
Citation preview
開発環境メーカが教える
マイコンプラットフォームの移行に伴う
開発環境の移植方法とは?
1
IARシステムズ 技術部 殿下信二
このセッションで学べる事
• C/C++言語は規格で決まっているので、C/C++コンパイラが異なっても短時間で開発環境の移行が出来ると思われますが、事前の調査、準備、目標設定を誤ると、効率的に進める事は出来ませんので、手順と問題点を明らかにする事が必要です
•開発環境移行は、C/C++コンパイラのエラー対策を行う静的環境移行と、プログラム動作タイミングの移行を行う動的環境移行に分ける事が出来ます
•本セクションでは、静的環境移行を効率良く実施する手順と、動的環境移行に伴う問題を減らす方法を説明します
2
3
Agenda
–マイコンプラットフォームの移行を始める前に!–移行を始めましょう!–C/C++コンパイラ移行の実際–アセンブラ移行の実際–リンカ移行の実際
はじめに• 半導体メーカが提供するGCCベースの開発環境は手軽に始めることが出来ますが、Armプロセッサを使用した組込み開発の利点を100%発揮する事は出来ない
4
Cortex-M4
FLASH
RAM
USART
I2C
GPIO
USBSDA社
Cortex-M4
FLASH
RAM
D/A
GPIO
A/D
EtherB社
Eclipse+CDTA社拡張
Eclipse+CDTB社拡張
Cortex-M4
FLASH
RAM
USART
I2C
GPIO
USBSD
Cortex-M4
FLASH
RAM
D/A
GPIO
A/D
Ether32ビットArmプロセッサを使用した組込み開発が半導体メーカに関係なく効率良く可能
マイコンプラットフォームの移行を始める前に!
5
IAR Embedded Workbench for ARMを使おう!
• IAR Embedded Workbench for ARM(EWARM)と評価ボードで動作確認を実施–評価ボードは、半導体メーカ各社から安価に販売され、インサーキットエミュレータ(ICE)を使わずに開発が可能
–多くの評価ボードには、ICEが内蔵されており、USBケーブルでホストパーソナルコンピュータに接続するだけ
•評価ボードの選択基準のポイントは、同一メーカー・型式のマイコンを選択する
•サンプルプログラムは、「Arm用IARインフォメーションセンタ」から、使用するメーカーのサンプルプログラムをダウンロードして、確認スタート!
6
マイコンプラットフォームの移行に伴う課題とは?
• マイコンプラットフォームの移行には、2種類の大きな課題を克服が必要
7
• C/C++、アセンブラソースコード、リンカ設定を適切に行い、ビルドが正常に出来る
C/C++ソースコード
アセンブラソースコード
C/C++コンパイラ
アセンブラ
実行オブジェクト
リンカ
リンカ設定ファイル
標準ライブラリ
ライブラリ
• 最適化の影響で、関数の処理時間が変化するので、タイミング設計の妥当性の検証が必要
コンパイラ性能の違いにより、実行時間が異なる
静的環境移行 動的環境移行
目標と手順を確認しましょう!
• 移行の具体的な実施内容を決め、少し余裕を持って期間を決めましょう!–エラーの対処は全て実施する–警告の対処は行うか?–スタートアップコードは移行するか?–割込みハンドラをC言語化するか?–アセンブラ関数をEWARMの組込み関数に置き換えるか?–コメントアウトや#if 0~#defを削除するか?
8
C/C++ソースコード移行完了
アセンブラソースコード移行完了
スタートアップコード追加
プロジェクト作成および設定完了
リンカによるメモリ配置移行完了
既存ソフトウェアの
調査
【プラットフォームの移行フロー】
移行を始める前に
• 移行する前に既存ソフトウェアに隠れた問題を確認
9
Cortex-M7
FLASH
ITCM
USARTI2C
GPIOUSBSD デバイスドライバ
ミドルウェア
アプリケーション
DTCM
• 設計書や評価結果を確認しても、機能追加や不適合修正を繰り返した、ソフトウェアの品質は把握出来ないが確認は必要!
1. 最適化設定値を変え、不安定な挙動を示さないか動作確認を実施
2. 個別ソースファイルのみ、最適化設定値が異なっていないか確認
3. 過去に修正時に、“このコードを消したら動作しないと”などのコメントが無いか確認
過去の経緯を理解する事は、移行を進める上で重要!
C/C++ソースコードの確認
• 修正を重ねたソースコードには、不要なコードが存在する事は、特別な事ではありませんが、把握する事は必要!
• GCCスタイル属性(__attribute__ ((attribute-list)))の一部は対応しているので、移行作業は不要– 詳細は、「IAR C/C++ 開発ガイド コンパイルおよびリンク」-「パート2. リファレンス情報」-「拡張キーワード」-「サポートされるGCC 属性」を参照
– 詳細は、付録のGCC スタイル属性(__attribute__ ((attribute-list)))を参照
• #pragmaディレクティブは、C/C++コンパイラ固有設定になりますので、使用状況を把握する事は必要!– 詳細は、「IAR C/C++ 開発ガイド コンパイルおよびリンク」-「パート2. リファレンス情報」-「拡張キーワード」-「プラグマディレクティブ」を参照
• 異なるフォルダに同一名ヘッダファイルが存在するか確認
10
アセンブラとスタートアップコードは?
• Cortex-Mシリーズの場合は、サンプルプログラムのスタートアップコードを使用する事がお勧め– CMSIS(Cortex Microcontroller Software Interface Standard)を使用o system_<DeviceName>.c/startup_<DeviceName>.s/<DeviceName>_it.co __ICC_ARM__の定義が既存スタートアップコードが分離されている場合、移行作業は必要無い
• Cortex-A/Rシリーズは、サンプルプログラムのスタートアップコードを使用する事がお勧め
• 既存スタートアップコードを使用する場合は、アセンブラディレクティブ、リンカ設定値を参照の変更およびC/C++コンパイラ初期化処理の変更する事が必要
• アセンブラソースコードを使用する場合は、アセンブラディレクティブの変更が必要
11
リンカ設定は?
• GCCのリンカスクリプトとEWARMのリンカ設定ファイルは互換性がありません• ハードウェアメモリマップからソフトウェアメモリマップを作成
– 例外ベクタテーブルの配置空間は決まっています– アプリケーションとconst型変数の配置– グローバル変数またはstatic型変数の配置– スタック配置とスタックサイズ– プログラムの実行はフラッシュメモリ実行かRAM実行か?
• はじめは、デフォルトのリンカ設定ファイルを使用がお勧め
12
ハードウェアメモリマップ
ソフトウェアメモリマップ
リンカ設定ファイル
ビルド環境に投資する• EWARMでは、並列ビルドをデフォルトで有効となるので、コア数が多いプロセッサを搭載する事はビルド時間短縮に有効!
• EWARMでは、デフォルト搭載コアの1/2コアをビルドに使用(IDEオプションで設定変更可能)
13
• ビルドを行う場合、ハードディスクへのアクセスが頻発しますので、Solid State Drive(SSD)を使用する事がお勧め!
ファイルアクセス速度向上でビルド時間が短縮!
欲を出さない
•マイコンプラットフォームの移行するのが最優先事項!•コメントアウトが一杯!だから...何とかしたい• #ifdef(#if)で不要なコードが一杯だから...何とかしたい•デバッグ用の変数が一杯だから...何とかしたい
14
移行を始めてましょう!
15
まずは、プロジェクトを作りましょう• Eclipseベースの開発環境は、プロジェクトフォルダ以下のフォルダイメージで、ビルドに必要な各種ファイルが自動登録されます
• EWARMでは、グループ機能を使用して、同様のプロジェクトを作成出来ます
• Eclipseでは、プロジェクトのフォルダとファイル構成が依存しますが、EWARMの場合は依存性はありません
• 移行する場合、フォルダイメージで作成する事をお勧めします
16
この設定は必ず実施!(1)• EWARMでは[セミホスティング]機能が搭載され、
C-SPYデバッガのターミナルにprintf()関数を使って表示する事が出来ますが、GCC環境の場合は使用する事が出来ません
• オプション設定の[一般オプション]-[低レベルインターフェースライブラリの実装(B)]-[無し(N)]を選択
17
この設定は必ず実施!(2)• 最適化設定値は、[無し]を選択する• オプション設定の[C/C++コンパイラ]-[最適化]-[レベル(E)]-[なし(N)]を選択
18
プリプロセッサシンボルの定義を設定19
• プリプロセッサシンボルの定義は、GCCコンパイラ設定の[Preprocessor]の設定で確認
インクルードフォルダの確認と設定• プロセッサ選択を正しく行う事で、コンパイラのコード生成の設定は行われます• インクルードファイルのパス、プリプロセッサシンボルの定義の設定の把握が必要
20
【 Eclipseベースの環境は設定内容を確認】 【make使用時はクリーンビルド結果を確認】
arm-none-eabi-gcc -mcpu=cortex-a9 -march=armv7-a -marm -mlittle-endian -mfloat-hardIn file included from C:/Workspace/Migration/iodefine/iodefine.h:48:0,
from ../generate/drivers/cpg/src/lld/cpg_lld.c:39:
arm-none-eabi-gcc -mcpu=cortex-a9 -march=armv7-a -marm -mlittle-endian -mfloat-abi=hardarm-none-eabi-gcc -mcpu=cortex-a9 -march=armv7-a -marm -mlittle-endian -mfloat-abi=hardIn file included from C:/Workspace/Migration/generate/system/inc/devlink_wrapper.h:67:0,
from C:/Workspace/Migration/generate/drivers/cpg/inc/cpg_lld.h:31,from C:/Workspace/Migration/generate/drivers/cpg/inc/cpg_drv_link.h:32,from ../generate/drivers/r_cpg/src/hld/r_cpg_drv_api.c:32:
'Building file: ../generate/compiler/init/_exit.c''Building file: ../generate/compiler/init/_kill.c''Invoking: Cross ARM C++ Compiler'arm-none-eabi-gcc -mcpu=cortex-a9 -march=armv7-a -marm -mlittle-endian -mfloat-abi=hard'Invoking: Cross ARM C++ Compiler'arm-none-eabi-gcc -mcpu=cortex-a9 -march=armv7-a -marm -mlittle-endian -mfloat-abi=hardIn file included from C:/Workspace/Migration/generate/system/iodefine/iodefine.h:64:0,
from ../generate/drivers/r_cache/src/lld/cache_lld.c:33:
• コンパイラオプション設定– -I:インクルードファイルのパス– -D:プリプロセッサシンボルの定義
C/C++コンパイラ移行の実際
21
環境移行の始めの一歩(1)• メイクを実行し、エラー発生状態を確認します
22
エラーの合計数: 289 ワーニングの合計数: 1
環境移行の始めの一歩(2)• アセンブラソースファイルを除外して、再ビルドを実施
23
エラーの合計数: 11 ワーニングの合計数: 1
環境移行の始めの一歩(3)• [致命的なエラー[Pe1696]: cannot open source file]の解消を実施する
24
環境移行の始めの一歩(4)• GCCコンパイルオプションに、-v(Verbose)オプション追加し、ビルド実行でヘッダファイルサーチパスを確認
25
gcc version 7.3.1 20180622 (release) [ARM/embedded-7-branch revision 261907] (GNU Tools for STM32 7-2018-......#include "..." search starts here:#include <...> search starts here:../Inc../Drivers/CMSIS/Include../Drivers/STM32F4xx_HAL_Driver/Inc../Drivers/CMSIS/Device/ST/STM32F4xx/Include../Drivers/STM32F4xx_HAL_Driver/Inc/Legacyc:¥gcc version 731 20180622¥tools¥bin¥../arm-none-eabi/include/newlib-nanoc:¥gcc version 731 20180622¥tools¥bin¥../lib/gcc/arm-none-eabi/7.3.1/includec:¥gcc version 731 20180622¥tools¥bin¥../lib/gcc/arm-none-eabi/7.3.1/include-fixedc:¥gcc version 731 20180622¥tools¥bin¥../lib/gcc/arm-none-eabi/7.3.1/../../../../arm-none-eabi/includeEnd of search list....
【-vオプション設定ビルド結果】
ユーザ定義ヘッダファイルパス
コンパイラヘッダファイルパス
環境移行の始めの一歩(5)• [sys/stat.h]ヘッダファイルとは何か?
– ファイルのステータスとディレクトリの関数で使用されるヘッダファイルで、C言語の標準関数を定義していません
– 本ヘッダファイルは、IAR C/C++コンパイラには含まれていません
• EWARMに含まれていないヘッダファイルで機能としては不要です
• ビルドを除外するには、[syscalls.c]ソースファイルを選択し、右クリックでメニューを表示し、[ビルドから除外]を設定します
26
環境移行の始めの一歩(6)• [system.c]ソースファイルは、エラー内容を確認すると、_sbrk()に関連する実装を行っていることが理解出来ます。
• [system.c]ソースファイルは、ビルド対処外と判断します– _sbrk()関数は、メモリ確保を行う場合に使用される
– caddr_tの定義は、[sys/type.h]で定義されており、該当ヘッダファイルはIAR C/C++コンパイラでは対応していません
– register char * stack_ptr asm(“sp”)及びextern char end asm(“end”)の実装はGCC独自実装
27
ポインタは注意
• ポインタの検査が厳しいので、明示的な型変換が必要
28
【GCCコンパイラ】 【IAR C/C++コンパイラ】void func(void);typedef struct{
int32_t mode;...void * function;
} st_config_t;
const st_config_t config_table[] ={
10,...func
};
void func(void);typedef struct{
int32_t mode;...void * function;
} st_config_t;
const st_config_t config_table[] ={
10,...(void *)func
};
const型は注意
• const型ポインタの使用時は注意が必要
29
【GCCコンパイラ】 【IAR C/C++コンパイラ】const char ss[10]={1,2,3,4,5,6,7,8,9};
int main( void ){}
void func( char *s ){...}
const char ss[10]={1,2,3,4,5,6,7,8,9};
int main( void ){}
void func( const char *s ){...}
const型に型変換は禁止!
配列の注意点
• 配列の定義の要素定義が無い場合は、’NULL’が必要です
30
【GCCコンパイラ】 【IAR C/C++コンパイラ】typedef struct{
int32_t mode;...void * function;
} st_config_t;
const st_config_t table[] ={};
const char sss[10]={};char ttt[10]={};
typedef struct{
int32_t mode;...void * function;
} st_config_t;
const st_config_t table[] ={
NULL};
const char sss[10]={NULL};char ttt[10]={NULL};
GCC属性は対応済み
• GCC属性設定の一部は、オプション設定の「C/C++ Compiler」-「Language 1」-「Language conformance」の設定の「Standard with IAR extensions」を選択する事で「__attribute__ ((attribute-list))」の設定属性をサポート
alias aligned always_inline constructor
deprecated noinline noreturn packed
pcs section target transparent_union
unused used volatile weak
31
※:GCC属性の対応状況に関しては、「IAR C/C++ 開発ガイド コンパイルおよびリンク」でご確認ください
cmse_nonsecure_call cmse_nonsecure_entry
アセンブラ移行の実際
32
アセンブラソースは最初に移行しない• アセンブラで使用するアセンブラディレクティブの互換性が無く、大量のエラーが発生する
33
約450行のアセンブラソースコードに対して、「257エラー、0ワーニング」の結果
置き換える事で対応可能!
• IARアセンブラディレクティブに置き換える事で対処
34
GNUアセンブラディレクティブ
IARアセンブラディレクティブ 対処方法および機能概要
.arm ARM Arm(32ビット)命令を生成します.thumb THUMB Thumb命令(32/16ビット)命令を生成します
#または@ //または; 単一行コメント.section section セクション設定(リンカとの設定連携が必要).global PUBLIC 他のモジュールにシンボルをエクスポートします.weak EXTWEAK 外部シンボルをインポートします。シンボルは定義できませ.align ALIGNRAM プログラムロケーションカウンタをインクリメントして境界整列します.ascii DC8 文字列を含め 8 ビットの定数を生成します.word DCD 32ビットデータを配置する.weak PUBWEAK 他のモジュールにシンボルをエクスポートし複数の定義が許可されます。.end END ソースファイルの最後を指定します
削除と修正する事で対処可能!
• IARアセンブラで対応してない、アセンブラディレクティブは削除します
35
GNUアセンブラディレクティブ
.type
.func.endfunc.LTORG
• ‘.EQU’ディレクティブは修正– .EQU’ディレクティブは、モジュール内にローカルな値を割り当てます
– 宣言されたアセンブラソースコード内で、USR_MODEを使用した場合、0x10にアセンブラが置き換えてオブジェクトを生成します
– ‘,’と’.’を削除し、入れ替えを行う事で対処可能
.EQU USR_MODE, 0x10
USR_MODE EQU 0x10
main()関数を呼び出すまでの処理は異なる• リセットハンドラは処理内容が異なる
36
【GCCリセットハンドラ】 【IARリセットハンドラ】.section .text.Reset_Handler
Reset_Handler: ldr sp, =_estack /* set stack pointer */movs r1, #0 /* Copy the data segmentinitializers */
...CopyDataInit:
ldr r3, =_sidata... LoopCopyDataInit:
ldr r0, =_sdata...FillZerobss:...
bl mainbx lr
....section .isr_vector,"a",%progbits
g_pfnVectors:.word _estack.word Reset_Handler.word NMI_Handle
SECTION CSTACK:DATA:NOROOT(3)SECTION .intvec:CODE:NOROOT(2)
EXTERN __iar_program_startEXTERN SystemInitPUBLIC __vector_table
DATA__vector_table
DCD sfe(CSTACK)DCD Reset_Handler ; Reset HandlerDCD NMI_Handler ; NMI Handler
THUMBPUBWEAK Reset_HandlerSECTION .text:CODE:REORDER:NOROOT(2)
Reset_Handler
LDR R0, =SystemInitBLX R0LDR R0, =__iar_program_startBX R0
リンカスクリプトのスタック最終アドレスを取得
変数の初期化を行います
リンカ設定ファイルのスタック最終アドレスを取得
main()関数を呼び出し
変数の初期化後に、main()関数を呼び出し
リンカ移行の実際
37
まずは、デフォルトのリンカ設定ファイルを使う• 使用するプロセッサによって、移行方法が異なります
38
Cortex-MGPIOUARTPWMQSPI
FlashROM
RAM
• 内蔵フラッシュメモリのみで動作する場合は、デフォルトのリンカ設定ファイルを使用します
• IAR C/C++コンパイラは、コード効率が良いので、GCCで作成したサイズを超える事はありません
オブジェクト
Cortex-A
BSC
UARTQSPI
BootROM
RAM
オブジェクト
RAM
ROM
• オブジェクトがダウンロード出来るRAMエリアを使用して、デバッグを行います
• フラッシュROMで起動を行い、RAMで実行する場合のリンカ設定は、RAM実行を確認後!
GCCのスタックサイズの設定は?• GCCスタックサイズは、リンカスクリプトの設定で行います
39
/* Entry Point */ENTRY(Reset_Handler)
/* Highest address of the user mode stack */_estack = 0x20018000; /* end of "RAM" Ram type memory */
_Min_Heap_Size = 0x200; /* required amount of heap */_Min_Stack_Size= 0x400; /* required amount of stack */
/* Memories definition */MEMORY{
RAM (xrw):ORIGIN = 0x20000000,LENGTH = 96KFLASH (rx) :ORIGIN = 0x8000000, LENGTH = 512K
}...
スタックおよびヒープサイズ設定
RAM領域の最終アドレス設定
EWARMのスタックサイズの設定は?• オプション設定の[リンカ]-[設定]を選択し、
[リンカ設定ファイル]-[デフォルトのオーバライド]を有効にし、デフォルトファイルをプロジェクトフォルダにコピーし選択します
• [編集(E)...]ボタンをクリックし、スタックサイズとヒープサイズを設定します
• 設定後、[保存]ボタンをクリックします
40
41
Summary• 移行を行う時にすべき事を理解する事は重要• プロジェクトの作成からC/C++コンパイラ、アセンブラ、リンカの移行ポイントを理解
• プラットフォーム移行を不安と思うより、明日からでも始める事が重要!