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().
|
* * mbed_main: User's code to be executed before main().
|
||||||
* * main: Standard application code.
|
* * 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:
|
* Other notes:
|
||||||
*
|
*
|
||||||
* * In addition to the above, libc will use functions defined in mbed_boot.c: __rtos_malloc_lock/unlock,
|
* * 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 <stdlib.h>
|
||||||
|
|
||||||
#include "cmsis.h"
|
#include "cmsis.h"
|
||||||
#include "mbed_rtx.h"
|
|
||||||
#include "mbed_rtos_storage.h"
|
|
||||||
#include "cmsis_os2.h"
|
|
||||||
#include "mbed_toolchain.h"
|
#include "mbed_toolchain.h"
|
||||||
#include "mbed_error.h"
|
#include "mbed_boot.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;
|
|
||||||
|
|
||||||
|
int main(void);
|
||||||
|
static void mbed_cpy_nvic(void);
|
||||||
|
|
||||||
|
/* Stack limits */
|
||||||
unsigned char *mbed_stack_isr_start = 0;
|
unsigned char *mbed_stack_isr_start = 0;
|
||||||
uint32_t mbed_stack_isr_size = 0;
|
uint32_t mbed_stack_isr_size = 0;
|
||||||
|
|
||||||
WEAK void mbed_main(void);
|
void mbed_init(void)
|
||||||
void pre_main (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 */
|
MBED_WEAK void mbed_sdk_init(void)
|
||||||
#ifndef MBED_CONF_APP_MAIN_STACK_SIZE
|
{
|
||||||
#define MBED_CONF_APP_MAIN_STACK_SIZE 4096
|
// Nothing by default
|
||||||
#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_WEAK void software_init_hook_rtos()
|
||||||
mbed_rtos_storage_mutex_t singleton_mutex_obj;
|
{
|
||||||
osMutexAttr_t singleton_mutex_attr;
|
// Nothing by default
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
MBED_WEAK void mbed_main(void)
|
||||||
* Sanity check values
|
{
|
||||||
*/
|
// Nothing by default
|
||||||
#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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mbed_cpy_nvic(void)
|
static void mbed_cpy_nvic(void)
|
||||||
|
@ -296,513 +129,3 @@ static void mbed_cpy_nvic(void)
|
||||||
#endif /* NVIC_RAM_VECTOR_ADDRESS */
|
#endif /* NVIC_RAM_VECTOR_ADDRESS */
|
||||||
#endif /* !defined(__CORTEX_M0) && !defined(__CORTEX_A9) */
|
#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