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