1 /* --------------------------------------------------------------------------
2 * Copyright (c) 2024 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: C library startup hooks (unless handled by CMSIS-Compiler)
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 /* 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)
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)
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)
60 #if ((defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) && !defined(__MICROLIB))
61 /* Arm C/C++ Standard Library Interfaces */
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)))
68 /* Floating-point Initialization */
69 extern void $Super$$_fp_init (void);
71 void $Sub$$_fp_init (void);
72 void $Sub$$_fp_init (void) {
74 FPU->FPDSCR = __get_FPSCR();
79 #if (!defined(RTE_CMSIS_Compiler_OS_Interface_RTOS2_LIBSPACE) && \
80 !defined(RTE_CMSIS_Compiler_OS_Interface_RTOS2_LOCKS))
82 /* OS Kernel state checking */
83 static uint32_t os_kernel_is_active (void) {
84 if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) {
93 #ifndef RTE_CMSIS_Compiler_OS_Interface_RTOS2_LIBSPACE
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
100 #define LIBSPACE_SIZE 96
102 /* Libspace memory pool */
103 static uint32_t os_libspace[OS_THREAD_LIBSPACE_NUM+1][LIBSPACE_SIZE/sizeof(uint32_t)];
105 /* Array of Threads (IDs) using libspace */
106 static TaskHandle_t os_libspace_id[OS_THREAD_LIBSPACE_NUM];
108 /* Provide libspace for current thread */
109 void *__user_perthread_libspace (void);
110 void *__user_perthread_libspace (void) {
114 if (!os_kernel_is_active()) {
115 return (void *)&os_libspace[OS_THREAD_LIBSPACE_NUM][0];
118 id = xTaskGetCurrentTaskHandle();
120 for (n = 0U; n < OS_THREAD_LIBSPACE_NUM; n++) {
121 if (os_libspace_id[n] == NULL) {
123 os_libspace_id[n] = id;
125 return (void *)&os_libspace[n][0];
127 if (os_libspace_id[n] == id) {
128 return (void *)&os_libspace[n][0];
132 return (void *)&os_libspace[n][0];
135 #endif /* RTE_CMSIS_Compiler_OS_Interface_RTOS2_LIBSPACE */
137 #ifndef RTE_CMSIS_Compiler_OS_Interface_RTOS2_LOCKS
139 #if (__ARM_ARCH_7A__ == 1U)
140 /* CPSR mode bitmasks */
141 #define CPSR_MODE_USER 0x10U
142 #define CPSR_MODE_SYSTEM 0x1FU
144 #define IS_IRQ_MODE() ((__get_mode() != CPSR_MODE_USER) && (__get_mode() != CPSR_MODE_SYSTEM))
146 #define IS_IRQ_MODE() (__get_IPSR() != 0U)
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
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];
159 /* Define mutex object and function prototypes */
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);
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 */
172 return 0U; /* Handler mode */
176 /* Initialize mutex */
177 int _mutex_initialize(mutex *m) {
178 #if (OS_MUTEX_CLIB_NUM > 0)
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]);
190 /* Return mutex id */
191 *m = clib_mutex_id[i];
196 if ((*m == NULL) && (os_kernel_is_active())) {
197 /* Create mutex using dynamic memory */
198 *m = xSemaphoreCreateMutex();
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();
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);
223 void _mutex_release(mutex *m) {
225 if (os_kernel_is_active() && is_thread_mode()) {
231 void _mutex_free(mutex *m) {
232 #if (OS_MUTEX_CLIB_NUM > 0)
236 vSemaphoreDelete(*m);
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;
249 #endif /* RTE_CMSIS_Compiler_OS_Interface_RTOS2_LOCKS */