mbed-os/TESTS/mbedmicro-rtos-mbed/heap_and_stack/main.cpp

185 lines
4.9 KiB
C++
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

/*
* 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.
*/
#if defined(TARGET_CORTEX_A)
  #error [NOT_SUPPORTED] This function not supported for this target
#endif
#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;
}