gccとリンカスクリプト(ld)のメモ [仕事とプログラムのハナシ]
自分用めも。
【前提】
組み込み。
STM32(ARMコアのMCU)に、OSなしでファームを載せる。
ツールチェーンはお馴染みの開発環境Sourcery G++ lite (arm-none-eabi-gcc などが一式入ったやつ )を使う。
プロジェクトは複数のソースファイルで構成。
ぜんぶをビルドして、ひとつのelfファイルにまとめる。
(motでもhexでもいいんだけど)
【やりたいこと】
main.c
aaa.c
bbb.c
のうち、bbbだけ別領域に配置したい。
mainとaaaはごく普通にFlash ROMに配置、
bbb.cは外付けメモリに配置、みたいに。
マイコン徹底入門さんのプロジェクトとかを参考にしてると、全部Flash ROMに置いてるんじゃないかな??(←未確認)
少なくとも私が参考にしたところ(別サイト)は、そうだった。
【やろうとして失敗したこと】
配置を決めるなら、bbb.cだけ違うセクションにしてやれば、簡単にリンカスクリプトで配置できるんじゃね?
↓
各関数に__attribute__((section("xxx")))をつければ、それを付けた関数は.textセクションじゃなくなることを確認。
変数も同様にセクション変更可能なことを確認。
でも、.rodata(ソースべた書きの文字列とか定数とか)がうまく変更できない。
なんとかこのファイルだけセクション変更したいのに.rodataはどうやればいいのー??
gccのオプションで変更できたりしないのー??
↓
って考えたのがそもそもの間違いだった。
ぐぐってたら、ファイル単位で云々したいならリンカスクリプトのマニュアルをあたれって書かれてた。
【じゃあどうしろっての?】
リンカスクリプトのマニュアル、ざーっと読む。
そしたら、すごく簡単で拍子抜け。。。
※以下、リンカスクリプト。
記載していない部分でFlash ROMや外付けメモリのアドレス、サイズは定義済み。
みたいになってると思うので
ってするだけ。
bbb.cのソースで__attribute__使う必要なんて全くない。元に戻そう。
【ざっくり過ぎる解説】
*(.text) が、全ファイルの.textセクションという意味なんだって。
(カッコ前のアスタリスクが、ファイル名ワイルドカードになってる)
で、そこより前に bbb.o(.text) と書いて、bbb.oの.textセクションを配置しちゃう。
(カッコ前がファイル名、ここはldに渡されるファイル名なので.oで指定)
*(.text) に来たときは、すでにbbbは配置済みだから、未配置の全ファイルがここで配置される。
.rodataも同じ要領でおけ。
ソース側でセクション名変更しようとしてた自分がばかだったよ、ほんとに。
【教訓】
環境やツールをよく理解しましょう(←当たり前、しかもまだ理解しきってない)
【余談】
リンク時にガーベージコレクションのオプションをいれてあると、使ってないセクションが消されちゃうので・・・
それぞれKEEPで括っとくといいかも。
bbb.o(.text) → KEEP(bbb.o(.text))
*(.text) → KEEP(*(.text))
みたいに。.rodataも同じ要領でおけ。
以上、自分用めもでした。
【前提】
組み込み。
STM32(ARMコアのMCU)に、OSなしでファームを載せる。
ツールチェーンはお馴染みの開発環境Sourcery G++ lite (arm-none-eabi-gcc などが一式入ったやつ )を使う。
プロジェクトは複数のソースファイルで構成。
ぜんぶをビルドして、ひとつのelfファイルにまとめる。
(motでもhexでもいいんだけど)
【やりたいこと】
main.c
aaa.c
bbb.c
のうち、bbbだけ別領域に配置したい。
mainとaaaはごく普通にFlash ROMに配置、
bbb.cは外付けメモリに配置、みたいに。
マイコン徹底入門さんのプロジェクトとかを参考にしてると、全部Flash ROMに置いてるんじゃないかな??(←未確認)
少なくとも私が参考にしたところ(別サイト)は、そうだった。
【やろうとして失敗したこと】
配置を決めるなら、bbb.cだけ違うセクションにしてやれば、簡単にリンカスクリプトで配置できるんじゃね?
↓
各関数に__attribute__((section("xxx")))をつければ、それを付けた関数は.textセクションじゃなくなることを確認。
変数も同様にセクション変更可能なことを確認。
でも、.rodata(ソースべた書きの文字列とか定数とか)がうまく変更できない。
なんとかこのファイルだけセクション変更したいのに.rodataはどうやればいいのー??
gccのオプションで変更できたりしないのー??
↓
って考えたのがそもそもの間違いだった。
ぐぐってたら、ファイル単位で云々したいならリンカスクリプトのマニュアルをあたれって書かれてた。
【じゃあどうしろっての?】
リンカスクリプトのマニュアル、ざーっと読む。
そしたら、すごく簡単で拍子抜け。。。
※以下、リンカスクリプト。
記載していない部分でFlash ROMや外付けメモリのアドレス、サイズは定義済み。
SECTIONS
{
.text :
{
.=ALIGN(4);
*(.text)
*(.text.*)
*(.rodata)
*(.rodata.*)
.=ALIGN(4) ;
} >FLASH
みたいになってると思うので
SECTIONS
{
.sample :
{
.=ALIGN(4) ;
bbb.o(.text)
bbb.o(.text.*)
bbb.o(.rodata)
bbb.o(.rodata.*)
.=ALIGN(4) ;
} >EXT_MEM
.text :
{
.=ALIGN(4);
*(.text)
*(.text.*)
*(.rodata)
*(.rodata.*)
.=ALIGN(4) ;
} >FLASH
ってするだけ。
bbb.cのソースで__attribute__使う必要なんて全くない。元に戻そう。
【ざっくり過ぎる解説】
*(.text) が、全ファイルの.textセクションという意味なんだって。
(カッコ前のアスタリスクが、ファイル名ワイルドカードになってる)
で、そこより前に bbb.o(.text) と書いて、bbb.oの.textセクションを配置しちゃう。
(カッコ前がファイル名、ここはldに渡されるファイル名なので.oで指定)
*(.text) に来たときは、すでにbbbは配置済みだから、未配置の全ファイルがここで配置される。
.rodataも同じ要領でおけ。
ソース側でセクション名変更しようとしてた自分がばかだったよ、ほんとに。
【教訓】
環境やツールをよく理解しましょう(←当たり前、しかもまだ理解しきってない)
【余談】
リンク時にガーベージコレクションのオプションをいれてあると、使ってないセクションが消されちゃうので・・・
それぞれKEEPで括っとくといいかも。
bbb.o(.text) → KEEP(bbb.o(.text))
*(.text) → KEEP(*(.text))
みたいに。.rodataも同じ要領でおけ。
以上、自分用めもでした。
2012-07-10 23:55
nice!(0)
コメント(1)
トラックバック(0)
ldの記事を探していたら偶然探しあてました。
マニュアルを読んで直ぐに分かるのがウラヤマシイです。
他の記事も参考にさせてもらいます。
ロボット遊びで使う予定です。
ターゲットはSH4を考えていますが、
購入出来るか予算の関係で未定です。
私は後期高齢に近い高齢者です。
by ポンチャン (2016-10-24 06:09)