TrueSTUDIOforARMにおけるsprintf()のコンパイルエラー

「[NUCLEO-F401RE で TOPPERS/ASP(RTOS)を動かす](http://qiita.com/exshonda/items/bf691541526975b8f78c)」を参考に、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)