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