2012-05-06 6 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이 사용하는 구조와 관련이 있다고 의심합니다.

.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가 다음 인터럽트 벡터 테이블에 설정됩니다

는 램 메모리를 정의하는 LD 스크립트의 일부입니다.

이제 다른지도를 비교해보십시오. 코드에서의 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을 사용하지 않고 약 10 시간이 디버깅을 보낸 후

*(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

그래서, 나는 마지막으로 작동 만들었습니다. 문제는 링커 스크립트에 있습니다. 그러나 필자가 게시 한 bss 섹션에는 없지만 텍스트 및 데이터 섹션에 있습니다. 다음은 작동하는 스크립트입니다. 아직도 무슨 일이 있었는지 이해하는 나에게 많이했다하더라도,

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

이 두 페이지가 매우 도움이되었다 :

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

가 나는 또한 내 초기화 코드에 일부 변수 초기화를 추가했다 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라고 섹션 제로 아웃해야합니다'에 대한 (= uint32_t의 * P는 & _start_bss; P <&_ebss; ++ 피) * P = 0;' –

+0

@Marga,이 모든 것을 파악 주셔서 감사합니다. 나는 그것을 사용할거야! – nic

-15

예산이 충분하다면 ARM 컴파일러 라이센스를 구입하는 것이 좋습니다. Keil과 IAR은 모두 툴체인 문제의 대부분을 처리 할 훌륭한 ARM 컴파일러를 만들었으며 두 가지 모두 훌륭한 지원을 받았습니다.

+15

학습을 중지하기 위해 돈을 사용하는 사람을 말하지 마. 그녀가 발견 한 결과를 접지 작업 케일과 IAR이 무엇을했는지 지시에 중대하다. 그녀가 지금 후드 무엇을 이해하기 때문에 결국, 그녀는 더 강력한 프로그래머 수 있습니다. – nic