]> begriffs open source - cmsis-freertos/blob - CMSIS/RTOS2/FreeRTOS/Source/clib_os.c
Correct memory allocation and access in osMemoryPoolNew (#142)
[cmsis-freertos] / CMSIS / RTOS2 / FreeRTOS / Source / clib_os.c
1 /* -------------------------------------------------------------------------- 
2  * Copyright (c) 2024 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_os.c
19  *      Purpose: C library startup hooks (unless handled by CMSIS-Compiler)
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 /* Event Recorder initialization before entering function "main" */
31 #if (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) && !defined(__MICROLIB))
32 extern void _platform_post_stackheap_init (void);
33 __WEAK void _platform_post_stackheap_init (void) {
34   /* Initialize Event Recorder and apply initial filter configuration */
35   #if defined(RTE_Compiler_EventRecorder) || defined(RTE_CMSIS_View_EventRecorder)
36     EvrFreeRTOSSetup(0);
37   #endif
38 }
39 #elif defined(__GNUC__)
40 extern void software_init_hook (void);
41 __WEAK void software_init_hook (void) {
42   /* Initialize Event Recorder and apply initial filter configuration */
43   #if defined(RTE_Compiler_EventRecorder) || defined(RTE_CMSIS_View_EventRecorder)
44     EvrFreeRTOSSetup(0);
45   #endif
46 }
47
48 #elif defined(__ICCARM__)
49 extern void $Super$$__iar_data_init3 (void);
50 void $Sub$$__iar_data_init3 (void) {
51   $Super$$__iar_data_init3();
52   /* Initialize Event Recorder and apply initial filter configuration */
53   #if defined(RTE_Compiler_EventRecorder) || defined(RTE_CMSIS_View_EventRecorder)
54     EvrFreeRTOSSetup(0);
55   #endif
56 }
57
58 #endif
59
60 #if ((defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) && !defined(__MICROLIB))
61 /* Arm C/C++ Standard Library Interfaces */
62
63 #if (!defined(CLIB_NO_FP_INIT) && \
64      !defined(__ARM_ARCH_7A__) && \
65      (defined(__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
66      (defined(__FPU_USED   ) && (__FPU_USED    == 1U)))
67
68 /* Floating-point Initialization */
69 extern void $Super$$_fp_init (void);
70
71 void $Sub$$_fp_init (void);
72 void $Sub$$_fp_init (void) {
73   $Super$$_fp_init();
74   FPU->FPDSCR = __get_FPSCR();
75 }
76
77 #endif
78
79 #if (!defined(RTE_CMSIS_Compiler_OS_Interface_RTOS2_LIBSPACE) && \
80      !defined(RTE_CMSIS_Compiler_OS_Interface_RTOS2_LOCKS))
81
82 /* OS Kernel state checking */
83 static uint32_t os_kernel_is_active (void) {
84   if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) {
85     return 1U;
86   } else {
87     return 0U;
88   }
89 }
90
91 #endif
92
93 #ifndef RTE_CMSIS_Compiler_OS_Interface_RTOS2_LIBSPACE
94
95 /* Define the number of Threads which use standard C/C++ library libspace */
96 #ifndef OS_THREAD_LIBSPACE_NUM
97   #define OS_THREAD_LIBSPACE_NUM      4
98 #endif
99
100 #define LIBSPACE_SIZE 96
101
102 /* Libspace memory pool */
103 static uint32_t os_libspace[OS_THREAD_LIBSPACE_NUM+1][LIBSPACE_SIZE/sizeof(uint32_t)];
104
105 /* Array of Threads (IDs) using libspace */
106 static TaskHandle_t os_libspace_id[OS_THREAD_LIBSPACE_NUM];
107
108 /* Provide libspace for current thread */
109 void *__user_perthread_libspace (void);
110 void *__user_perthread_libspace (void) {
111   TaskHandle_t id;
112   uint32_t     n;
113
114   if (!os_kernel_is_active()) {
115     return (void *)&os_libspace[OS_THREAD_LIBSPACE_NUM][0];
116   }
117
118   id = xTaskGetCurrentTaskHandle();
119
120   for (n = 0U; n < OS_THREAD_LIBSPACE_NUM; n++) {
121     if (os_libspace_id[n] == NULL) {
122
123       os_libspace_id[n] = id;
124
125       return (void *)&os_libspace[n][0];
126     }
127     if (os_libspace_id[n] == id) {
128       return (void *)&os_libspace[n][0];
129     }
130   }
131
132   return (void *)&os_libspace[n][0];
133 }
134
135 #endif /* RTE_CMSIS_Compiler_OS_Interface_RTOS2_LIBSPACE */
136
137 #ifndef RTE_CMSIS_Compiler_OS_Interface_RTOS2_LOCKS
138
139 #if (__ARM_ARCH_7A__ == 1U)
140 /* CPSR mode bitmasks */
141 #define CPSR_MODE_USER            0x10U
142 #define CPSR_MODE_SYSTEM          0x1FU
143
144 #define IS_IRQ_MODE()             ((__get_mode() != CPSR_MODE_USER) && (__get_mode() != CPSR_MODE_SYSTEM))
145 #else
146 #define IS_IRQ_MODE()             (__get_IPSR() != 0U)
147 #endif
148
149 /* Define the number of Mutexes used by standard C/C++ library for stream protection */
150 #ifndef OS_MUTEX_CLIB_NUM
151   #define OS_MUTEX_CLIB_NUM           5
152 #endif
153
154 #if (OS_MUTEX_CLIB_NUM > 0)
155 static StaticSemaphore_t clib_mutex_cb[OS_MUTEX_CLIB_NUM];
156 static SemaphoreHandle_t clib_mutex_id[OS_MUTEX_CLIB_NUM];
157 #endif
158
159 /* Define mutex object and function prototypes */
160 typedef void *mutex;
161
162 __USED int  _mutex_initialize(mutex *m);
163 __USED void _mutex_acquire   (mutex *m);
164 __USED void _mutex_release   (mutex *m);
165 __USED void _mutex_free      (mutex *m);
166
167 /* Check if processor is in Thread or Handler mode */
168 static uint32_t is_thread_mode (void) {
169   if (IS_IRQ_MODE() != 0) {
170     return 1U; /* Thread mode  */
171   } else {
172     return 0U; /* Handler mode */
173   }
174 }
175
176 /* Initialize mutex */
177 int _mutex_initialize(mutex *m) {
178 #if (OS_MUTEX_CLIB_NUM > 0)
179   uint32_t i;
180 #endif
181
182   *m = NULL;
183
184 #if (OS_MUTEX_CLIB_NUM > 0)
185   for (i = 0U; i < OS_MUTEX_CLIB_NUM; i++) {
186     if (clib_mutex_id[i] == NULL) {
187       /* Create mutex using static memory */
188       clib_mutex_id[i] = xSemaphoreCreateMutexStatic(&clib_mutex_cb[i]);
189
190       /* Return mutex id */
191       *m = clib_mutex_id[i];
192       break;
193     }
194   }
195 #endif
196   if ((*m == NULL) && (os_kernel_is_active())) {
197     /* Create mutex using dynamic memory */
198     *m = xSemaphoreCreateMutex();
199   }
200
201   /* FreeRTOS disables interrupts when its API is called before the kernel is started. */
202   /* This is pre-main context and since interrupts shall not happen before reaching    */
203   /* main we can re-enable interrupts and have consistent state when main gets called. */
204   portENABLE_INTERRUPTS();
205
206   if (*m == NULL) {
207     return 0;
208   }
209   return 1;
210 }
211
212 /* Acquire mutex */
213 void _mutex_acquire(mutex *m) {
214   /* Don't allow mutex operations when the kernel is not switching tasks and also   */
215   /* block protection when in interrupt. Using stdio streams in interrupt is bad    */
216   /* practice, but some applications call printf as last resort for debug purposes. */
217   if (os_kernel_is_active() && is_thread_mode()) {
218     xSemaphoreTake(*m, portMAX_DELAY);
219   }
220 }
221
222 /* Release mutex */
223 void _mutex_release(mutex *m) {
224
225   if (os_kernel_is_active() && is_thread_mode()) {
226     xSemaphoreGive(*m);
227   }
228 }
229
230 /* Free mutex */
231 void _mutex_free(mutex *m) {
232 #if (OS_MUTEX_CLIB_NUM > 0)
233   uint32_t i;
234 #endif
235
236   vSemaphoreDelete(*m);
237
238 #if (OS_MUTEX_CLIB_NUM > 0)
239   /* Check if mutex was using static memory */
240   for (i = 0U; i < OS_MUTEX_CLIB_NUM; i++) {
241     if (*m == clib_mutex_id[i]) {
242       clib_mutex_id[i] = NULL;
243       break;
244     }
245   }
246 #endif
247 }
248
249 #endif /* RTE_CMSIS_Compiler_OS_Interface_RTOS2_LOCKS */
250 #endif