2017年6月21日水曜日

りはびり:02

前回の続き。
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 件のコメント:

コメントを投稿