Skip to content

Commit 88eb8aa

Browse files
author
Cruz Monrreal
authored
Merge pull request #7794 from c1728p9/boot_overhaul
Update Mbed 5 boot sequence
2 parents 56117a8 + 325565b commit 88eb8aa

File tree

8 files changed

+892
-705
lines changed

8 files changed

+892
-705
lines changed

platform/SingletonPtr.h

+8
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ extern osMutexId_t singleton_mutex_id;
4343
inline static void singleton_lock(void)
4444
{
4545
#ifdef MBED_CONF_RTOS_PRESENT
46+
if (!singleton_mutex_id) {
47+
// RTOS has not booted yet so no mutex is needed
48+
return;
49+
}
4650
osMutexAcquire(singleton_mutex_id, osWaitForever);
4751
#endif
4852
}
@@ -56,6 +60,10 @@ inline static void singleton_lock(void)
5660
inline static void singleton_unlock(void)
5761
{
5862
#ifdef MBED_CONF_RTOS_PRESENT
63+
if (!singleton_mutex_id) {
64+
// RTOS has not booted yet so no mutex is needed
65+
return;
66+
}
5967
osMutexRelease(singleton_mutex_id);
6068
#endif
6169
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2018-2018 ARM Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#include <stdlib.h>
17+
#include <string.h>
18+
19+
#include "mbed_boot.h"
20+
#include "mbed_assert.h"
21+
22+
/* Symbols that are typically defined in startup_<mcu>.S */
23+
extern uint32_t __initial_sp[];
24+
extern uint32_t __heap_base[];
25+
extern uint32_t __heap_limit[];
26+
27+
/*
28+
* mbed entry point for the MICROLIB toolchain
29+
*
30+
* Override the microlib function _main_init to run code earlier in
31+
* the boot sequence. The function _main_init is responsible for invoking main.
32+
* This function must be placed in the ".ARM.Collect" section
33+
* or it won't get called.
34+
*/
35+
void _main_init(void) __attribute__((section(".ARM.Collect$$$$000000FF")));
36+
void _main_init(void)
37+
{
38+
/* microlib only supports the two region memory model */
39+
40+
mbed_heap_start = (unsigned char*)__heap_base;
41+
mbed_heap_size = (uint32_t)__heap_base - (uint32_t)__heap_limit;
42+
43+
mbed_stack_isr_start = (unsigned char*)((uint32_t)__initial_sp - ISR_STACK_SIZE);
44+
mbed_stack_isr_size = ISR_STACK_SIZE;
45+
46+
mbed_init();
47+
mbed_rtos_start();
48+
}
49+
50+
void $Sub$$__cpp_initialize__aeabi_(void);
51+
void $Super$$__cpp_initialize__aeabi_(void);
52+
void $Sub$$__cpp_initialize__aeabi_(void)
53+
{
54+
/* This should invoke C++ initializers but we keep
55+
* this empty and invoke them RTX is initialized.
56+
*/
57+
}
58+
59+
void mbed_toolchain_init()
60+
{
61+
/* Run the C++ global object constructors */
62+
$Super$$__cpp_initialize__aeabi_();
63+
}
64+
65+
MBED_WEAK void __aeabi_assert(const char *expr, const char *file, int line)
66+
{
67+
mbed_assert_internal(expr, file, line);
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2018-2018 ARM Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#include <stdlib.h>
17+
#include <string.h>
18+
19+
#include "cmsis.h"
20+
#include "mbed_critical.h"
21+
#include "mbed_boot.h"
22+
#include <rt_misc.h>
23+
#include "mbed_rtos_storage.h"
24+
#include "cmsis_os2.h"
25+
26+
__value_in_regs struct __argc_argv __rt_lib_init(unsigned heapbase, unsigned heaptop);
27+
void _platform_post_stackheap_init(void);
28+
29+
#if !defined(HEAP_START)
30+
/* Defined by linker script */
31+
extern uint32_t Image$$RW_IRAM1$$ZI$$Limit[];
32+
#define HEAP_START ((unsigned char*)Image$$RW_IRAM1$$ZI$$Limit)
33+
#define HEAP_SIZE ((uint32_t)((uint32_t)INITIAL_SP - (uint32_t)HEAP_START))
34+
#endif
35+
36+
/*
37+
* Note - Overriding the function __cpp_initialize__aeabi_ for the Arm
38+
* standard library causes a crash when there are no global constructors.
39+
* To avoid this do not override __cpp_initialize__aeabi_ with the super$$
40+
* sub$$ mechanism for the Arm standard library. The uARM library is not
41+
* effected by this problem.
42+
*/
43+
44+
/*
45+
* mbed entry point for the ARM standard toolchain
46+
*
47+
* Override the ARM standard library function __rt_entry to run code earlier in
48+
* the boot sequence. This is after scatter loading has taken place but before
49+
* the C library has been initialized.
50+
*/
51+
void __rt_entry(void)
52+
{
53+
unsigned char *free_start = HEAP_START;
54+
uint32_t free_size = HEAP_SIZE;
55+
56+
#ifdef ISR_STACK_START
57+
/* Interrupt stack explicitly specified */
58+
mbed_stack_isr_size = ISR_STACK_SIZE;
59+
mbed_stack_isr_start = ISR_STACK_START;
60+
#else
61+
/* Interrupt stack - reserve space at the end of the free block */
62+
mbed_stack_isr_size = ISR_STACK_SIZE < free_size ? ISR_STACK_SIZE : free_size;
63+
mbed_stack_isr_start = free_start + free_size - mbed_stack_isr_size;
64+
free_size -= mbed_stack_isr_size;
65+
#endif
66+
67+
/* Heap - everything else */
68+
mbed_heap_size = free_size;
69+
mbed_heap_start = free_start;
70+
mbed_init();
71+
72+
_platform_post_stackheap_init();
73+
mbed_rtos_start();
74+
}
75+
76+
void mbed_toolchain_init()
77+
{
78+
/* Run the C++ global object constructors */
79+
__rt_lib_init((unsigned)mbed_heap_start, (unsigned)(mbed_heap_start + mbed_heap_size));
80+
}
81+
82+
/* Move all code here from RTX code base (rtx_lib.c) and do some modifications:
83+
*
84+
* 1. _mutex_initialize/_mutex_free are re-implemented to meet Mbed.
85+
* 2. All _mutex_* functions are declared with '__USED' to avoid excluded by linker.
86+
*/
87+
#if defined(RTX_NO_MULTITHREAD_CLIB)
88+
89+
/* The single memory model is checking for stack collision at run time, verifying
90+
that the heap pointer is underneath the stack pointer.
91+
With the RTOS there is not only one stack above the heap, there are multiple
92+
stacks and some of them are underneath the heap pointer.
93+
*/
94+
#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
95+
__asm(".global __use_two_region_memory\n\t");
96+
__asm(".global __use_no_semihosting\n\t");
97+
#else
98+
#pragma import(__use_two_region_memory)
99+
#endif
100+
101+
#define LIBSPACE_SIZE 96
102+
103+
//lint -esym(714,__user_perthread_libspace,_mutex_*) "Referenced by C library"
104+
//lint -esym(765,__user_perthread_libspace,_mutex_*) "Global scope"
105+
//lint -esym(9003, os_libspace*) "variables 'os_libspace*' defined at module scope"
106+
107+
// Memory for libspace
108+
static uint32_t os_libspace[OS_THREAD_LIBSPACE_NUM+1][LIBSPACE_SIZE/4] \
109+
__attribute__((section(".bss.os.libspace")));
110+
111+
// Thread IDs for libspace
112+
static osThreadId_t os_libspace_id[OS_THREAD_LIBSPACE_NUM] \
113+
__attribute__((section(".bss.os.libspace")));
114+
115+
// Check if Kernel has been started
116+
static uint32_t os_kernel_is_active (void) {
117+
static uint8_t os_kernel_active = 0U;
118+
119+
if (os_kernel_active == 0U) {
120+
if (osKernelGetState() > osKernelReady) {
121+
os_kernel_active = 1U;
122+
}
123+
}
124+
return (uint32_t)os_kernel_active;
125+
}
126+
127+
// Provide libspace for current thread
128+
void *__user_perthread_libspace (void) {
129+
osThreadId_t id;
130+
uint32_t n;
131+
132+
if (os_kernel_is_active() != 0U) {
133+
id = osThreadGetId();
134+
for (n = 0U; n < (uint32_t)OS_THREAD_LIBSPACE_NUM; n++) {
135+
if (os_libspace_id[n] == NULL) {
136+
os_libspace_id[n] = id;
137+
}
138+
if (os_libspace_id[n] == id) {
139+
break;
140+
}
141+
}
142+
if (n == (uint32_t)OS_THREAD_LIBSPACE_NUM) {
143+
(void)osRtxErrorNotify(osRtxErrorClibSpace, id);
144+
}
145+
} else {
146+
n = OS_THREAD_LIBSPACE_NUM;
147+
}
148+
149+
//lint -e{9087} "cast between pointers to different object types"
150+
return (void *)&os_libspace[n][0];
151+
}
152+
153+
/* ARM toolchain requires dynamically created mutexes to enforce thread safety. There's
154+
up to 8 static mutexes, protecting atexit, signalinit, stdin, stdout, stderr, stream_list,
155+
fp_trap_init and the heap. Additionally for each call to fopen one extra mutex will be
156+
created.
157+
mbed OS provides a RTX pool for 8 mutexes, to satisfy the static requirements. All
158+
additional mutexes will be allocated on the heap. We can't use the heap allocation for
159+
all the required mutexes, as the heap operations also require a mutex. We don't need to
160+
worry about freeing the allocated memory as library mutexes are only freed when the
161+
application finishes executing.
162+
*/
163+
164+
typedef void *mutex;
165+
#define OS_MUTEX_STATIC_NUM 8
166+
mutex _static_mutexes[OS_MUTEX_STATIC_NUM] = {NULL};
167+
mbed_rtos_storage_mutex_t _static_mutexes_mem[OS_MUTEX_STATIC_NUM] = {NULL};
168+
169+
//lint -save "Function prototypes defined in C library"
170+
//lint -e970 "Use of 'int' outside of a typedef"
171+
//lint -e818 "Pointer 'm' could be declared as pointing to const"
172+
173+
/* Initialize mutex */
174+
__USED int _mutex_initialize(mutex *m)
175+
{
176+
osMutexAttr_t attr;
177+
memset(&attr, 0, sizeof(attr));
178+
attr.name = "ARM toolchain mutex";
179+
attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust;
180+
181+
mutex *slot = NULL;
182+
core_util_critical_section_enter();
183+
for (int i = 0; i < OS_MUTEX_STATIC_NUM; i++) {
184+
if (_static_mutexes[i] == NULL) {
185+
_static_mutexes[i] = (mutex)-1; // dummy value to reserve slot
186+
slot = &_static_mutexes[i];
187+
//Use the static attrs
188+
attr.cb_size = sizeof(mbed_rtos_storage_mutex_t);
189+
attr.cb_mem = &_static_mutexes_mem[i];
190+
break;
191+
}
192+
}
193+
core_util_critical_section_exit();
194+
195+
if (slot != NULL) {
196+
*m = osMutexNew(&attr);
197+
*slot = *m;
198+
if (*m != NULL) {
199+
return 1;
200+
}
201+
}
202+
203+
/* Mutex pool exhausted, try using HEAP */
204+
attr.cb_size = sizeof(mbed_rtos_storage_mutex_t);
205+
attr.cb_mem = (void*)malloc(attr.cb_size);
206+
if (attr.cb_mem == NULL) {
207+
osRtxErrorNotify(osRtxErrorClibSpace, m);
208+
return 0;
209+
}
210+
211+
*m = osMutexNew(&attr);
212+
if (*m == NULL) {
213+
osRtxErrorNotify(osRtxErrorClibMutex, m);
214+
return 0;
215+
}
216+
217+
return 1;
218+
}
219+
220+
/* Acquire mutex */
221+
__USED void _mutex_acquire(mutex *m) {
222+
if (os_kernel_is_active() != 0U) {
223+
(void)osMutexAcquire(*m, osWaitForever);
224+
}
225+
}
226+
227+
/* Release mutex */
228+
__USED void _mutex_release(mutex *m) {
229+
if (os_kernel_is_active() != 0U) {
230+
(void)osMutexRelease(*m);
231+
}
232+
}
233+
234+
/* Free mutex */
235+
__USED void _mutex_free(mutex *m) {
236+
mutex *slot = NULL;
237+
core_util_critical_section_enter();
238+
for (int i = 0; i < OS_MUTEX_STATIC_NUM; i++) {
239+
if (_static_mutexes[i] == *m) {
240+
slot = &_static_mutexes[i];
241+
break;
242+
}
243+
}
244+
core_util_critical_section_exit();
245+
246+
osMutexDelete(*m);
247+
248+
// if no slot reserved for mutex, must have been dynamically allocated
249+
if (!slot) {
250+
free(m);
251+
} else {
252+
*slot = NULL;
253+
}
254+
255+
}
256+
257+
#endif /* RTX_NO_MULTITHREAD_CLIB */

0 commit comments

Comments
 (0)