mirror of https://github.com/ARMmbed/mbed-os.git
Fix heap limit checking and make memory explicit
Set well defined limits for the heap and configure GCC and ARMCC to correctly check these. IAR already correctly checked its heap. This also statically declares the main thread stack so the linker is responsible for its placement.pull/2499/head
parent
21903917c4
commit
e913f49350
|
@ -68,6 +68,10 @@ extern const char __stdout_name[] = "/stdout";
|
||||||
extern const char __stderr_name[] = "/stderr";
|
extern const char __stderr_name[] = "/stderr";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Heap limits - only used if set
|
||||||
|
unsigned char *mbed_heap_start = 0;
|
||||||
|
uint32_t mbed_heap_size = 0;
|
||||||
|
|
||||||
/* newlib has the filehandle field in the FILE struct as a short, so
|
/* newlib has the filehandle field in the FILE struct as a short, so
|
||||||
* we can't just return a Filehandle* from _open and instead have to
|
* we can't just return a Filehandle* from _open and instead have to
|
||||||
* put it in a filehandles array and return the index into that array
|
* put it in a filehandles array and return the index into that array
|
||||||
|
@ -596,6 +600,12 @@ extern "C" caddr_t _sbrk(int incr) {
|
||||||
return (caddr_t)-1;
|
return (caddr_t)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Additional heap checking if set
|
||||||
|
if (mbed_heap_size && (new_heap >= mbed_heap_start + mbed_heap_size)) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
return (caddr_t)-1;
|
||||||
|
}
|
||||||
|
|
||||||
heap = new_heap;
|
heap = new_heap;
|
||||||
return (caddr_t) prev_heap;
|
return (caddr_t) prev_heap;
|
||||||
}
|
}
|
||||||
|
|
|
@ -350,7 +350,41 @@ __attribute__((used)) void _mutex_release (OS_ID *mutex) {
|
||||||
|
|
||||||
/* Main Thread definition */
|
/* Main Thread definition */
|
||||||
extern void pre_main (void);
|
extern void pre_main (void);
|
||||||
osThreadDef_t os_thread_def_main = {(os_pthread)pre_main, osPriorityNormal, 1U, 0U, NULL};
|
static uint32_t thread_stack_main[DEFAULT_STACK_SIZE * 2 / sizeof(uint32_t)];
|
||||||
|
osThreadDef_t os_thread_def_main = {(os_pthread)pre_main, osPriorityNormal, 1U, sizeof(thread_stack_main), thread_stack_main};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IAR Default Memory layout notes:
|
||||||
|
* -Heap defined by "HEAP" region in .icf file
|
||||||
|
* -Interrupt stack defined by "CSTACK" region in .icf file
|
||||||
|
* -Value INITIAL_SP is ignored
|
||||||
|
*
|
||||||
|
* IAR Custom Memory layout notes:
|
||||||
|
* -There is no custom layout available for IAR - everything must be defined in
|
||||||
|
* the .icf file and use the default layout
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* GCC Default Memory layout notes:
|
||||||
|
* -Block of memory from symbol __end__ to define INITIAL_SP used to setup interrupt
|
||||||
|
* stack and heap in the function set_stack_heap()
|
||||||
|
* -ISR_STACK_SIZE can be overridden to be larger or smaller
|
||||||
|
*
|
||||||
|
* GCC Custom Memory layout notes:
|
||||||
|
* -Heap can be explicitly placed by defining both HEAP_START and HEAP_SIZE
|
||||||
|
* -Interrupt stack can be explicitly placed by defining both ISR_STACK_START and ISR_STACK_SIZE
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* ARM Memory layout
|
||||||
|
* -Block of memory from end of region "RW_IRAM1" to define INITIAL_SP used to setup interrupt
|
||||||
|
* stack and heap in the function set_stack_heap()
|
||||||
|
* -ISR_STACK_SIZE can be overridden to be larger or smaller
|
||||||
|
*
|
||||||
|
* ARM Custom Memory layout notes:
|
||||||
|
* -Heap can be explicitly placed by defining both HEAP_START and HEAP_SIZE
|
||||||
|
* -Interrupt stack can be explicitly placed by defining both ISR_STACK_START and ISR_STACK_SIZE
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
// This define should be probably moved to the CMSIS layer
|
// This define should be probably moved to the CMSIS layer
|
||||||
#if defined(TARGET_LPC1768)
|
#if defined(TARGET_LPC1768)
|
||||||
|
@ -534,19 +568,25 @@ extern uint32_t __StackTop[];
|
||||||
|
|
||||||
#elif defined(TARGET_NUMAKER_PFM_NUC472)
|
#elif defined(TARGET_NUMAKER_PFM_NUC472)
|
||||||
# if defined(__CC_ARM)
|
# if defined(__CC_ARM)
|
||||||
extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Limit[];
|
extern uint32_t Image$$ARM_LIB_HEAP$$Base[];
|
||||||
|
extern uint32_t Image$$ARM_LIB_HEAP$$Length[];
|
||||||
extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Base[];
|
extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Base[];
|
||||||
#define INITIAL_SP ((uint32_t) Image$$ARM_LIB_STACK$$ZI$$Limit)
|
extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Length[];
|
||||||
#define FINAL_SP ((uint32_t) Image$$ARM_LIB_STACK$$ZI$$Base)
|
#define HEAP_START ((unsigned char*) Image$$ARM_LIB_HEAP$$Base)
|
||||||
|
#define HEAP_SIZE ((uint32_t) Image$$ARM_LIB_HEAP$$Length)
|
||||||
|
#define ISR_STACK_START ((unsigned char*)Image$$ARM_LIB_STACK$$ZI$$Base)
|
||||||
|
#define ISR_STACK_SIZE ((uint32_t)Image$$ARM_LIB_STACK$$ZI$$Length)
|
||||||
# elif defined(__GNUC__)
|
# elif defined(__GNUC__)
|
||||||
extern uint32_t __StackTop[];
|
extern uint32_t __StackTop[];
|
||||||
extern uint32_t __StackLimit[];
|
extern uint32_t __StackLimit[];
|
||||||
#define INITIAL_SP ((uint32_t) __StackTop)
|
extern uint32_t __end__[];
|
||||||
#define FINAL_SP ((uint32_t) __StackLimit)
|
extern uint32_t __HeapLimit[];
|
||||||
|
#define HEAP_START ((unsigned char*)__end__)
|
||||||
|
#define HEAP_SIZE ((uint32_t)((uint32_t)__HeapLimit - (uint32_t)HEAP_START))
|
||||||
|
#define ISR_STACK_START ((unsigned char*)__StackLimit)
|
||||||
|
#define ISR_STACK_SIZE ((uint32_t)((uint32_t)__StackTop - (uint32_t)__StackLimit))
|
||||||
# elif defined(__ICCARM__)
|
# elif defined(__ICCARM__)
|
||||||
#pragma section="CSTACK"
|
/* No region declarations needed */
|
||||||
#define INITIAL_SP ((uint32_t) __section_end("CSTACK"))
|
|
||||||
#define FINAL_SP ((uint32_t) __section_begin("CSTACK"))
|
|
||||||
# else
|
# else
|
||||||
#error "no toolchain defined"
|
#error "no toolchain defined"
|
||||||
# endif
|
# endif
|
||||||
|
@ -556,48 +596,90 @@ extern uint32_t __StackLimit[];
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __CC_ARM
|
extern unsigned char *mbed_heap_start;
|
||||||
#if defined(TARGET_NUMAKER_PFM_NUC472)
|
extern uint32_t mbed_heap_size;
|
||||||
extern uint32_t Image$$ARM_LIB_HEAP$$Base[];
|
|
||||||
#define HEAP_START ((uint32_t) Image$$ARM_LIB_HEAP$$Base)
|
unsigned char *mbed_stack_isr_start = 0;
|
||||||
#else
|
uint32_t mbed_stack_isr_size = 0;
|
||||||
extern uint32_t Image$$RW_IRAM1$$ZI$$Limit[];
|
|
||||||
#define HEAP_START (Image$$RW_IRAM1$$ZI$$Limit)
|
/*
|
||||||
|
* Sanity check values
|
||||||
|
*/
|
||||||
|
#if defined(__ICCARM__) && \
|
||||||
|
(defined(HEAP_START) || defined(HEAP_SIZE) || \
|
||||||
|
defined(ISR_STACK_START) && defined(ISR_STACK_SIZE))
|
||||||
|
#error "No custom layout allowed for IAR. Use .icf file instead"
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(HEAP_START) && !defined(HEAP_SIZE)
|
||||||
|
#error "HEAP_SIZE must be defined if HEAP_START is defined"
|
||||||
|
#endif
|
||||||
|
#if defined(ISR_STACK_START) && !defined(ISR_STACK_SIZE)
|
||||||
|
#error "ISR_STACK_SIZE must be defined if ISR_STACK_START is defined"
|
||||||
|
#endif
|
||||||
|
#if defined(HEAP_SIZE) && !defined(HEAP_START)
|
||||||
|
#error "HEAP_START must be defined if HEAP_SIZE is defined"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Interrupt stack and heap always defined for IAR
|
||||||
|
* Main thread defined here
|
||||||
|
*/
|
||||||
|
#if defined(__ICCARM__)
|
||||||
|
#pragma section="CSTACK"
|
||||||
|
#pragma section="HEAP"
|
||||||
|
#define HEAP_START ((unsigned char*)__section_begin("HEAP"))
|
||||||
|
#define HEAP_SIZE ((uint32_t)__section_size("HEAP"))
|
||||||
|
#define ISR_STACK_START ((unsigned char*)__section_begin("CSTACK"))
|
||||||
|
#define ISR_STACK_SIZE ((uint32_t)__section_size("CSTACK"))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define heap region if it has not been defined already */
|
||||||
|
#if !defined(HEAP_START)
|
||||||
|
#if defined(__ICCARM__)
|
||||||
|
#error "Heap should already be defined for IAR"
|
||||||
|
#elif defined(__CC_ARM)
|
||||||
|
extern uint32_t Image$$RW_IRAM1$$ZI$$Limit[];
|
||||||
|
#define HEAP_START ((unsigned char*)Image$$RW_IRAM1$$ZI$$Limit)
|
||||||
|
#define HEAP_SIZE ((uint32_t)((uint32_t)INITIAL_SP - (uint32_t)HEAP_START))
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
extern uint32_t __end__[];
|
extern uint32_t __end__[];
|
||||||
#define HEAP_START (__end__)
|
#define HEAP_START ((unsigned char*)__end__)
|
||||||
#elif defined(__ICCARM__)
|
#define HEAP_SIZE ((uint32_t)((uint32_t)INITIAL_SP - (uint32_t)HEAP_START))
|
||||||
#pragma section="HEAP"
|
#endif
|
||||||
#define HEAP_END (void *)__section_end("HEAP")
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void set_main_stack(void) {
|
/* Define stack sizes if they haven't been set already */
|
||||||
#if defined(TARGET_NUMAKER_PFM_NUC472)
|
#if !defined(ISR_STACK_SIZE)
|
||||||
// Scheduler stack: OS_MAINSTKSIZE words
|
#define ISR_STACK_SIZE ((uint32_t)OS_MAINSTKSIZE * 4)
|
||||||
// Main thread stack: Reserved stack size - OS_MAINSTKSIZE words
|
#endif
|
||||||
os_thread_def_main.stack_pointer = (uint32_t *) FINAL_SP;
|
|
||||||
os_thread_def_main.stacksize = (uint32_t) INITIAL_SP - (uint32_t) FINAL_SP - OS_MAINSTKSIZE * 4;
|
/*
|
||||||
|
* set_stack_heap purpose is to set the following variables:
|
||||||
|
* -mbed_heap_start
|
||||||
|
* -mbed_heap_size
|
||||||
|
* -mbed_stack_isr_start
|
||||||
|
* -mbed_stack_isr_size
|
||||||
|
*
|
||||||
|
* Along with setting up os_thread_def_main
|
||||||
|
*/
|
||||||
|
void set_stack_heap(void) {
|
||||||
|
|
||||||
|
unsigned char *free_start = HEAP_START;
|
||||||
|
uint32_t free_size = HEAP_SIZE;
|
||||||
|
|
||||||
|
#ifdef ISR_STACK_START
|
||||||
|
/* Interrupt stack explicitly specified */
|
||||||
|
mbed_stack_isr_size = ISR_STACK_SIZE;
|
||||||
|
mbed_stack_isr_start = ISR_STACK_START;
|
||||||
#else
|
#else
|
||||||
uint32_t interrupt_stack_size = ((uint32_t)OS_MAINSTKSIZE * 4);
|
/* Interrupt stack - reserve space at the end of the free block */
|
||||||
#if defined(__ICCARM__)
|
mbed_stack_isr_size = ISR_STACK_SIZE;
|
||||||
/* For IAR heap is defined .icf file */
|
mbed_stack_isr_start = free_start + free_size - mbed_stack_isr_size;
|
||||||
uint32_t main_stack_size = ((uint32_t)INITIAL_SP - (uint32_t)HEAP_END) - interrupt_stack_size;
|
free_size -= mbed_stack_isr_size;
|
||||||
#else
|
|
||||||
/* For ARM , uARM, or GCC_ARM , heap can grow and reach main stack */
|
|
||||||
uint32_t heap_plus_stack_size = ((uint32_t)INITIAL_SP - (uint32_t)HEAP_START) - interrupt_stack_size;
|
|
||||||
// Main thread's stack is 1/4 of the heap
|
|
||||||
uint32_t main_stack_size = heap_plus_stack_size/4;
|
|
||||||
#endif
|
#endif
|
||||||
// The main thread must be 4 byte aligned
|
|
||||||
uint32_t main_stack_start = ((uint32_t)INITIAL_SP - interrupt_stack_size - main_stack_size) & ~0x7;
|
|
||||||
|
|
||||||
// That is the bottom of the main stack block: no collision detection
|
/* Heap - everything else */
|
||||||
os_thread_def_main.stack_pointer = (uint32_t*)main_stack_start;
|
mbed_heap_size = free_size;
|
||||||
|
mbed_heap_start = free_start;
|
||||||
// Leave OS_MAINSTKSIZE words for the scheduler and interrupts
|
|
||||||
os_thread_def_main.stacksize = main_stack_size;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined (__CC_ARM)
|
#if defined (__CC_ARM)
|
||||||
|
@ -611,7 +693,7 @@ void $Super$$__cpp_initialize__aeabi_(void);
|
||||||
void _main_init (void) {
|
void _main_init (void) {
|
||||||
osKernelInitialize();
|
osKernelInitialize();
|
||||||
#ifdef __MBED_CMSIS_RTOS_CM
|
#ifdef __MBED_CMSIS_RTOS_CM
|
||||||
set_main_stack();
|
set_stack_heap();
|
||||||
#endif
|
#endif
|
||||||
osThreadCreate(&os_thread_def_main, NULL);
|
osThreadCreate(&os_thread_def_main, NULL);
|
||||||
osKernelStart();
|
osKernelStart();
|
||||||
|
@ -633,15 +715,12 @@ void pre_main()
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
void * armcc_heap_base;
|
|
||||||
void * armcc_heap_top;
|
|
||||||
|
|
||||||
int main(void);
|
int main(void);
|
||||||
|
|
||||||
void pre_main (void)
|
void pre_main (void)
|
||||||
{
|
{
|
||||||
singleton_mutex_id = osMutexCreate(osMutex(singleton_mutex));
|
singleton_mutex_id = osMutexCreate(osMutex(singleton_mutex));
|
||||||
__rt_lib_init((unsigned)armcc_heap_base, (unsigned)armcc_heap_top);
|
__rt_lib_init((unsigned)mbed_heap_start, (unsigned)(mbed_heap_start + mbed_heap_size));
|
||||||
main();
|
main();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -656,12 +735,10 @@ void pre_main (void)
|
||||||
__asm void __rt_entry (void) {
|
__asm void __rt_entry (void) {
|
||||||
|
|
||||||
IMPORT __user_setup_stackheap
|
IMPORT __user_setup_stackheap
|
||||||
IMPORT armcc_heap_base
|
|
||||||
IMPORT armcc_heap_top
|
|
||||||
IMPORT os_thread_def_main
|
IMPORT os_thread_def_main
|
||||||
IMPORT osKernelInitialize
|
IMPORT osKernelInitialize
|
||||||
#ifdef __MBED_CMSIS_RTOS_CM
|
#ifdef __MBED_CMSIS_RTOS_CM
|
||||||
IMPORT set_main_stack
|
IMPORT set_stack_heap
|
||||||
#endif
|
#endif
|
||||||
IMPORT osKernelStart
|
IMPORT osKernelStart
|
||||||
IMPORT osThreadCreate
|
IMPORT osThreadCreate
|
||||||
|
@ -675,13 +752,12 @@ __asm void __rt_entry (void) {
|
||||||
* ARM Compiler ARM C and C++ Libraries and Floating-Point Support User Guide
|
* ARM Compiler ARM C and C++ Libraries and Floating-Point Support User Guide
|
||||||
*/
|
*/
|
||||||
BL __user_setup_stackheap
|
BL __user_setup_stackheap
|
||||||
LDR R3,=armcc_heap_base
|
/* Ignore return value of __user_setup_stackheap since
|
||||||
LDR R4,=armcc_heap_top
|
* this will be setup by set_stack_heap
|
||||||
STR R0,[R3]
|
*/
|
||||||
STR R2,[R4]
|
|
||||||
BL osKernelInitialize
|
BL osKernelInitialize
|
||||||
#ifdef __MBED_CMSIS_RTOS_CM
|
#ifdef __MBED_CMSIS_RTOS_CM
|
||||||
BL set_main_stack
|
BL set_stack_heap
|
||||||
#endif
|
#endif
|
||||||
LDR R0,=os_thread_def_main
|
LDR R0,=os_thread_def_main
|
||||||
MOVS R1,#0
|
MOVS R1,#0
|
||||||
|
@ -719,7 +795,7 @@ __attribute__((naked)) void software_init_hook_rtos (void) {
|
||||||
__asm (
|
__asm (
|
||||||
"bl osKernelInitialize\n"
|
"bl osKernelInitialize\n"
|
||||||
#ifdef __MBED_CMSIS_RTOS_CM
|
#ifdef __MBED_CMSIS_RTOS_CM
|
||||||
"bl set_main_stack\n"
|
"bl set_stack_heap\n"
|
||||||
#endif
|
#endif
|
||||||
"ldr r0,=os_thread_def_main\n"
|
"ldr r0,=os_thread_def_main\n"
|
||||||
"movs r1,#0\n"
|
"movs r1,#0\n"
|
||||||
|
@ -796,7 +872,7 @@ void __iar_program_start( void )
|
||||||
#endif
|
#endif
|
||||||
osKernelInitialize();
|
osKernelInitialize();
|
||||||
#ifdef __MBED_CMSIS_RTOS_CM
|
#ifdef __MBED_CMSIS_RTOS_CM
|
||||||
set_main_stack();
|
set_stack_heap();
|
||||||
#endif
|
#endif
|
||||||
osThreadCreate(&os_thread_def_main, NULL);
|
osThreadCreate(&os_thread_def_main, NULL);
|
||||||
osKernelStart();
|
osKernelStart();
|
||||||
|
|
Loading…
Reference in New Issue