Top > STM32F >リンカスクリプト

メモリマップ

 ここでは、例としてSTM32F103x8Bのリンカスクリプトを作ることを考えます。 右の図がSTM32F103x8Bのメモリマップです。メモリは8つのブロックに分けられ、 外部バスを持つデバイスでは、3〜4の空きブロックに外部メモリを割り当てることが可能です。


リンカスクリプト

リンカスクリプトは、STマイクロのサンプルプログラムに同梱されている

STM32F10x_StdPeriph_Lib_V3.3.0 Project\STM32F10x_StdPeriph_Template\RIDE\stm32f10x_flash_extsram.ld

を必要に応じて修正して使っています。入出力セクションの関係を表にしてみました。 MEMORY定義とARM.extab,ARM.exidxを修正・追加しています。 ARM.extab,ARM.exidxはnewlibを使うときに必要となるセクションで、 例外処理のために使われているらしいです。 なお、アドレス欄の赤文字は開始アドレス、 青文字は終了アドレスを表しています。

memoryoutputinputaddressinformation
Flash.isr_vector.isr_vector 0x08000000割り込みベクタ領域
.text.text
コード領域
.text.*
その他のコード領域
.rodata
定数データ
.rodata.*
その他の定数データ
.glue_7
ARMインターワーキング用?
.glue_7.*
-
.ARM.extab.ARM.extab*
例外テーブル(newlib)
.gnu.linkonce.armextab.*
.ARM.exidx.ARM.exidx* __exidx_start
__exidx_end, _etext
例外インデックス(newlib)
.gnu.linkonce.armexidx.*


_sidata.dataの初期値
RAM.data.data 0x20000000, _sdata
_edata
初期化子を持つ変数
.data.*-
.bss.bss _sbss, _bss_start
_ebss, __bss_end
初期化子を持たない変数
COMMONコモンシンボル。
._usrstack
_susrstack
_eusrstack
スタック予約領域。_Minimum_Stack_Sizeが確保できなくなるとリンカエラーが出る。


0x200007ff, _estackスタックの底

以下、リンカスクリプト本体です。デバッグ関連のセクションについては省略しています。 デバッガ関連については、おいおい調査したいと思います。

リンカスクリプト
/* デフォルトのスタックサイズ */
__Stack_Size = 1024 ;

/* _Stack_Size の弱い定義(プログラムで上書き可能) */
PROVIDE ( _Stack_Size = __Stack_Size ) ;

/* スタックの開始アドレス */
__Stack_Init = _estack  - __Stack_Size ;

/* _Stack_Init の弱い定義 */
PROVIDE ( _Stack_Init = __Stack_Init ) ;

/* スタックサイズが以下を下回ったときにリンカエラーを出すようにする */
_Minimum_Stack_Size = 0x100 ;

/* Flash領域とRAM領域を定義します(以下はSTM32F10x用) */
MEMORY
{
	RAM (xrw)	: ORIGIN = 0x20000000, LENGTH = 20k
	FLASH (rx)	: ORIGIN = 0x08000000, LENGTH = 64k
}

/* スタックの底のアドレス(RAM領域の終端)を _estack に設定 */
_estack = 0x20000000 + 20k;

/* プログラムセクション定義 */
SECTIONS
{
	/* Cortexデバイス用スタートアップ、割り込みベクタのセクション */
	.isr_vector :
	{
		. = ALIGN(4);
		KEEP(*(.isr_vector))	/* Startup code */
		. = ALIGN(4);
	} >FLASH
 
	/* プログラムセクション */
	.text :
	{
		. = ALIGN(4);
		*(.text)				/* コードセクション */
		*(.text.*)
		*(.rodata)				/* 定数データ */
		*(.rodata*)
		*(.glue_7)				/* インターワーキング用? */
		*(.glue_7t)
		. = ALIGN(4);
	} >FLASH

	/* 標準ライブラリで使用するセクション */
	.ARM.extab :
	{
		*(.ARM.extab* .gnu.linkonce.armextab.*)
	} >FLASH
	
	__exidx_start = .;
	.ARM.exidx :
	{
		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
	} >FLASH
	__exidx_end = .;
	
	/* コードセクションの終端、.dataの初期化データ領域の開始位置 */
	_etext = .;
	_sidata = _etext;
	
	/* 初期化データを持つ変数領域 */
	/* スタートアップ内で初期化データがコピーされます */
	.data  : AT ( _sidata )
	{
		. = ALIGN(4);
		_sdata = . ;		/* スタートアップ内で参照 */
		*(.data)
		*(.data.*)
		. = ALIGN(4);
		 _edata = . ;		/* スタートアップ内で参照 */
	} >RAM

	/* 初期化子を持たない変数領域 */
	.bss :
	{
		. = ALIGN(4);
		_sbss = .;			/* スタートアップ内で参照 */
		__bss_start__ = .;
		*(.bss)
		*(COMMON)
		. = ALIGN(4);
		 _ebss = . ;		/* スタートアップ内で参照 */
		 __bss_end__ = . ;
	} >RAM

	PROVIDE ( end = _ebss );
	PROVIDE ( _end = _ebss );

	/* 残りスタック領域 */
	/* MinStackSizeより小さい場合はリンカエラーを出します */
	._usrstack :
	{
		. = ALIGN(4);
		_susrstack = . ;
		. = . + _Minimum_Stack_Size ;
		. = ALIGN(4);
		_eusrstack = . ;
	} >RAM

	/* remove the debugging information from the standard libraries */
	DISCARD :
	{
		libc.a ( * )
		libm.a ( * )
		libgcc.a ( * )
	}
}