LoginSignup
2
2

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-09-19

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()が使えるようになりました。

参考にしたページ

2
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2