「NUCLEO-F401RE で TOPPERS/ASP(RTOS)を動かす」を参考に、TrueSTUDIOでいろいろいじっている最中、sprintf()を使おうとしたらコンパイルエラーが発生。
いろいろ調べて試した結果、根本的な解決ではないとは思われますが、とりあえずsprintf()は動作したのでメモとして作業内容を書き留めます。
まず具体的なエラーの内容ですが、
c:/program files (x86)/atollic/truestudio for arm 5.5.2/armtools/bin/../lib/gcc/arm-atollic-eabi/5.3.1/../../../../arm-atollic-eabi/lib/armv7e-m/softfp\libc.a(lib_a-mallocr.o): In function `_malloc_r':
makefile:349: recipe for target 'asp.elf' failed
mallocr.c:(.text._malloc_r+0x42c): undefined reference to `malloc_getpagesize_P'
mallocr.c:(.text._malloc_r+0x43c): undefined reference to `malloc_getpagesize_P'
c:/program files (x86)/atollic/truestudio for arm 5.5.2/armtools/bin/../lib/gcc/arm-atollic-eabi/5.3.1/../../../../arm-atollic-eabi/lib/armv7e-m/softfp\libc.a(lib_a-sbrkr.o): In function `_sbrk_r':
sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk'
c:/program files (x86)/atollic/truestudio for arm 5.5.2/armtools/bin/../lib/gcc/arm-atollic-eabi/5.3.1/../../../../arm-atollic-eabi/lib/armv7e-m/softfp\libc.a(lib_a-freer.o): In function `_malloc_trim_r':
mallocr.c:(.text._malloc_trim_r+0xa8): undefined reference to `malloc_getpagesize_P'
collect2.exe: error: ld returned 1 exit status
make: *** [asp.elf] Error 1
という具合で、ライブラリのビルドでエラーが出ています。
一つが「malloc_getpagesize_P」が未定義というもの。
詳しくはよくわかりませんが調べてみると、mallocで取得するメモリサイズの定義らしく、Makefileの中のLDFLAGSの行に、-Wlに続くオプションを追加しました。
#
# 共通コンパイルオプションの定義
#
COPTS := $(COPTS) -g -MD
ifndef OMIT_WARNING_ALL
COPTS := $(COPTS) -Wall
endif
ifndef OMIT_OPTIMIZATION
COPTS := $(COPTS) -O2
endif
CDEFS := $(CDEFS)
INCLUDES := -I. -I$(SRCDIR)/include -I$(SRCDIR)/arch -I$(SRCDIR) $(INCLUDES)
LDFLAGS := $(LDFLAGS) -Wl,--defsym=malloc_getpagesize_P=0x1000
CFG1_OUT_LDFLAGS := $(CFG1_OUT_LDFLAGS)
LIBS := $(LIBS) $(CXXLIBS)
CFLAGS = $(COPTS) $(CDEFS) $(INCLUDES)
P=0x1000は4kbyteのメモリを割り当てるという意味なのですが、多すぎる場合は0x80(128byte)とか適宜変更します。
もう一つのエラーが「_sbrk」が未定義というもの。
これも調べてみると「syscall.c」という処理を加えると良いらしいということが分かったので、その中の_sbrkに関する部分だけをソースに加えました。
ヘッダのインクルード、プロトタイプ宣言、および_sbrkの処理をそれぞれ適切な場所に追加。
#include <stdlib.h>
#include <errno.h>
#include <string.h>
caddr_t _sbrk_r (struct _reent *r, int incr);
/* Register name faking - works in collusion with the linker. */
register char * stack_ptr asm ("sp");
caddr_t _sbrk_r (struct _reent *r, int incr)
{
extern char end asm ("end"); /* Defined by the linker. */
static char * heap_end;
char * prev_heap_end;
if (heap_end == NULL)
heap_end = & end;
prev_heap_end = heap_end;
if (heap_end + incr > stack_ptr)
{
/* Some of the libstdc++-v3 tests rely upon detecting
out of memory errors, so do not abort here. */
#if 0
extern void abort (void);
_write (1, "_sbrk: Heap and stack collision\n", 32);
abort ();
#else
errno = ENOMEM;
return (caddr_t) -1;
#endif
}
heap_end += incr;
return (caddr_t) prev_heap_end;
}
これで無事sprintf()が使えるようになりました。
参考にしたページ
-
[26.なぜプロジェクトをリンクしているときに 'Undefined reference to malloc_getpagesize_P'が表示されますか?]
(https://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0ahUKEwj_sNOukZvPAhUQ2GMKHZiiBjoQFggfMAA&url=http%3A%2F%2Fwww2012ua.sakura.ne.jp%2Ftop-slider%2F25-2011-11-26-02-30-49%2Fatollic%2F1463-26-undefined-reference-to-mallocgetpagesizep.html&usg=AFQjCNFRfzmRHJ6S_VexIodCGzdObGuvcA&sig2=W6OI882GI_QR2d0BklMO5w) -
[STM32技術解説/007 atof()を使うとundefined reference to _sbrkというエラーがでる対処]
(https://sites.google.com/site/stm32datasheet/home/howto-programming/007-undefined-sbrk)