mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #2402 from c1728p9/main_thread_stack_checking_alt_impl
Main thread stack checking alt implpull/2423/head
commit
4382db1a6e
|
@ -23,6 +23,8 @@
|
|||
#include "mbed_interface.h"
|
||||
#include "SingletonPtr.h"
|
||||
#include "PlatformMutex.h"
|
||||
#include "mbed_error.h"
|
||||
#include <stdlib.h>
|
||||
#if DEVICE_STDIO_MESSAGES
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
@ -68,6 +70,10 @@ extern const char __stdout_name[] = "/stdout";
|
|||
extern const char __stderr_name[] = "/stderr";
|
||||
#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
|
||||
* 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
|
||||
|
@ -596,6 +602,12 @@ extern "C" caddr_t _sbrk(int incr) {
|
|||
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;
|
||||
return (caddr_t) prev_heap;
|
||||
}
|
||||
|
@ -714,3 +726,34 @@ extern "C" void __env_unlock( struct _reent *_r )
|
|||
#endif
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
void *operator new(std::size_t count)
|
||||
{
|
||||
void *buffer = malloc(count);
|
||||
if (NULL == buffer) {
|
||||
error("Operator new out of memory\r\n");
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void *operator new[](std::size_t count)
|
||||
{
|
||||
void *buffer = malloc(count);
|
||||
if (NULL == buffer) {
|
||||
error("Operator new[] out of memory\r\n");
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void operator delete(void *ptr)
|
||||
{
|
||||
if (ptr != NULL) {
|
||||
free(ptr);
|
||||
}
|
||||
}
|
||||
void operator delete[](void *ptr)
|
||||
{
|
||||
if (ptr != NULL) {
|
||||
free(ptr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
; POSSIBILITY OF SUCH DAMAGE.
|
||||
; ---------------------------------------------------------------------------*/
|
||||
|
||||
__initial_sp EQU 0x20008000
|
||||
__initial_sp EQU 0x20010000
|
||||
|
||||
PRESERVE8
|
||||
THUMB
|
||||
|
|
|
@ -11,7 +11,7 @@ define symbol __ICFEDIT_region_IRAM_end__ = 0x20010000;
|
|||
define symbol __ICFEDIT_region_XRAM_start__ = 0x60000000;
|
||||
define symbol __ICFEDIT_region_XRAM_end__ = 0x60100000;
|
||||
/*-Sizes-*/
|
||||
define symbol __ICFEDIT_size_cstack__ = 0x3000;
|
||||
define symbol __ICFEDIT_size_cstack__ = 0x2000;
|
||||
define symbol __ICFEDIT_size_heap__ = 0xC0000;
|
||||
/**** End of ICF editor section. ###ICF###*/
|
||||
|
||||
|
|
|
@ -90,32 +90,6 @@ void rt_init_stack (P_TCB p_TCB, FUNCP task_body) {
|
|||
/* Task entry point. */
|
||||
p_TCB->ptask = task_body;
|
||||
|
||||
|
||||
#ifdef __MBED_CMSIS_RTOS_CM
|
||||
/* Set a magic word for checking of stack overflow.
|
||||
For the main thread (ID: MAIN_THREAD_ID) the stack is in a memory area shared with the
|
||||
heap, therefore the last word of the stack is a moving target.
|
||||
We want to do stack/heap collision detection instead.
|
||||
Similar applies to stack filling for the magic pattern.
|
||||
*/
|
||||
if (p_TCB->task_id != MAIN_THREAD_ID) {
|
||||
p_TCB->stack[0] = MAGIC_WORD;
|
||||
|
||||
/* Initialize stack with magic pattern. */
|
||||
if (os_stackinfo & 0x10000000U) {
|
||||
if (size > (16U+1U)) {
|
||||
for (i = ((size - 16U)/2U) - 1U; i; i--) {
|
||||
stk -= 2U;
|
||||
stk[1] = MAGIC_PATTERN;
|
||||
stk[0] = MAGIC_PATTERN;
|
||||
}
|
||||
if (--stk > p_TCB->stack) {
|
||||
*stk = MAGIC_PATTERN;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* Initialize stack with magic pattern. */
|
||||
if (os_stackinfo & 0x10000000U) {
|
||||
if (size > (16U+1U)) {
|
||||
|
@ -132,7 +106,6 @@ void rt_init_stack (P_TCB p_TCB, FUNCP task_body) {
|
|||
|
||||
/* Set a magic word for checking of stack overflow. */
|
||||
p_TCB->stack[0] = MAGIC_WORD;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -350,7 +350,46 @@ __attribute__((used)) void _mutex_release (OS_ID *mutex) {
|
|||
|
||||
/* Main Thread definition */
|
||||
extern void pre_main (void);
|
||||
osThreadDef_t os_thread_def_main = {(os_pthread)pre_main, osPriorityNormal, 1U, 0U, NULL};
|
||||
|
||||
#if defined(TARGET_MCU_NRF51822) || defined(TARGET_MCU_NRF52832)
|
||||
static uint32_t thread_stack_main[DEFAULT_STACK_SIZE / sizeof(uint32_t)];
|
||||
#else
|
||||
static uint32_t thread_stack_main[DEFAULT_STACK_SIZE * 2 / sizeof(uint32_t)];
|
||||
#endif
|
||||
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
|
||||
#if defined(TARGET_LPC1768)
|
||||
|
@ -381,12 +420,15 @@ osThreadDef_t os_thread_def_main = {(os_pthread)pre_main, osPriorityNormal, 1U,
|
|||
#define INITIAL_SP (0x20003000UL)
|
||||
|
||||
#elif defined(TARGET_K64F)
|
||||
#if defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED)
|
||||
#if defined(__GNUC__) && !defined(__CC_ARM) /* GCC */
|
||||
extern uint32_t __StackTop[];
|
||||
#define INITIAL_SP (__StackTop)
|
||||
#else
|
||||
#define INITIAL_SP (0x20030000UL)
|
||||
#endif
|
||||
#if defined(__CC_ARM) || defined(__GNUC__)
|
||||
#define ISR_STACK_SIZE (0x1000)
|
||||
#endif
|
||||
|
||||
#elif defined(TARGET_K22F)
|
||||
#define INITIAL_SP (0x20010000UL)
|
||||
|
@ -534,19 +576,25 @@ extern uint32_t __StackTop[];
|
|||
|
||||
#elif defined(TARGET_NUMAKER_PFM_NUC472)
|
||||
# if defined(__CC_ARM)
|
||||
extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Limit[];
|
||||
extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Base[];
|
||||
#define INITIAL_SP ((uint32_t) Image$$ARM_LIB_STACK$$ZI$$Limit)
|
||||
#define FINAL_SP ((uint32_t) Image$$ARM_LIB_STACK$$ZI$$Base)
|
||||
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$$Length[];
|
||||
#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__)
|
||||
extern uint32_t __StackTop[];
|
||||
extern uint32_t __StackLimit[];
|
||||
#define INITIAL_SP ((uint32_t) __StackTop)
|
||||
#define FINAL_SP ((uint32_t) __StackLimit)
|
||||
extern uint32_t __end__[];
|
||||
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__)
|
||||
#pragma section="CSTACK"
|
||||
#define INITIAL_SP ((uint32_t) __section_end("CSTACK"))
|
||||
#define FINAL_SP ((uint32_t) __section_begin("CSTACK"))
|
||||
/* No region declarations needed */
|
||||
# else
|
||||
#error "no toolchain defined"
|
||||
# endif
|
||||
|
@ -556,48 +604,90 @@ extern uint32_t __StackLimit[];
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef __CC_ARM
|
||||
#if defined(TARGET_NUMAKER_PFM_NUC472)
|
||||
extern uint32_t Image$$ARM_LIB_HEAP$$Base[];
|
||||
#define HEAP_START ((uint32_t) Image$$ARM_LIB_HEAP$$Base)
|
||||
#else
|
||||
extern uint32_t Image$$RW_IRAM1$$ZI$$Limit[];
|
||||
#define HEAP_START (Image$$RW_IRAM1$$ZI$$Limit)
|
||||
extern unsigned char *mbed_heap_start;
|
||||
extern uint32_t mbed_heap_size;
|
||||
|
||||
unsigned char *mbed_stack_isr_start = 0;
|
||||
uint32_t mbed_stack_isr_size = 0;
|
||||
|
||||
/*
|
||||
* 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
|
||||
#elif defined(__GNUC__)
|
||||
extern uint32_t __end__[];
|
||||
#define HEAP_START (__end__)
|
||||
#elif defined(__ICCARM__)
|
||||
#pragma section="HEAP"
|
||||
#define HEAP_END (void *)__section_end("HEAP")
|
||||
#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
|
||||
|
||||
void set_main_stack(void) {
|
||||
#if defined(TARGET_NUMAKER_PFM_NUC472)
|
||||
// Scheduler stack: OS_MAINSTKSIZE words
|
||||
// Main thread stack: Reserved stack size - OS_MAINSTKSIZE words
|
||||
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;
|
||||
#else
|
||||
uint32_t interrupt_stack_size = ((uint32_t)OS_MAINSTKSIZE * 4);
|
||||
/* Interrupt stack and heap always defined for IAR
|
||||
* Main thread defined here
|
||||
*/
|
||||
#if defined(__ICCARM__)
|
||||
/* For IAR heap is defined .icf file */
|
||||
uint32_t main_stack_size = ((uint32_t)INITIAL_SP - (uint32_t)HEAP_END) - interrupt_stack_size;
|
||||
#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__)
|
||||
extern uint32_t __end__[];
|
||||
#define HEAP_START ((unsigned char*)__end__)
|
||||
#define HEAP_SIZE ((uint32_t)((uint32_t)INITIAL_SP - (uint32_t)HEAP_START))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Define stack sizes if they haven't been set already */
|
||||
#if !defined(ISR_STACK_SIZE)
|
||||
#define ISR_STACK_SIZE ((uint32_t)OS_MAINSTKSIZE * 4)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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
|
||||
/* 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;
|
||||
/* Interrupt stack - reserve space at the end of the free block */
|
||||
mbed_stack_isr_size = ISR_STACK_SIZE;
|
||||
mbed_stack_isr_start = free_start + free_size - mbed_stack_isr_size;
|
||||
free_size -= mbed_stack_isr_size;
|
||||
#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
|
||||
os_thread_def_main.stack_pointer = (uint32_t*)main_stack_start;
|
||||
|
||||
// Leave OS_MAINSTKSIZE words for the scheduler and interrupts
|
||||
os_thread_def_main.stacksize = main_stack_size;
|
||||
#endif
|
||||
/* Heap - everything else */
|
||||
mbed_heap_size = free_size;
|
||||
mbed_heap_start = free_start;
|
||||
}
|
||||
|
||||
#if defined (__CC_ARM)
|
||||
|
@ -611,7 +701,7 @@ void $Super$$__cpp_initialize__aeabi_(void);
|
|||
void _main_init (void) {
|
||||
osKernelInitialize();
|
||||
#ifdef __MBED_CMSIS_RTOS_CM
|
||||
set_main_stack();
|
||||
set_stack_heap();
|
||||
#endif
|
||||
osThreadCreate(&os_thread_def_main, NULL);
|
||||
osKernelStart();
|
||||
|
@ -633,15 +723,12 @@ void pre_main()
|
|||
|
||||
#else
|
||||
|
||||
void * armcc_heap_base;
|
||||
void * armcc_heap_top;
|
||||
|
||||
int main(void);
|
||||
|
||||
void pre_main (void)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -656,12 +743,10 @@ void pre_main (void)
|
|||
__asm void __rt_entry (void) {
|
||||
|
||||
IMPORT __user_setup_stackheap
|
||||
IMPORT armcc_heap_base
|
||||
IMPORT armcc_heap_top
|
||||
IMPORT os_thread_def_main
|
||||
IMPORT osKernelInitialize
|
||||
#ifdef __MBED_CMSIS_RTOS_CM
|
||||
IMPORT set_main_stack
|
||||
IMPORT set_stack_heap
|
||||
#endif
|
||||
IMPORT osKernelStart
|
||||
IMPORT osThreadCreate
|
||||
|
@ -675,13 +760,12 @@ __asm void __rt_entry (void) {
|
|||
* ARM Compiler ARM C and C++ Libraries and Floating-Point Support User Guide
|
||||
*/
|
||||
BL __user_setup_stackheap
|
||||
LDR R3,=armcc_heap_base
|
||||
LDR R4,=armcc_heap_top
|
||||
STR R0,[R3]
|
||||
STR R2,[R4]
|
||||
/* Ignore return value of __user_setup_stackheap since
|
||||
* this will be setup by set_stack_heap
|
||||
*/
|
||||
BL osKernelInitialize
|
||||
#ifdef __MBED_CMSIS_RTOS_CM
|
||||
BL set_main_stack
|
||||
BL set_stack_heap
|
||||
#endif
|
||||
LDR R0,=os_thread_def_main
|
||||
MOVS R1,#0
|
||||
|
@ -719,7 +803,7 @@ __attribute__((naked)) void software_init_hook_rtos (void) {
|
|||
__asm (
|
||||
"bl osKernelInitialize\n"
|
||||
#ifdef __MBED_CMSIS_RTOS_CM
|
||||
"bl set_main_stack\n"
|
||||
"bl set_stack_heap\n"
|
||||
#endif
|
||||
"ldr r0,=os_thread_def_main\n"
|
||||
"movs r1,#0\n"
|
||||
|
@ -796,7 +880,7 @@ void __iar_program_start( void )
|
|||
#endif
|
||||
osKernelInitialize();
|
||||
#ifdef __MBED_CMSIS_RTOS_CM
|
||||
set_main_stack();
|
||||
set_stack_heap();
|
||||
#endif
|
||||
osThreadCreate(&os_thread_def_main, NULL);
|
||||
osKernelStart();
|
||||
|
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "cmsis.h"
|
||||
#include "mbed.h"
|
||||
#include "rtos.h"
|
||||
#include "mbed_assert.h"
|
||||
|
||||
// Amount to malloc for each iteration
|
||||
#define MALLOC_TEST_SIZE 256
|
||||
// Malloc fill pattern
|
||||
#define MALLOC_FILL 0x55
|
||||
|
||||
extern uint32_t mbed_heap_start;
|
||||
extern uint32_t mbed_heap_size;
|
||||
extern uint32_t mbed_stack_isr_start;
|
||||
extern uint32_t mbed_stack_isr_size;
|
||||
|
||||
static uint32_t max_allocation_size = 0;
|
||||
|
||||
static bool inrange(uint32_t addr, uint32_t start, uint32_t size);
|
||||
static bool rangeinrange(uint32_t addr, uint32_t size, uint32_t start, uint32_t len);
|
||||
static bool valid_fill(uint8_t * data, uint32_t size, uint8_t fill);
|
||||
static bool allocate_and_fill_heap(void);
|
||||
static bool check_and_free_heap(void);
|
||||
|
||||
int main (void) {
|
||||
GREENTEA_SETUP(30, "default_auto");
|
||||
|
||||
char c;
|
||||
char * initial_stack = &c;
|
||||
char *initial_heap;
|
||||
|
||||
// Sanity check malloc
|
||||
initial_heap = (char*)malloc(1);
|
||||
if (initial_heap == NULL) {
|
||||
printf("Unable to malloc a single byte\n");
|
||||
GREENTEA_TESTSUITE_RESULT(false);
|
||||
}
|
||||
|
||||
if (!inrange((uint32_t)initial_heap, mbed_heap_start, mbed_heap_size)) {
|
||||
printf("Heap in wrong location\n");
|
||||
GREENTEA_TESTSUITE_RESULT(false);
|
||||
}
|
||||
// MSP stack should be very near end (test using within 128 bytes)
|
||||
uint32_t msp = __get_MSP();
|
||||
if (!inrange(msp, mbed_stack_isr_start + mbed_stack_isr_size - 128, 128)) {
|
||||
printf("Interrupt stack in wrong location\n");
|
||||
GREENTEA_TESTSUITE_RESULT(false);
|
||||
}
|
||||
|
||||
// Fully allocate the heap and stack
|
||||
bool ret = true;
|
||||
ret = ret && allocate_and_fill_heap();
|
||||
ret = ret && check_and_free_heap();
|
||||
|
||||
// Force a task switch so a stack check is performed
|
||||
Thread::wait(10);
|
||||
|
||||
printf("Total size dynamically allocated: %lu\n", max_allocation_size);
|
||||
|
||||
GREENTEA_TESTSUITE_RESULT(ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if addr is in range [start:start+size)
|
||||
*/
|
||||
static bool inrange(uint32_t addr, uint32_t start, uint32_t size)
|
||||
{
|
||||
return (addr >= start) && (addr < start + size) ? true : false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if [addr:addr+size] is inside [start:start+len]
|
||||
*/
|
||||
static bool rangeinrange(uint32_t addr, uint32_t size, uint32_t start, uint32_t len)
|
||||
{
|
||||
if (addr + size > start + len) {
|
||||
return false;
|
||||
}
|
||||
if (addr < start) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true of the region is filled only the the specified fill value
|
||||
*/
|
||||
static bool valid_fill(uint8_t * data, uint32_t size, uint8_t fill)
|
||||
{
|
||||
for (uint32_t i = 0; i < size; i++) {
|
||||
if (data[i] != fill) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
struct linked_list {
|
||||
linked_list * next;
|
||||
uint8_t data[MALLOC_TEST_SIZE];
|
||||
};
|
||||
|
||||
static linked_list *head = NULL;
|
||||
static bool allocate_and_fill_heap()
|
||||
{
|
||||
|
||||
linked_list *current;
|
||||
|
||||
current = (linked_list*)malloc(sizeof(linked_list));
|
||||
if (0 == current) {
|
||||
return false;
|
||||
}
|
||||
current->next = NULL;
|
||||
memset((void*)current->data, MALLOC_FILL, sizeof(current->data));
|
||||
|
||||
// Allocate until malloc returns NULL
|
||||
bool pass = true;
|
||||
head = current;
|
||||
while (true) {
|
||||
|
||||
// Allocate
|
||||
linked_list *temp = (linked_list*)malloc(sizeof(linked_list));
|
||||
if (NULL == temp) {
|
||||
break;
|
||||
}
|
||||
if (!rangeinrange((uint32_t)temp, sizeof(linked_list), mbed_heap_start, mbed_heap_size)) {
|
||||
printf("Memory allocation out of range\n");
|
||||
pass = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Init
|
||||
temp->next = NULL;
|
||||
memset((void*)temp->data, MALLOC_FILL, sizeof(current->data));
|
||||
|
||||
// Add to list
|
||||
current->next = temp;
|
||||
current = temp;
|
||||
}
|
||||
return pass;
|
||||
}
|
||||
|
||||
static bool check_and_free_heap()
|
||||
{
|
||||
uint32_t total_size = 0;
|
||||
linked_list * current = head;
|
||||
bool pass = true;
|
||||
while (current != NULL) {
|
||||
total_size += sizeof(linked_list);
|
||||
if (!valid_fill(current->data, sizeof(current->data), MALLOC_FILL)) {
|
||||
pass = false;
|
||||
}
|
||||
linked_list * next = current->next;
|
||||
free(current);
|
||||
current = next;
|
||||
}
|
||||
|
||||
max_allocation_size = total_size;
|
||||
return pass;
|
||||
}
|
|
@ -80,14 +80,6 @@
|
|||
#define OS_TIMERS 0
|
||||
#endif
|
||||
|
||||
/* If os timers macro is set to 0, there's no timer thread created, therefore
|
||||
* main thread has tid 0x01
|
||||
*/
|
||||
#if defined(OS_TIMERS) && (OS_TIMERS == 0)
|
||||
#define MAIN_THREAD_ID 0x01
|
||||
#else
|
||||
#define MAIN_THREAD_ID 0x02
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define DEFAULT_STACK_SIZE (WORDS_STACK_SIZE*4)
|
||||
|
|
|
@ -313,22 +313,10 @@ void rt_systick (void) {
|
|||
/*--------------------------- rt_stk_check ----------------------------------*/
|
||||
|
||||
__weak void rt_stk_check (void) {
|
||||
#ifdef __MBED_CMSIS_RTOS_CM
|
||||
/* Check for stack overflow. */
|
||||
if (os_tsk.run->task_id == MAIN_THREAD_ID) {
|
||||
// TODO: For the main thread the check should be done against the main heap pointer
|
||||
} else {
|
||||
if ((os_tsk.run->tsk_stack < (U32)os_tsk.run->stack) ||
|
||||
(os_tsk.run->stack[0] != MAGIC_WORD)) {
|
||||
os_error (OS_ERR_STK_OVF);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if ((os_tsk.run->tsk_stack < (U32)os_tsk.run->stack) ||
|
||||
(os_tsk.run->stack[0] != MAGIC_WORD)) {
|
||||
os_error (OS_ERR_STK_OVF);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in New Issue