1 /* --------------------------------------------------------------------------
2 * Copyright (c) 2013-2019 Arm Limited. All rights reserved.
4 * SPDX-License-Identifier: Apache-2.0
6 * Licensed under the Apache License, Version 2.0 (the License); you may
7 * not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 * Purpose: ARM C library startup and initialization support
21 *---------------------------------------------------------------------------*/
26 #include "FreeRTOS.h" // ARM.FreeRTOS::RTOS:Core
27 #include "task.h" // ARM.FreeRTOS::RTOS:Core
28 #include "semphr.h" // ARM.FreeRTOS::RTOS:Core
30 /* Define the number of Threads which use standard C/C++ library libspace */
31 #ifndef OS_THREAD_LIBSPACE_NUM
32 #define OS_THREAD_LIBSPACE_NUM 4
35 /* Define the number of Mutexes used by standard C/C++ library for stream protection */
36 #ifndef OS_MUTEX_CLIB_NUM
37 #define OS_MUTEX_CLIB_NUM 5
40 /*----------------------------------------------------------------------------*/
42 /* Initialization after stack and heap setup */
43 #if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
47 void _platform_post_stackheap_init (void);
48 void _platform_post_stackheap_init (void) {
49 /* Initialize OS, memory, etc. */
50 #if defined(RTE_Compiler_EventRecorder)
54 #endif /* __MICROLIB */
56 #elif defined(__GNUC__)
58 void software_init_hook (void);
59 void software_init_hook (void) {
60 /* Initialize OS, memory, etc. */
61 #if defined(RTE_Compiler_EventRecorder)
68 /*----------------------------------------------------------------------------*/
70 /* C/C++ Standard Library Multithreading Interface */
71 #if (( defined(__CC_ARM) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))) && !defined(__MICROLIB))
73 #define LIBSPACE_SIZE 96
75 /* Libspace memory pool */
76 static uint32_t os_libspace[OS_THREAD_LIBSPACE_NUM+1][LIBSPACE_SIZE/sizeof(uint32_t)];
78 /* Array of Threads (IDs) using libspace */
79 static TaskHandle_t os_libspace_id[OS_THREAD_LIBSPACE_NUM];
81 /* OS Kernel state checking */
82 static uint32_t os_kernel_is_active (void) {
83 static uint8_t os_kernel_active = 0U;
85 if (os_kernel_active == 0U) {
86 if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
87 os_kernel_active = 1U;
96 /* Provide libspace for current thread */
97 void *__user_perthread_libspace (void);
98 void *__user_perthread_libspace (void) {
102 if (!os_kernel_is_active()) {
103 return (void *)&os_libspace[OS_THREAD_LIBSPACE_NUM][0];
106 id = xTaskGetCurrentTaskHandle();
108 for (n = 0U; n < OS_THREAD_LIBSPACE_NUM; n++) {
109 if (os_libspace_id[n] == NULL) {
111 os_libspace_id[n] = id;
113 return (void *)&os_libspace[n][0];
115 if (os_libspace_id[n] == id) {
116 return (void *)&os_libspace[n][0];
120 return (void *)&os_libspace[n][0];
123 /*----------------------------------------------------------------------------*/
125 #if (OS_MUTEX_CLIB_NUM > 0)
126 static StaticSemaphore_t clib_mutex_cb[OS_MUTEX_CLIB_NUM];
127 static SemaphoreHandle_t clib_mutex_id[OS_MUTEX_CLIB_NUM];
130 /* Define mutex object and function prototypes */
133 __USED int _mutex_initialize(mutex *m);
134 __USED void _mutex_acquire (mutex *m);
135 __USED void _mutex_release (mutex *m);
136 __USED void _mutex_free (mutex *m);
139 /* Initialize mutex */
140 int _mutex_initialize(mutex *m) {
141 #if (OS_MUTEX_CLIB_NUM > 0)
147 #if (OS_MUTEX_CLIB_NUM > 0)
148 for (i = 0U; i < OS_MUTEX_CLIB_NUM; i++) {
149 if (clib_mutex_id[i] == NULL) {
150 /* Create mutex using static memory */
151 clib_mutex_id[i] = xSemaphoreCreateMutexStatic(&clib_mutex_cb[i]);
153 /* Return mutex id */
154 *m = clib_mutex_id[i];
160 if (os_kernel_is_active()) {
161 /* Create mutex using dynamic memory */
162 *m = xSemaphoreCreateMutex();
172 void _mutex_acquire(mutex *m) {
174 if (os_kernel_is_active()) {
175 xSemaphoreTake(*m, portMAX_DELAY);
180 void _mutex_release(mutex *m) {
182 if (os_kernel_is_active()) {
188 void _mutex_free(mutex *m) {
189 #if (OS_MUTEX_CLIB_NUM > 0)
193 vSemaphoreDelete(*m);
195 #if (OS_MUTEX_CLIB_NUM > 0)
196 /* Check if mutex was using static memory */
197 for (i = 0U; i < OS_MUTEX_CLIB_NUM; i++) {
198 if (*m == clib_mutex_id[i]) {
199 clib_mutex_id[i] = NULL;