在 ARM Cortex-M3 中使用 newlib 的 malloc [英] Using newlib's malloc in an ARM Cortex-M3
问题描述
我正在为 ARM Cortex-M3(NXP 的 LCP17xx)创建代码.到目前为止,我一直在使用静态内存,一切运行良好.我尝试添加动态内存支持,但是一旦调用malloc,系统就卡住了.
I'm creating code for an ARM Cortex-M3 (NXP's LCP17xx). I've been using static memory up to now and everything worked well. I tried to add dynamic memory support, but once I call malloc, the system gets stuck.
我正在使用 gcc 为 arm 裸机编译,并使用 newlib.版本:gcc-arm-none-eabi-4_6-2012q1
I'm compiling with gcc for arm bare metal, and using newlib. Version: gcc-arm-none-eabi-4_6-2012q1
为了添加 malloc 支持,我实现了一个简单的 _sbrk 函数并修改了我的链接器脚本以为堆腾出一些空间(我已经阅读了许多关于这部分的不同教程,但没有一个涵盖我接下来遇到的问题).
To add malloc support, I implemented a simple _sbrk function and modified my linker script to make some space for the heap (I've read many different tutorials about this part, but none cover the problem that I encountered next).
在一些 LED 的帮助下,我可以确定代码一直运行到它调用 malloc
为止,然后它不会继续运行.它甚至没有达到我的 _sbrk
功能.此外,如果我稍后在代码中包含对 malloc
的调用,它会卡在对 sizeof
的调用中.
With the help of some leds, I can be certain that the code runs up until the point that it calls malloc
, then it doesn't go on. It doesn't even reach my _sbrk
function. Also, it will get stuck in a call to sizeof
, if I include a call to malloc
later on in the code.
那么,当调用 malloc
时,代码卡住了,而没有到达 _sbrk
或返回,我可能做错了什么?
So, what can I be doing wrong that when calling malloc
the code gets stuck without ever reaching _sbrk
or returning?
在盯着包含 malloc
调用和不包含时生成的内存映射一段时间后,我怀疑它与 malloc使用的结构有关代码>.
After staring for quite a while to the memory map generated when the malloc
call is included and when it's not, I suspect that it's related to the structures that are used by malloc
.
这是定义 ram 内存的 ld 脚本部分:
This is the part of the ld script that defines the ram memory:
.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 然后在中断向量表中设置.
_end_stack is then set in the interrupt vector table.
现在是不同地图的比较.在代码中不使用 malloc:
And now a comparison of the different maps. Without using malloc in the code:
*(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的内存映射:
Memory map using malloc in the code:
*(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 = .
推荐答案
所以,经过大约 10 个小时的调试后,我终于让它工作了.问题出在链接器脚本中.不过我发的不是bss版块,而是文本和数据版块.这是有效的脚本.
So, after some 10 hours spent debugging this, I have finally made it work. The problem was in the linker script. However, it was not in the bss section that I had posted, but in the text and data section. Here's the script that works.
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 = .);
我还必须在我的初始化代码中添加一些变量初始化:
I also had to add some variable initialization to my init code:
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
These two pages were quite helpful, although it still took me a lot to understand what was going on: http://fun-tech.se/stm32/linker/index.php and http://e2e.ti.com/support/microcontrollers/stellaris_arm_cortex-m3_microcontroller/f/473/t/44452.aspx?pi23648=1
我希望这对遇到我遇到的相同问题的其他人有用.
I hope this might be useful to somebody else experiencing the same problems I was experiencing.
这篇关于在 ARM Cortex-M3 中使用 newlib 的 malloc的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!