gcc 標準ライブラリー libc.a の改造

SH-2A には USB が内臓なのだが、こいつと通信する為には、色々なスタックを実装する必要がある、ソースコードも公開されているのだが、色々ハマりそうと考えて、とりあえず、シリアルインターフェースを繋げる事にした。

最近のPCには、シリアルポートはまず無いので、USB-シリアルのブリッジを使う。
秋月電子で、FT232を使った格安なモジュールを売っている。
FT232 モジュール

とりあえず、これを繋いで、シリアルコンソールに文字を出す事が出来た。
でも、サンプルのコードはポーリングなので、割り込み処理にしないと実用性が無いな・・・

FT-232 USB シリアル

とりあえず、本格的なシリアルドライバーは後回しで、gcc の標準ライブラリーに細工する時が来た~

まず、重要なのは、記憶割り当てを行う「malloc」関数群、色々調べると、syscallsモジュールに、「_sbrk」という関数があり、「malloc」は、この低レベルメモリー割り当てを呼ぶ、通常は、シンボル「end」から、スタックの間のメモリー空間を使って、そこに記憶割り当て空間を作り、そこで記憶割り当てを行うのだが、それは、多少まずい、そこで、以下のように改修した。

caddr_t _sbrk (int incr)
{
extern char alloc_top;
extern char alloc_end;
static char *heap_end;
char *prev_heap_end;

if(heap_end == 0) {
heap_end = &alloc_top;
}

prev_heap_end = heap_end;
if((heap_end + incr) >= &alloc_end) {

CPU_UartPuts("Heap and Stack Collision occured...\n");
// abort();
return (caddr_t)NULL;
}
heap_end += incr;
return (caddr_t)prev_heap_end;
}

「alloc_top」、「alloc_end」は、独自のセクションで領域を割り当てていて、この空間内で、メモリーのアロケーションを行う。

※startup.s
.section .MEMALLOC, "w"
.align
.global _alloc_top
_alloc_top:
.space 65536
.global _alloc_end
_alloc_end:

現在は仮に65536バイト確保してある。

※リンク情報
.bss (NOLOAD) :
{
__bss_start__ = . ;
*(.bss)
*(.bss.*)
*(COMMON)
*(.got.*)
. = ALIGN(4);
__bss_end__ = . ;
_end = . ;
} > TRAM

.memalloc (NOLOAD) :
{
. = ALIGN(4);
__alloc_start__ = . ;
*(.MEMALLOC)
__alloc_end__ = . ;
} > TRAM

.stack (NOLOAD) :
{
__stack_start__ = . ;
*(.STACK)
*(.stack)
. = ALIGN(4);
__stack_end__ = . ;
} > TRAM

syscalls のモジュールは、通常、libc.a にアーカイブされているので、sh-elf-arコマンドを使い、オリジナルのlibc.aから、syscallsモジュールを削除しておいた。

リンクする場合、元のsyscalls内の関数全てを実装する必要があるので、とりあえず、ダミー関数を入れておいた。

次は、stdout、stdin、stderrなどファイル関係のサポートだな。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください