2012-05-06 2 views
14

Я создаю код для ARM Cortex-M3 (LCP17xx от NXP). Я до сих пор использую статическую память, и все работает хорошо. Я попытался добавить поддержку динамической памяти, но как только я позвоню malloc, система застрянет.Использование malloc newlib в ARM Cortex-M3

Я компилирую с gcc для руки голый металл и используя newlib. Версия: gcc-arm-none-eabi-4_6-2012q1

Чтобы добавить поддержку malloc, я внедрил простую функцию _sbrk и изменил свой сценарий компоновщика, чтобы сделать некоторое пространство для кучи (я прочитал много разных руководств об этом часть, но никто не охватывает проблему, с которой я столкнулся в следующий раз).

С помощью некоторых светодиодов я могу быть уверен, что код работает до тех пор, пока он не назовет malloc, а затем он не будет продолжаться. Он даже не достигает моей функции _sbrk. Кроме того, он застрянет в вызове sizeof, если я включу в код код malloc.

Итак, что я могу делать неправильно, что при вызове malloc код застревает без достижения _sbrk или возврата?

После долгого просмотра карты памяти, сгенерированной при включении вызова malloc, и когда это не так, я подозреваю, что он связан со структурами, которые используются malloc.

Это часть сценария 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 затем устанавливается в таблице векторов прерываний.

И теперь сравнение разных карт. Без использования таНоса в коде:

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

карты памяти с помощью таНоса в коде:

*(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. Это связано с целым материалом newlib. Вероятно, вам нужно изменить сценарий связывания, хотя я не могу понять, что. –

ответ

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 = .); 

Я также должен добавить некоторую переменную инициализации в мой инициализации кода:

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++; 
    } 

Эти две страницы были весьма полезны, хотя он по-прежнему у меня ушло много, чтобы понять, что происходит: http://fun-tech.se/stm32/linker/index.php и http://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

Смежные вопросы