2012-05-06 26 views
14

Tôi đang tạo mã cho ARM Cortex-M3 (NXP's LCP17xx). Tôi đã sử dụng bộ nhớ tĩnh đến nay và mọi thứ hoạt động tốt. Tôi đã cố gắng để thêm hỗ trợ bộ nhớ động, nhưng một khi tôi gọi malloc, hệ thống bị mắc kẹt.Sử dụng malloc newlib trong ARM Cortex-M3

Tôi đang biên dịch bằng gcc cho kim loại trần cánh tay và sử dụng newlib. Phiên bản: gcc-arm-none-eabi-4_6-2012q1

Để thêm hỗ trợ malloc, tôi đã thực hiện một hàm _sbrk đơn giản và sửa đổi tập lệnh trình liên kết của tôi để tạo khoảng trống cho heap (Tôi đã đọc nhiều hướng dẫn khác nhau về điều này một phần, nhưng không bao gồm vấn đề mà tôi gặp phải tiếp theo).

Với sự trợ giúp của một số đèn LED, tôi có thể chắc chắn rằng mã chạy lên cho đến khi nó gọi là malloc, sau đó nó không tiếp tục. Nó thậm chí không đạt được chức năng _sbrk của tôi. Ngoài ra, nó sẽ bị kẹt trong một cuộc gọi đến sizeof, nếu tôi bao gồm một cuộc gọi đến malloc sau này trong mã.

Vì vậy, tôi có thể làm gì sai khi gọi malloc mã bị kẹt mà không bao giờ đạt đến _sbrk hoặc quay lại?

Sau khi xem bản đồ bộ nhớ được tạo khi cuộc gọi malloc được bao gồm và khi không, tôi nghi ngờ rằng nó liên quan đến cấu trúc được sử dụng bởi malloc.

Đây là một phần của kịch bản ld định nghĩa bộ nhớ ram: sau đó

.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 được thiết lập trong bảng vector ngắt.

Và bây giờ so sánh các bản đồ khác nhau. Mà không sử dụng malloc trong các mã:

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

bản đồ bộ nhớ sử dụng malloc trong các mã:

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

Bạn có chắc là bạn đang gọi mã khởi động đúng cách, điều này sẽ khởi tạo cấu trúc heap? –

+0

Tôi rõ ràng đang làm điều gì đó sai, vấn đề là tôi không biết tôi đang làm gì sai. Tôi đã thêm thông tin bổ sung về bản đồ bộ nhớ, hy vọng sẽ giúp tìm ra lỗi. –

+0

Một vấn đề rất giống nhau xảy ra khi sử dụng sprintf. Vì vậy, nó không chỉ là một vấn đề malloc. Nó phải làm với toàn bộ công cụ mới. Nó có thể cần một sự thay đổi trong kịch bản liên kết, mặc dù tôi không thể tìm ra cái gì. –

Trả lời

16

Vì vậy, sau khoảng 10 giờ làm việc gỡ lỗi này, tôi cuối cùng đã làm cho nó hoạt động. Vấn đề là trong kịch bản linker. Tuy nhiên, nó không nằm trong phần bss mà tôi đã đăng, nhưng trong phần văn bản và dữ liệu. Đây là kịch bản hoạt động.

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

Tôi cũng đã có thêm một số khởi tạo biến để mã init của tôi:

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

Hai trang khá hữu ích, mặc dù nó vẫn mất tôi rất nhiều để hiểu những gì đang xảy ra: 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

Tôi hy vọng điều này có thể hữu ích cho người khác gặp phải cùng một vấn đề mà tôi đang gặp phải.

+6

Bạn cũng cần phải loại bỏ phần .bss: 'cho (uint32_t * p = & _start_bss; p <&_ebss; ++ p) * p = 0;' –

+0

@Marga, cảm ơn bạn đã tìm hiểu tất cả điều này. Tôi sẽ sử dụng nó! – nic

-15

Nếu ngân sách của bạn nằm trong ngân sách của bạn, hãy xem xét mua giấy phép cho trình biên dịch ARM. Keil và IAR đều tạo ra các trình biên dịch ARM tuyệt vời, sẽ xử lý phần lớn các vấn đề về chuỗi công cụ của bạn và cả hai đều có hỗ trợ tốt.

+15

Đừng nói với ai đó sử dụng tiền để ngừng học. Các kết quả mà cô tìm thấy là rất tốt khi hướng dẫn công việc mà Keil và IAR đã làm. Cuối cùng, cô ấy sẽ trở thành một lập trình viên mạnh mẽ hơn vì bây giờ cô ấy hiểu được những gì dưới mui xe. – nic

Các vấn đề liên quan