因为项目需要,最近重新拾起来STM32,正好趁着这个机会好好的梳理下遇到的知识细节。
STM32CubeMx默认移植和链接newlib,因此理论上我们可以方便的使用printf,malloc,free等功能,如下图:

这里我们只关注内存这块,移植newlib时需要_sbrk函数,这里STM32CubeMX在生成工程的时候帮忙生成了代码,如下:
//sysmem.c /** * Pointer to the current high watermark of the heap usage */ static uint8_t *__sbrk_heap_end = NULL; /** * @brief _sbrk() allocates memory to the newlib heap and is used by malloc * and others from the C library * * @verbatim * ############################################################################ * # .data # .bss # newlib heap # MSP stack # * # # # # Reserved by _Min_Stack_Size # * ############################################################################ * ^-- RAM start ^-- _end _estack, RAM end --^ * @endverbatim * * This implementation starts allocating at the '_end' linker symbol * The '_Min_Stack_Size' linker symbol reserves a memory for the MSP stack * The implementation considers '_estack' linker symbol to be RAM end * NOTE: If the MSP stack, at any point during execution, grows larger than the * reserved size, please increase the '_Min_Stack_Size'. * * @param incr Memory size * @return Pointer to allocated memory */ void *_sbrk(ptrdiff_t incr) { extern uint8_t _end; /* Symbol defined in the linker script */ extern uint8_t _estack; /* Symbol defined in the linker script */ extern uint32_t _Min_Stack_Size; /* Symbol defined in the linker script */ const uint32_t stack_limit = (uint32_t)&_estack - (uint32_t)&_Min_Stack_Size; const uint8_t *max_heap = (uint8_t *)stack_limit; uint8_t *prev_heap_end; /* Initalize heap end at first call */ if (NULL == __sbrk_heap_end) { __sbrk_heap_end = &_end; } /* Protect heap from growing into the reserved MSP stack */ if (__sbrk_heap_end + incr > max_heap) { errno = ENOMEM; return (void *)-1; } prev_heap_end = __sbrk_heap_end; __sbrk_heap_end += incr; return (void *)prev_heap_end; }
这里 __sbrk_heap_end 指向的是当前堆的指针位置,max_heap指向的是堆默认的最大值。这里各个指针偏移如下图:

地址偏移是如何计算的呢,这里可以看下最终的链接脚本:
/* XXXX_FLASH.ld */ /* Highest address of the user mode stack */ _estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */ _Min_Heap_Size = 0x200 ; /* required amount of heap */ _Min_Stack_Size = 0x400 ; /* required amount of stack */ 。。。。 。。。。 /* Initialized data sections into "RAM" Ram type memory */ .data : { . = ALIGN(4); _sdata = .; /* create a global symbol at data start */ *(.data) /* .data sections */ *(.data*) /* .data* sections */ . = ALIGN(4); _edata = .; /* define a global symbol at data end */ } >RAM AT> FLASH /* data第一个链接进RAM */ /* Uninitialized data section into "RAM" Ram type memory */ . = ALIGN(4); .bss : { /* This is used by the startup in order to initialize the .bss section */ _sbss = .; /* define a global symbol at bss start */ __bss_start__ = _sbss; *(.bss) *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; /* define a global symbol at bss end */ __bss_end__ = _ebss; } >RAM /* bss第二个链接进RAM */ /* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */ ._user_heap_stack : { . = ALIGN(8); PROVIDE ( end = . ); PROVIDE ( _end = . ); . = . + _Min_Heap_Size; . = . + _Min_Stack_Size; . = ALIGN(8); } >RAM /* _user_heap_stack第三个链接进RAM */
发表评论