mbed-os
Dependents: cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more
rtos/TARGET_CORTEX/mbed_boot.c@0:b74591d5ab33, 2017-12-11 (annotated)
- Committer:
- be_bryan
- Date:
- Mon Dec 11 17:54:04 2017 +0000
- Revision:
- 0:b74591d5ab33
motor ++
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
be_bryan | 0:b74591d5ab33 | 1 | /* mbed Microcontroller Library |
be_bryan | 0:b74591d5ab33 | 2 | * Copyright (c) 2006-2016 ARM Limited |
be_bryan | 0:b74591d5ab33 | 3 | * |
be_bryan | 0:b74591d5ab33 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
be_bryan | 0:b74591d5ab33 | 5 | * you may not use this file except in compliance with the License. |
be_bryan | 0:b74591d5ab33 | 6 | * You may obtain a copy of the License at |
be_bryan | 0:b74591d5ab33 | 7 | * |
be_bryan | 0:b74591d5ab33 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
be_bryan | 0:b74591d5ab33 | 9 | * |
be_bryan | 0:b74591d5ab33 | 10 | * Unless required by applicable law or agreed to in writing, software |
be_bryan | 0:b74591d5ab33 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
be_bryan | 0:b74591d5ab33 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
be_bryan | 0:b74591d5ab33 | 13 | * See the License for the specific language governing permissions and |
be_bryan | 0:b74591d5ab33 | 14 | * limitations under the License. |
be_bryan | 0:b74591d5ab33 | 15 | */ |
be_bryan | 0:b74591d5ab33 | 16 | |
be_bryan | 0:b74591d5ab33 | 17 | /* mbed OS boot sequence |
be_bryan | 0:b74591d5ab33 | 18 | * |
be_bryan | 0:b74591d5ab33 | 19 | * Most of mbed supported targets use default ARM Cortex M boot approach, where the core starts executing reset vector |
be_bryan | 0:b74591d5ab33 | 20 | * after power up. Reset ISR is defined for each target by the vendor (basing on CMSIS template). Reset vector is |
be_bryan | 0:b74591d5ab33 | 21 | * responsible for low level platform init and then calling in libc (__main). Depending on compiler and version of C |
be_bryan | 0:b74591d5ab33 | 22 | * library, predefined function will be called which is implemented by mbed OS. |
be_bryan | 0:b74591d5ab33 | 23 | * |
be_bryan | 0:b74591d5ab33 | 24 | * There's number of functions, vendor and users can provide to setup the platform and/or inject a code to be executed |
be_bryan | 0:b74591d5ab33 | 25 | * before main(): |
be_bryan | 0:b74591d5ab33 | 26 | * * Reset vector and SystemInit: Reset vector should do low level core and board initialization. |
be_bryan | 0:b74591d5ab33 | 27 | * * mbed_sdk_init: Higher level board init and making sure the board is ready for the mbed OS. |
be_bryan | 0:b74591d5ab33 | 28 | * * mbed_main: User's code to be executed before main(). |
be_bryan | 0:b74591d5ab33 | 29 | * * main: Standard application code. |
be_bryan | 0:b74591d5ab33 | 30 | * |
be_bryan | 0:b74591d5ab33 | 31 | * Detailed boot procedures: |
be_bryan | 0:b74591d5ab33 | 32 | * |
be_bryan | 0:b74591d5ab33 | 33 | * For ARMCC: |
be_bryan | 0:b74591d5ab33 | 34 | * ========== |
be_bryan | 0:b74591d5ab33 | 35 | * |
be_bryan | 0:b74591d5ab33 | 36 | * Reset (TARGET) |
be_bryan | 0:b74591d5ab33 | 37 | * -> SystemInit (TARGET) |
be_bryan | 0:b74591d5ab33 | 38 | * -> __main (LIBC) |
be_bryan | 0:b74591d5ab33 | 39 | * -> __rt_entry (MBED: rtos/mbed_boot.c) |
be_bryan | 0:b74591d5ab33 | 40 | * -> __user_setup_stackheap (LIBC) |
be_bryan | 0:b74591d5ab33 | 41 | * -> mbed_set_stack_heap (MBED: rtos/mbed_boot.c) |
be_bryan | 0:b74591d5ab33 | 42 | * -> mbed_cpy_nvic (MBED: rtos/mbed_boot.c) |
be_bryan | 0:b74591d5ab33 | 43 | * -> mbed_sdk_init (TARGET) |
be_bryan | 0:b74591d5ab33 | 44 | * -> _platform_post_stackheap_init (RTX) |
be_bryan | 0:b74591d5ab33 | 45 | * -> osKernelInitialize (RTX) |
be_bryan | 0:b74591d5ab33 | 46 | * -> mbed_start_main (MBED: rtos/mbed_boot.c) |
be_bryan | 0:b74591d5ab33 | 47 | * -> osThreadNew (RTX) |
be_bryan | 0:b74591d5ab33 | 48 | * -> pre_main(MBED: rtos/mbed_boot.c) |
be_bryan | 0:b74591d5ab33 | 49 | * -> __rt_lib_init (LIBC) |
be_bryan | 0:b74591d5ab33 | 50 | * -> $Sub$$main (MBED: rtos/mbed_boot.c) |
be_bryan | 0:b74591d5ab33 | 51 | * -> mbed_main (MBED: rtos/mbed_boot.c) |
be_bryan | 0:b74591d5ab33 | 52 | * -> main (APP) |
be_bryan | 0:b74591d5ab33 | 53 | * -> osKernelStart (RTX) |
be_bryan | 0:b74591d5ab33 | 54 | * |
be_bryan | 0:b74591d5ab33 | 55 | * In addition to the above, libc will use functions defined by RTX: __user_perthread_libspace, _mutex_initialize, |
be_bryan | 0:b74591d5ab33 | 56 | * _mutex_acquire, _mutex_release, _mutex_free for details consult: ARM C and C++ Libraries and Floating-Point |
be_bryan | 0:b74591d5ab33 | 57 | * Support User Guide. |
be_bryan | 0:b74591d5ab33 | 58 | * |
be_bryan | 0:b74591d5ab33 | 59 | * For MICROLIB: |
be_bryan | 0:b74591d5ab33 | 60 | * ========== |
be_bryan | 0:b74591d5ab33 | 61 | * |
be_bryan | 0:b74591d5ab33 | 62 | * Reset (TARGET) |
be_bryan | 0:b74591d5ab33 | 63 | * -> SystemInit (TARGET) |
be_bryan | 0:b74591d5ab33 | 64 | * -> __main (LIBC) |
be_bryan | 0:b74591d5ab33 | 65 | * -> _main_init (MBED: rtos/mbed_boot.c) |
be_bryan | 0:b74591d5ab33 | 66 | * -> mbed_set_stack_heap (MBED: rtos/mbed_boot.c) |
be_bryan | 0:b74591d5ab33 | 67 | * -> mbed_cpy_nvic (MBED: rtos/mbed_boot.c) |
be_bryan | 0:b74591d5ab33 | 68 | * -> mbed_sdk_init (TARGET) |
be_bryan | 0:b74591d5ab33 | 69 | * -> osKernelInitialize (RTX) |
be_bryan | 0:b74591d5ab33 | 70 | * -> mbed_start_main (MBED: rtos/mbed_boot.c) |
be_bryan | 0:b74591d5ab33 | 71 | * -> osThreadNew (RTX) |
be_bryan | 0:b74591d5ab33 | 72 | * -> pre_main(MBED: rtos/mbed_boot.c) |
be_bryan | 0:b74591d5ab33 | 73 | * -> __cpp_initialize__aeabi_ (LIBC) |
be_bryan | 0:b74591d5ab33 | 74 | * -> $Sub$$main (MBED: rtos/mbed_boot.c) |
be_bryan | 0:b74591d5ab33 | 75 | * -> mbed_main (MBED: rtos/mbed_boot.c) |
be_bryan | 0:b74591d5ab33 | 76 | * -> main (APP) |
be_bryan | 0:b74591d5ab33 | 77 | * -> osKernelStart (RTX) |
be_bryan | 0:b74591d5ab33 | 78 | * |
be_bryan | 0:b74591d5ab33 | 79 | * For GCC: |
be_bryan | 0:b74591d5ab33 | 80 | * ======== |
be_bryan | 0:b74591d5ab33 | 81 | * |
be_bryan | 0:b74591d5ab33 | 82 | * Reset (TARGET) |
be_bryan | 0:b74591d5ab33 | 83 | * -> SystemInit (TARGET) |
be_bryan | 0:b74591d5ab33 | 84 | * -> __main (LIBC) |
be_bryan | 0:b74591d5ab33 | 85 | * -> software_init_hook (MBED: rtos/mbed_boot.c) |
be_bryan | 0:b74591d5ab33 | 86 | * -> mbed_set_stack_heap (MBED: rtos/mbed_boot.c) |
be_bryan | 0:b74591d5ab33 | 87 | * -> mbed_cpy_nvic (MBED: rtos/mbed_boot.c) |
be_bryan | 0:b74591d5ab33 | 88 | * -> mbed_sdk_init (TARGET) |
be_bryan | 0:b74591d5ab33 | 89 | * -> osKernelInitialize (RTX) |
be_bryan | 0:b74591d5ab33 | 90 | * -> mbed_start_main (MBED: rtos/mbed_boot.c) |
be_bryan | 0:b74591d5ab33 | 91 | * -> osThreadNew (RTX) |
be_bryan | 0:b74591d5ab33 | 92 | * -> pre_main(MBED: rtos/mbed_boot.c) |
be_bryan | 0:b74591d5ab33 | 93 | * -> __libc_init_array (LIBC) |
be_bryan | 0:b74591d5ab33 | 94 | * -> __wrap_main (MBED: rtos/mbed_boot.c) |
be_bryan | 0:b74591d5ab33 | 95 | * -> mbed_main (MBED: rtos/mbed_boot.c) |
be_bryan | 0:b74591d5ab33 | 96 | * -> __real_main (APP) |
be_bryan | 0:b74591d5ab33 | 97 | * -> osKernelStart (RTX) |
be_bryan | 0:b74591d5ab33 | 98 | * |
be_bryan | 0:b74591d5ab33 | 99 | * For IAR: |
be_bryan | 0:b74591d5ab33 | 100 | * ======== |
be_bryan | 0:b74591d5ab33 | 101 | * |
be_bryan | 0:b74591d5ab33 | 102 | * Reset (TARGET) |
be_bryan | 0:b74591d5ab33 | 103 | * -> SystemInit (TARGET) |
be_bryan | 0:b74591d5ab33 | 104 | * -> __iar_program_start |
be_bryan | 0:b74591d5ab33 | 105 | * -> __iar_init_core |
be_bryan | 0:b74591d5ab33 | 106 | * -> __iar_init_core |
be_bryan | 0:b74591d5ab33 | 107 | * -> __iar_init_vfp |
be_bryan | 0:b74591d5ab33 | 108 | * -> __low_level_init |
be_bryan | 0:b74591d5ab33 | 109 | * -> __iar_data_init3 |
be_bryan | 0:b74591d5ab33 | 110 | * -> mbed_cpy_nvic (MBED: rtos/mbed_boot.c) |
be_bryan | 0:b74591d5ab33 | 111 | * -> mbed_sdk_init (TARGET) |
be_bryan | 0:b74591d5ab33 | 112 | * -> mbed_set_stack_heap (MBED: rtos/mbed_boot.c) |
be_bryan | 0:b74591d5ab33 | 113 | * -> osKernelInitialize (RTX) |
be_bryan | 0:b74591d5ab33 | 114 | * -> mbed_start_main (MBED: rtos/mbed_boot.c) |
be_bryan | 0:b74591d5ab33 | 115 | * -> osThreadNew (RTX) |
be_bryan | 0:b74591d5ab33 | 116 | * -> pre_main(MBED: rtos/mbed_boot.c) |
be_bryan | 0:b74591d5ab33 | 117 | * -> __iar_dynamic_initialization |
be_bryan | 0:b74591d5ab33 | 118 | * -> main |
be_bryan | 0:b74591d5ab33 | 119 | * -> osKernelStart (RTX) |
be_bryan | 0:b74591d5ab33 | 120 | * |
be_bryan | 0:b74591d5ab33 | 121 | * Other notes: |
be_bryan | 0:b74591d5ab33 | 122 | * |
be_bryan | 0:b74591d5ab33 | 123 | * * In addition to the above, libc will use functions defined in mbed_boot.c: __rtos_malloc_lock/unlock, |
be_bryan | 0:b74591d5ab33 | 124 | * __rtos_env_lock/unlock. |
be_bryan | 0:b74591d5ab33 | 125 | * |
be_bryan | 0:b74591d5ab33 | 126 | * * First step after the execution is passed to mbed, software_init_hook for GCC and __rt_entry for ARMC is to |
be_bryan | 0:b74591d5ab33 | 127 | * initialize heap. |
be_bryan | 0:b74591d5ab33 | 128 | * |
be_bryan | 0:b74591d5ab33 | 129 | * Memory layout notes: |
be_bryan | 0:b74591d5ab33 | 130 | * ==================== |
be_bryan | 0:b74591d5ab33 | 131 | * |
be_bryan | 0:b74591d5ab33 | 132 | * IAR Default Memory layout notes: |
be_bryan | 0:b74591d5ab33 | 133 | * -Heap defined by "HEAP" region in .icf file |
be_bryan | 0:b74591d5ab33 | 134 | * -Interrupt stack defined by "CSTACK" region in .icf file |
be_bryan | 0:b74591d5ab33 | 135 | * -Value INITIAL_SP is ignored |
be_bryan | 0:b74591d5ab33 | 136 | * |
be_bryan | 0:b74591d5ab33 | 137 | * IAR Custom Memory layout notes: |
be_bryan | 0:b74591d5ab33 | 138 | * -There is no custom layout available for IAR - everything must be defined in |
be_bryan | 0:b74591d5ab33 | 139 | * the .icf file and use the default layout |
be_bryan | 0:b74591d5ab33 | 140 | * |
be_bryan | 0:b74591d5ab33 | 141 | * |
be_bryan | 0:b74591d5ab33 | 142 | * GCC Default Memory layout notes: |
be_bryan | 0:b74591d5ab33 | 143 | * -Block of memory from symbol __end__ to define INITIAL_SP used to setup interrupt |
be_bryan | 0:b74591d5ab33 | 144 | * stack and heap in the function set_stack_heap() |
be_bryan | 0:b74591d5ab33 | 145 | * -ISR_STACK_SIZE can be overridden to be larger or smaller |
be_bryan | 0:b74591d5ab33 | 146 | * |
be_bryan | 0:b74591d5ab33 | 147 | * GCC Custom Memory layout notes: |
be_bryan | 0:b74591d5ab33 | 148 | * -Heap can be explicitly placed by defining both HEAP_START and HEAP_SIZE |
be_bryan | 0:b74591d5ab33 | 149 | * -Interrupt stack can be explicitly placed by defining both ISR_STACK_START and ISR_STACK_SIZE |
be_bryan | 0:b74591d5ab33 | 150 | * |
be_bryan | 0:b74591d5ab33 | 151 | * |
be_bryan | 0:b74591d5ab33 | 152 | * ARM Memory layout |
be_bryan | 0:b74591d5ab33 | 153 | * -Block of memory from end of region "RW_IRAM1" to define INITIAL_SP used to setup interrupt |
be_bryan | 0:b74591d5ab33 | 154 | * stack and heap in the function set_stack_heap() |
be_bryan | 0:b74591d5ab33 | 155 | * -ISR_STACK_SIZE can be overridden to be larger or smaller |
be_bryan | 0:b74591d5ab33 | 156 | * |
be_bryan | 0:b74591d5ab33 | 157 | * ARM Custom Memory layout notes: |
be_bryan | 0:b74591d5ab33 | 158 | * -Heap can be explicitly placed by defining both HEAP_START and HEAP_SIZE |
be_bryan | 0:b74591d5ab33 | 159 | * -Interrupt stack can be explicitly placed by defining both ISR_STACK_START and ISR_STACK_SIZE |
be_bryan | 0:b74591d5ab33 | 160 | * |
be_bryan | 0:b74591d5ab33 | 161 | */ |
be_bryan | 0:b74591d5ab33 | 162 | |
be_bryan | 0:b74591d5ab33 | 163 | #include <stdlib.h> |
be_bryan | 0:b74591d5ab33 | 164 | |
be_bryan | 0:b74591d5ab33 | 165 | #include "cmsis.h" |
be_bryan | 0:b74591d5ab33 | 166 | #include "mbed_rtx.h" |
be_bryan | 0:b74591d5ab33 | 167 | #include "mbed_rtos_storage.h" |
be_bryan | 0:b74591d5ab33 | 168 | #include "cmsis_os2.h" |
be_bryan | 0:b74591d5ab33 | 169 | #include "mbed_toolchain.h" |
be_bryan | 0:b74591d5ab33 | 170 | #include "mbed_error.h" |
be_bryan | 0:b74591d5ab33 | 171 | #include "mbed_critical.h" |
be_bryan | 0:b74591d5ab33 | 172 | #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ >= 8000000) |
be_bryan | 0:b74591d5ab33 | 173 | #include <DLib_Threads.h> |
be_bryan | 0:b74591d5ab33 | 174 | #endif |
be_bryan | 0:b74591d5ab33 | 175 | /* Heap limits - only used if set */ |
be_bryan | 0:b74591d5ab33 | 176 | extern unsigned char *mbed_heap_start; |
be_bryan | 0:b74591d5ab33 | 177 | extern uint32_t mbed_heap_size; |
be_bryan | 0:b74591d5ab33 | 178 | |
be_bryan | 0:b74591d5ab33 | 179 | unsigned char *mbed_stack_isr_start = 0; |
be_bryan | 0:b74591d5ab33 | 180 | uint32_t mbed_stack_isr_size = 0; |
be_bryan | 0:b74591d5ab33 | 181 | |
be_bryan | 0:b74591d5ab33 | 182 | WEAK void mbed_main(void); |
be_bryan | 0:b74591d5ab33 | 183 | void pre_main (void); |
be_bryan | 0:b74591d5ab33 | 184 | |
be_bryan | 0:b74591d5ab33 | 185 | osThreadAttr_t _main_thread_attr; |
be_bryan | 0:b74591d5ab33 | 186 | |
be_bryan | 0:b74591d5ab33 | 187 | /** The main thread's stack size can be configured by the application, if not explicitly specified it'll default to 4K */ |
be_bryan | 0:b74591d5ab33 | 188 | #ifndef MBED_CONF_APP_MAIN_STACK_SIZE |
be_bryan | 0:b74591d5ab33 | 189 | #define MBED_CONF_APP_MAIN_STACK_SIZE 4096 |
be_bryan | 0:b74591d5ab33 | 190 | #endif |
be_bryan | 0:b74591d5ab33 | 191 | MBED_ALIGN(8) char _main_stack[MBED_CONF_APP_MAIN_STACK_SIZE]; |
be_bryan | 0:b74591d5ab33 | 192 | mbed_rtos_storage_thread_t _main_obj; |
be_bryan | 0:b74591d5ab33 | 193 | |
be_bryan | 0:b74591d5ab33 | 194 | osMutexId_t singleton_mutex_id; |
be_bryan | 0:b74591d5ab33 | 195 | mbed_rtos_storage_mutex_t singleton_mutex_obj; |
be_bryan | 0:b74591d5ab33 | 196 | osMutexAttr_t singleton_mutex_attr; |
be_bryan | 0:b74591d5ab33 | 197 | |
be_bryan | 0:b74591d5ab33 | 198 | /* |
be_bryan | 0:b74591d5ab33 | 199 | * Sanity check values |
be_bryan | 0:b74591d5ab33 | 200 | */ |
be_bryan | 0:b74591d5ab33 | 201 | #if defined(__ICCARM__) && \ |
be_bryan | 0:b74591d5ab33 | 202 | (defined(HEAP_START) || defined(HEAP_SIZE) || \ |
be_bryan | 0:b74591d5ab33 | 203 | defined(ISR_STACK_START) && defined(ISR_STACK_SIZE)) |
be_bryan | 0:b74591d5ab33 | 204 | #error "No custom layout allowed for IAR. Use .icf file instead" |
be_bryan | 0:b74591d5ab33 | 205 | #endif |
be_bryan | 0:b74591d5ab33 | 206 | #if defined(HEAP_START) && !defined(HEAP_SIZE) |
be_bryan | 0:b74591d5ab33 | 207 | #error "HEAP_SIZE must be defined if HEAP_START is defined" |
be_bryan | 0:b74591d5ab33 | 208 | #endif |
be_bryan | 0:b74591d5ab33 | 209 | #if defined(ISR_STACK_START) && !defined(ISR_STACK_SIZE) |
be_bryan | 0:b74591d5ab33 | 210 | #error "ISR_STACK_SIZE must be defined if ISR_STACK_START is defined" |
be_bryan | 0:b74591d5ab33 | 211 | #endif |
be_bryan | 0:b74591d5ab33 | 212 | #if defined(HEAP_SIZE) && !defined(HEAP_START) |
be_bryan | 0:b74591d5ab33 | 213 | #error "HEAP_START must be defined if HEAP_SIZE is defined" |
be_bryan | 0:b74591d5ab33 | 214 | #endif |
be_bryan | 0:b74591d5ab33 | 215 | |
be_bryan | 0:b74591d5ab33 | 216 | /* IAR - INITIAL_SP and HEAP_START ignored as described in Memory layout notes above |
be_bryan | 0:b74591d5ab33 | 217 | */ |
be_bryan | 0:b74591d5ab33 | 218 | #if !defined(__ICCARM__) && !defined(INITIAL_SP) && !defined(HEAP_START) |
be_bryan | 0:b74591d5ab33 | 219 | #error "no target defined" |
be_bryan | 0:b74591d5ab33 | 220 | #endif |
be_bryan | 0:b74591d5ab33 | 221 | |
be_bryan | 0:b74591d5ab33 | 222 | /* Interrupt stack and heap always defined for IAR |
be_bryan | 0:b74591d5ab33 | 223 | * Main thread defined here |
be_bryan | 0:b74591d5ab33 | 224 | */ |
be_bryan | 0:b74591d5ab33 | 225 | #if defined(__ICCARM__) |
be_bryan | 0:b74591d5ab33 | 226 | #pragma section="CSTACK" |
be_bryan | 0:b74591d5ab33 | 227 | #pragma section="HEAP" |
be_bryan | 0:b74591d5ab33 | 228 | #define HEAP_START ((unsigned char*)__section_begin("HEAP")) |
be_bryan | 0:b74591d5ab33 | 229 | #define HEAP_SIZE ((uint32_t)__section_size("HEAP")) |
be_bryan | 0:b74591d5ab33 | 230 | #define ISR_STACK_START ((unsigned char*)__section_begin("CSTACK")) |
be_bryan | 0:b74591d5ab33 | 231 | #define ISR_STACK_SIZE ((uint32_t)__section_size("CSTACK")) |
be_bryan | 0:b74591d5ab33 | 232 | #endif |
be_bryan | 0:b74591d5ab33 | 233 | |
be_bryan | 0:b74591d5ab33 | 234 | /* Define heap region if it has not been defined already */ |
be_bryan | 0:b74591d5ab33 | 235 | #if !defined(HEAP_START) |
be_bryan | 0:b74591d5ab33 | 236 | #if defined(__ICCARM__) |
be_bryan | 0:b74591d5ab33 | 237 | #error "Heap should already be defined for IAR" |
be_bryan | 0:b74591d5ab33 | 238 | #elif defined(__CC_ARM) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) |
be_bryan | 0:b74591d5ab33 | 239 | extern uint32_t Image$$RW_IRAM1$$ZI$$Limit[]; |
be_bryan | 0:b74591d5ab33 | 240 | #define HEAP_START ((unsigned char*)Image$$RW_IRAM1$$ZI$$Limit) |
be_bryan | 0:b74591d5ab33 | 241 | #define HEAP_SIZE ((uint32_t)((uint32_t)INITIAL_SP - (uint32_t)HEAP_START)) |
be_bryan | 0:b74591d5ab33 | 242 | #elif defined(__GNUC__) |
be_bryan | 0:b74591d5ab33 | 243 | extern uint32_t __end__[]; |
be_bryan | 0:b74591d5ab33 | 244 | #define HEAP_START ((unsigned char*)__end__) |
be_bryan | 0:b74591d5ab33 | 245 | #define HEAP_SIZE ((uint32_t)((uint32_t)INITIAL_SP - (uint32_t)HEAP_START)) |
be_bryan | 0:b74591d5ab33 | 246 | #endif |
be_bryan | 0:b74591d5ab33 | 247 | #endif |
be_bryan | 0:b74591d5ab33 | 248 | |
be_bryan | 0:b74591d5ab33 | 249 | /* Define stack sizes if they haven't been set already */ |
be_bryan | 0:b74591d5ab33 | 250 | #if !defined(ISR_STACK_SIZE) |
be_bryan | 0:b74591d5ab33 | 251 | #define ISR_STACK_SIZE ((uint32_t)1024) |
be_bryan | 0:b74591d5ab33 | 252 | #endif |
be_bryan | 0:b74591d5ab33 | 253 | |
be_bryan | 0:b74591d5ab33 | 254 | /* |
be_bryan | 0:b74591d5ab33 | 255 | * mbed_set_stack_heap purpose is to set the following variables: |
be_bryan | 0:b74591d5ab33 | 256 | * -mbed_heap_start |
be_bryan | 0:b74591d5ab33 | 257 | * -mbed_heap_size |
be_bryan | 0:b74591d5ab33 | 258 | * -mbed_stack_isr_start |
be_bryan | 0:b74591d5ab33 | 259 | * -mbed_stack_isr_size |
be_bryan | 0:b74591d5ab33 | 260 | */ |
be_bryan | 0:b74591d5ab33 | 261 | void mbed_set_stack_heap(void) { |
be_bryan | 0:b74591d5ab33 | 262 | |
be_bryan | 0:b74591d5ab33 | 263 | unsigned char *free_start = HEAP_START; |
be_bryan | 0:b74591d5ab33 | 264 | uint32_t free_size = HEAP_SIZE; |
be_bryan | 0:b74591d5ab33 | 265 | |
be_bryan | 0:b74591d5ab33 | 266 | #ifdef ISR_STACK_START |
be_bryan | 0:b74591d5ab33 | 267 | /* Interrupt stack explicitly specified */ |
be_bryan | 0:b74591d5ab33 | 268 | mbed_stack_isr_size = ISR_STACK_SIZE; |
be_bryan | 0:b74591d5ab33 | 269 | mbed_stack_isr_start = ISR_STACK_START; |
be_bryan | 0:b74591d5ab33 | 270 | #else |
be_bryan | 0:b74591d5ab33 | 271 | /* Interrupt stack - reserve space at the end of the free block */ |
be_bryan | 0:b74591d5ab33 | 272 | mbed_stack_isr_size = ISR_STACK_SIZE < free_size ? ISR_STACK_SIZE : free_size; |
be_bryan | 0:b74591d5ab33 | 273 | mbed_stack_isr_start = free_start + free_size - mbed_stack_isr_size; |
be_bryan | 0:b74591d5ab33 | 274 | free_size -= mbed_stack_isr_size; |
be_bryan | 0:b74591d5ab33 | 275 | #endif |
be_bryan | 0:b74591d5ab33 | 276 | |
be_bryan | 0:b74591d5ab33 | 277 | /* Heap - everything else */ |
be_bryan | 0:b74591d5ab33 | 278 | mbed_heap_size = free_size; |
be_bryan | 0:b74591d5ab33 | 279 | mbed_heap_start = free_start; |
be_bryan | 0:b74591d5ab33 | 280 | } |
be_bryan | 0:b74591d5ab33 | 281 | |
be_bryan | 0:b74591d5ab33 | 282 | static void mbed_cpy_nvic(void) |
be_bryan | 0:b74591d5ab33 | 283 | { |
be_bryan | 0:b74591d5ab33 | 284 | /* If vector address in RAM is defined, copy and switch to dynamic vectors. Exceptions for M0 which doesn't have |
be_bryan | 0:b74591d5ab33 | 285 | VTOR register and for A9 for which CMSIS doesn't define NVIC_SetVector; in both cases target code is |
be_bryan | 0:b74591d5ab33 | 286 | responsible for correctly handling the vectors. |
be_bryan | 0:b74591d5ab33 | 287 | */ |
be_bryan | 0:b74591d5ab33 | 288 | #if !defined(__CORTEX_M0) && !defined(__CORTEX_A9) |
be_bryan | 0:b74591d5ab33 | 289 | #ifdef NVIC_RAM_VECTOR_ADDRESS |
be_bryan | 0:b74591d5ab33 | 290 | uint32_t *old_vectors = (uint32_t *)SCB->VTOR; |
be_bryan | 0:b74591d5ab33 | 291 | uint32_t *vectors = (uint32_t*)NVIC_RAM_VECTOR_ADDRESS; |
be_bryan | 0:b74591d5ab33 | 292 | for (int i = 0; i < NVIC_NUM_VECTORS; i++) { |
be_bryan | 0:b74591d5ab33 | 293 | vectors[i] = old_vectors[i]; |
be_bryan | 0:b74591d5ab33 | 294 | } |
be_bryan | 0:b74591d5ab33 | 295 | SCB->VTOR = (uint32_t)NVIC_RAM_VECTOR_ADDRESS; |
be_bryan | 0:b74591d5ab33 | 296 | #endif /* NVIC_RAM_VECTOR_ADDRESS */ |
be_bryan | 0:b74591d5ab33 | 297 | #endif /* !defined(__CORTEX_M0) && !defined(__CORTEX_A9) */ |
be_bryan | 0:b74591d5ab33 | 298 | } |
be_bryan | 0:b74591d5ab33 | 299 | |
be_bryan | 0:b74591d5ab33 | 300 | /* mbed_main is a function that is called before main() |
be_bryan | 0:b74591d5ab33 | 301 | * mbed_sdk_init() is also a function that is called before main(), but unlike |
be_bryan | 0:b74591d5ab33 | 302 | * mbed_main(), it is not meant for user code, but for the SDK itself to perform |
be_bryan | 0:b74591d5ab33 | 303 | * initializations before main() is called. |
be_bryan | 0:b74591d5ab33 | 304 | */ |
be_bryan | 0:b74591d5ab33 | 305 | WEAK void mbed_main(void) { |
be_bryan | 0:b74591d5ab33 | 306 | |
be_bryan | 0:b74591d5ab33 | 307 | } |
be_bryan | 0:b74591d5ab33 | 308 | |
be_bryan | 0:b74591d5ab33 | 309 | /* This function can be implemented by the target to perform higher level target initialization, before the mbed OS or |
be_bryan | 0:b74591d5ab33 | 310 | * RTX is started. |
be_bryan | 0:b74591d5ab33 | 311 | */ |
be_bryan | 0:b74591d5ab33 | 312 | void mbed_sdk_init(void); |
be_bryan | 0:b74591d5ab33 | 313 | WEAK void mbed_sdk_init(void) { |
be_bryan | 0:b74591d5ab33 | 314 | } |
be_bryan | 0:b74591d5ab33 | 315 | |
be_bryan | 0:b74591d5ab33 | 316 | void mbed_start_main(void) |
be_bryan | 0:b74591d5ab33 | 317 | { |
be_bryan | 0:b74591d5ab33 | 318 | _main_thread_attr.stack_mem = _main_stack; |
be_bryan | 0:b74591d5ab33 | 319 | _main_thread_attr.stack_size = sizeof(_main_stack); |
be_bryan | 0:b74591d5ab33 | 320 | _main_thread_attr.cb_size = sizeof(_main_obj); |
be_bryan | 0:b74591d5ab33 | 321 | _main_thread_attr.cb_mem = &_main_obj; |
be_bryan | 0:b74591d5ab33 | 322 | _main_thread_attr.priority = osPriorityNormal; |
be_bryan | 0:b74591d5ab33 | 323 | _main_thread_attr.name = "main_thread"; |
be_bryan | 0:b74591d5ab33 | 324 | osThreadId_t result = osThreadNew((osThreadFunc_t)pre_main, NULL, &_main_thread_attr); |
be_bryan | 0:b74591d5ab33 | 325 | if ((void *)result == NULL) { |
be_bryan | 0:b74591d5ab33 | 326 | error("Pre main thread not created"); |
be_bryan | 0:b74591d5ab33 | 327 | } |
be_bryan | 0:b74591d5ab33 | 328 | |
be_bryan | 0:b74591d5ab33 | 329 | osKernelStart(); |
be_bryan | 0:b74591d5ab33 | 330 | } |
be_bryan | 0:b74591d5ab33 | 331 | |
be_bryan | 0:b74591d5ab33 | 332 | /******************** Toolchain specific code ********************/ |
be_bryan | 0:b74591d5ab33 | 333 | |
be_bryan | 0:b74591d5ab33 | 334 | #if defined (__CC_ARM) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) |
be_bryan | 0:b74591d5ab33 | 335 | |
be_bryan | 0:b74591d5ab33 | 336 | /* Common for both ARMC and MICROLIB */ |
be_bryan | 0:b74591d5ab33 | 337 | int $Super$$main(void); |
be_bryan | 0:b74591d5ab33 | 338 | int $Sub$$main(void) { |
be_bryan | 0:b74591d5ab33 | 339 | mbed_main(); |
be_bryan | 0:b74591d5ab33 | 340 | return $Super$$main(); |
be_bryan | 0:b74591d5ab33 | 341 | } |
be_bryan | 0:b74591d5ab33 | 342 | |
be_bryan | 0:b74591d5ab33 | 343 | #if defined (__MICROLIB) /******************** MICROLIB ********************/ |
be_bryan | 0:b74591d5ab33 | 344 | |
be_bryan | 0:b74591d5ab33 | 345 | int main(void); |
be_bryan | 0:b74591d5ab33 | 346 | void _main_init (void) __attribute__((section(".ARM.Collect$$$$000000FF"))); |
be_bryan | 0:b74591d5ab33 | 347 | void $Super$$__cpp_initialize__aeabi_(void); |
be_bryan | 0:b74591d5ab33 | 348 | |
be_bryan | 0:b74591d5ab33 | 349 | void _main_init (void) { |
be_bryan | 0:b74591d5ab33 | 350 | mbed_set_stack_heap(); |
be_bryan | 0:b74591d5ab33 | 351 | /* Copy the vector table to RAM only if uVisor is not in use. */ |
be_bryan | 0:b74591d5ab33 | 352 | #if !(defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED)) |
be_bryan | 0:b74591d5ab33 | 353 | mbed_cpy_nvic(); |
be_bryan | 0:b74591d5ab33 | 354 | #endif |
be_bryan | 0:b74591d5ab33 | 355 | mbed_sdk_init(); |
be_bryan | 0:b74591d5ab33 | 356 | osKernelInitialize(); |
be_bryan | 0:b74591d5ab33 | 357 | mbed_start_main(); |
be_bryan | 0:b74591d5ab33 | 358 | for (;;); |
be_bryan | 0:b74591d5ab33 | 359 | } |
be_bryan | 0:b74591d5ab33 | 360 | |
be_bryan | 0:b74591d5ab33 | 361 | void $Sub$$__cpp_initialize__aeabi_(void) |
be_bryan | 0:b74591d5ab33 | 362 | { |
be_bryan | 0:b74591d5ab33 | 363 | /* This should invoke C++ initializers prior _main_init, we keep this empty and |
be_bryan | 0:b74591d5ab33 | 364 | * invoke them after _main_init, when the RTX is already initilized. |
be_bryan | 0:b74591d5ab33 | 365 | */ |
be_bryan | 0:b74591d5ab33 | 366 | } |
be_bryan | 0:b74591d5ab33 | 367 | |
be_bryan | 0:b74591d5ab33 | 368 | void pre_main() |
be_bryan | 0:b74591d5ab33 | 369 | { |
be_bryan | 0:b74591d5ab33 | 370 | singleton_mutex_attr.name = "singleton_mutex"; |
be_bryan | 0:b74591d5ab33 | 371 | singleton_mutex_attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust; |
be_bryan | 0:b74591d5ab33 | 372 | singleton_mutex_attr.cb_size = sizeof(singleton_mutex_obj); |
be_bryan | 0:b74591d5ab33 | 373 | singleton_mutex_attr.cb_mem = &singleton_mutex_obj; |
be_bryan | 0:b74591d5ab33 | 374 | singleton_mutex_id = osMutexNew(&singleton_mutex_attr); |
be_bryan | 0:b74591d5ab33 | 375 | |
be_bryan | 0:b74591d5ab33 | 376 | $Super$$__cpp_initialize__aeabi_(); |
be_bryan | 0:b74591d5ab33 | 377 | main(); |
be_bryan | 0:b74591d5ab33 | 378 | } |
be_bryan | 0:b74591d5ab33 | 379 | |
be_bryan | 0:b74591d5ab33 | 380 | #else /******************** ARMC ********************/ |
be_bryan | 0:b74591d5ab33 | 381 | |
be_bryan | 0:b74591d5ab33 | 382 | #include <rt_misc.h> |
be_bryan | 0:b74591d5ab33 | 383 | extern __value_in_regs struct __argc_argv __rt_lib_init(unsigned heapbase, unsigned heaptop); |
be_bryan | 0:b74591d5ab33 | 384 | extern __value_in_regs struct __initial_stackheap __user_setup_stackheap(void); |
be_bryan | 0:b74591d5ab33 | 385 | extern void _platform_post_stackheap_init (void); |
be_bryan | 0:b74591d5ab33 | 386 | extern int main(int argc, char* argv[]); |
be_bryan | 0:b74591d5ab33 | 387 | |
be_bryan | 0:b74591d5ab33 | 388 | void pre_main (void) |
be_bryan | 0:b74591d5ab33 | 389 | { |
be_bryan | 0:b74591d5ab33 | 390 | singleton_mutex_attr.name = "singleton_mutex"; |
be_bryan | 0:b74591d5ab33 | 391 | singleton_mutex_attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust; |
be_bryan | 0:b74591d5ab33 | 392 | singleton_mutex_attr.cb_size = sizeof(singleton_mutex_obj); |
be_bryan | 0:b74591d5ab33 | 393 | singleton_mutex_attr.cb_mem = &singleton_mutex_obj; |
be_bryan | 0:b74591d5ab33 | 394 | singleton_mutex_id = osMutexNew(&singleton_mutex_attr); |
be_bryan | 0:b74591d5ab33 | 395 | |
be_bryan | 0:b74591d5ab33 | 396 | __rt_lib_init((unsigned)mbed_heap_start, (unsigned)(mbed_heap_start + mbed_heap_size)); |
be_bryan | 0:b74591d5ab33 | 397 | |
be_bryan | 0:b74591d5ab33 | 398 | main(0, NULL); |
be_bryan | 0:b74591d5ab33 | 399 | } |
be_bryan | 0:b74591d5ab33 | 400 | |
be_bryan | 0:b74591d5ab33 | 401 | /* The single memory model is checking for stack collision at run time, verifing |
be_bryan | 0:b74591d5ab33 | 402 | that the heap pointer is underneath the stack pointer. |
be_bryan | 0:b74591d5ab33 | 403 | With the RTOS there is not only one stack above the heap, there are multiple |
be_bryan | 0:b74591d5ab33 | 404 | stacks and some of them are underneath the heap pointer. |
be_bryan | 0:b74591d5ab33 | 405 | */ |
be_bryan | 0:b74591d5ab33 | 406 | #if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) |
be_bryan | 0:b74591d5ab33 | 407 | __asm(".global __use_two_region_memory\n\t"); |
be_bryan | 0:b74591d5ab33 | 408 | __asm(".global __use_no_semihosting\n\t"); |
be_bryan | 0:b74591d5ab33 | 409 | #else |
be_bryan | 0:b74591d5ab33 | 410 | #pragma import(__use_two_region_memory) |
be_bryan | 0:b74591d5ab33 | 411 | #endif |
be_bryan | 0:b74591d5ab33 | 412 | |
be_bryan | 0:b74591d5ab33 | 413 | /* Called by the C library */ |
be_bryan | 0:b74591d5ab33 | 414 | void __rt_entry (void) { |
be_bryan | 0:b74591d5ab33 | 415 | __user_setup_stackheap(); |
be_bryan | 0:b74591d5ab33 | 416 | mbed_set_stack_heap(); |
be_bryan | 0:b74591d5ab33 | 417 | /* Copy the vector table to RAM only if uVisor is not in use. */ |
be_bryan | 0:b74591d5ab33 | 418 | #if !(defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED)) |
be_bryan | 0:b74591d5ab33 | 419 | mbed_cpy_nvic(); |
be_bryan | 0:b74591d5ab33 | 420 | #endif |
be_bryan | 0:b74591d5ab33 | 421 | mbed_sdk_init(); |
be_bryan | 0:b74591d5ab33 | 422 | _platform_post_stackheap_init(); |
be_bryan | 0:b74591d5ab33 | 423 | mbed_start_main(); |
be_bryan | 0:b74591d5ab33 | 424 | } |
be_bryan | 0:b74591d5ab33 | 425 | |
be_bryan | 0:b74591d5ab33 | 426 | typedef void *mutex; |
be_bryan | 0:b74591d5ab33 | 427 | mutex _static_mutexes[OS_MUTEX_NUM] = {NULL}; |
be_bryan | 0:b74591d5ab33 | 428 | |
be_bryan | 0:b74591d5ab33 | 429 | /* ARM toolchain requires dynamically created mutexes to enforce thread safety. There's |
be_bryan | 0:b74591d5ab33 | 430 | up to 8 static mutexes, protecting atexit, signalinit, stdin, stdout, stderr, stream_list, |
be_bryan | 0:b74591d5ab33 | 431 | fp_trap_init and the heap. Additionally for each call to fopen one extra mutex will be |
be_bryan | 0:b74591d5ab33 | 432 | created. |
be_bryan | 0:b74591d5ab33 | 433 | mbed OS provides a RTX pool for 8 mutexes, to satisfy the static requirements. All |
be_bryan | 0:b74591d5ab33 | 434 | additional mutexes will be allocated on the heap. We can't use the heap allocation for |
be_bryan | 0:b74591d5ab33 | 435 | all the required mutexes, as the heap operations also require a mutex. We don't need to |
be_bryan | 0:b74591d5ab33 | 436 | worry about freeing the allocated memory as library mutexes are only freed when the |
be_bryan | 0:b74591d5ab33 | 437 | application finishes executing. |
be_bryan | 0:b74591d5ab33 | 438 | */ |
be_bryan | 0:b74591d5ab33 | 439 | int _mutex_initialize(mutex *m) |
be_bryan | 0:b74591d5ab33 | 440 | { |
be_bryan | 0:b74591d5ab33 | 441 | osMutexAttr_t attr; |
be_bryan | 0:b74591d5ab33 | 442 | memset(&attr, 0, sizeof(attr)); |
be_bryan | 0:b74591d5ab33 | 443 | attr.name = "ARM toolchain mutex"; |
be_bryan | 0:b74591d5ab33 | 444 | attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust; |
be_bryan | 0:b74591d5ab33 | 445 | |
be_bryan | 0:b74591d5ab33 | 446 | mutex *slot = NULL; |
be_bryan | 0:b74591d5ab33 | 447 | core_util_critical_section_enter(); |
be_bryan | 0:b74591d5ab33 | 448 | for (int i = 0; i < OS_MUTEX_NUM; i++) { |
be_bryan | 0:b74591d5ab33 | 449 | if (_static_mutexes[i] == NULL) { |
be_bryan | 0:b74591d5ab33 | 450 | _static_mutexes[i] = (mutex)-1; // dummy value to reserve slot |
be_bryan | 0:b74591d5ab33 | 451 | slot = &_static_mutexes[i]; |
be_bryan | 0:b74591d5ab33 | 452 | break; |
be_bryan | 0:b74591d5ab33 | 453 | } |
be_bryan | 0:b74591d5ab33 | 454 | } |
be_bryan | 0:b74591d5ab33 | 455 | core_util_critical_section_exit(); |
be_bryan | 0:b74591d5ab33 | 456 | |
be_bryan | 0:b74591d5ab33 | 457 | if (slot != NULL) { |
be_bryan | 0:b74591d5ab33 | 458 | *m = osMutexNew(&attr); |
be_bryan | 0:b74591d5ab33 | 459 | *slot = *m; |
be_bryan | 0:b74591d5ab33 | 460 | if (*m != NULL) { |
be_bryan | 0:b74591d5ab33 | 461 | return 1; |
be_bryan | 0:b74591d5ab33 | 462 | } |
be_bryan | 0:b74591d5ab33 | 463 | } |
be_bryan | 0:b74591d5ab33 | 464 | |
be_bryan | 0:b74591d5ab33 | 465 | /* Mutex pool exhausted, try using HEAP */ |
be_bryan | 0:b74591d5ab33 | 466 | attr.cb_size = sizeof(mbed_rtos_storage_mutex_t); |
be_bryan | 0:b74591d5ab33 | 467 | attr.cb_mem = (void*)malloc(attr.cb_size); |
be_bryan | 0:b74591d5ab33 | 468 | if (attr.cb_mem == NULL) { |
be_bryan | 0:b74591d5ab33 | 469 | osRtxErrorNotify(osRtxErrorClibSpace, m); |
be_bryan | 0:b74591d5ab33 | 470 | return 0; |
be_bryan | 0:b74591d5ab33 | 471 | } |
be_bryan | 0:b74591d5ab33 | 472 | |
be_bryan | 0:b74591d5ab33 | 473 | *m = osMutexNew(&attr); |
be_bryan | 0:b74591d5ab33 | 474 | if (*m == NULL) { |
be_bryan | 0:b74591d5ab33 | 475 | osRtxErrorNotify(osRtxErrorClibMutex, m); |
be_bryan | 0:b74591d5ab33 | 476 | return 0; |
be_bryan | 0:b74591d5ab33 | 477 | } |
be_bryan | 0:b74591d5ab33 | 478 | |
be_bryan | 0:b74591d5ab33 | 479 | return 1; |
be_bryan | 0:b74591d5ab33 | 480 | } |
be_bryan | 0:b74591d5ab33 | 481 | |
be_bryan | 0:b74591d5ab33 | 482 | void _mutex_free(mutex *m) { |
be_bryan | 0:b74591d5ab33 | 483 | mutex *slot = NULL; |
be_bryan | 0:b74591d5ab33 | 484 | core_util_critical_section_enter(); |
be_bryan | 0:b74591d5ab33 | 485 | for (int i = 0; i < OS_MUTEX_NUM; i++) { |
be_bryan | 0:b74591d5ab33 | 486 | if (_static_mutexes[i] == *m) { |
be_bryan | 0:b74591d5ab33 | 487 | slot = &_static_mutexes[i]; |
be_bryan | 0:b74591d5ab33 | 488 | break; |
be_bryan | 0:b74591d5ab33 | 489 | } |
be_bryan | 0:b74591d5ab33 | 490 | } |
be_bryan | 0:b74591d5ab33 | 491 | core_util_critical_section_exit(); |
be_bryan | 0:b74591d5ab33 | 492 | |
be_bryan | 0:b74591d5ab33 | 493 | osMutexDelete(*m); |
be_bryan | 0:b74591d5ab33 | 494 | |
be_bryan | 0:b74591d5ab33 | 495 | // if no slot reserved for mutex, must have been dynamically allocated |
be_bryan | 0:b74591d5ab33 | 496 | if (!slot) { |
be_bryan | 0:b74591d5ab33 | 497 | free(m); |
be_bryan | 0:b74591d5ab33 | 498 | } else { |
be_bryan | 0:b74591d5ab33 | 499 | *slot = NULL; |
be_bryan | 0:b74591d5ab33 | 500 | } |
be_bryan | 0:b74591d5ab33 | 501 | |
be_bryan | 0:b74591d5ab33 | 502 | } |
be_bryan | 0:b74591d5ab33 | 503 | |
be_bryan | 0:b74591d5ab33 | 504 | #endif /* ARMC */ |
be_bryan | 0:b74591d5ab33 | 505 | #elif defined (__GNUC__) /******************** GCC ********************/ |
be_bryan | 0:b74591d5ab33 | 506 | |
be_bryan | 0:b74591d5ab33 | 507 | extern int main(int argc, char* argv[]); |
be_bryan | 0:b74591d5ab33 | 508 | extern void __libc_init_array (void); |
be_bryan | 0:b74591d5ab33 | 509 | extern int __real_main(void); |
be_bryan | 0:b74591d5ab33 | 510 | |
be_bryan | 0:b74591d5ab33 | 511 | osMutexId_t malloc_mutex_id; |
be_bryan | 0:b74591d5ab33 | 512 | mbed_rtos_storage_mutex_t malloc_mutex_obj; |
be_bryan | 0:b74591d5ab33 | 513 | osMutexAttr_t malloc_mutex_attr; |
be_bryan | 0:b74591d5ab33 | 514 | |
be_bryan | 0:b74591d5ab33 | 515 | osMutexId_t env_mutex_id; |
be_bryan | 0:b74591d5ab33 | 516 | mbed_rtos_storage_mutex_t env_mutex_obj; |
be_bryan | 0:b74591d5ab33 | 517 | osMutexAttr_t env_mutex_attr; |
be_bryan | 0:b74591d5ab33 | 518 | |
be_bryan | 0:b74591d5ab33 | 519 | #ifdef FEATURE_UVISOR |
be_bryan | 0:b74591d5ab33 | 520 | #include "uvisor-lib/uvisor-lib.h" |
be_bryan | 0:b74591d5ab33 | 521 | #endif/* FEATURE_UVISOR */ |
be_bryan | 0:b74591d5ab33 | 522 | |
be_bryan | 0:b74591d5ab33 | 523 | int __wrap_main(void) { |
be_bryan | 0:b74591d5ab33 | 524 | mbed_main(); |
be_bryan | 0:b74591d5ab33 | 525 | return __real_main(); |
be_bryan | 0:b74591d5ab33 | 526 | } |
be_bryan | 0:b74591d5ab33 | 527 | |
be_bryan | 0:b74591d5ab33 | 528 | void pre_main(void) |
be_bryan | 0:b74591d5ab33 | 529 | { |
be_bryan | 0:b74591d5ab33 | 530 | singleton_mutex_attr.name = "singleton_mutex"; |
be_bryan | 0:b74591d5ab33 | 531 | singleton_mutex_attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust; |
be_bryan | 0:b74591d5ab33 | 532 | singleton_mutex_attr.cb_size = sizeof(singleton_mutex_obj); |
be_bryan | 0:b74591d5ab33 | 533 | singleton_mutex_attr.cb_mem = &singleton_mutex_obj; |
be_bryan | 0:b74591d5ab33 | 534 | singleton_mutex_id = osMutexNew(&singleton_mutex_attr); |
be_bryan | 0:b74591d5ab33 | 535 | |
be_bryan | 0:b74591d5ab33 | 536 | malloc_mutex_attr.name = "malloc_mutex"; |
be_bryan | 0:b74591d5ab33 | 537 | malloc_mutex_attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust; |
be_bryan | 0:b74591d5ab33 | 538 | malloc_mutex_attr.cb_size = sizeof(malloc_mutex_obj); |
be_bryan | 0:b74591d5ab33 | 539 | malloc_mutex_attr.cb_mem = &malloc_mutex_obj; |
be_bryan | 0:b74591d5ab33 | 540 | malloc_mutex_id = osMutexNew(&malloc_mutex_attr); |
be_bryan | 0:b74591d5ab33 | 541 | |
be_bryan | 0:b74591d5ab33 | 542 | env_mutex_attr.name = "env_mutex"; |
be_bryan | 0:b74591d5ab33 | 543 | env_mutex_attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust; |
be_bryan | 0:b74591d5ab33 | 544 | env_mutex_attr.cb_size = sizeof(env_mutex_obj); |
be_bryan | 0:b74591d5ab33 | 545 | env_mutex_attr.cb_mem = &env_mutex_obj; |
be_bryan | 0:b74591d5ab33 | 546 | env_mutex_id = osMutexNew(&env_mutex_attr); |
be_bryan | 0:b74591d5ab33 | 547 | |
be_bryan | 0:b74591d5ab33 | 548 | __libc_init_array(); |
be_bryan | 0:b74591d5ab33 | 549 | |
be_bryan | 0:b74591d5ab33 | 550 | main(0, NULL); |
be_bryan | 0:b74591d5ab33 | 551 | } |
be_bryan | 0:b74591d5ab33 | 552 | |
be_bryan | 0:b74591d5ab33 | 553 | void software_init_hook(void) |
be_bryan | 0:b74591d5ab33 | 554 | { |
be_bryan | 0:b74591d5ab33 | 555 | mbed_set_stack_heap(); |
be_bryan | 0:b74591d5ab33 | 556 | /* Copy the vector table to RAM only if uVisor is not in use. */ |
be_bryan | 0:b74591d5ab33 | 557 | #if !(defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED)) |
be_bryan | 0:b74591d5ab33 | 558 | mbed_cpy_nvic(); |
be_bryan | 0:b74591d5ab33 | 559 | #endif |
be_bryan | 0:b74591d5ab33 | 560 | mbed_sdk_init(); |
be_bryan | 0:b74591d5ab33 | 561 | osKernelInitialize(); |
be_bryan | 0:b74591d5ab33 | 562 | /* uvisor_lib_init calls RTOS functions, so must be called after the RTOS has |
be_bryan | 0:b74591d5ab33 | 563 | * been initialized. */ |
be_bryan | 0:b74591d5ab33 | 564 | #ifdef FEATURE_UVISOR |
be_bryan | 0:b74591d5ab33 | 565 | int return_code; |
be_bryan | 0:b74591d5ab33 | 566 | |
be_bryan | 0:b74591d5ab33 | 567 | return_code = uvisor_lib_init(); |
be_bryan | 0:b74591d5ab33 | 568 | if (return_code) { |
be_bryan | 0:b74591d5ab33 | 569 | mbed_die(); |
be_bryan | 0:b74591d5ab33 | 570 | } |
be_bryan | 0:b74591d5ab33 | 571 | #endif/* FEATURE_UVISOR */ |
be_bryan | 0:b74591d5ab33 | 572 | mbed_start_main(); |
be_bryan | 0:b74591d5ab33 | 573 | } |
be_bryan | 0:b74591d5ab33 | 574 | |
be_bryan | 0:b74591d5ab33 | 575 | /* Opaque declaration of _reent structure */ |
be_bryan | 0:b74591d5ab33 | 576 | struct _reent; |
be_bryan | 0:b74591d5ab33 | 577 | |
be_bryan | 0:b74591d5ab33 | 578 | void __rtos_malloc_lock( struct _reent *_r ) |
be_bryan | 0:b74591d5ab33 | 579 | { |
be_bryan | 0:b74591d5ab33 | 580 | osMutexAcquire(malloc_mutex_id, osWaitForever); |
be_bryan | 0:b74591d5ab33 | 581 | } |
be_bryan | 0:b74591d5ab33 | 582 | |
be_bryan | 0:b74591d5ab33 | 583 | void __rtos_malloc_unlock( struct _reent *_r ) |
be_bryan | 0:b74591d5ab33 | 584 | { |
be_bryan | 0:b74591d5ab33 | 585 | osMutexRelease(malloc_mutex_id); |
be_bryan | 0:b74591d5ab33 | 586 | } |
be_bryan | 0:b74591d5ab33 | 587 | |
be_bryan | 0:b74591d5ab33 | 588 | void __rtos_env_lock( struct _reent *_r ) |
be_bryan | 0:b74591d5ab33 | 589 | { |
be_bryan | 0:b74591d5ab33 | 590 | osMutexAcquire(env_mutex_id, osWaitForever); |
be_bryan | 0:b74591d5ab33 | 591 | } |
be_bryan | 0:b74591d5ab33 | 592 | |
be_bryan | 0:b74591d5ab33 | 593 | void __rtos_env_unlock( struct _reent *_r ) |
be_bryan | 0:b74591d5ab33 | 594 | { |
be_bryan | 0:b74591d5ab33 | 595 | osMutexRelease(env_mutex_id); |
be_bryan | 0:b74591d5ab33 | 596 | } |
be_bryan | 0:b74591d5ab33 | 597 | |
be_bryan | 0:b74591d5ab33 | 598 | #endif |
be_bryan | 0:b74591d5ab33 | 599 | |
be_bryan | 0:b74591d5ab33 | 600 | #if defined(__ICCARM__) /******************** IAR ********************/ |
be_bryan | 0:b74591d5ab33 | 601 | |
be_bryan | 0:b74591d5ab33 | 602 | extern void* __vector_table; |
be_bryan | 0:b74591d5ab33 | 603 | extern int __low_level_init(void); |
be_bryan | 0:b74591d5ab33 | 604 | extern void __iar_data_init3(void); |
be_bryan | 0:b74591d5ab33 | 605 | extern __weak void __iar_init_core( void ); |
be_bryan | 0:b74591d5ab33 | 606 | extern __weak void __iar_init_vfp( void ); |
be_bryan | 0:b74591d5ab33 | 607 | extern void __iar_dynamic_initialization(void); |
be_bryan | 0:b74591d5ab33 | 608 | extern void mbed_sdk_init(void); |
be_bryan | 0:b74591d5ab33 | 609 | extern int main(void); |
be_bryan | 0:b74591d5ab33 | 610 | extern void exit(int arg); |
be_bryan | 0:b74591d5ab33 | 611 | |
be_bryan | 0:b74591d5ab33 | 612 | static uint8_t low_level_init_needed; |
be_bryan | 0:b74591d5ab33 | 613 | |
be_bryan | 0:b74591d5ab33 | 614 | void pre_main(void) |
be_bryan | 0:b74591d5ab33 | 615 | { |
be_bryan | 0:b74591d5ab33 | 616 | singleton_mutex_attr.name = "singleton_mutex"; |
be_bryan | 0:b74591d5ab33 | 617 | singleton_mutex_attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust; |
be_bryan | 0:b74591d5ab33 | 618 | singleton_mutex_attr.cb_size = sizeof(singleton_mutex_obj); |
be_bryan | 0:b74591d5ab33 | 619 | singleton_mutex_attr.cb_mem = &singleton_mutex_obj; |
be_bryan | 0:b74591d5ab33 | 620 | singleton_mutex_id = osMutexNew(&singleton_mutex_attr); |
be_bryan | 0:b74591d5ab33 | 621 | |
be_bryan | 0:b74591d5ab33 | 622 | #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ >= 8000000) |
be_bryan | 0:b74591d5ab33 | 623 | __iar_Initlocks(); |
be_bryan | 0:b74591d5ab33 | 624 | #endif |
be_bryan | 0:b74591d5ab33 | 625 | |
be_bryan | 0:b74591d5ab33 | 626 | if (low_level_init_needed) { |
be_bryan | 0:b74591d5ab33 | 627 | __iar_dynamic_initialization(); |
be_bryan | 0:b74591d5ab33 | 628 | } |
be_bryan | 0:b74591d5ab33 | 629 | |
be_bryan | 0:b74591d5ab33 | 630 | mbed_main(); |
be_bryan | 0:b74591d5ab33 | 631 | main(); |
be_bryan | 0:b74591d5ab33 | 632 | } |
be_bryan | 0:b74591d5ab33 | 633 | |
be_bryan | 0:b74591d5ab33 | 634 | #pragma required=__vector_table |
be_bryan | 0:b74591d5ab33 | 635 | void __iar_program_start( void ) |
be_bryan | 0:b74591d5ab33 | 636 | { |
be_bryan | 0:b74591d5ab33 | 637 | __iar_init_core(); |
be_bryan | 0:b74591d5ab33 | 638 | __iar_init_vfp(); |
be_bryan | 0:b74591d5ab33 | 639 | |
be_bryan | 0:b74591d5ab33 | 640 | uint8_t low_level_init_needed_local; |
be_bryan | 0:b74591d5ab33 | 641 | |
be_bryan | 0:b74591d5ab33 | 642 | low_level_init_needed_local = __low_level_init(); |
be_bryan | 0:b74591d5ab33 | 643 | if (low_level_init_needed_local) { |
be_bryan | 0:b74591d5ab33 | 644 | __iar_data_init3(); |
be_bryan | 0:b74591d5ab33 | 645 | |
be_bryan | 0:b74591d5ab33 | 646 | /* Copy the vector table to RAM only if uVisor is not in use. */ |
be_bryan | 0:b74591d5ab33 | 647 | #if !(defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED)) |
be_bryan | 0:b74591d5ab33 | 648 | mbed_cpy_nvic(); |
be_bryan | 0:b74591d5ab33 | 649 | #endif |
be_bryan | 0:b74591d5ab33 | 650 | mbed_sdk_init(); |
be_bryan | 0:b74591d5ab33 | 651 | } |
be_bryan | 0:b74591d5ab33 | 652 | |
be_bryan | 0:b74591d5ab33 | 653 | mbed_set_stack_heap(); |
be_bryan | 0:b74591d5ab33 | 654 | |
be_bryan | 0:b74591d5ab33 | 655 | /* Store in a global variable after RAM has been initialized */ |
be_bryan | 0:b74591d5ab33 | 656 | low_level_init_needed = low_level_init_needed_local; |
be_bryan | 0:b74591d5ab33 | 657 | |
be_bryan | 0:b74591d5ab33 | 658 | osKernelInitialize(); |
be_bryan | 0:b74591d5ab33 | 659 | |
be_bryan | 0:b74591d5ab33 | 660 | mbed_start_main(); |
be_bryan | 0:b74591d5ab33 | 661 | } |
be_bryan | 0:b74591d5ab33 | 662 | |
be_bryan | 0:b74591d5ab33 | 663 | /* Thread safety */ |
be_bryan | 0:b74591d5ab33 | 664 | static osMutexId_t std_mutex_id_sys[_MAX_LOCK] = {0}; |
be_bryan | 0:b74591d5ab33 | 665 | static mbed_rtos_storage_mutex_t std_mutex_sys[_MAX_LOCK] = {0}; |
be_bryan | 0:b74591d5ab33 | 666 | #define _FOPEN_MAX 10 |
be_bryan | 0:b74591d5ab33 | 667 | static osMutexId_t std_mutex_id_file[_FOPEN_MAX] = {0}; |
be_bryan | 0:b74591d5ab33 | 668 | static mbed_rtos_storage_mutex_t std_mutex_file[_FOPEN_MAX] = {0}; |
be_bryan | 0:b74591d5ab33 | 669 | |
be_bryan | 0:b74591d5ab33 | 670 | void __iar_system_Mtxinit(__iar_Rmtx *mutex) /* Initialize a system lock */ |
be_bryan | 0:b74591d5ab33 | 671 | { |
be_bryan | 0:b74591d5ab33 | 672 | osMutexAttr_t attr; |
be_bryan | 0:b74591d5ab33 | 673 | uint32_t index; |
be_bryan | 0:b74591d5ab33 | 674 | for (index = 0; index < _MAX_LOCK; index++) { |
be_bryan | 0:b74591d5ab33 | 675 | if (0 == std_mutex_id_sys[index]) { |
be_bryan | 0:b74591d5ab33 | 676 | attr.name = "system_mutex"; |
be_bryan | 0:b74591d5ab33 | 677 | attr.cb_mem = &std_mutex_sys[index]; |
be_bryan | 0:b74591d5ab33 | 678 | attr.cb_size = sizeof(std_mutex_sys[index]); |
be_bryan | 0:b74591d5ab33 | 679 | attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust; |
be_bryan | 0:b74591d5ab33 | 680 | std_mutex_id_sys[index] = osMutexNew(&attr); |
be_bryan | 0:b74591d5ab33 | 681 | *mutex = (__iar_Rmtx*)&std_mutex_id_sys[index]; |
be_bryan | 0:b74591d5ab33 | 682 | return; |
be_bryan | 0:b74591d5ab33 | 683 | } |
be_bryan | 0:b74591d5ab33 | 684 | } |
be_bryan | 0:b74591d5ab33 | 685 | |
be_bryan | 0:b74591d5ab33 | 686 | /* This should never happen */ |
be_bryan | 0:b74591d5ab33 | 687 | error("Not enough mutexes\n"); |
be_bryan | 0:b74591d5ab33 | 688 | } |
be_bryan | 0:b74591d5ab33 | 689 | |
be_bryan | 0:b74591d5ab33 | 690 | void __iar_system_Mtxdst(__iar_Rmtx *mutex) /* Destroy a system lock */ |
be_bryan | 0:b74591d5ab33 | 691 | { |
be_bryan | 0:b74591d5ab33 | 692 | osMutexDelete(*(osMutexId_t*)*mutex); |
be_bryan | 0:b74591d5ab33 | 693 | *mutex = 0; |
be_bryan | 0:b74591d5ab33 | 694 | } |
be_bryan | 0:b74591d5ab33 | 695 | |
be_bryan | 0:b74591d5ab33 | 696 | void __iar_system_Mtxlock(__iar_Rmtx *mutex) /* Lock a system lock */ |
be_bryan | 0:b74591d5ab33 | 697 | { |
be_bryan | 0:b74591d5ab33 | 698 | osMutexAcquire(*(osMutexId_t*)*mutex, osWaitForever); |
be_bryan | 0:b74591d5ab33 | 699 | } |
be_bryan | 0:b74591d5ab33 | 700 | |
be_bryan | 0:b74591d5ab33 | 701 | void __iar_system_Mtxunlock(__iar_Rmtx *mutex) /* Unlock a system lock */ |
be_bryan | 0:b74591d5ab33 | 702 | { |
be_bryan | 0:b74591d5ab33 | 703 | osMutexRelease(*(osMutexId_t*)*mutex); |
be_bryan | 0:b74591d5ab33 | 704 | } |
be_bryan | 0:b74591d5ab33 | 705 | |
be_bryan | 0:b74591d5ab33 | 706 | void __iar_file_Mtxinit(__iar_Rmtx *mutex) /* Initialize a file lock */ |
be_bryan | 0:b74591d5ab33 | 707 | { |
be_bryan | 0:b74591d5ab33 | 708 | osMutexAttr_t attr; |
be_bryan | 0:b74591d5ab33 | 709 | uint32_t index; |
be_bryan | 0:b74591d5ab33 | 710 | for (index = 0; index < _FOPEN_MAX; index++) { |
be_bryan | 0:b74591d5ab33 | 711 | if (0 == std_mutex_id_file[index]) { |
be_bryan | 0:b74591d5ab33 | 712 | attr.name = "file_mutex"; |
be_bryan | 0:b74591d5ab33 | 713 | attr.cb_mem = &std_mutex_file[index]; |
be_bryan | 0:b74591d5ab33 | 714 | attr.cb_size = sizeof(std_mutex_file[index]); |
be_bryan | 0:b74591d5ab33 | 715 | attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust; |
be_bryan | 0:b74591d5ab33 | 716 | std_mutex_id_file[index] = osMutexNew(&attr); |
be_bryan | 0:b74591d5ab33 | 717 | *mutex = (__iar_Rmtx*)&std_mutex_id_file[index]; |
be_bryan | 0:b74591d5ab33 | 718 | return; |
be_bryan | 0:b74591d5ab33 | 719 | } |
be_bryan | 0:b74591d5ab33 | 720 | } |
be_bryan | 0:b74591d5ab33 | 721 | /* The variable _FOPEN_MAX needs to be increased */ |
be_bryan | 0:b74591d5ab33 | 722 | error("Not enough mutexes\n"); |
be_bryan | 0:b74591d5ab33 | 723 | } |
be_bryan | 0:b74591d5ab33 | 724 | |
be_bryan | 0:b74591d5ab33 | 725 | void __iar_file_Mtxdst(__iar_Rmtx *mutex) /* Destroy a file lock */ |
be_bryan | 0:b74591d5ab33 | 726 | { |
be_bryan | 0:b74591d5ab33 | 727 | osMutexDelete(*(osMutexId_t*)*mutex); |
be_bryan | 0:b74591d5ab33 | 728 | *mutex = 0; |
be_bryan | 0:b74591d5ab33 | 729 | } |
be_bryan | 0:b74591d5ab33 | 730 | |
be_bryan | 0:b74591d5ab33 | 731 | void __iar_file_Mtxlock(__iar_Rmtx *mutex) /* Lock a file lock */ |
be_bryan | 0:b74591d5ab33 | 732 | { |
be_bryan | 0:b74591d5ab33 | 733 | osMutexAcquire(*(osMutexId_t*)*mutex, osWaitForever); |
be_bryan | 0:b74591d5ab33 | 734 | } |
be_bryan | 0:b74591d5ab33 | 735 | |
be_bryan | 0:b74591d5ab33 | 736 | void __iar_file_Mtxunlock(__iar_Rmtx *mutex) /* Unlock a file lock */ |
be_bryan | 0:b74591d5ab33 | 737 | { |
be_bryan | 0:b74591d5ab33 | 738 | osMutexRelease(*(osMutexId_t*)*mutex); |
be_bryan | 0:b74591d5ab33 | 739 | } |
be_bryan | 0:b74591d5ab33 | 740 | |
be_bryan | 0:b74591d5ab33 | 741 | #endif |