mirror of https://github.com/ARMmbed/mbed-os.git
Refactor boot process
Refactor the Mbed 5 boot process to make is simpler and more modular. This is done by breaking the boot sequence into 4 distinct steps - Target setup, Toolchain setup, RTOS setup and Mbed setup. This patch also move toolchain specific code into a per toolchain folder to make it more maintainable.pull/7794/head
parent
ec19bf1de4
commit
325565bf79
|
@ -0,0 +1,68 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018-2018 ARM Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mbed_boot.h"
|
||||
#include "mbed_assert.h"
|
||||
|
||||
/* Symbols that are typically defined in startup_<mcu>.S */
|
||||
extern uint32_t __initial_sp[];
|
||||
extern uint32_t __heap_base[];
|
||||
extern uint32_t __heap_limit[];
|
||||
|
||||
/*
|
||||
* mbed entry point for the MICROLIB toolchain
|
||||
*
|
||||
* Override the microlib function _main_init to run code earlier in
|
||||
* the boot sequence. The function _main_init is responsible for invoking main.
|
||||
* This function must be placed in the ".ARM.Collect" section
|
||||
* or it won't get called.
|
||||
*/
|
||||
void _main_init(void) __attribute__((section(".ARM.Collect$$$$000000FF")));
|
||||
void _main_init(void)
|
||||
{
|
||||
/* microlib only supports the two region memory model */
|
||||
|
||||
mbed_heap_start = (unsigned char*)__heap_base;
|
||||
mbed_heap_size = (uint32_t)__heap_base - (uint32_t)__heap_limit;
|
||||
|
||||
mbed_stack_isr_start = (unsigned char*)((uint32_t)__initial_sp - ISR_STACK_SIZE);
|
||||
mbed_stack_isr_size = ISR_STACK_SIZE;
|
||||
|
||||
mbed_init();
|
||||
mbed_rtos_start();
|
||||
}
|
||||
|
||||
void $Sub$$__cpp_initialize__aeabi_(void);
|
||||
void $Super$$__cpp_initialize__aeabi_(void);
|
||||
void $Sub$$__cpp_initialize__aeabi_(void)
|
||||
{
|
||||
/* This should invoke C++ initializers but we keep
|
||||
* this empty and invoke them RTX is initialized.
|
||||
*/
|
||||
}
|
||||
|
||||
void mbed_toolchain_init()
|
||||
{
|
||||
/* Run the C++ global object constructors */
|
||||
$Super$$__cpp_initialize__aeabi_();
|
||||
}
|
||||
|
||||
MBED_WEAK void __aeabi_assert(const char *expr, const char *file, int line)
|
||||
{
|
||||
mbed_assert_internal(expr, file, line);
|
||||
}
|
|
@ -0,0 +1,257 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018-2018 ARM Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cmsis.h"
|
||||
#include "mbed_critical.h"
|
||||
#include "mbed_boot.h"
|
||||
#include <rt_misc.h>
|
||||
#include "mbed_rtos_storage.h"
|
||||
#include "cmsis_os2.h"
|
||||
|
||||
__value_in_regs struct __argc_argv __rt_lib_init(unsigned heapbase, unsigned heaptop);
|
||||
void _platform_post_stackheap_init(void);
|
||||
|
||||
#if !defined(HEAP_START)
|
||||
/* Defined by linker script */
|
||||
extern uint32_t Image$$RW_IRAM1$$ZI$$Limit[];
|
||||
#define HEAP_START ((unsigned char*)Image$$RW_IRAM1$$ZI$$Limit)
|
||||
#define HEAP_SIZE ((uint32_t)((uint32_t)INITIAL_SP - (uint32_t)HEAP_START))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Note - Overriding the function __cpp_initialize__aeabi_ for the Arm
|
||||
* standard library causes a crash when there are no global constructors.
|
||||
* To avoid this do not override __cpp_initialize__aeabi_ with the super$$
|
||||
* sub$$ mechanism for the Arm standard library. The uARM library is not
|
||||
* effected by this problem.
|
||||
*/
|
||||
|
||||
/*
|
||||
* mbed entry point for the ARM standard toolchain
|
||||
*
|
||||
* Override the ARM standard library function __rt_entry to run code earlier in
|
||||
* the boot sequence. This is after scatter loading has taken place but before
|
||||
* the C library has been initialized.
|
||||
*/
|
||||
void __rt_entry(void)
|
||||
{
|
||||
unsigned char *free_start = HEAP_START;
|
||||
uint32_t free_size = HEAP_SIZE;
|
||||
|
||||
#ifdef ISR_STACK_START
|
||||
/* Interrupt stack explicitly specified */
|
||||
mbed_stack_isr_size = ISR_STACK_SIZE;
|
||||
mbed_stack_isr_start = ISR_STACK_START;
|
||||
#else
|
||||
/* Interrupt stack - reserve space at the end of the free block */
|
||||
mbed_stack_isr_size = ISR_STACK_SIZE < free_size ? ISR_STACK_SIZE : free_size;
|
||||
mbed_stack_isr_start = free_start + free_size - mbed_stack_isr_size;
|
||||
free_size -= mbed_stack_isr_size;
|
||||
#endif
|
||||
|
||||
/* Heap - everything else */
|
||||
mbed_heap_size = free_size;
|
||||
mbed_heap_start = free_start;
|
||||
mbed_init();
|
||||
|
||||
_platform_post_stackheap_init();
|
||||
mbed_rtos_start();
|
||||
}
|
||||
|
||||
void mbed_toolchain_init()
|
||||
{
|
||||
/* Run the C++ global object constructors */
|
||||
__rt_lib_init((unsigned)mbed_heap_start, (unsigned)(mbed_heap_start + mbed_heap_size));
|
||||
}
|
||||
|
||||
/* Move all code here from RTX code base (rtx_lib.c) and do some modifications:
|
||||
*
|
||||
* 1. _mutex_initialize/_mutex_free are re-implemented to meet Mbed.
|
||||
* 2. All _mutex_* functions are declared with '__USED' to avoid excluded by linker.
|
||||
*/
|
||||
#if defined(RTX_NO_MULTITHREAD_CLIB)
|
||||
|
||||
/* The single memory model is checking for stack collision at run time, verifying
|
||||
that the heap pointer is underneath the stack pointer.
|
||||
With the RTOS there is not only one stack above the heap, there are multiple
|
||||
stacks and some of them are underneath the heap pointer.
|
||||
*/
|
||||
#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
__asm(".global __use_two_region_memory\n\t");
|
||||
__asm(".global __use_no_semihosting\n\t");
|
||||
#else
|
||||
#pragma import(__use_two_region_memory)
|
||||
#endif
|
||||
|
||||
#define LIBSPACE_SIZE 96
|
||||
|
||||
//lint -esym(714,__user_perthread_libspace,_mutex_*) "Referenced by C library"
|
||||
//lint -esym(765,__user_perthread_libspace,_mutex_*) "Global scope"
|
||||
//lint -esym(9003, os_libspace*) "variables 'os_libspace*' defined at module scope"
|
||||
|
||||
// Memory for libspace
|
||||
static uint32_t os_libspace[OS_THREAD_LIBSPACE_NUM+1][LIBSPACE_SIZE/4] \
|
||||
__attribute__((section(".bss.os.libspace")));
|
||||
|
||||
// Thread IDs for libspace
|
||||
static osThreadId_t os_libspace_id[OS_THREAD_LIBSPACE_NUM] \
|
||||
__attribute__((section(".bss.os.libspace")));
|
||||
|
||||
// Check if Kernel has been started
|
||||
static uint32_t os_kernel_is_active (void) {
|
||||
static uint8_t os_kernel_active = 0U;
|
||||
|
||||
if (os_kernel_active == 0U) {
|
||||
if (osKernelGetState() > osKernelReady) {
|
||||
os_kernel_active = 1U;
|
||||
}
|
||||
}
|
||||
return (uint32_t)os_kernel_active;
|
||||
}
|
||||
|
||||
// Provide libspace for current thread
|
||||
void *__user_perthread_libspace (void) {
|
||||
osThreadId_t id;
|
||||
uint32_t n;
|
||||
|
||||
if (os_kernel_is_active() != 0U) {
|
||||
id = osThreadGetId();
|
||||
for (n = 0U; n < (uint32_t)OS_THREAD_LIBSPACE_NUM; n++) {
|
||||
if (os_libspace_id[n] == NULL) {
|
||||
os_libspace_id[n] = id;
|
||||
}
|
||||
if (os_libspace_id[n] == id) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (n == (uint32_t)OS_THREAD_LIBSPACE_NUM) {
|
||||
(void)osRtxErrorNotify(osRtxErrorClibSpace, id);
|
||||
}
|
||||
} else {
|
||||
n = OS_THREAD_LIBSPACE_NUM;
|
||||
}
|
||||
|
||||
//lint -e{9087} "cast between pointers to different object types"
|
||||
return (void *)&os_libspace[n][0];
|
||||
}
|
||||
|
||||
/* ARM toolchain requires dynamically created mutexes to enforce thread safety. There's
|
||||
up to 8 static mutexes, protecting atexit, signalinit, stdin, stdout, stderr, stream_list,
|
||||
fp_trap_init and the heap. Additionally for each call to fopen one extra mutex will be
|
||||
created.
|
||||
mbed OS provides a RTX pool for 8 mutexes, to satisfy the static requirements. All
|
||||
additional mutexes will be allocated on the heap. We can't use the heap allocation for
|
||||
all the required mutexes, as the heap operations also require a mutex. We don't need to
|
||||
worry about freeing the allocated memory as library mutexes are only freed when the
|
||||
application finishes executing.
|
||||
*/
|
||||
|
||||
typedef void *mutex;
|
||||
#define OS_MUTEX_STATIC_NUM 8
|
||||
mutex _static_mutexes[OS_MUTEX_STATIC_NUM] = {NULL};
|
||||
mbed_rtos_storage_mutex_t _static_mutexes_mem[OS_MUTEX_STATIC_NUM] = {NULL};
|
||||
|
||||
//lint -save "Function prototypes defined in C library"
|
||||
//lint -e970 "Use of 'int' outside of a typedef"
|
||||
//lint -e818 "Pointer 'm' could be declared as pointing to const"
|
||||
|
||||
/* Initialize mutex */
|
||||
__USED int _mutex_initialize(mutex *m)
|
||||
{
|
||||
osMutexAttr_t attr;
|
||||
memset(&attr, 0, sizeof(attr));
|
||||
attr.name = "ARM toolchain mutex";
|
||||
attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust;
|
||||
|
||||
mutex *slot = NULL;
|
||||
core_util_critical_section_enter();
|
||||
for (int i = 0; i < OS_MUTEX_STATIC_NUM; i++) {
|
||||
if (_static_mutexes[i] == NULL) {
|
||||
_static_mutexes[i] = (mutex)-1; // dummy value to reserve slot
|
||||
slot = &_static_mutexes[i];
|
||||
//Use the static attrs
|
||||
attr.cb_size = sizeof(mbed_rtos_storage_mutex_t);
|
||||
attr.cb_mem = &_static_mutexes_mem[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
core_util_critical_section_exit();
|
||||
|
||||
if (slot != NULL) {
|
||||
*m = osMutexNew(&attr);
|
||||
*slot = *m;
|
||||
if (*m != NULL) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mutex pool exhausted, try using HEAP */
|
||||
attr.cb_size = sizeof(mbed_rtos_storage_mutex_t);
|
||||
attr.cb_mem = (void*)malloc(attr.cb_size);
|
||||
if (attr.cb_mem == NULL) {
|
||||
osRtxErrorNotify(osRtxErrorClibSpace, m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*m = osMutexNew(&attr);
|
||||
if (*m == NULL) {
|
||||
osRtxErrorNotify(osRtxErrorClibMutex, m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Acquire mutex */
|
||||
__USED void _mutex_acquire(mutex *m) {
|
||||
if (os_kernel_is_active() != 0U) {
|
||||
(void)osMutexAcquire(*m, osWaitForever);
|
||||
}
|
||||
}
|
||||
|
||||
/* Release mutex */
|
||||
__USED void _mutex_release(mutex *m) {
|
||||
if (os_kernel_is_active() != 0U) {
|
||||
(void)osMutexRelease(*m);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free mutex */
|
||||
__USED void _mutex_free(mutex *m) {
|
||||
mutex *slot = NULL;
|
||||
core_util_critical_section_enter();
|
||||
for (int i = 0; i < OS_MUTEX_STATIC_NUM; i++) {
|
||||
if (_static_mutexes[i] == *m) {
|
||||
slot = &_static_mutexes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
core_util_critical_section_exit();
|
||||
|
||||
osMutexDelete(*m);
|
||||
|
||||
// if no slot reserved for mutex, must have been dynamically allocated
|
||||
if (!slot) {
|
||||
free(m);
|
||||
} else {
|
||||
*slot = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* RTX_NO_MULTITHREAD_CLIB */
|
|
@ -0,0 +1,115 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018-2018 ARM Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "cmsis.h"
|
||||
#include "mbed_toolchain.h"
|
||||
#include "mbed_boot.h"
|
||||
#include "mbed_rtos_storage.h"
|
||||
#include "cmsis_os2.h"
|
||||
|
||||
static osMutexId_t malloc_mutex_id;
|
||||
static mbed_rtos_storage_mutex_t malloc_mutex_obj;
|
||||
static osMutexAttr_t malloc_mutex_attr;
|
||||
|
||||
static osMutexId_t env_mutex_id;
|
||||
static mbed_rtos_storage_mutex_t env_mutex_obj;
|
||||
static osMutexAttr_t env_mutex_attr;
|
||||
|
||||
#if !defined(HEAP_START)
|
||||
/* Defined by linker script */
|
||||
extern uint32_t __end__[];
|
||||
#define HEAP_START ((unsigned char*)__end__)
|
||||
#define HEAP_SIZE ((uint32_t)((uint32_t)INITIAL_SP - (uint32_t)HEAP_START))
|
||||
#endif
|
||||
|
||||
extern void __libc_init_array (void);
|
||||
|
||||
/*
|
||||
* mbed entry point for the GCC toolchain
|
||||
*
|
||||
* Override gcc boot hook software_init_hook to run code before main.
|
||||
*/
|
||||
void software_init_hook(void)
|
||||
{
|
||||
unsigned char *free_start = HEAP_START;
|
||||
uint32_t free_size = HEAP_SIZE;
|
||||
|
||||
#ifdef ISR_STACK_START
|
||||
/* Interrupt stack explicitly specified */
|
||||
mbed_stack_isr_size = ISR_STACK_SIZE;
|
||||
mbed_stack_isr_start = ISR_STACK_START;
|
||||
#else
|
||||
/* Interrupt stack - reserve space at the end of the free block */
|
||||
mbed_stack_isr_size = ISR_STACK_SIZE < free_size ? ISR_STACK_SIZE : free_size;
|
||||
mbed_stack_isr_start = free_start + free_size - mbed_stack_isr_size;
|
||||
free_size -= mbed_stack_isr_size;
|
||||
#endif
|
||||
|
||||
/* Heap - everything else */
|
||||
mbed_heap_size = free_size;
|
||||
mbed_heap_start = free_start;
|
||||
|
||||
|
||||
mbed_init();
|
||||
mbed_rtos_start();
|
||||
}
|
||||
|
||||
void mbed_toolchain_init()
|
||||
{
|
||||
malloc_mutex_attr.name = "malloc_mutex";
|
||||
malloc_mutex_attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust;
|
||||
malloc_mutex_attr.cb_size = sizeof(malloc_mutex_obj);
|
||||
malloc_mutex_attr.cb_mem = &malloc_mutex_obj;
|
||||
malloc_mutex_id = osMutexNew(&malloc_mutex_attr);
|
||||
|
||||
env_mutex_attr.name = "env_mutex";
|
||||
env_mutex_attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust;
|
||||
env_mutex_attr.cb_size = sizeof(env_mutex_obj);
|
||||
env_mutex_attr.cb_mem = &env_mutex_obj;
|
||||
env_mutex_id = osMutexNew(&env_mutex_attr);
|
||||
|
||||
/* Run the C++ global object constructors */
|
||||
__libc_init_array();
|
||||
}
|
||||
|
||||
extern int __real_main(void);
|
||||
int __wrap_main(void) {
|
||||
/* For backwards compatibility */
|
||||
return __real_main();
|
||||
}
|
||||
|
||||
/* Opaque declaration of _reent structure */
|
||||
struct _reent;
|
||||
|
||||
void __rtos_malloc_lock( struct _reent *_r )
|
||||
{
|
||||
osMutexAcquire(malloc_mutex_id, osWaitForever);
|
||||
}
|
||||
|
||||
void __rtos_malloc_unlock( struct _reent *_r )
|
||||
{
|
||||
osMutexRelease(malloc_mutex_id);
|
||||
}
|
||||
|
||||
void __rtos_env_lock( struct _reent *_r )
|
||||
{
|
||||
osMutexAcquire(env_mutex_id, osWaitForever);
|
||||
}
|
||||
|
||||
void __rtos_env_unlock( struct _reent *_r )
|
||||
{
|
||||
osMutexRelease(env_mutex_id);
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018-2018 ARM Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "cmsis.h"
|
||||
#include "mbed_error.h"
|
||||
#include "mbed_boot.h"
|
||||
#if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ >= 8000000)
|
||||
#include <DLib_Threads.h>
|
||||
#endif
|
||||
#include "mbed_rtos_storage.h"
|
||||
#include "cmsis_os2.h"
|
||||
|
||||
/* Defined by linker script */
|
||||
#pragma section="CSTACK"
|
||||
#pragma section="HEAP"
|
||||
|
||||
extern void* __vector_table;
|
||||
extern int __low_level_init(void);
|
||||
extern void __iar_data_init3(void);
|
||||
extern __weak void __iar_init_core(void);
|
||||
extern __weak void __iar_init_vfp(void);
|
||||
extern void __iar_dynamic_initialization(void);
|
||||
|
||||
/*
|
||||
* mbed entry point for the IAR toolchain
|
||||
*
|
||||
* Override __iar_program_start to run code before main.
|
||||
* This is the first function called after the low level
|
||||
* target initialization, so RAM has not been setup yet.
|
||||
*
|
||||
* Details on what this function are supposed to do can
|
||||
* be found by looking at the IAR source for this file.
|
||||
*
|
||||
* IAR source files for ARM instruction set:
|
||||
* <IAR>\arm\src\lib\arm\cstartup.s
|
||||
* <IAR>\arm\src\lib\arm\cmain.s
|
||||
*
|
||||
* IAR source files for THUMB instruction set:
|
||||
* <IAR>\arm\src\lib\thumb\cmain.s
|
||||
* <IAR>\arm\src\lib\thumb\cstartup_M.s
|
||||
*/
|
||||
#pragma required=__vector_table
|
||||
void __iar_program_start( void )
|
||||
{
|
||||
/* the calls below are normally made in IAR cstartup */
|
||||
__iar_init_core();
|
||||
__iar_init_vfp();
|
||||
|
||||
/* the calls below are normally made in IAR cmain
|
||||
*
|
||||
* The function "__low_level_init" is a user overrideable hook
|
||||
* that does nothing by default. Returning zero means that
|
||||
* ram initialization should be skipped. Skipping ram initialization
|
||||
* is not allowed by mbed.
|
||||
*
|
||||
* The function "__iar_data_init3" is an IAR function which
|
||||
* initializes ram.
|
||||
*
|
||||
*/
|
||||
__low_level_init();
|
||||
__iar_data_init3();
|
||||
|
||||
/* mbed specific code */
|
||||
mbed_heap_start = (unsigned char*)__section_begin("HEAP");
|
||||
mbed_heap_size = (uint32_t)__section_size("HEAP");
|
||||
|
||||
mbed_stack_isr_start = (unsigned char*)__section_begin("CSTACK");
|
||||
mbed_stack_isr_size = (uint32_t)__section_size("CSTACK");
|
||||
|
||||
mbed_init();
|
||||
mbed_rtos_start();
|
||||
}
|
||||
|
||||
void mbed_toolchain_init(void)
|
||||
{
|
||||
#if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ >= 8000000)
|
||||
__iar_Initlocks();
|
||||
#endif
|
||||
|
||||
/* Run the C++ global object constructors */
|
||||
__iar_dynamic_initialization();
|
||||
}
|
||||
|
||||
/* Thread safety */
|
||||
static osMutexId_t std_mutex_id_sys[_MAX_LOCK] = {0};
|
||||
static mbed_rtos_storage_mutex_t std_mutex_sys[_MAX_LOCK] = {0};
|
||||
#define _FOPEN_MAX 10
|
||||
static osMutexId_t std_mutex_id_file[_FOPEN_MAX] = {0};
|
||||
static mbed_rtos_storage_mutex_t std_mutex_file[_FOPEN_MAX] = {0};
|
||||
|
||||
void __iar_system_Mtxinit(__iar_Rmtx *mutex) /* Initialize a system lock */
|
||||
{
|
||||
osMutexAttr_t attr;
|
||||
uint32_t index;
|
||||
for (index = 0; index < _MAX_LOCK; index++) {
|
||||
if (0 == std_mutex_id_sys[index]) {
|
||||
attr.name = "system_mutex";
|
||||
attr.cb_mem = &std_mutex_sys[index];
|
||||
attr.cb_size = sizeof(std_mutex_sys[index]);
|
||||
attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust;
|
||||
std_mutex_id_sys[index] = osMutexNew(&attr);
|
||||
*mutex = (__iar_Rmtx*)&std_mutex_id_sys[index];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* This should never happen */
|
||||
error("Not enough mutexes\n");
|
||||
}
|
||||
|
||||
void __iar_system_Mtxdst(__iar_Rmtx *mutex) /* Destroy a system lock */
|
||||
{
|
||||
osMutexDelete(*(osMutexId_t*)*mutex);
|
||||
*mutex = 0;
|
||||
}
|
||||
|
||||
void __iar_system_Mtxlock(__iar_Rmtx *mutex) /* Lock a system lock */
|
||||
{
|
||||
osMutexAcquire(*(osMutexId_t*)*mutex, osWaitForever);
|
||||
}
|
||||
|
||||
void __iar_system_Mtxunlock(__iar_Rmtx *mutex) /* Unlock a system lock */
|
||||
{
|
||||
osMutexRelease(*(osMutexId_t*)*mutex);
|
||||
}
|
||||
|
||||
void __iar_file_Mtxinit(__iar_Rmtx *mutex) /* Initialize a file lock */
|
||||
{
|
||||
osMutexAttr_t attr;
|
||||
uint32_t index;
|
||||
for (index = 0; index < _FOPEN_MAX; index++) {
|
||||
if (0 == std_mutex_id_file[index]) {
|
||||
attr.name = "file_mutex";
|
||||
attr.cb_mem = &std_mutex_file[index];
|
||||
attr.cb_size = sizeof(std_mutex_file[index]);
|
||||
attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust;
|
||||
std_mutex_id_file[index] = osMutexNew(&attr);
|
||||
*mutex = (__iar_Rmtx*)&std_mutex_id_file[index];
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* The variable _FOPEN_MAX needs to be increased */
|
||||
error("Not enough mutexes\n");
|
||||
}
|
||||
|
||||
void __iar_file_Mtxdst(__iar_Rmtx *mutex) /* Destroy a file lock */
|
||||
{
|
||||
osMutexDelete(*(osMutexId_t*)*mutex);
|
||||
*mutex = 0;
|
||||
}
|
||||
|
||||
void __iar_file_Mtxlock(__iar_Rmtx *mutex) /* Lock a file lock */
|
||||
{
|
||||
osMutexAcquire(*(osMutexId_t*)*mutex, osWaitForever);
|
||||
}
|
||||
|
||||
void __iar_file_Mtxunlock(__iar_Rmtx *mutex) /* Unlock a file lock */
|
||||
{
|
||||
osMutexRelease(*(osMutexId_t*)*mutex);
|
||||
}
|
|
@ -28,96 +28,6 @@
|
|||
* * mbed_main: User's code to be executed before main().
|
||||
* * main: Standard application code.
|
||||
*
|
||||
* Detailed boot procedures:
|
||||
*
|
||||
* For ARMCC:
|
||||
* ==========
|
||||
*
|
||||
* Reset (TARGET)
|
||||
* -> SystemInit (TARGET)
|
||||
* -> __main (LIBC)
|
||||
* -> __rt_entry (MBED: rtos/mbed_boot.c)
|
||||
* -> __user_setup_stackheap (LIBC)
|
||||
* -> mbed_set_stack_heap (MBED: rtos/mbed_boot.c)
|
||||
* -> mbed_cpy_nvic (MBED: rtos/mbed_boot.c)
|
||||
* -> mbed_sdk_init (TARGET)
|
||||
* -> _platform_post_stackheap_init (RTX)
|
||||
* -> osKernelInitialize (RTX)
|
||||
* -> mbed_start_main (MBED: rtos/mbed_boot.c)
|
||||
* -> osThreadNew (RTX)
|
||||
* -> pre_main(MBED: rtos/mbed_boot.c)
|
||||
* -> __rt_lib_init (LIBC)
|
||||
* -> $Sub$$main (MBED: rtos/mbed_boot.c)
|
||||
* -> mbed_main (MBED: rtos/mbed_boot.c)
|
||||
* -> main (APP)
|
||||
* -> osKernelStart (RTX)
|
||||
*
|
||||
* In addition to the above, libc will use functions defined by RTX: __user_perthread_libspace, _mutex_initialize,
|
||||
* _mutex_acquire, _mutex_release, _mutex_free for details consult: ARM C and C++ Libraries and Floating-Point
|
||||
* Support User Guide.
|
||||
*
|
||||
* For MICROLIB:
|
||||
* ==========
|
||||
*
|
||||
* Reset (TARGET)
|
||||
* -> SystemInit (TARGET)
|
||||
* -> __main (LIBC)
|
||||
* -> _main_init (MBED: rtos/mbed_boot.c)
|
||||
* -> mbed_set_stack_heap (MBED: rtos/mbed_boot.c)
|
||||
* -> mbed_cpy_nvic (MBED: rtos/mbed_boot.c)
|
||||
* -> mbed_sdk_init (TARGET)
|
||||
* -> osKernelInitialize (RTX)
|
||||
* -> mbed_start_main (MBED: rtos/mbed_boot.c)
|
||||
* -> osThreadNew (RTX)
|
||||
* -> pre_main(MBED: rtos/mbed_boot.c)
|
||||
* -> __cpp_initialize__aeabi_ (LIBC)
|
||||
* -> $Sub$$main (MBED: rtos/mbed_boot.c)
|
||||
* -> mbed_main (MBED: rtos/mbed_boot.c)
|
||||
* -> main (APP)
|
||||
* -> osKernelStart (RTX)
|
||||
*
|
||||
* For GCC:
|
||||
* ========
|
||||
*
|
||||
* Reset (TARGET)
|
||||
* -> SystemInit (TARGET)
|
||||
* -> __main (LIBC)
|
||||
* -> software_init_hook (MBED: rtos/mbed_boot.c)
|
||||
* -> mbed_set_stack_heap (MBED: rtos/mbed_boot.c)
|
||||
* -> mbed_cpy_nvic (MBED: rtos/mbed_boot.c)
|
||||
* -> mbed_sdk_init (TARGET)
|
||||
* -> osKernelInitialize (RTX)
|
||||
* -> mbed_start_main (MBED: rtos/mbed_boot.c)
|
||||
* -> osThreadNew (RTX)
|
||||
* -> pre_main(MBED: rtos/mbed_boot.c)
|
||||
* -> __libc_init_array (LIBC)
|
||||
* -> __wrap_main (MBED: rtos/mbed_boot.c)
|
||||
* -> mbed_main (MBED: rtos/mbed_boot.c)
|
||||
* -> __real_main (APP)
|
||||
* -> osKernelStart (RTX)
|
||||
*
|
||||
* For IAR:
|
||||
* ========
|
||||
*
|
||||
* Reset (TARGET)
|
||||
* -> SystemInit (TARGET)
|
||||
* -> __iar_program_start
|
||||
* -> __iar_init_core
|
||||
* -> __iar_init_core
|
||||
* -> __iar_init_vfp
|
||||
* -> __low_level_init
|
||||
* -> __iar_data_init3
|
||||
* -> mbed_cpy_nvic (MBED: rtos/mbed_boot.c)
|
||||
* -> mbed_sdk_init (TARGET)
|
||||
* -> mbed_set_stack_heap (MBED: rtos/mbed_boot.c)
|
||||
* -> osKernelInitialize (RTX)
|
||||
* -> mbed_start_main (MBED: rtos/mbed_boot.c)
|
||||
* -> osThreadNew (RTX)
|
||||
* -> pre_main(MBED: rtos/mbed_boot.c)
|
||||
* -> __iar_dynamic_initialization
|
||||
* -> main
|
||||
* -> osKernelStart (RTX)
|
||||
*
|
||||
* Other notes:
|
||||
*
|
||||
* * In addition to the above, libc will use functions defined in mbed_boot.c: __rtos_malloc_lock/unlock,
|
||||
|
@ -163,120 +73,43 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include "cmsis.h"
|
||||
#include "mbed_rtx.h"
|
||||
#include "mbed_rtos_storage.h"
|
||||
#include "cmsis_os2.h"
|
||||
#include "mbed_toolchain.h"
|
||||
#include "mbed_error.h"
|
||||
#include "mbed_critical.h"
|
||||
#if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ >= 8000000)
|
||||
#include <DLib_Threads.h>
|
||||
#endif
|
||||
/* Heap limits - only used if set */
|
||||
extern unsigned char *mbed_heap_start;
|
||||
extern uint32_t mbed_heap_size;
|
||||
#include "mbed_boot.h"
|
||||
|
||||
int main(void);
|
||||
static void mbed_cpy_nvic(void);
|
||||
|
||||
/* Stack limits */
|
||||
unsigned char *mbed_stack_isr_start = 0;
|
||||
uint32_t mbed_stack_isr_size = 0;
|
||||
|
||||
WEAK void mbed_main(void);
|
||||
void pre_main (void);
|
||||
void mbed_init(void)
|
||||
{
|
||||
mbed_cpy_nvic();
|
||||
mbed_sdk_init();
|
||||
mbed_rtos_init();
|
||||
}
|
||||
|
||||
osThreadAttr_t _main_thread_attr;
|
||||
void mbed_start(void)
|
||||
{
|
||||
mbed_toolchain_init();
|
||||
mbed_main();
|
||||
main();
|
||||
}
|
||||
|
||||
/** The main thread's stack size can be configured by the application, if not explicitly specified it'll default to 4K */
|
||||
#ifndef MBED_CONF_APP_MAIN_STACK_SIZE
|
||||
#define MBED_CONF_APP_MAIN_STACK_SIZE 4096
|
||||
#endif
|
||||
MBED_ALIGN(8) char _main_stack[MBED_CONF_APP_MAIN_STACK_SIZE];
|
||||
mbed_rtos_storage_thread_t _main_obj;
|
||||
MBED_WEAK void mbed_sdk_init(void)
|
||||
{
|
||||
// Nothing by default
|
||||
}
|
||||
|
||||
osMutexId_t singleton_mutex_id;
|
||||
mbed_rtos_storage_mutex_t singleton_mutex_obj;
|
||||
osMutexAttr_t singleton_mutex_attr;
|
||||
MBED_WEAK void software_init_hook_rtos()
|
||||
{
|
||||
// Nothing by default
|
||||
}
|
||||
|
||||
/*
|
||||
* Sanity check values
|
||||
*/
|
||||
#if defined(__ICCARM__) && \
|
||||
(defined(HEAP_START) || defined(HEAP_SIZE) || \
|
||||
defined(ISR_STACK_START) && defined(ISR_STACK_SIZE))
|
||||
#error "No custom layout allowed for IAR. Use .icf file instead"
|
||||
#endif
|
||||
#if defined(HEAP_START) && !defined(HEAP_SIZE)
|
||||
#error "HEAP_SIZE must be defined if HEAP_START is defined"
|
||||
#endif
|
||||
#if defined(ISR_STACK_START) && !defined(ISR_STACK_SIZE)
|
||||
#error "ISR_STACK_SIZE must be defined if ISR_STACK_START is defined"
|
||||
#endif
|
||||
#if defined(HEAP_SIZE) && !defined(HEAP_START)
|
||||
#error "HEAP_START must be defined if HEAP_SIZE is defined"
|
||||
#endif
|
||||
|
||||
/* IAR - INITIAL_SP and HEAP_START ignored as described in Memory layout notes above
|
||||
*/
|
||||
#if !defined(__ICCARM__) && !defined(INITIAL_SP) && !defined(HEAP_START)
|
||||
#error "no target defined"
|
||||
#endif
|
||||
|
||||
/* Interrupt stack and heap always defined for IAR
|
||||
* Main thread defined here
|
||||
*/
|
||||
#if defined(__ICCARM__)
|
||||
#pragma section="CSTACK"
|
||||
#pragma section="HEAP"
|
||||
#define HEAP_START ((unsigned char*)__section_begin("HEAP"))
|
||||
#define HEAP_SIZE ((uint32_t)__section_size("HEAP"))
|
||||
#define ISR_STACK_START ((unsigned char*)__section_begin("CSTACK"))
|
||||
#define ISR_STACK_SIZE ((uint32_t)__section_size("CSTACK"))
|
||||
#endif
|
||||
|
||||
/* Define heap region if it has not been defined already */
|
||||
#if !defined(HEAP_START)
|
||||
#if defined(__ICCARM__)
|
||||
#error "Heap should already be defined for IAR"
|
||||
#elif defined(__CC_ARM) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
|
||||
extern uint32_t Image$$RW_IRAM1$$ZI$$Limit[];
|
||||
#define HEAP_START ((unsigned char*)Image$$RW_IRAM1$$ZI$$Limit)
|
||||
#define HEAP_SIZE ((uint32_t)((uint32_t)INITIAL_SP - (uint32_t)HEAP_START))
|
||||
#elif defined(__GNUC__)
|
||||
extern uint32_t __end__[];
|
||||
#define HEAP_START ((unsigned char*)__end__)
|
||||
#define HEAP_SIZE ((uint32_t)((uint32_t)INITIAL_SP - (uint32_t)HEAP_START))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Define stack sizes if they haven't been set already */
|
||||
#if !defined(ISR_STACK_SIZE)
|
||||
#define ISR_STACK_SIZE ((uint32_t)1024)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* mbed_set_stack_heap purpose is to set the following variables:
|
||||
* -mbed_heap_start
|
||||
* -mbed_heap_size
|
||||
* -mbed_stack_isr_start
|
||||
* -mbed_stack_isr_size
|
||||
*/
|
||||
void mbed_set_stack_heap(void) {
|
||||
|
||||
unsigned char *free_start = HEAP_START;
|
||||
uint32_t free_size = HEAP_SIZE;
|
||||
|
||||
#ifdef ISR_STACK_START
|
||||
/* Interrupt stack explicitly specified */
|
||||
mbed_stack_isr_size = ISR_STACK_SIZE;
|
||||
mbed_stack_isr_start = ISR_STACK_START;
|
||||
#else
|
||||
/* Interrupt stack - reserve space at the end of the free block */
|
||||
mbed_stack_isr_size = ISR_STACK_SIZE < free_size ? ISR_STACK_SIZE : free_size;
|
||||
mbed_stack_isr_start = free_start + free_size - mbed_stack_isr_size;
|
||||
free_size -= mbed_stack_isr_size;
|
||||
#endif
|
||||
|
||||
/* Heap - everything else */
|
||||
mbed_heap_size = free_size;
|
||||
mbed_heap_start = free_start;
|
||||
MBED_WEAK void mbed_main(void)
|
||||
{
|
||||
// Nothing by default
|
||||
}
|
||||
|
||||
static void mbed_cpy_nvic(void)
|
||||
|
@ -296,513 +129,3 @@ static void mbed_cpy_nvic(void)
|
|||
#endif /* NVIC_RAM_VECTOR_ADDRESS */
|
||||
#endif /* !defined(__CORTEX_M0) && !defined(__CORTEX_A9) */
|
||||
}
|
||||
|
||||
/* mbed_main is a function that is called before main()
|
||||
* mbed_sdk_init() is also a function that is called before main(), but unlike
|
||||
* mbed_main(), it is not meant for user code, but for the SDK itself to perform
|
||||
* initializations before main() is called.
|
||||
*/
|
||||
WEAK void mbed_main(void) {
|
||||
|
||||
}
|
||||
|
||||
/* This function can be implemented by the target to perform higher level target initialization, before the mbed OS or
|
||||
* RTX is started.
|
||||
*/
|
||||
void mbed_sdk_init(void);
|
||||
WEAK void mbed_sdk_init(void) {
|
||||
}
|
||||
|
||||
void mbed_start_main(void)
|
||||
{
|
||||
_main_thread_attr.stack_mem = _main_stack;
|
||||
_main_thread_attr.stack_size = sizeof(_main_stack);
|
||||
_main_thread_attr.cb_size = sizeof(_main_obj);
|
||||
_main_thread_attr.cb_mem = &_main_obj;
|
||||
_main_thread_attr.priority = osPriorityNormal;
|
||||
_main_thread_attr.name = "main_thread";
|
||||
|
||||
/* Allow non-secure main thread to call secure functions */
|
||||
#if defined(DOMAIN_NS) && (DOMAIN_NS == 1U)
|
||||
_main_thread_attr.tz_module = 1U;
|
||||
#endif
|
||||
|
||||
osThreadId_t result = osThreadNew((osThreadFunc_t)pre_main, NULL, &_main_thread_attr);
|
||||
if ((void *)result == NULL) {
|
||||
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_INITIALIZATION_FAILED), "Pre main thread not created", &_main_thread_attr);
|
||||
}
|
||||
|
||||
osKernelStart();
|
||||
}
|
||||
|
||||
/******************** Toolchain specific code ********************/
|
||||
|
||||
#if defined (__CC_ARM) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
|
||||
|
||||
/* Common for both ARMC and MICROLIB */
|
||||
int $Super$$main(void);
|
||||
int $Sub$$main(void) {
|
||||
mbed_main();
|
||||
return $Super$$main();
|
||||
}
|
||||
|
||||
#if defined (__MICROLIB) /******************** MICROLIB ********************/
|
||||
|
||||
int main(void);
|
||||
void _main_init (void) __attribute__((section(".ARM.Collect$$$$000000FF")));
|
||||
void $Super$$__cpp_initialize__aeabi_(void);
|
||||
|
||||
void _main_init (void) {
|
||||
mbed_set_stack_heap();
|
||||
mbed_cpy_nvic();
|
||||
mbed_sdk_init();
|
||||
osKernelInitialize();
|
||||
mbed_start_main();
|
||||
for (;;);
|
||||
}
|
||||
|
||||
void $Sub$$__cpp_initialize__aeabi_(void)
|
||||
{
|
||||
/* This should invoke C++ initializers prior _main_init, we keep this empty and
|
||||
* invoke them after _main_init, when the RTX is already initilized.
|
||||
*/
|
||||
}
|
||||
|
||||
void pre_main()
|
||||
{
|
||||
singleton_mutex_attr.name = "singleton_mutex";
|
||||
singleton_mutex_attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust;
|
||||
singleton_mutex_attr.cb_size = sizeof(singleton_mutex_obj);
|
||||
singleton_mutex_attr.cb_mem = &singleton_mutex_obj;
|
||||
singleton_mutex_id = osMutexNew(&singleton_mutex_attr);
|
||||
|
||||
$Super$$__cpp_initialize__aeabi_();
|
||||
main();
|
||||
}
|
||||
|
||||
#else /******************** ARMC ********************/
|
||||
|
||||
#include <rt_misc.h>
|
||||
extern __value_in_regs struct __argc_argv __rt_lib_init(unsigned heapbase, unsigned heaptop);
|
||||
extern __value_in_regs struct __initial_stackheap __user_setup_stackheap(void);
|
||||
extern void _platform_post_stackheap_init (void);
|
||||
extern int main(int argc, char* argv[]);
|
||||
|
||||
void pre_main (void)
|
||||
{
|
||||
singleton_mutex_attr.name = "singleton_mutex";
|
||||
singleton_mutex_attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust;
|
||||
singleton_mutex_attr.cb_size = sizeof(singleton_mutex_obj);
|
||||
singleton_mutex_attr.cb_mem = &singleton_mutex_obj;
|
||||
singleton_mutex_id = osMutexNew(&singleton_mutex_attr);
|
||||
|
||||
__rt_lib_init((unsigned)mbed_heap_start, (unsigned)(mbed_heap_start + mbed_heap_size));
|
||||
|
||||
main(0, NULL);
|
||||
}
|
||||
|
||||
/* The single memory model is checking for stack collision at run time, verifing
|
||||
that the heap pointer is underneath the stack pointer.
|
||||
With the RTOS there is not only one stack above the heap, there are multiple
|
||||
stacks and some of them are underneath the heap pointer.
|
||||
*/
|
||||
#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
__asm(".global __use_two_region_memory\n\t");
|
||||
__asm(".global __use_no_semihosting\n\t");
|
||||
#else
|
||||
#pragma import(__use_two_region_memory)
|
||||
#endif
|
||||
|
||||
/* Called by the C library */
|
||||
void __rt_entry (void) {
|
||||
__user_setup_stackheap();
|
||||
mbed_set_stack_heap();
|
||||
mbed_cpy_nvic();
|
||||
mbed_sdk_init();
|
||||
_platform_post_stackheap_init();
|
||||
mbed_start_main();
|
||||
}
|
||||
|
||||
/* Move all code here from RTX code base (rtx_lib.c) and do some modifications:
|
||||
*
|
||||
* 1. _mutex_initialize/_mutex_free are re-implemented to meet Mbed.
|
||||
* 2. All _mutex_* functions are declared with '__USED' to avoid excluded by linker.
|
||||
*/
|
||||
#if defined(RTX_NO_MULTITHREAD_CLIB)
|
||||
|
||||
#define LIBSPACE_SIZE 96
|
||||
|
||||
//lint -esym(714,__user_perthread_libspace,_mutex_*) "Referenced by C library"
|
||||
//lint -esym(765,__user_perthread_libspace,_mutex_*) "Global scope"
|
||||
//lint -esym(9003, os_libspace*) "variables 'os_libspace*' defined at module scope"
|
||||
|
||||
// Memory for libspace
|
||||
static uint32_t os_libspace[OS_THREAD_LIBSPACE_NUM+1][LIBSPACE_SIZE/4] \
|
||||
__attribute__((section(".bss.os.libspace")));
|
||||
|
||||
// Thread IDs for libspace
|
||||
static osThreadId_t os_libspace_id[OS_THREAD_LIBSPACE_NUM] \
|
||||
__attribute__((section(".bss.os.libspace")));
|
||||
|
||||
// Check if Kernel has been started
|
||||
static uint32_t os_kernel_is_active (void) {
|
||||
static uint8_t os_kernel_active = 0U;
|
||||
|
||||
if (os_kernel_active == 0U) {
|
||||
if (osKernelGetState() > osKernelReady) {
|
||||
os_kernel_active = 1U;
|
||||
}
|
||||
}
|
||||
return (uint32_t)os_kernel_active;
|
||||
}
|
||||
|
||||
// Provide libspace for current thread
|
||||
void *__user_perthread_libspace (void) {
|
||||
osThreadId_t id;
|
||||
uint32_t n;
|
||||
|
||||
if (os_kernel_is_active() != 0U) {
|
||||
id = osThreadGetId();
|
||||
for (n = 0U; n < (uint32_t)OS_THREAD_LIBSPACE_NUM; n++) {
|
||||
if (os_libspace_id[n] == NULL) {
|
||||
os_libspace_id[n] = id;
|
||||
}
|
||||
if (os_libspace_id[n] == id) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (n == (uint32_t)OS_THREAD_LIBSPACE_NUM) {
|
||||
(void)osRtxErrorNotify(osRtxErrorClibSpace, id);
|
||||
}
|
||||
} else {
|
||||
n = OS_THREAD_LIBSPACE_NUM;
|
||||
}
|
||||
|
||||
//lint -e{9087} "cast between pointers to different object types"
|
||||
return (void *)&os_libspace[n][0];
|
||||
}
|
||||
|
||||
/* ARM toolchain requires dynamically created mutexes to enforce thread safety. There's
|
||||
up to 8 static mutexes, protecting atexit, signalinit, stdin, stdout, stderr, stream_list,
|
||||
fp_trap_init and the heap. Additionally for each call to fopen one extra mutex will be
|
||||
created.
|
||||
mbed OS provides a RTX pool for 8 mutexes, to satisfy the static requirements. All
|
||||
additional mutexes will be allocated on the heap. We can't use the heap allocation for
|
||||
all the required mutexes, as the heap operations also require a mutex. We don't need to
|
||||
worry about freeing the allocated memory as library mutexes are only freed when the
|
||||
application finishes executing.
|
||||
*/
|
||||
|
||||
typedef void *mutex;
|
||||
#define OS_MUTEX_STATIC_NUM 8
|
||||
mutex _static_mutexes[OS_MUTEX_STATIC_NUM] = {NULL};
|
||||
mbed_rtos_storage_mutex_t _static_mutexes_mem[OS_MUTEX_STATIC_NUM] = {NULL};
|
||||
|
||||
//lint -save "Function prototypes defined in C library"
|
||||
//lint -e970 "Use of 'int' outside of a typedef"
|
||||
//lint -e818 "Pointer 'm' could be declared as pointing to const"
|
||||
|
||||
/* Initialize mutex */
|
||||
__USED int _mutex_initialize(mutex *m)
|
||||
{
|
||||
osMutexAttr_t attr;
|
||||
memset(&attr, 0, sizeof(attr));
|
||||
attr.name = "ARM toolchain mutex";
|
||||
attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust;
|
||||
|
||||
mutex *slot = NULL;
|
||||
core_util_critical_section_enter();
|
||||
for (int i = 0; i < OS_MUTEX_STATIC_NUM; i++) {
|
||||
if (_static_mutexes[i] == NULL) {
|
||||
_static_mutexes[i] = (mutex)-1; // dummy value to reserve slot
|
||||
slot = &_static_mutexes[i];
|
||||
//Use the static attrs
|
||||
attr.cb_size = sizeof(mbed_rtos_storage_mutex_t);
|
||||
attr.cb_mem = &_static_mutexes_mem[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
core_util_critical_section_exit();
|
||||
|
||||
if (slot != NULL) {
|
||||
*m = osMutexNew(&attr);
|
||||
*slot = *m;
|
||||
if (*m != NULL) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mutex pool exhausted, try using HEAP */
|
||||
attr.cb_size = sizeof(mbed_rtos_storage_mutex_t);
|
||||
attr.cb_mem = (void*)malloc(attr.cb_size);
|
||||
if (attr.cb_mem == NULL) {
|
||||
osRtxErrorNotify(osRtxErrorClibSpace, m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*m = osMutexNew(&attr);
|
||||
if (*m == NULL) {
|
||||
osRtxErrorNotify(osRtxErrorClibMutex, m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Acquire mutex */
|
||||
__USED void _mutex_acquire(mutex *m) {
|
||||
if (os_kernel_is_active() != 0U) {
|
||||
(void)osMutexAcquire(*m, osWaitForever);
|
||||
}
|
||||
}
|
||||
|
||||
/* Release mutex */
|
||||
__USED void _mutex_release(mutex *m) {
|
||||
if (os_kernel_is_active() != 0U) {
|
||||
(void)osMutexRelease(*m);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free mutex */
|
||||
__USED void _mutex_free(mutex *m) {
|
||||
mutex *slot = NULL;
|
||||
core_util_critical_section_enter();
|
||||
for (int i = 0; i < OS_MUTEX_STATIC_NUM; i++) {
|
||||
if (_static_mutexes[i] == *m) {
|
||||
slot = &_static_mutexes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
core_util_critical_section_exit();
|
||||
|
||||
osMutexDelete(*m);
|
||||
|
||||
// if no slot reserved for mutex, must have been dynamically allocated
|
||||
if (!slot) {
|
||||
free(m);
|
||||
} else {
|
||||
*slot = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* RTX_NO_MULTITHREAD_CLIB */
|
||||
#endif /* ARMC */
|
||||
#elif defined (__GNUC__) /******************** GCC ********************/
|
||||
|
||||
extern int main(int argc, char* argv[]);
|
||||
extern void __libc_init_array (void);
|
||||
extern int __real_main(void);
|
||||
|
||||
osMutexId_t malloc_mutex_id;
|
||||
mbed_rtos_storage_mutex_t malloc_mutex_obj;
|
||||
osMutexAttr_t malloc_mutex_attr;
|
||||
|
||||
osMutexId_t env_mutex_id;
|
||||
mbed_rtos_storage_mutex_t env_mutex_obj;
|
||||
osMutexAttr_t env_mutex_attr;
|
||||
|
||||
|
||||
int __wrap_main(void) {
|
||||
mbed_main();
|
||||
return __real_main();
|
||||
}
|
||||
|
||||
void pre_main(void)
|
||||
{
|
||||
singleton_mutex_attr.name = "singleton_mutex";
|
||||
singleton_mutex_attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust;
|
||||
singleton_mutex_attr.cb_size = sizeof(singleton_mutex_obj);
|
||||
singleton_mutex_attr.cb_mem = &singleton_mutex_obj;
|
||||
singleton_mutex_id = osMutexNew(&singleton_mutex_attr);
|
||||
|
||||
malloc_mutex_attr.name = "malloc_mutex";
|
||||
malloc_mutex_attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust;
|
||||
malloc_mutex_attr.cb_size = sizeof(malloc_mutex_obj);
|
||||
malloc_mutex_attr.cb_mem = &malloc_mutex_obj;
|
||||
malloc_mutex_id = osMutexNew(&malloc_mutex_attr);
|
||||
|
||||
env_mutex_attr.name = "env_mutex";
|
||||
env_mutex_attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust;
|
||||
env_mutex_attr.cb_size = sizeof(env_mutex_obj);
|
||||
env_mutex_attr.cb_mem = &env_mutex_obj;
|
||||
env_mutex_id = osMutexNew(&env_mutex_attr);
|
||||
|
||||
__libc_init_array();
|
||||
|
||||
main(0, NULL);
|
||||
}
|
||||
|
||||
void software_init_hook(void)
|
||||
{
|
||||
mbed_set_stack_heap();
|
||||
mbed_cpy_nvic();
|
||||
mbed_sdk_init();
|
||||
osKernelInitialize();
|
||||
mbed_start_main();
|
||||
}
|
||||
|
||||
/* Opaque declaration of _reent structure */
|
||||
struct _reent;
|
||||
|
||||
void __rtos_malloc_lock( struct _reent *_r )
|
||||
{
|
||||
osMutexAcquire(malloc_mutex_id, osWaitForever);
|
||||
}
|
||||
|
||||
void __rtos_malloc_unlock( struct _reent *_r )
|
||||
{
|
||||
osMutexRelease(malloc_mutex_id);
|
||||
}
|
||||
|
||||
void __rtos_env_lock( struct _reent *_r )
|
||||
{
|
||||
osMutexAcquire(env_mutex_id, osWaitForever);
|
||||
}
|
||||
|
||||
void __rtos_env_unlock( struct _reent *_r )
|
||||
{
|
||||
osMutexRelease(env_mutex_id);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__ICCARM__) /******************** IAR ********************/
|
||||
|
||||
extern void* __vector_table;
|
||||
extern int __low_level_init(void);
|
||||
extern void __iar_data_init3(void);
|
||||
extern __weak void __iar_init_core( void );
|
||||
extern __weak void __iar_init_vfp( void );
|
||||
extern void __iar_dynamic_initialization(void);
|
||||
extern void mbed_sdk_init(void);
|
||||
extern int main(void);
|
||||
extern void exit(int arg);
|
||||
|
||||
static uint8_t low_level_init_needed;
|
||||
|
||||
void pre_main(void)
|
||||
{
|
||||
singleton_mutex_attr.name = "singleton_mutex";
|
||||
singleton_mutex_attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust;
|
||||
singleton_mutex_attr.cb_size = sizeof(singleton_mutex_obj);
|
||||
singleton_mutex_attr.cb_mem = &singleton_mutex_obj;
|
||||
singleton_mutex_id = osMutexNew(&singleton_mutex_attr);
|
||||
|
||||
#if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ >= 8000000)
|
||||
__iar_Initlocks();
|
||||
#endif
|
||||
|
||||
if (low_level_init_needed) {
|
||||
__iar_dynamic_initialization();
|
||||
}
|
||||
|
||||
mbed_main();
|
||||
main();
|
||||
}
|
||||
|
||||
#pragma required=__vector_table
|
||||
void __iar_program_start( void )
|
||||
{
|
||||
__iar_init_core();
|
||||
__iar_init_vfp();
|
||||
|
||||
uint8_t low_level_init_needed_local;
|
||||
|
||||
low_level_init_needed_local = __low_level_init();
|
||||
if (low_level_init_needed_local) {
|
||||
__iar_data_init3();
|
||||
|
||||
mbed_cpy_nvic();
|
||||
mbed_sdk_init();
|
||||
}
|
||||
|
||||
mbed_set_stack_heap();
|
||||
|
||||
/* Store in a global variable after RAM has been initialized */
|
||||
low_level_init_needed = low_level_init_needed_local;
|
||||
|
||||
osKernelInitialize();
|
||||
|
||||
mbed_start_main();
|
||||
}
|
||||
|
||||
/* Thread safety */
|
||||
static osMutexId_t std_mutex_id_sys[_MAX_LOCK] = {0};
|
||||
static mbed_rtos_storage_mutex_t std_mutex_sys[_MAX_LOCK] = {0};
|
||||
#define _FOPEN_MAX 10
|
||||
static osMutexId_t std_mutex_id_file[_FOPEN_MAX] = {0};
|
||||
static mbed_rtos_storage_mutex_t std_mutex_file[_FOPEN_MAX] = {0};
|
||||
|
||||
void __iar_system_Mtxinit(__iar_Rmtx *mutex) /* Initialize a system lock */
|
||||
{
|
||||
osMutexAttr_t attr;
|
||||
uint32_t index;
|
||||
for (index = 0; index < _MAX_LOCK; index++) {
|
||||
if (0 == std_mutex_id_sys[index]) {
|
||||
attr.name = "system_mutex";
|
||||
attr.cb_mem = &std_mutex_sys[index];
|
||||
attr.cb_size = sizeof(std_mutex_sys[index]);
|
||||
attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust;
|
||||
std_mutex_id_sys[index] = osMutexNew(&attr);
|
||||
*mutex = (__iar_Rmtx*)&std_mutex_id_sys[index];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* This should never happen */
|
||||
error("Not enough mutexes\n");
|
||||
}
|
||||
|
||||
void __iar_system_Mtxdst(__iar_Rmtx *mutex) /* Destroy a system lock */
|
||||
{
|
||||
osMutexDelete(*(osMutexId_t*)*mutex);
|
||||
*mutex = 0;
|
||||
}
|
||||
|
||||
void __iar_system_Mtxlock(__iar_Rmtx *mutex) /* Lock a system lock */
|
||||
{
|
||||
osMutexAcquire(*(osMutexId_t*)*mutex, osWaitForever);
|
||||
}
|
||||
|
||||
void __iar_system_Mtxunlock(__iar_Rmtx *mutex) /* Unlock a system lock */
|
||||
{
|
||||
osMutexRelease(*(osMutexId_t*)*mutex);
|
||||
}
|
||||
|
||||
void __iar_file_Mtxinit(__iar_Rmtx *mutex) /* Initialize a file lock */
|
||||
{
|
||||
osMutexAttr_t attr;
|
||||
uint32_t index;
|
||||
for (index = 0; index < _FOPEN_MAX; index++) {
|
||||
if (0 == std_mutex_id_file[index]) {
|
||||
attr.name = "file_mutex";
|
||||
attr.cb_mem = &std_mutex_file[index];
|
||||
attr.cb_size = sizeof(std_mutex_file[index]);
|
||||
attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust;
|
||||
std_mutex_id_file[index] = osMutexNew(&attr);
|
||||
*mutex = (__iar_Rmtx*)&std_mutex_id_file[index];
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* The variable _FOPEN_MAX needs to be increased */
|
||||
error("Not enough mutexes\n");
|
||||
}
|
||||
|
||||
void __iar_file_Mtxdst(__iar_Rmtx *mutex) /* Destroy a file lock */
|
||||
{
|
||||
osMutexDelete(*(osMutexId_t*)*mutex);
|
||||
*mutex = 0;
|
||||
}
|
||||
|
||||
void __iar_file_Mtxlock(__iar_Rmtx *mutex) /* Lock a file lock */
|
||||
{
|
||||
osMutexAcquire(*(osMutexId_t*)*mutex, osWaitForever);
|
||||
}
|
||||
|
||||
void __iar_file_Mtxunlock(__iar_Rmtx *mutex) /* Unlock a file lock */
|
||||
{
|
||||
osMutexRelease(*(osMutexId_t*)*mutex);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018-2018 ARM Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef MBED_BOOT_H
|
||||
#define MBED_BOOT_H
|
||||
|
||||
#include "mbed_toolchain.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "mbed_rtx.h"
|
||||
|
||||
/**
|
||||
* \defgroup boot Boot sequence
|
||||
* Boot sequence overview
|
||||
*
|
||||
* 1. Setup target
|
||||
* - Configure clocks
|
||||
* - Configure watchdog (if applicable)
|
||||
* - Turn on RAM (if applicable)
|
||||
* - Jump to setup toolchain
|
||||
* 2. Setup toolchain
|
||||
* - Initialize RAM
|
||||
* - Initialize standard library
|
||||
* - Call mbed_init
|
||||
* - jump to start rtos
|
||||
* 3. Start RTOS
|
||||
* - Create main thread
|
||||
* - Start scheduler
|
||||
* - main thread calls start mbed
|
||||
* 4. Start mbed
|
||||
* - Call mbed_main
|
||||
* - Call main
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Define stack sizes if they haven't been set already */
|
||||
#if !defined(ISR_STACK_SIZE)
|
||||
#define ISR_STACK_SIZE ((uint32_t)1024)
|
||||
#endif
|
||||
|
||||
/* Heap limits - only used if set */
|
||||
extern unsigned char *mbed_heap_start;
|
||||
extern uint32_t mbed_heap_size;
|
||||
|
||||
/* Stack limits */
|
||||
extern unsigned char *mbed_stack_isr_start;
|
||||
extern uint32_t mbed_stack_isr_size;
|
||||
|
||||
/**
|
||||
* Perform low level init of mbed
|
||||
*
|
||||
* The toolchain calls this function as part of the boot
|
||||
* sequence. This function does the following:
|
||||
* - Sets up NVIC so interrupts can be used
|
||||
* - Calls into the vendor SDK so it can be used
|
||||
* - Initializes the RTOS so it can be used
|
||||
*
|
||||
* Preconditions:
|
||||
* - Target is initialized
|
||||
* - Ram is initialized
|
||||
* - value set for mbed_heap_start
|
||||
* - value set for mbed_heap_size
|
||||
* - value set for mbed_stack_isr_start
|
||||
* - value set for mbed_stack_isr_size
|
||||
*
|
||||
* The following events must not have happened yet:
|
||||
* - global constructors must not be called yet
|
||||
*
|
||||
*/
|
||||
void mbed_init(void);
|
||||
|
||||
/**
|
||||
* Start the main mbed application
|
||||
*
|
||||
* This is the last stage of the boot sequence. This function must be
|
||||
* called only after the RTOS has been fully initialized.
|
||||
* This function does the following:
|
||||
* - Initialize the toolchain
|
||||
* - Run mbed_main
|
||||
* - Run main
|
||||
*
|
||||
* Preconditions:
|
||||
* - The RTOS has been started by a call to mbed_rtos_start
|
||||
*
|
||||
*/
|
||||
void mbed_start(void);
|
||||
|
||||
/**
|
||||
* Perform low level initialization of the RTOS
|
||||
*
|
||||
* Set the RTOS to a known state but don't start the scheduler. After
|
||||
* the RTOS has been initialized it is safe to create RTOS primitives
|
||||
* for file locks or other purposes.
|
||||
*
|
||||
* Preconditions:
|
||||
* - Ram is initialized
|
||||
* - NVIC is setup
|
||||
* - Vendor SDK must be initialized by a call to mbed_sdk_init
|
||||
*/
|
||||
void mbed_rtos_init(void);
|
||||
|
||||
/**
|
||||
* Start the RTOS
|
||||
*
|
||||
* Start the RTOS scheduler and call mbed_start on the
|
||||
* main thread. This function does not return.
|
||||
*
|
||||
* Preconditions:
|
||||
* - RTOS has been initialized by a call to mbed_rtos_init
|
||||
*/
|
||||
MBED_NORETURN void mbed_rtos_start(void);
|
||||
|
||||
/**
|
||||
* Perform toolchain specific initialization
|
||||
*
|
||||
* Initialize locks if this has not been done already
|
||||
* and call global C++ constructors.
|
||||
*
|
||||
* Preconditions:
|
||||
* - The RTOS has been started by a call to mbed_rtos_start
|
||||
*/
|
||||
void mbed_toolchain_init(void);
|
||||
|
||||
/**
|
||||
* SDK hook for running code before ctors or OS
|
||||
*
|
||||
* This is a weak function which can be overridden by a target's
|
||||
* SDK to allow code to run after ram is initialized but before
|
||||
* the OS has been started or constructors have run.
|
||||
*
|
||||
* Preconditions:
|
||||
* - Ram is initialized
|
||||
* - NVIC is setup
|
||||
*/
|
||||
void mbed_sdk_init(void);
|
||||
|
||||
/**
|
||||
* Application hook for running code before main
|
||||
*
|
||||
* This is a weak function which can be overridden by an application
|
||||
* to allow code to run before main is called.
|
||||
*
|
||||
* Preconditions:
|
||||
* - The RTOS has been started by a call to mbed_rtos_start
|
||||
* - The toolchain has been initialized by a call to mbed_toolchain_init
|
||||
*/
|
||||
void mbed_main(void);
|
||||
|
||||
/**@}*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MBED_BOOT_H */
|
|
@ -0,0 +1,72 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018-2018 ARM Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "cmsis.h"
|
||||
#include "mbed_rtx.h"
|
||||
#include "mbed_rtos_storage.h"
|
||||
#include "cmsis_os2.h"
|
||||
#include "mbed_toolchain.h"
|
||||
#include "mbed_error.h"
|
||||
#include "mbed_critical.h"
|
||||
#include "mbed_boot.h"
|
||||
|
||||
osThreadAttr_t _main_thread_attr;
|
||||
|
||||
/** The main thread's stack size can be configured by the application, if not explicitly specified it'll default to 4K */
|
||||
#ifndef MBED_CONF_APP_MAIN_STACK_SIZE
|
||||
#define MBED_CONF_APP_MAIN_STACK_SIZE 4096
|
||||
#endif
|
||||
MBED_ALIGN(8) char _main_stack[MBED_CONF_APP_MAIN_STACK_SIZE];
|
||||
mbed_rtos_storage_thread_t _main_obj;
|
||||
|
||||
osMutexId_t singleton_mutex_id;
|
||||
mbed_rtos_storage_mutex_t singleton_mutex_obj;
|
||||
osMutexAttr_t singleton_mutex_attr;
|
||||
|
||||
void mbed_rtos_init()
|
||||
{
|
||||
osKernelInitialize();
|
||||
}
|
||||
|
||||
MBED_NORETURN void mbed_rtos_start()
|
||||
{
|
||||
singleton_mutex_attr.name = "singleton_mutex";
|
||||
singleton_mutex_attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust;
|
||||
singleton_mutex_attr.cb_size = sizeof(singleton_mutex_obj);
|
||||
singleton_mutex_attr.cb_mem = &singleton_mutex_obj;
|
||||
|
||||
_main_thread_attr.stack_mem = _main_stack;
|
||||
_main_thread_attr.stack_size = sizeof(_main_stack);
|
||||
_main_thread_attr.cb_size = sizeof(_main_obj);
|
||||
_main_thread_attr.cb_mem = &_main_obj;
|
||||
_main_thread_attr.priority = osPriorityNormal;
|
||||
_main_thread_attr.name = "main_thread";
|
||||
|
||||
/* Allow non-secure main thread to call secure functions */
|
||||
#if defined(DOMAIN_NS) && (DOMAIN_NS == 1U)
|
||||
_main_thread_attr.tz_module = 1U;
|
||||
#endif
|
||||
|
||||
singleton_mutex_id = osMutexNew(&singleton_mutex_attr);
|
||||
osThreadId_t result = osThreadNew((osThreadFunc_t)mbed_start, NULL, &_main_thread_attr);
|
||||
if ((void *)result == NULL) {
|
||||
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_INITIALIZATION_FAILED), "Pre main thread not created", &_main_thread_attr);
|
||||
}
|
||||
|
||||
osKernelStart();
|
||||
MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_INITIALIZATION_FAILED), "Failed to start RTOS");
|
||||
while (1); // Code should never get here
|
||||
}
|
Loading…
Reference in New Issue