Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
main.cpp
00001 /* 00002 * Copyright (c) 2016-2017, ARM Limited, All Rights Reserved 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00006 * not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #if defined(TARGET_CORTEX_A) 00019 #error [NOT_SUPPORTED] This function not supported for this target 00020 #endif 00021 00022 #include <stdio.h> 00023 #include <stdlib.h> 00024 #include <string.h> 00025 00026 #include "mbed.h" 00027 #include "cmsis.h" 00028 #include "greentea-client/test_env.h" 00029 #include "utest/utest.h" 00030 #include "unity/unity.h" 00031 00032 using utest::v1::Case; 00033 00034 static const int test_timeout = 30; 00035 00036 00037 // Amount to malloc for each iteration 00038 #define MALLOC_TEST_SIZE 256 00039 // Malloc fill pattern 00040 #define MALLOC_FILL 0x55 00041 00042 extern uint32_t mbed_heap_start; 00043 extern uint32_t mbed_heap_size; 00044 extern uint32_t mbed_stack_isr_start; 00045 extern uint32_t mbed_stack_isr_size; 00046 00047 00048 struct linked_list { 00049 linked_list * next; 00050 uint8_t data[MALLOC_TEST_SIZE]; 00051 }; 00052 00053 00054 00055 /* TODO: add memory layout test. 00056 * 00057 * The test was skipped for now since not all devices seems to comply with Mbed OS memory. 00058 * 00059 * @note Mbed OS memory model: https://os.mbed.com/docs/latest/reference/memory.html 00060 * 00061 */ 00062 00063 00064 /* 00065 * Return true if addr is in range [start:start+size) 00066 */ 00067 static bool inrange(uint32_t addr, uint32_t start, uint32_t size) 00068 { 00069 return (addr >= start) && (addr < (start + size)); 00070 } 00071 00072 /* 00073 * Return true if [addr:addr+size] is inside [start:start+len] 00074 */ 00075 static bool rangeinrange(uint32_t addr, uint32_t size, uint32_t start, uint32_t len) 00076 { 00077 if ((addr + size) > (start + len)) { 00078 return false; 00079 } 00080 if (addr < start) { 00081 return false; 00082 } 00083 return true; 00084 } 00085 00086 /* 00087 * Return true if the region is filled only with the specified value 00088 */ 00089 static bool valid_fill(uint8_t * data, uint32_t size, uint8_t fill) 00090 { 00091 for (uint32_t i = 0; i < size; i++) { 00092 if (data[i] != fill) { 00093 return false; 00094 } 00095 } 00096 return true; 00097 } 00098 00099 static void allocate_and_fill_heap(linked_list *&head) 00100 { 00101 linked_list *current; 00102 00103 current = (linked_list*) malloc(sizeof(linked_list)); 00104 TEST_ASSERT_NOT_NULL(current); 00105 00106 current->next = NULL; 00107 memset((void*) current->data, MALLOC_FILL, sizeof(current->data)); 00108 00109 // Allocate until malloc returns NULL 00110 head = current; 00111 while (true) { 00112 00113 // Allocate 00114 linked_list *temp = (linked_list*) malloc(sizeof(linked_list)); 00115 00116 if (NULL == temp) { 00117 break; 00118 } 00119 bool result = rangeinrange((uint32_t) temp, sizeof(linked_list), mbed_heap_start, mbed_heap_size); 00120 00121 TEST_ASSERT_TRUE_MESSAGE(result, "Memory allocation out of range"); 00122 00123 // Init 00124 temp->next = NULL; 00125 memset((void*) temp->data, MALLOC_FILL, sizeof(current->data)); 00126 00127 // Add to list 00128 current->next = temp; 00129 current = temp; 00130 } 00131 } 00132 00133 static void check_and_free_heap(linked_list *head, uint32_t &max_allocation_size) 00134 { 00135 uint32_t total_size = 0; 00136 linked_list * current = head; 00137 00138 while (current != NULL) { 00139 total_size += sizeof(linked_list); 00140 bool result = valid_fill(current->data, sizeof(current->data), MALLOC_FILL); 00141 00142 TEST_ASSERT_TRUE_MESSAGE(result, "Memory fill check failed"); 00143 00144 linked_list * next = current->next; 00145 free(current); 00146 current = next; 00147 } 00148 00149 max_allocation_size = total_size; 00150 } 00151 00152 /** Test heap allocation 00153 00154 Given a heap 00155 When memory is allocated from heap 00156 Then the memory is within heap boundary 00157 00158 */ 00159 void test_heap_in_range(void) 00160 { 00161 char *initial_heap; 00162 00163 // Sanity check malloc 00164 initial_heap = (char*) malloc(1); 00165 TEST_ASSERT_NOT_NULL(initial_heap); 00166 00167 bool result = inrange((uint32_t) initial_heap, mbed_heap_start, mbed_heap_size); 00168 00169 TEST_ASSERT_TRUE_MESSAGE(result, "Heap in wrong location"); 00170 free(initial_heap); 00171 } 00172 00173 /** Test for Main thread stack 00174 00175 Given a Main thread and its stack 00176 When check Main thread stack pointer 00177 Then the SP is within Main stack boundary 00178 */ 00179 void test_main_stack_in_range(void) 00180 { 00181 os_thread_t *thread = (os_thread_t*) osThreadGetId(); 00182 00183 uint32_t psp = __get_PSP(); 00184 uint8_t *stack_mem = (uint8_t*) thread->stack_mem; 00185 uint32_t stack_size = thread->stack_size; 00186 00187 // PSP stack should be somewhere in the middle 00188 bool result = inrange(psp, (uint32_t) stack_mem, stack_size); 00189 00190 TEST_ASSERT_TRUE_MESSAGE(result, "Main stack in wrong location"); 00191 } 00192 00193 /** Test for Scheduler/ISR thread stack 00194 00195 Given a Scheduler/ISR thread and its stack 00196 When check Scheduler/ISR thread stack pointer 00197 Then the SP is within Scheduler/ISR stack boundary 00198 */ 00199 void test_isr_stack_in_range(void) 00200 { 00201 // MSP stack should be very near end (test using within 128 bytes) 00202 uint32_t msp = __get_MSP(); 00203 bool result = inrange(msp, mbed_stack_isr_start + mbed_stack_isr_size - 128, 128); 00204 00205 TEST_ASSERT_TRUE_MESSAGE(result, "Interrupt stack in wrong location"); 00206 } 00207 00208 /** Test full heap allocation 00209 00210 Given a heap and linked_list data structure 00211 When linked_list is filled till run out of heap memory 00212 Then the memory is properly initialised and freed 00213 */ 00214 void test_heap_allocation_free(void) 00215 { 00216 linked_list *head = NULL; 00217 uint32_t max_allocation_size = 0; 00218 00219 // Fully allocate the heap and stack 00220 allocate_and_fill_heap(head); 00221 00222 check_and_free_heap(head, max_allocation_size); 00223 00224 // Force a task switch so a stack check is performed 00225 Thread::wait(10); 00226 00227 printf("Total size dynamically allocated: %luB\n", max_allocation_size); 00228 } 00229 00230 00231 // Test cases 00232 Case cases[] = { 00233 Case("Test heap in range", test_heap_in_range), 00234 Case("Test main stack in range", test_main_stack_in_range), 00235 Case("Test isr stack in range", test_isr_stack_in_range), 00236 Case("Test heap allocation and free", test_heap_allocation_free) 00237 }; 00238 00239 utest::v1::status_t greentea_test_setup(const size_t number_of_cases) 00240 { 00241 GREENTEA_SETUP(test_timeout, "default_auto"); 00242 return utest::v1::greentea_test_setup_handler(number_of_cases); 00243 } 00244 00245 utest::v1::Specification specification(greentea_test_setup, cases); 00246 00247 int main() 00248 { 00249 return !utest::v1::Harness::run(specification); 00250 }
Generated on Sun Jul 17 2022 08:25:27 by 1.7.2