2012-05-06 23 views
14

私はARM Cortex-M3(NXPのLCP17xx)用のコードを作成しています。私は今まで静的メモリを使用してきており、すべてがうまくいきました。動的メモリサポートを追加しようとしましたが、mallocを呼び出すと、システムが停止します。ARM Cortex-M3でのnewlibのmallocの使用

私は、裸の金属のためにgccでコンパイルしており、newlibを使用しています。バージョン:gcc-arm-none-eabi-4_6-2012q1

mallocサポートを追加するには、単純な_sbrk関数を実装し、リンカースクリプトを変更してヒープのスペースを確保しました(これについて多くのチュートリアルを読んでいます私は次に遭遇する問題をカバーしていません)。

いくつかのLEDの助けを借りて、mallocというコードが実行されるまでコードが実行されているとは限りません。それは私の_sbrk機能にも達しません。また、後でmallocへの呼び出しをコードに含めると、sizeofへの呼び出しで停止することがあります。

mallocを呼び出すと、コードが_sbrkに届かずに戻ったり返ったりすることなく止まってしまったらどうしたらいいですか?

mallocコールが含まれているときに生成されたメモリマップにしばらくお待ちしてから、それがない場合は、mallocで使用されている構造に関係していると思われます。

これはRAMメモリを定義LDスクリプトの一部である:

.bss : 
{ 
    _start_bss = .; 
    *(.bss) 
    *(COMMON) 
    _ebss = .; 
    . = ALIGN (8); 
    _end = .; 
} >sram 
. = ALIGN(4); 
_end_bss = .; 
. = ALIGN(256); 
_start_heap = .; 
PROVIDE(__cs3_heap_start = _start_heap) 

_end_stack = 0x10008000; 

_end_stackは、割り込みベクタテーブルに設定されています。

これで異なるマップの比較ができました。コード内でmallocを使用

*(COMMON) 
      0x1000000c    _ebss = . 
      0x10000010    . = ALIGN (0x8) 
*fill*  0x1000000c  0x4 00 
      0x10000010    _end = . 
      0x10000010    . = ALIGN (0x4) 
      0x10000010    _end_bss = . 
      0x10000100    . = ALIGN (0x100) 
      0x10000100    _start_heap = . 

メモリマップ:コード内でのmalloc使用しなくてもそう

*(COMMON) 
COMMON  0x10000848  0x4 ...arm-none-eabi/lib/armv7-m/libc.a(lib_a-reent.o) 
      0x10000848    errno 
      0x1000084c    _ebss = . 
      0x10000850    . = ALIGN (0x8) 
*fill*  0x1000084c  0x4 00 
      0x10000850    _end = . 

.bss.__malloc_max_total_mem 
      0x10000850  0x4 
.bss.__malloc_max_total_mem 
      0x10000850  0x4 ...arm-none-eabi/lib/armv7-m/libc.a(lib_a-mallocr.o) 
      0x10000850    __malloc_max_total_mem 

(...) It goes on (...) 
      0x1000085c    __malloc_current_mallinfo 
      0x10000884    . = ALIGN (0x4) 
      0x10000884    _end_bss = . 
      0x10000900    . = ALIGN (0x100) 
      0x10000900    _start_heap = . 
+0

起動コードを適切に呼び出すと、ヒープ構造が初期化されますか? –

+0

私は明らかに何か間違っている、問題は私が間違って何をしているのか分からないということです。メモリマップについての追加情報を追加しました。うまくいけば間違いを見つけるのに役立ちます。 –

+0

sprintfを使用すると、非常によく似た問題が発生します。だから、それは単なるmallocの問題ではありません。それは新しいライブラリのものと関係があります。私は何を理解することはできませんが、おそらくリンクスクリプトの変更が必要です。 –

答えて

16

を、これをデバッグ過ごしたいくつかの10時間後、私は最終的にそれがうまく行きました。問題はリンカースクリプトにありました。しかし、私が投稿したbssセクションではなく、テキストセクションとデータセクションにありました。ここで動作するスクリプトです。

OUTPUT_FORMAT("elf32-littlearm") 
OUTPUT_ARCH(arm) 
ENTRY(_startup) 

MEMORY 
{ 
    rom (rx) : ORIGIN = 0x00000000, LENGTH = 512K 
    ram (rwx) : ORIGIN = 0x10000000, LENGTH = 32K 
} 

/* Define the top our stack at the end of SRAM */ 
_end_stack = 0x10008000; 

EXTERN(__interrupt_vector_table); 

SECTIONS 
{ 
    .text : 
    { 
     /* Insert the interrupt vector table first */ 
     __interrupt_vector_table = .; 
     *(.interrupt_vector_table) 
     /* Startup assembly */ 
     *(.startup) 
     /* Rest of the code (C) */ 
     *(.text) *(.text.*) *(.glue_7) *(.glue_7t) 
     *(.vfp11_veneer) 
     *(.ARM.extab* .gnu.linkonce.armextab.*) 
     *(.rodata) *(.rodata.*) 
     . = ALIGN(8); 
     _end_text = .; 
     _start_datai = .; 
    } >rom 

    .data : 
    { 
     _start_data = .; 
     *(vtable) 
     *(.data) *(.data.*) 
     . = ALIGN (8); 
     _end_data = .; 
    } >ram AT >rom 

    .data_init : { _end_datai = .; } >rom 

    __exidx_start = .; 
    .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } > rom 
    __exidx_end = .; 

    .bss : 
    { 
     _start_bss = .; 
     *(.bss) 
     *(COMMON) 
    } >ram 

    . = ALIGN(4); 
    _end_bss = .; 
    . = ALIGN(256); 

    _start_heap = .; 
    PROVIDE(__cs3_heap_start = _start_heap); 

    /* Linker wants .eh_frame section defined because of gcc 4.4.X bug, 
    * just discard it here. */ 
    /DISCARD/ : { *(.eh_*) } 
} 

_end = .; 
PROVIDE(end = .); 

私はまた私のinitコードにいくつかの変数の初期化を追加する必要がありました:それはまだ起こっていたかを理解するために私をたくさん取ったものの

extern unsigned int _start_data; 
extern unsigned int _end_data; 
extern unsigned int _start_datai; 
extern unsigned int _end_datai; 

void init(void) { 

    // (...) Other stuff 

    // Initialize Global Variables 
    uint32_t* data_begin = (uint32_t*) &_start_data; 
    uint32_t* data_end = (uint32_t*) &_end_data; 
    uint32_t* datai_begin = (uint32_t*) &_start_datai; 
    uint32_t* datai_end = (uint32_t*) &_end_datai; 
    while(data_begin < data_end) 
    { 
     *data_begin = *datai_begin; 
     data_begin++; 
     datai_begin++; 
    } 

これらの2つのページには、非常に有用だった:http://fun-tech.se/stm32/linker/index.phphttp://e2e.ti.com/support/microcontrollers/stellaris_arm_cortex-m3_microcontroller/f/473/t/44452.aspx?pi23648=1

これは、私が経験していたのと同じ問題を経験している他の人にも役立つことを願っています。

+6

また、.bssセクションをゼロにする必要があります。 'for(uint32_t * p =&_start_bss; p <&_ebss; ++ p)* p = 0;' –

+0

@Marga、これをすべて計算していただきありがとうございます。私はそれを使用します! – nic

-15

予算内であれば、ARMコンパイラのライセンスを購入することを検討してください。 KeilとIARはどちらも、あなたのツールチェーンの問題の大部分を処理する偉大なARMコンパイラを作成しており、両方ともまともなサポートを持っています。

+15

誰かに学習をやめるためにお金を使ってはいけない。彼女が見つけた結果は、KeilとIARがどのような地上作業を行ったのかを指導する上で非常に優れています。結局のところ、彼女は今、ボンネットの下にあるものを理解しているので、より強力なプログラマーになるでしょう。 – nic

関連する問題