]> begriffs open source - cmsis-freertos/blob - CMSIS/RTOS2/FreeRTOS/Source/ARM/clib_arm.c
- Build Event Recorder setup function conditionally.
[cmsis-freertos] / CMSIS / RTOS2 / FreeRTOS / Source / ARM / clib_arm.c
1 /* -------------------------------------------------------------------------- 
2  * Copyright (c) 2013-2019 Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
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
9  *
10  * www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  *      Name:    clib_arm.c
19  *      Purpose: ARM C library startup and initialization support
20  *
21  *---------------------------------------------------------------------------*/
22
23 #include <stdint.h>
24 #include <stddef.h>
25
26 #include "FreeRTOS.h"                   // ARM.FreeRTOS::RTOS:Core
27 #include "task.h"                       // ARM.FreeRTOS::RTOS:Core
28 #include "semphr.h"                     // ARM.FreeRTOS::RTOS:Core
29
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
33 #endif
34
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
38 #endif
39
40 /*----------------------------------------------------------------------------*/
41
42 /* Initialization after stack and heap setup */
43 #if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
44
45 #ifndef __MICROLIB
46 __WEAK
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)
51     EvrFreeRTOSSetup(0);
52   #endif
53 }
54 #endif /* __MICROLIB */
55
56 #elif defined(__GNUC__)
57 __WEAK
58 void software_init_hook (void);
59 void software_init_hook (void) {
60   /* Initialize OS, memory, etc. */
61   #if defined(RTE_Compiler_EventRecorder)
62     EvrFreeRTOSSetup(0);
63   #endif
64 }
65
66 #endif
67
68 /*----------------------------------------------------------------------------*/
69
70 /* C/C++ Standard Library Multithreading Interface */
71 #if (( defined(__CC_ARM) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))) && !defined(__MICROLIB))
72
73 #define LIBSPACE_SIZE 96
74
75 /* Libspace memory pool */
76 static uint32_t os_libspace[OS_THREAD_LIBSPACE_NUM+1][LIBSPACE_SIZE/sizeof(uint32_t)];
77
78 /* Array of Threads (IDs) using libspace */
79 static TaskHandle_t os_libspace_id[OS_THREAD_LIBSPACE_NUM];
80
81 /* OS Kernel state checking */
82 static uint32_t os_kernel_is_active (void) {
83   static uint8_t os_kernel_active = 0U;
84
85   if (os_kernel_active == 0U) {
86     if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
87       os_kernel_active = 1U;
88       return 1U;
89     }
90     return 0U;
91   } else {
92     return 1U;
93   }
94 }
95
96 /* Provide libspace for current thread */
97 void *__user_perthread_libspace (void);
98 void *__user_perthread_libspace (void) {
99   TaskHandle_t id;
100   uint32_t     n;
101
102   if (!os_kernel_is_active()) {
103     return (void *)&os_libspace[OS_THREAD_LIBSPACE_NUM][0];
104   }
105
106   id = xTaskGetCurrentTaskHandle();
107
108   for (n = 0U; n < OS_THREAD_LIBSPACE_NUM; n++) {
109     if (os_libspace_id[n] == NULL) {
110
111       os_libspace_id[n] = id;
112
113       return (void *)&os_libspace[n][0];
114     }
115     if (os_libspace_id[n] == id) {
116       return (void *)&os_libspace[n][0];
117     }
118   }
119
120   return (void *)&os_libspace[n][0];
121 }
122
123 /*----------------------------------------------------------------------------*/
124
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];
128 #endif
129
130 /* Define mutex object and function prototypes */
131 typedef void *mutex;
132
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);
137
138
139 /* Initialize mutex */
140 int _mutex_initialize(mutex *m) {
141 #if (OS_MUTEX_CLIB_NUM > 0)
142   uint32_t i;
143 #endif
144
145   *m = NULL;
146
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]);
152
153       /* Return mutex id */
154       *m = clib_mutex_id[i];
155
156       return 1;
157     }
158   }
159 #endif
160   if (os_kernel_is_active()) {
161     /* Create mutex using dynamic memory */
162     *m = xSemaphoreCreateMutex();
163   }
164
165   if (*m == NULL) {
166     return 0;
167   }
168   return 1;
169 }
170
171 /* Acquire mutex */
172 void _mutex_acquire(mutex *m) {
173
174   if (os_kernel_is_active()) {
175     xSemaphoreTake(*m, portMAX_DELAY);
176   }
177 }
178
179 /* Release mutex */
180 void _mutex_release(mutex *m) {
181
182   if (os_kernel_is_active()) {
183     xSemaphoreGive(*m);
184   }
185 }
186
187 /* Free mutex */
188 void _mutex_free(mutex *m) {
189 #if (OS_MUTEX_CLIB_NUM > 0)
190   uint32_t i;
191 #endif
192
193   vSemaphoreDelete(*m);
194
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;
200       break;
201     }
202   }
203 #endif
204 }
205
206 #endif