Skip to content

Commit 1615dca

Browse files
committed
Add a test for heap and stack layout
Test the following components of the heap and stacks: -Heap and interrupt stack are at the expected locations -Entire heap can be used -Heap limit is properly enforced and returns NULL when out of of memory
1 parent 81382eb commit 1615dca

File tree

1 file changed

+179
-0
lines changed
  • rtos/rtx/TARGET_CORTEX_M/TESTS/memory/heap_and_stack

1 file changed

+179
-0
lines changed
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
/*
2+
* Copyright (c) 2016-2016, ARM Limited, All Rights Reserved
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License"); you may
6+
* not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
#include <stdio.h>
18+
#include <stdlib.h>
19+
#include <string.h>
20+
#include "greentea-client/test_env.h"
21+
#include "cmsis.h"
22+
#include "mbed.h"
23+
#include "rtos.h"
24+
#include "mbed_assert.h"
25+
26+
// Amount to malloc for each iteration
27+
#define MALLOC_TEST_SIZE 256
28+
// Malloc fill pattern
29+
#define MALLOC_FILL 0x55
30+
31+
extern uint32_t mbed_heap_start;
32+
extern uint32_t mbed_heap_size;
33+
extern uint32_t mbed_stack_isr_start;
34+
extern uint32_t mbed_stack_isr_size;
35+
36+
static uint32_t max_allocation_size = 0;
37+
38+
static bool inrange(uint32_t addr, uint32_t start, uint32_t size);
39+
static bool rangeinrange(uint32_t addr, uint32_t size, uint32_t start, uint32_t len);
40+
static bool valid_fill(uint8_t * data, uint32_t size, uint8_t fill);
41+
static bool allocate_and_fill_heap(void);
42+
static bool check_and_free_heap(void);
43+
44+
int main (void) {
45+
GREENTEA_SETUP(30, "default_auto");
46+
47+
char c;
48+
char * initial_stack = &c;
49+
char *initial_heap;
50+
51+
// Sanity check malloc
52+
initial_heap = (char*)malloc(1);
53+
if (initial_heap == NULL) {
54+
printf("Unable to malloc a single byte\n");
55+
GREENTEA_TESTSUITE_RESULT(false);
56+
}
57+
58+
if (!inrange((uint32_t)initial_heap, mbed_heap_start, mbed_heap_size)) {
59+
printf("Heap in wrong location\n");
60+
GREENTEA_TESTSUITE_RESULT(false);
61+
}
62+
// MSP stack should be very near end (test using within 128 bytes)
63+
uint32_t msp = __get_MSP();
64+
if (!inrange(msp, mbed_stack_isr_start + mbed_stack_isr_size - 128, 128)) {
65+
printf("Interrupt stack in wrong location\n");
66+
GREENTEA_TESTSUITE_RESULT(false);
67+
}
68+
69+
// Fully allocate the heap and stack
70+
bool ret = true;
71+
ret = ret && allocate_and_fill_heap();
72+
ret = ret && check_and_free_heap();
73+
74+
// Force a task switch so a stack check is performed
75+
Thread::wait(10);
76+
77+
printf("Total size dynamically allocated: %lu\n", max_allocation_size);
78+
79+
GREENTEA_TESTSUITE_RESULT(ret);
80+
}
81+
82+
/*
83+
* Return true if addr is in range [start:start+size)
84+
*/
85+
static bool inrange(uint32_t addr, uint32_t start, uint32_t size)
86+
{
87+
return (addr >= start) && (addr < start + size) ? true : false;
88+
}
89+
90+
/*
91+
* Return true if [addr:addr+size] is inside [start:start+len]
92+
*/
93+
static bool rangeinrange(uint32_t addr, uint32_t size, uint32_t start, uint32_t len)
94+
{
95+
if (addr + size > start + len) {
96+
return false;
97+
}
98+
if (addr < start) {
99+
return false;
100+
}
101+
return true;
102+
}
103+
104+
/*
105+
* Return true of the region is filled only the the specified fill value
106+
*/
107+
static bool valid_fill(uint8_t * data, uint32_t size, uint8_t fill)
108+
{
109+
for (uint32_t i = 0; i < size; i++) {
110+
if (data[i] != fill) {
111+
return false;
112+
}
113+
}
114+
return true;
115+
}
116+
117+
struct linked_list {
118+
linked_list * next;
119+
uint8_t data[MALLOC_TEST_SIZE];
120+
};
121+
122+
static linked_list *head = NULL;
123+
static bool allocate_and_fill_heap()
124+
{
125+
126+
linked_list *current;
127+
128+
current = (linked_list*)malloc(sizeof(linked_list));
129+
if (0 == current) {
130+
return false;
131+
}
132+
current->next = NULL;
133+
memset((void*)current->data, MALLOC_FILL, sizeof(current->data));
134+
135+
// Allocate until malloc returns NULL
136+
bool pass = true;
137+
head = current;
138+
while (true) {
139+
140+
// Allocate
141+
linked_list *temp = (linked_list*)malloc(sizeof(linked_list));
142+
if (NULL == temp) {
143+
break;
144+
}
145+
if (!rangeinrange((uint32_t)temp, sizeof(linked_list), mbed_heap_start, mbed_heap_size)) {
146+
printf("Memory allocation out of range\n");
147+
pass = false;
148+
break;
149+
}
150+
151+
// Init
152+
temp->next = NULL;
153+
memset((void*)temp->data, MALLOC_FILL, sizeof(current->data));
154+
155+
// Add to list
156+
current->next = temp;
157+
current = temp;
158+
}
159+
return pass;
160+
}
161+
162+
static bool check_and_free_heap()
163+
{
164+
uint32_t total_size = 0;
165+
linked_list * current = head;
166+
bool pass = true;
167+
while (current != NULL) {
168+
total_size += sizeof(linked_list);
169+
if (!valid_fill(current->data, sizeof(current->data), MALLOC_FILL)) {
170+
pass = false;
171+
}
172+
linked_list * next = current->next;
173+
free(current);
174+
current = next;
175+
}
176+
177+
max_allocation_size = total_size;
178+
return pass;
179+
}

0 commit comments

Comments
 (0)