前回の続き。
main.cをコンパイルしたらエラーになる話。
> arm-none-eabi-gcc.exe main.c -o main
arm-none-eabi/lib\libc.a(lib_a-exit.o): In function `exit':
exit.c:(.text.exit+0x2c): undefined reference to `_exit'
collect2.exe: error: ld returned 1 exit status
この_exitは参照した覚えがない。
C言語の勉強をすると、ほぼ必ず、「C言語はmain関数から始まります」と教えられる。
基本的にはそれで正しいのだと思うけれど、組み込みC言語の目線では正しくない。
組み込みの世界ではmain関数を呼び出すためのスタートアップルーチンという裏方さんに、どんな仕事をしてほしいか、きっちり教えて上げる必要がある。
教育の機会に恵まれない裏方さんは、とりあえず万人向けの仕事をしようとする。その仕事の一つが_exitという処理なのだ(難しい話なので抽象化して書いてます)。
ひとまず、裏方さんには大人しくしていて貰いたいので、「-nostartfiles」というオプションをつけてコンパイルしてみます。このオプションについてはgccの公式ページを見てください。
>arm-none-eabi-gcc main.c -o main.o -nostartfiles
arm-none-eabi/bin/ld.exe: warning: cannot find entry symbol _start; defaulting to 00008000
今度はwarningが発生しています。_startのエントリがないので、デフォルトの00008000にするよ、というメッセージです。
何を言っているのか、分かりませんね。
うまく説明できないので強引に対策だけいうと、リンカスクリプトをオプションで指定します。
「-T ./STM32F405RGT6.ld」です。
STM32F405RGT6.ld ファイルは、ねむいさんが公開されているサンプルコードから流用させてもらいました。STマイクロのサンプルコード集にも別マイコン用のリンカスクリプトがあるので、それをもとに自分で作れる人は頑張ってください。
ちなみに、「STM32F405RGT6.ld」は内部で「STM32F40_41xxx_FLASH.ld」を呼び出しているので、同じフォルダにおいておきます。
>arm-none-eabi-gcc main.c -o main.o -nostartfiles -T ./STM32F405RGT6.ld
ひとまずエラーはでなくなった。
最後に、main.oをgccが出力する実行形式のelf形式に変換します。
>arm-none-eabi-gcc -nostartfiles -T ./STM32F405RGT6.ld main.o -o main.elf
今日はここまで。
エラーが出なくなったからって、動くものが出来たわけではないのが、組み込みの怖いところ。(笑)
0 件のコメント:
コメントを投稿