1 /*
2  * Copyright (c) 2013-2021 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  * -----------------------------------------------------------------------------
19  *
20  * Project:     CMSIS-RTOS RTX
21  * Title:       RTX Library Configuration
22  *
23  * -----------------------------------------------------------------------------
24  */
25 
26 #include "cmsis_compiler.h"
27 #include "rtx_os.h"
28 
29 #ifdef    RTE_Compiler_EventRecorder
30 #include "EventRecorder.h"
31 #include "EventRecorderConf.h"
32 #endif
33 #include "rtx_evr.h"
34 
35 
36 // System Configuration
37 // ====================
38 
39 // Dynamic Memory
40 #if (OS_DYNAMIC_MEM_SIZE != 0)
41 #if ((OS_DYNAMIC_MEM_SIZE % 8) != 0)
42 #error "Invalid Dynamic Memory size!"
43 #endif
44 static uint64_t os_mem[OS_DYNAMIC_MEM_SIZE/8] \
45 __attribute__((section(".bss.os")));
46 #endif
47 
48 // Kernel Tick Frequency
49 #if (OS_TICK_FREQ < 1)
50 #error "Invalid Kernel Tick Frequency!"
51 #endif
52 
53 // ISR FIFO Queue
54 #if (OS_ISR_FIFO_QUEUE < 4)
55 #error "Invalid ISR FIFO Queue size!"
56 #endif
57 static void *os_isr_queue[OS_ISR_FIFO_QUEUE] \
58 __attribute__((section(".bss.os")));
59 
60 
61 // Thread Configuration
62 // ====================
63 
64 #if (((OS_STACK_SIZE % 8) != 0) || (OS_STACK_SIZE < 72))
65 #error "Invalid default Thread Stack size!"
66 #endif
67 
68 #if (((OS_IDLE_THREAD_STACK_SIZE % 8) != 0) || (OS_IDLE_THREAD_STACK_SIZE < 72))
69 #error "Invalid Idle Thread Stack size!"
70 #endif
71 
72 
73 #if (OS_THREAD_OBJ_MEM != 0)
74 
75 #if (OS_THREAD_NUM == 0)
76 #error "Invalid number of user Threads!"
77 #endif
78 
79 #if ((OS_THREAD_USER_STACK_SIZE != 0) && ((OS_THREAD_USER_STACK_SIZE % 8) != 0))
80 #error "Invalid total Stack size!"
81 #endif
82 
83 // Thread Control Blocks
84 static osRtxThread_t os_thread_cb[OS_THREAD_NUM] \
85 __attribute__((section(".bss.os.thread.cb")));
86 
87 // Thread Default Stack
88 #if (OS_THREAD_DEF_STACK_NUM != 0)
89 static uint64_t os_thread_def_stack[(OS_THREAD_DEF_STACK_NUM*OS_STACK_SIZE)/8] \
90 __attribute__((section(".bss.os.thread.stack")));
91 #endif
92 
93 // Memory Pool for Thread Control Blocks
94 static osRtxMpInfo_t os_mpi_thread \
95 __attribute__((section(".data.os.thread.mpi"))) =
96 { (uint32_t)OS_THREAD_NUM, 0U, (uint32_t)osRtxThreadCbSize, &os_thread_cb[0], NULL, NULL };
97 
98 // Memory Pool for Thread Default Stack
99 #if (OS_THREAD_DEF_STACK_NUM != 0)
100 static osRtxMpInfo_t os_mpi_def_stack \
101 __attribute__((section(".data.os.thread.mpi"))) =
102 { (uint32_t)OS_THREAD_DEF_STACK_NUM, 0U, (uint32_t)OS_STACK_SIZE, &os_thread_def_stack[0], NULL, NULL };
103 #endif
104 
105 // Memory Pool for Thread Stack
106 #if (OS_THREAD_USER_STACK_SIZE != 0)
107 static uint64_t os_thread_stack[(16 + (8*OS_THREAD_NUM) + OS_THREAD_USER_STACK_SIZE)/8] \
108 __attribute__((section(".bss.os.thread.stack")));
109 #endif
110 
111 #endif  // (OS_THREAD_OBJ_MEM != 0)
112 
113 
114 // Idle Thread Control Block
115 static osRtxThread_t os_idle_thread_cb \
116 __attribute__((section(".bss.os.thread.cb")));
117 
118 // Idle Thread Stack
119 static uint64_t os_idle_thread_stack[OS_IDLE_THREAD_STACK_SIZE/8] \
120 __attribute__((section(".bss.os.thread.idle.stack")));
121 
122 // Idle Thread Attributes
123 static const osThreadAttr_t os_idle_thread_attr = {
124 #if defined(OS_IDLE_THREAD_NAME)
125   OS_IDLE_THREAD_NAME,
126 #else
127   NULL,
128 #endif
129   osThreadDetached,
130   &os_idle_thread_cb,
131   (uint32_t)sizeof(os_idle_thread_cb),
132   &os_idle_thread_stack[0],
133   (uint32_t)sizeof(os_idle_thread_stack),
134   osPriorityIdle,
135 #if defined(OS_IDLE_THREAD_TZ_MOD_ID)
136   (uint32_t)OS_IDLE_THREAD_TZ_MOD_ID,
137 #else
138   0U,
139 #endif
140   0U
141 };
142 
143 
144 // Timer Configuration
145 // ===================
146 
147 #if (OS_TIMER_OBJ_MEM != 0)
148 
149 #if (OS_TIMER_NUM == 0)
150 #error "Invalid number of Timer objects!"
151 #endif
152 
153 // Timer Control Blocks
154 static osRtxTimer_t os_timer_cb[OS_TIMER_NUM] \
155 __attribute__((section(".bss.os.timer.cb")));
156 
157 // Memory Pool for Timer Control Blocks
158 static osRtxMpInfo_t os_mpi_timer \
159 __attribute__((section(".data.os.timer.mpi"))) =
160 { (uint32_t)OS_TIMER_NUM, 0U, (uint32_t)osRtxTimerCbSize, &os_timer_cb[0], NULL, NULL };
161 
162 #endif  // (OS_TIMER_OBJ_MEM != 0)
163 
164 
165 #if ((OS_TIMER_THREAD_STACK_SIZE != 0) && (OS_TIMER_CB_QUEUE != 0))
166 
167 #if (((OS_TIMER_THREAD_STACK_SIZE % 8) != 0) || (OS_TIMER_THREAD_STACK_SIZE < 96))
168 #error "Invalid Timer Thread Stack size!"
169 #endif
170 
171 // Timer Thread Control Block
172 static osRtxThread_t os_timer_thread_cb \
173 __attribute__((section(".bss.os.thread.cb")));
174 
175 // Timer Thread Stack
176 static uint64_t os_timer_thread_stack[OS_TIMER_THREAD_STACK_SIZE/8] \
177 __attribute__((section(".bss.os.thread.timer.stack")));
178 
179 // Timer Thread Attributes
180 static const osThreadAttr_t os_timer_thread_attr = {
181 #if defined(OS_TIMER_THREAD_NAME)
182   OS_TIMER_THREAD_NAME,
183 #else
184   NULL,
185 #endif
186   osThreadDetached,
187   &os_timer_thread_cb,
188   (uint32_t)sizeof(os_timer_thread_cb),
189   &os_timer_thread_stack[0],
190   (uint32_t)sizeof(os_timer_thread_stack),
191   //lint -e{9030} -e{9034} "cast from signed to enum"
192   (osPriority_t)OS_TIMER_THREAD_PRIO,
193 #if defined(OS_TIMER_THREAD_TZ_MOD_ID)
194   (uint32_t)OS_TIMER_THREAD_TZ_MOD_ID,
195 #else
196   0U,
197 #endif
198   0U
199 };
200 
201 // Timer Message Queue Control Block
202 static osRtxMessageQueue_t os_timer_mq_cb \
203 __attribute__((section(".bss.os.msgqueue.cb")));
204 
205 // Timer Message Queue Data
206 static uint32_t os_timer_mq_data[osRtxMessageQueueMemSize(OS_TIMER_CB_QUEUE,8)/4] \
207 __attribute__((section(".bss.os.msgqueue.mem")));
208 
209 // Timer Message Queue Attributes
210 static const osMessageQueueAttr_t os_timer_mq_attr = {
211   NULL,
212   0U,
213   &os_timer_mq_cb,
214   (uint32_t)sizeof(os_timer_mq_cb),
215   &os_timer_mq_data[0],
216   (uint32_t)sizeof(os_timer_mq_data)
217 };
218 
219 extern int32_t osRtxTimerSetup  (void);
220 extern void    osRtxTimerThread (void *argument);
221 
222 #endif  // ((OS_TIMER_THREAD_STACK_SIZE != 0) && (OS_TIMER_CB_QUEUE != 0))
223 
224 
225 // Event Flags Configuration
226 // =========================
227 
228 #if (OS_EVFLAGS_OBJ_MEM != 0)
229 
230 #if (OS_EVFLAGS_NUM == 0)
231 #error "Invalid number of Event Flags objects!"
232 #endif
233 
234 // Event Flags Control Blocks
235 static osRtxEventFlags_t os_ef_cb[OS_EVFLAGS_NUM] \
236 __attribute__((section(".bss.os.evflags.cb")));
237 
238 // Memory Pool for Event Flags Control Blocks
239 static osRtxMpInfo_t os_mpi_ef \
240 __attribute__((section(".data.os.evflags.mpi"))) =
241 { (uint32_t)OS_EVFLAGS_NUM, 0U, (uint32_t)osRtxEventFlagsCbSize, &os_ef_cb[0], NULL, NULL };
242 
243 #endif  // (OS_EVFLAGS_OBJ_MEM != 0)
244 
245 
246 // Mutex Configuration
247 // ===================
248 
249 #if (OS_MUTEX_OBJ_MEM != 0)
250 
251 #if (OS_MUTEX_NUM == 0)
252 #error "Invalid number of Mutex objects!"
253 #endif
254 
255 // Mutex Control Blocks
256 static osRtxMutex_t os_mutex_cb[OS_MUTEX_NUM] \
257 __attribute__((section(".bss.os.mutex.cb")));
258 
259 // Memory Pool for Mutex Control Blocks
260 static osRtxMpInfo_t os_mpi_mutex \
261 __attribute__((section(".data.os.mutex.mpi"))) =
262 { (uint32_t)OS_MUTEX_NUM, 0U, (uint32_t)osRtxMutexCbSize, &os_mutex_cb[0], NULL, NULL };
263 
264 #endif  // (OS_MUTEX_OBJ_MEM != 0)
265 
266 
267 // Semaphore Configuration
268 // =======================
269 
270 #if (OS_SEMAPHORE_OBJ_MEM != 0)
271 
272 #if (OS_SEMAPHORE_NUM == 0)
273 #error "Invalid number of Semaphore objects!"
274 #endif
275 
276 // Semaphore Control Blocks
277 static osRtxSemaphore_t os_semaphore_cb[OS_SEMAPHORE_NUM] \
278 __attribute__((section(".bss.os.semaphore.cb")));
279 
280 // Memory Pool for Semaphore Control Blocks
281 static osRtxMpInfo_t os_mpi_semaphore \
282 __attribute__((section(".data.os.semaphore.mpi"))) =
283 { (uint32_t)OS_SEMAPHORE_NUM, 0U, (uint32_t)osRtxSemaphoreCbSize, &os_semaphore_cb[0], NULL, NULL };
284 
285 #endif  // (OS_SEMAPHORE_OBJ_MEM != 0)
286 
287 
288 // Memory Pool Configuration
289 // =========================
290 
291 #if (OS_MEMPOOL_OBJ_MEM != 0)
292 
293 #if (OS_MEMPOOL_NUM == 0)
294 #error "Invalid number of Memory Pool objects!"
295 #endif
296 
297 // Memory Pool Control Blocks
298 static osRtxMemoryPool_t os_mp_cb[OS_MEMPOOL_NUM] \
299 __attribute__((section(".bss.os.mempool.cb")));
300 
301 // Memory Pool for Memory Pool Control Blocks
302 static osRtxMpInfo_t os_mpi_mp \
303 __attribute__((section(".data.os.mempool.mpi"))) =
304 { (uint32_t)OS_MEMPOOL_NUM, 0U, (uint32_t)osRtxMemoryPoolCbSize, &os_mp_cb[0], NULL, NULL };
305 
306 // Memory Pool for Memory Pool Data Storage
307 #if (OS_MEMPOOL_DATA_SIZE != 0)
308 #if ((OS_MEMPOOL_DATA_SIZE % 8) != 0)
309 #error "Invalid Data Memory size for Memory Pools!"
310 #endif
311 static uint64_t os_mp_data[(16 + (8*OS_MEMPOOL_NUM) + OS_MEMPOOL_DATA_SIZE)/8] \
312 __attribute__((section(".bss.os.mempool.mem")));
313 #endif
314 
315 #endif  // (OS_MEMPOOL_OBJ_MEM != 0)
316 
317 
318 // Message Queue Configuration
319 // ===========================
320 
321 #if (OS_MSGQUEUE_OBJ_MEM != 0)
322 
323 #if (OS_MSGQUEUE_NUM == 0)
324 #error "Invalid number of Message Queue objects!"
325 #endif
326 
327 // Message Queue Control Blocks
328 static osRtxMessageQueue_t os_mq_cb[OS_MSGQUEUE_NUM] \
329 __attribute__((section(".bss.os.msgqueue.cb")));
330 
331 // Memory Pool for Message Queue Control Blocks
332 static osRtxMpInfo_t os_mpi_mq \
333 __attribute__((section(".data.os.msgqueue.mpi"))) =
334 { (uint32_t)OS_MSGQUEUE_NUM, 0U, (uint32_t)osRtxMessageQueueCbSize, &os_mq_cb[0], NULL, NULL };
335 
336 // Memory Pool for Message Queue Data Storage
337 #if (OS_MSGQUEUE_DATA_SIZE != 0)
338 #if ((OS_MSGQUEUE_DATA_SIZE % 8) != 0)
339 #error "Invalid Data Memory size for Message Queues!"
340 #endif
341 static uint64_t os_mq_data[(16 + ((8+12)*OS_MSGQUEUE_NUM) + OS_MSGQUEUE_DATA_SIZE + 7)/8] \
342 __attribute__((section(".bss.os.msgqueue.mem")));
343 #endif
344 
345 #endif  // (OS_MSGQUEUE_OBJ_MEM != 0)
346 
347 
348 // Event Recorder Configuration
349 // ============================
350 
351 #if (defined(OS_EVR_INIT) && (OS_EVR_INIT != 0))
352 
353 #ifdef RTE_Compiler_EventRecorder
354 
355 // Event Recorder Initialize
evr_initialize(void)356 __STATIC_INLINE void evr_initialize (void) {
357 
358   (void)EventRecorderInitialize(OS_EVR_LEVEL, (uint32_t)OS_EVR_START);
359 
360 #if ((OS_EVR_MEMORY_LEVEL & 0x80U) != 0U)
361   (void)EventRecorderEnable(  OS_EVR_MEMORY_LEVEL & 0x0FU,    EvtRtxMemoryNo,       EvtRtxMemoryNo);
362   (void)EventRecorderDisable(~OS_EVR_MEMORY_LEVEL & 0x0FU,    EvtRtxMemoryNo,       EvtRtxMemoryNo);
363 #endif
364 #if ((OS_EVR_KERNEL_LEVEL & 0x80U) != 0U)
365   (void)EventRecorderEnable(  OS_EVR_KERNEL_LEVEL & 0x0FU,    EvtRtxKernelNo,       EvtRtxKernelNo);
366   (void)EventRecorderDisable(~OS_EVR_KERNEL_LEVEL & 0x0FU,    EvtRtxKernelNo,       EvtRtxMemoryNo);
367 #endif
368 #if ((OS_EVR_THREAD_LEVEL & 0x80U) != 0U)
369   (void)EventRecorderEnable(  OS_EVR_THREAD_LEVEL & 0x0FU,    EvtRtxThreadNo,       EvtRtxThreadNo);
370   (void)EventRecorderDisable(~OS_EVR_THREAD_LEVEL & 0x0FU,    EvtRtxThreadNo,       EvtRtxThreadNo);
371 #endif
372 #if ((OS_EVR_WAIT_LEVEL & 0x80U) != 0U)
373   (void)EventRecorderEnable(  OS_EVR_WAIT_LEVEL & 0x0FU,      EvtRtxWaitNo,         EvtRtxWaitNo);
374   (void)EventRecorderDisable(~OS_EVR_WAIT_LEVEL & 0x0FU,      EvtRtxWaitNo,         EvtRtxWaitNo);
375 #endif
376 #if ((OS_EVR_THFLAGS_LEVEL & 0x80U) != 0U)
377   (void)EventRecorderEnable(  OS_EVR_THFLAGS_LEVEL & 0x0FU,   EvtRtxThreadFlagsNo,  EvtRtxThreadFlagsNo);
378   (void)EventRecorderDisable(~OS_EVR_THFLAGS_LEVEL & 0x0FU,   EvtRtxThreadFlagsNo,  EvtRtxThreadFlagsNo);
379 #endif
380 #if ((OS_EVR_EVFLAGS_LEVEL & 0x80U) != 0U)
381   (void)EventRecorderEnable(  OS_EVR_EVFLAGS_LEVEL & 0x0FU,   EvtRtxEventFlagsNo,   EvtRtxEventFlagsNo);
382   (void)EventRecorderDisable(~OS_EVR_EVFLAGS_LEVEL & 0x0FU,   EvtRtxEventFlagsNo,   EvtRtxEventFlagsNo);
383 #endif
384 #if ((OS_EVR_TIMER_LEVEL & 0x80U) != 0U)
385   (void)EventRecorderEnable(  OS_EVR_TIMER_LEVEL & 0x0FU,     EvtRtxTimerNo,        EvtRtxTimerNo);
386   (void)EventRecorderDisable(~OS_EVR_TIMER_LEVEL & 0x0FU,     EvtRtxTimerNo,        EvtRtxTimerNo);
387 #endif
388 #if ((OS_EVR_MUTEX_LEVEL & 0x80U) != 0U)
389   (void)EventRecorderEnable(  OS_EVR_MUTEX_LEVEL & 0x0FU,     EvtRtxMutexNo,        EvtRtxMutexNo);
390   (void)EventRecorderDisable(~OS_EVR_MUTEX_LEVEL & 0x0FU,     EvtRtxMutexNo,        EvtRtxMutexNo);
391 #endif
392 #if ((OS_EVR_SEMAPHORE_LEVEL & 0x80U) != 0U)
393   (void)EventRecorderEnable(  OS_EVR_SEMAPHORE_LEVEL & 0x0FU, EvtRtxSemaphoreNo,    EvtRtxSemaphoreNo);
394   (void)EventRecorderDisable(~OS_EVR_SEMAPHORE_LEVEL & 0x0FU, EvtRtxSemaphoreNo,    EvtRtxSemaphoreNo);
395 #endif
396 #if ((OS_EVR_MEMPOOL_LEVEL & 0x80U) != 0U)
397   (void)EventRecorderEnable(  OS_EVR_MEMPOOL_LEVEL & 0x0FU,   EvtRtxMemoryPoolNo,   EvtRtxMemoryPoolNo);
398   (void)EventRecorderDisable(~OS_EVR_MEMPOOL_LEVEL & 0x0FU,   EvtRtxMemoryPoolNo,   EvtRtxMemoryPoolNo);
399 #endif
400 #if ((OS_EVR_MSGQUEUE_LEVEL & 0x80U) != 0U)
401   (void)EventRecorderEnable(  OS_EVR_MSGQUEUE_LEVEL & 0x0FU,  EvtRtxMessageQueueNo, EvtRtxMessageQueueNo);
402   (void)EventRecorderDisable(~OS_EVR_MSGQUEUE_LEVEL & 0x0FU,  EvtRtxMessageQueueNo, EvtRtxMessageQueueNo);
403 #endif
404 }
405 
406 #else
407 #warning "Event Recorder cannot be initialized (Event Recorder component is not selected)!"
408 #define evr_initialize()
409 #endif
410 
411 #endif  // (OS_EVR_INIT != 0)
412 
413 
414 // OS Configuration
415 // ================
416 
417 
418 const osRtxConfig_t osRtxConfig \
419 __USED \
420 __attribute__((section(".rodata"))) =
421 {
422   //lint -e{835} "Zero argument to operator"
423   0U   // Flags
424 #if (OS_PRIVILEGE_MODE != 0)
425   | osRtxConfigPrivilegedMode
426 #endif
427 #if (OS_STACK_CHECK != 0)
428   | osRtxConfigStackCheck
429 #endif
430 #if (OS_STACK_WATERMARK != 0)
431   | osRtxConfigStackWatermark
432 #endif
433   ,
434   (uint32_t)OS_TICK_FREQ,
435 #if (OS_ROBIN_ENABLE != 0)
436   (uint32_t)OS_ROBIN_TIMEOUT,
437 #else
438   0U,
439 #endif
440   { &os_isr_queue[0], (uint16_t)(sizeof(os_isr_queue)/sizeof(void *)), 0U },
441   {
442     // Memory Pools (Variable Block Size)
443 #if ((OS_THREAD_OBJ_MEM != 0) && (OS_THREAD_USER_STACK_SIZE != 0))
444     &os_thread_stack[0], sizeof(os_thread_stack),
445 #else
446     NULL, 0U,
447 #endif
448 #if ((OS_MEMPOOL_OBJ_MEM != 0) && (OS_MEMPOOL_DATA_SIZE != 0))
449     &os_mp_data[0], sizeof(os_mp_data),
450 #else
451     NULL, 0U,
452 #endif
453 #if ((OS_MSGQUEUE_OBJ_MEM != 0) && (OS_MSGQUEUE_DATA_SIZE != 0))
454     &os_mq_data[0], sizeof(os_mq_data),
455 #else
456     NULL, 0U,
457 #endif
458 #if (OS_DYNAMIC_MEM_SIZE != 0)
459     &os_mem[0], (uint32_t)OS_DYNAMIC_MEM_SIZE,
460 #else
461     NULL, 0U
462 #endif
463   },
464   {
465     // Memory Pools (Fixed Block Size)
466 #if (OS_THREAD_OBJ_MEM != 0)
467 #if (OS_THREAD_DEF_STACK_NUM != 0)
468     &os_mpi_def_stack,
469 #else
470     NULL,
471 #endif
472     &os_mpi_thread,
473 #else
474     NULL,
475     NULL,
476 #endif
477 #if (OS_TIMER_OBJ_MEM != 0)
478     &os_mpi_timer,
479 #else
480     NULL,
481 #endif
482 #if (OS_EVFLAGS_OBJ_MEM != 0)
483     &os_mpi_ef,
484 #else
485     NULL,
486 #endif
487 #if (OS_MUTEX_OBJ_MEM != 0)
488     &os_mpi_mutex,
489 #else
490     NULL,
491 #endif
492 #if (OS_SEMAPHORE_OBJ_MEM != 0)
493     &os_mpi_semaphore,
494 #else
495     NULL,
496 #endif
497 #if (OS_MEMPOOL_OBJ_MEM != 0)
498     &os_mpi_mp,
499 #else
500     NULL,
501 #endif
502 #if (OS_MSGQUEUE_OBJ_MEM != 0)
503     &os_mpi_mq,
504 #else
505     NULL,
506 #endif
507   },
508   (uint32_t)OS_STACK_SIZE,
509   &os_idle_thread_attr,
510 #if ((OS_TIMER_THREAD_STACK_SIZE != 0) && (OS_TIMER_CB_QUEUE != 0))
511   &os_timer_thread_attr,
512   osRtxTimerThread,
513   osRtxTimerSetup,
514   &os_timer_mq_attr,
515   (uint32_t)OS_TIMER_CB_QUEUE
516 #else
517   NULL,
518   NULL,
519   NULL,
520   NULL,
521   0U
522 #endif
523 };
524 
525 
526 // Non weak reference to library irq module
527 //lint -esym(526,irqRtxLib)    "Defined by Exception handlers"
528 //lint -esym(714,irqRtxLibRef) "Non weak reference"
529 //lint -esym(765,irqRtxLibRef) "Global scope"
530 extern const uint8_t         irqRtxLib;
531 extern const uint8_t * const irqRtxLibRef;
532        const uint8_t * const irqRtxLibRef = &irqRtxLib;
533 
534 // Default User SVC Table
535 //lint -esym(714,osRtxUserSVC) "Referenced by Exception handlers"
536 //lint -esym(765,osRtxUserSVC) "Global scope"
537 //lint -e{9067} "extern array declared without size"
538 extern void * const osRtxUserSVC[];
539 __WEAK void * const osRtxUserSVC[1] = { (void *)0 };
540 
541 
542 // OS Sections
543 // ===========
544 
545 #if  defined(__CC_ARM) || \
546     (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
547 // Initialized through linker
548 //lint -esym(728,  __os_thread_cb_start__,    __os_thread_cb_end__)
549 //lint -esym(728,  __os_timer_cb_start__,     __os_timer_cb_end__)
550 //lint -esym(728,  __os_evflags_cb_start__,   __os_evflags_cb_end__)
551 //lint -esym(728,  __os_mutex_cb_start__,     __os_mutex_cb_end__)
552 //lint -esym(728,  __os_semaphore_cb_start__, __os_semaphore_cb_end__)
553 //lint -esym(728,  __os_mempool_cb_start__,   __os_mempool_cb_end__)
554 //lint -esym(728,  __os_msgqueue_cb_start__,  __os_msgqueue_cb_end__)
555 static const uint32_t __os_thread_cb_start__    __attribute__((weakref(".bss.os.thread.cb$$Base")));
556 static const uint32_t __os_thread_cb_end__      __attribute__((weakref(".bss.os.thread.cb$$Limit")));
557 static const uint32_t __os_timer_cb_start__     __attribute__((weakref(".bss.os.timer.cb$$Base")));
558 static const uint32_t __os_timer_cb_end__       __attribute__((weakref(".bss.os.timer.cb$$Limit")));
559 static const uint32_t __os_evflags_cb_start__   __attribute__((weakref(".bss.os.evflags.cb$$Base")));
560 static const uint32_t __os_evflags_cb_end__     __attribute__((weakref(".bss.os.evflags.cb$$Limit")));
561 static const uint32_t __os_mutex_cb_start__     __attribute__((weakref(".bss.os.mutex.cb$$Base")));
562 static const uint32_t __os_mutex_cb_end__       __attribute__((weakref(".bss.os.mutex.cb$$Limit")));
563 static const uint32_t __os_semaphore_cb_start__ __attribute__((weakref(".bss.os.semaphore.cb$$Base")));
564 static const uint32_t __os_semaphore_cb_end__   __attribute__((weakref(".bss.os.semaphore.cb$$Limit")));
565 static const uint32_t __os_mempool_cb_start__   __attribute__((weakref(".bss.os.mempool.cb$$Base")));
566 static const uint32_t __os_mempool_cb_end__     __attribute__((weakref(".bss.os.mempool.cb$$Limit")));
567 static const uint32_t __os_msgqueue_cb_start__  __attribute__((weakref(".bss.os.msgqueue.cb$$Base")));
568 static const uint32_t __os_msgqueue_cb_end__    __attribute__((weakref(".bss.os.msgqueue.cb$$Limit")));
569 #else
570 extern const uint32_t __os_thread_cb_start__    __attribute__((weak));
571 extern const uint32_t __os_thread_cb_end__      __attribute__((weak));
572 extern const uint32_t __os_timer_cb_start__     __attribute__((weak));
573 extern const uint32_t __os_timer_cb_end__       __attribute__((weak));
574 extern const uint32_t __os_evflags_cb_start__   __attribute__((weak));
575 extern const uint32_t __os_evflags_cb_end__     __attribute__((weak));
576 extern const uint32_t __os_mutex_cb_start__     __attribute__((weak));
577 extern const uint32_t __os_mutex_cb_end__       __attribute__((weak));
578 extern const uint32_t __os_semaphore_cb_start__ __attribute__((weak));
579 extern const uint32_t __os_semaphore_cb_end__   __attribute__((weak));
580 extern const uint32_t __os_mempool_cb_start__   __attribute__((weak));
581 extern const uint32_t __os_mempool_cb_end__     __attribute__((weak));
582 extern const uint32_t __os_msgqueue_cb_start__  __attribute__((weak));
583 extern const uint32_t __os_msgqueue_cb_end__    __attribute__((weak));
584 #endif
585 
586 //lint -e{9067} "extern array declared without size"
587 extern const uint32_t * const os_cb_sections[];
588 
589 //lint -esym(714,os_cb_sections) "Referenced by debugger"
590 //lint -esym(765,os_cb_sections) "Global scope"
591 const uint32_t * const os_cb_sections[] \
592 __USED \
593 __attribute__((section(".rodata"))) =
594 {
595   &__os_thread_cb_start__,
596   &__os_thread_cb_end__,
597   &__os_timer_cb_start__,
598   &__os_timer_cb_end__,
599   &__os_evflags_cb_start__,
600   &__os_evflags_cb_end__,
601   &__os_mutex_cb_start__,
602   &__os_mutex_cb_end__,
603   &__os_semaphore_cb_start__,
604   &__os_semaphore_cb_end__,
605   &__os_mempool_cb_start__,
606   &__os_mempool_cb_end__,
607   &__os_msgqueue_cb_start__,
608   &__os_msgqueue_cb_end__
609 };
610 
611 
612 // OS Initialization
613 // =================
614 
615 #if  defined(__CC_ARM) || \
616     (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
617 
618 #ifndef __MICROLIB
619 //lint -esym(714,_platform_post_stackheap_init) "Referenced by C library"
620 //lint -esym(765,_platform_post_stackheap_init) "Global scope"
621 extern void _platform_post_stackheap_init (void);
_platform_post_stackheap_init(void)622 __WEAK void _platform_post_stackheap_init (void) {
623   (void)osKernelInitialize();
624 }
625 #endif
626 
627 #elif defined(__GNUC__)
628 
629 extern void software_init_hook (void);
software_init_hook(void)630 __WEAK void software_init_hook (void) {
631   (void)osKernelInitialize();
632 }
633 
634 #elif defined(__ICCARM__)
635 
636 extern void $Super$$__iar_data_init3 (void);
$Sub$$__iar_data_init3(void)637 void $Sub$$__iar_data_init3 (void) {
638   $Super$$__iar_data_init3();
639   (void)osKernelInitialize();
640 }
641 
642 #endif
643 
644 
645 // OS Hooks
646 // ========
647 
648 // RTOS Kernel Pre-Initialization Hook
649 #if (defined(OS_EVR_INIT) && (OS_EVR_INIT != 0))
650 void osRtxKernelPreInit (void);
osRtxKernelPreInit(void)651 void osRtxKernelPreInit (void) {
652   if (osKernelGetState() == osKernelInactive) {
653     evr_initialize();
654   }
655 }
656 #endif
657 
658 
659 // C/C++ Standard Library Multithreading Interface
660 // ===============================================
661 
662 #if ( !defined(RTX_NO_MULTITHREAD_CLIB) && \
663      ( defined(__CC_ARM) || \
664       (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))) && \
665       !defined(__MICROLIB))
666 
667 #define LIBSPACE_SIZE 96
668 
669 //lint -esym(714,__user_perthread_libspace,_mutex_*) "Referenced by C library"
670 //lint -esym(765,__user_perthread_libspace,_mutex_*) "Global scope"
671 //lint -esym(9003, os_libspace*) "variables 'os_libspace*' defined at module scope"
672 
673 // Memory for libspace
674 static uint32_t os_libspace[OS_THREAD_LIBSPACE_NUM+1][LIBSPACE_SIZE/4] \
675 __attribute__((section(".bss.os.libspace")));
676 
677 // Thread IDs for libspace
678 static osThreadId_t os_libspace_id[OS_THREAD_LIBSPACE_NUM] \
679 __attribute__((section(".bss.os.libspace")));
680 
681 // Check if Kernel has been started
os_kernel_is_active(void)682 static uint32_t os_kernel_is_active (void) {
683   static uint8_t os_kernel_active = 0U;
684 
685   if (os_kernel_active == 0U) {
686     if (osKernelGetState() > osKernelReady) {
687       os_kernel_active = 1U;
688     }
689   }
690   return (uint32_t)os_kernel_active;
691 }
692 
693 // Provide libspace for current thread
694 void *__user_perthread_libspace (void);
__user_perthread_libspace(void)695 void *__user_perthread_libspace (void) {
696   osThreadId_t id;
697   uint32_t     n;
698 
699   if (os_kernel_is_active() != 0U) {
700     id = osThreadGetId();
701     for (n = 0U; n < (uint32_t)OS_THREAD_LIBSPACE_NUM; n++) {
702       if (os_libspace_id[n] == NULL) {
703         os_libspace_id[n] = id;
704       }
705       if (os_libspace_id[n] == id) {
706         break;
707       }
708     }
709     if (n == (uint32_t)OS_THREAD_LIBSPACE_NUM) {
710       (void)osRtxKernelErrorNotify(osRtxErrorClibSpace, id);
711     }
712   } else {
713     n = OS_THREAD_LIBSPACE_NUM;
714   }
715 
716   //lint -e{9087} "cast between pointers to different object types"
717   return (void *)&os_libspace[n][0];
718 }
719 
720 // Mutex identifier
721 typedef void *mutex;
722 
723 //lint -save "Function prototypes defined in C library"
724 //lint -e970 "Use of 'int' outside of a typedef"
725 //lint -e818 "Pointer 'm' could be declared as pointing to const"
726 
727 // Initialize mutex
728 __USED
729 int _mutex_initialize(mutex *m);
_mutex_initialize(mutex * m)730 int _mutex_initialize(mutex *m) {
731   int result;
732 
733   *m = osMutexNew(NULL);
734   if (*m != NULL) {
735     result = 1;
736   } else {
737     result = 0;
738     (void)osRtxKernelErrorNotify(osRtxErrorClibMutex, m);
739   }
740   return result;
741 }
742 
743 // Acquire mutex
744 __USED
745 void _mutex_acquire(mutex *m);
_mutex_acquire(mutex * m)746 void _mutex_acquire(mutex *m) {
747   if (os_kernel_is_active() != 0U) {
748     (void)osMutexAcquire(*m, osWaitForever);
749   }
750 }
751 
752 // Release mutex
753 __USED
754 void _mutex_release(mutex *m);
_mutex_release(mutex * m)755 void _mutex_release(mutex *m) {
756   if (os_kernel_is_active() != 0U) {
757     (void)osMutexRelease(*m);
758   }
759 }
760 
761 // Free mutex
762 __USED
763 void _mutex_free(mutex *m);
_mutex_free(mutex * m)764 void _mutex_free(mutex *m) {
765   (void)osMutexDelete(*m);
766 }
767 
768 //lint -restore
769 
770 #endif
771