1 /*
2  * Copyright 2021-2022 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 /**
8 *   @file
9 *
10 *   @addtogroup RTE_MODULE
11 *   @{
12 */
13 
14 #ifdef __cplusplus
15 extern "C"{
16 #endif
17 
18 /*==================================================================================================
19 *                                         INCLUDE FILES
20 * 1) system and project includes
21 * 2) needed interfaces from external units
22 * 3) internal and external interfaces from this unit
23 ==================================================================================================*/
24 #include "Std_Types.h"
25 #include "Mcal.h"
26 #include "OsIf.h"
27 #include "SchM_Mcu.h"
28 #ifdef MCAL_TESTING_ENVIRONMENT
29 #include "EUnit.h" /* EUnit Test Suite */
30 #endif
31 
32 /*==================================================================================================
33 *                               SOURCE FILE VERSION INFORMATION
34 ==================================================================================================*/
35 #define SCHM_MCU_AR_RELEASE_MAJOR_VERSION_C     4
36 #define SCHM_MCU_AR_RELEASE_MINOR_VERSION_C     7
37 #define SCHM_MCU_AR_RELEASE_REVISION_VERSION_C  0
38 #define SCHM_MCU_SW_MAJOR_VERSION_C             0
39 #define SCHM_MCU_SW_MINOR_VERSION_C             9
40 #define SCHM_MCU_SW_PATCH_VERSION_C             0
41 
42 /*==================================================================================================
43 *                                       LOCAL CONSTANTS
44 ==================================================================================================*/
45 #ifdef MCAL_PLATFORM_ARM
46     #if (MCAL_PLATFORM_ARM == MCAL_ARM_AARCH64)
47         #define ISR_STATE_MASK     ((uint32)0x000000C0UL)   /**< @brief DAIF bit I and F */
48     #elif  (MCAL_PLATFORM_ARM == MCAL_ARM_RARCH)
49         #define ISR_STATE_MASK     ((uint32)0x00000080UL)   /**< @brief CPSR bit I */
50     #else
51         #if ((defined MCAL_ENABLE_USER_MODE_SUPPORT)&&(!defined MCAL_PLATFORM_ARM_M0PLUS))
52             #define ISR_STATE_MASK     ((uint32)0x000000FFUL)   /**< @brief BASEPRI[7:0] mask */
53         #else
54             #define ISR_STATE_MASK     ((uint32)0x00000001UL)   /**< @brief PRIMASK bit 0 */
55         #endif
56     #endif
57 #else
58     #ifdef MCAL_PLATFORM_S12
59         #define ISR_STATE_MASK     ((uint32)0x00000010UL)   /**< @brief I bit of CCR */
60     #else
61         #define ISR_STATE_MASK     ((uint32)0x00008000UL)   /**< @brief EE bit of MSR */
62     #endif
63 #endif
64 /*==================================================================================================
65 *                                       LOCAL MACROS
66 ==================================================================================================*/
67 #ifdef MCAL_PLATFORM_ARM
68     #if (MCAL_PLATFORM_ARM == MCAL_ARM_AARCH64)
69         #define ISR_ON(msr)            (uint32)(((uint32)(msr) & (uint32)(ISR_STATE_MASK)) != (uint32)(ISR_STATE_MASK))
70     #elif  (MCAL_PLATFORM_ARM == MCAL_ARM_RARCH)
71         #define ISR_ON(msr)            (uint32)(((uint32)(msr) & (uint32)(ISR_STATE_MASK)) != (uint32)(ISR_STATE_MASK))
72     #else
73         #define ISR_ON(msr)            (uint32)(((uint32)(msr) & (uint32)(ISR_STATE_MASK)) == (uint32)0)
74     #endif
75 #else
76     #ifdef MCAL_PLATFORM_S12
77         #define ISR_ON(msr)            (uint32)(((uint32)(msr) & (uint32)(ISR_STATE_MASK)) == (uint32)0)
78     #else
79         #define ISR_ON(msr)            (uint32)((uint32)(msr) & (uint32)(ISR_STATE_MASK))
80     #endif
81 #endif
82 
83 /*==================================================================================================
84 *                                      FILE VERSION CHECKS
85 ==================================================================================================*/
86 
87 /*==================================================================================================
88 *                          LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
89 ==================================================================================================*/
90 
91 
92 /*==================================================================================================
93 *                                       LOCAL VARIABLES
94 ==================================================================================================*/
95 #define RTE_START_SEC_VAR_CLEARED_32_NO_CACHEABLE
96 #include "Rte_MemMap.h"
97 VAR_SEC_NOCACHE(msr_MCU_EXCLUSIVE_AREA_00)           static volatile uint32 msr_MCU_EXCLUSIVE_AREA_00[NUMBER_OF_CORES];
98 VAR_SEC_NOCACHE(reentry_guard_MCU_EXCLUSIVE_AREA_00) static volatile uint32 reentry_guard_MCU_EXCLUSIVE_AREA_00[NUMBER_OF_CORES];
99 VAR_SEC_NOCACHE(msr_MCU_EXCLUSIVE_AREA_01)           static volatile uint32 msr_MCU_EXCLUSIVE_AREA_01[NUMBER_OF_CORES];
100 VAR_SEC_NOCACHE(reentry_guard_MCU_EXCLUSIVE_AREA_01) static volatile uint32 reentry_guard_MCU_EXCLUSIVE_AREA_01[NUMBER_OF_CORES];
101 VAR_SEC_NOCACHE(msr_MCU_EXCLUSIVE_AREA_02)           static volatile uint32 msr_MCU_EXCLUSIVE_AREA_02[NUMBER_OF_CORES];
102 VAR_SEC_NOCACHE(reentry_guard_MCU_EXCLUSIVE_AREA_02) static volatile uint32 reentry_guard_MCU_EXCLUSIVE_AREA_02[NUMBER_OF_CORES];
103 
104 #define RTE_STOP_SEC_VAR_CLEARED_32_NO_CACHEABLE
105 #include "Rte_MemMap.h"
106 /*==================================================================================================
107 *                                       GLOBAL CONSTANTS
108 ==================================================================================================*/
109 
110 
111 /*==================================================================================================
112 *                                       GLOBAL VARIABLES
113 ==================================================================================================*/
114 
115 /*==================================================================================================
116 *                                   LOCAL FUNCTION PROTOTYPES
117 ==================================================================================================*/
118 
119 #ifndef _COSMIC_C_S32ZE_
120 /*================================================================================================*/
121 /**
122 * @brief   This function returns the MSR register value (32 bits).
123 * @details This function returns the MSR register value (32 bits).
124 *
125 * @param[in]     void        No input parameters
126 * @return        uint32 msr  This function returns the MSR register value (32 bits).
127 *
128 * @pre  None
129 * @post None
130 *
131 */
132 uint32 Mcu_schm_read_msr(void);
133 #endif /*ifndef _COSMIC_C_S32ZE_*/
134 /*==================================================================================================
135 *                                       LOCAL FUNCTIONS
136 ==================================================================================================*/
137 #define RTE_START_SEC_CODE
138 #include "Rte_MemMap.h"
139 
140 #if (defined(_GREENHILLS_C_S32ZE_) || defined(_CODEWARRIOR_C_S32ZE_))
141 /*================================================================================================*/
142 /**
143 * @brief   This macro returns the MSR register value (32 bits).
144 * @details This macro function implementation returns the MSR register value in r3 (32 bits).
145 *
146 * @pre  None
147 * @post None
148 *
149 */
150 #ifdef MCAL_PLATFORM_ARM
151 #if (MCAL_PLATFORM_ARM == MCAL_ARM_AARCH64)
Mcu_schm_read_msr(void)152 ASM_KEYWORD uint32 Mcu_schm_read_msr(void)
153 {
154     mrs x0, S3_3_c4_c2_1
155 }
156 #elif  (MCAL_PLATFORM_ARM == MCAL_ARM_RARCH)
Mcu_schm_read_msr(void)157 ASM_KEYWORD uint32 Mcu_schm_read_msr(void)
158 {
159     mrs r0, CPSR
160 }
161 #else
Mcu_schm_read_msr(void)162 ASM_KEYWORD uint32 Mcu_schm_read_msr(void)
163 {
164 #if ((defined MCAL_ENABLE_USER_MODE_SUPPORT)&&(!defined MCAL_PLATFORM_ARM_M0PLUS))
165     mrs r0, BASEPRI
166 #else
167     mrs r0, PRIMASK
168 #endif
169 }
170 #endif
171 #else
172 #ifdef MCAL_PLATFORM_S12
Mcu_schm_read_msr(void)173 ASM_KEYWORD uint32 Mcu_schm_read_msr(void)
174 {
175    tfr ccr, d6
176 }
177 #else
Mcu_schm_read_msr(void)178 ASM_KEYWORD uint32 Mcu_schm_read_msr(void)
179 {
180     mfmsr r3
181 }
182 #endif
183 #endif
184 #endif /*#ifdef GHS||CW*/
185 
186 #ifdef _DIABDATA_C_S32ZE_
187 /**
188 * @brief   This function returns the MSR register value (32 bits).
189 * @details This function returns the MSR register value (32 bits).
190 *
191 * @param[in]     void        No input parameters
192 * @return        uint32 msr  This function returns the MSR register value (32 bits).
193 *
194 * @pre  None
195 * @post None
196 *
197 */
198 #ifdef MCAL_PLATFORM_ARM
Mcu_schm_read_msr(void)199 uint32 Mcu_schm_read_msr(void)
200 {
201     register uint32 reg_tmp;
202     #if (MCAL_PLATFORM_ARM == MCAL_ARM_AARCH64)
203         __asm volatile( " mrs %x0, DAIF " : "=r" (reg_tmp) );
204     #elif  (MCAL_PLATFORM_ARM == MCAL_ARM_RARCH)
205         __asm volatile( " mrs %0, CPSR " : "=r" (reg_tmp) );
206     #else
207         #if ((defined MCAL_ENABLE_USER_MODE_SUPPORT)&&(!defined MCAL_PLATFORM_ARM_M0PLUS))
208         __asm volatile( " mrs %0, basepri " : "=r" (reg_tmp) );
209         #else
210         __asm volatile( " mrs %0, primask " : "=r" (reg_tmp) );
211         #endif
212     #endif
213     return (uint32)reg_tmp;
214 }
215 #else
Mcu_schm_read_msr(void)216 ASM_KEYWORD uint32 Mcu_schm_read_msr(void)
217 {
218     mfmsr r3
219 }
220 #endif  /* MCAL_PLATFORM_ARM */
221 
222 #endif   /* _DIABDATA_C_S32ZE_*/
223 
224 #ifdef _COSMIC_C_S32ZE_
225 /*================================================================================================*/
226 /**
227 * @brief   This function returns the MSR register value (32 bits).
228 * @details This function returns the MSR register value (32 bits).
229 *
230 * @param[in]     void        No input parameters
231 * @return        uint32 msr  This function returns the MSR register value (32 bits).
232 *
233 * @pre  None
234 * @post None
235 *
236 */
237 
238 #ifdef MCAL_PLATFORM_S12
239     #define Mcu_schm_read_msr()  ASM_KEYWORD("tfr ccr, d6")
240 #else
241     #define Mcu_schm_read_msr() ASM_KEYWORD("mfmsr r3")
242 #endif
243 
244 #endif  /*Cosmic compiler only*/
245 
246 
247 #ifdef _HITECH_C_S32ZE_
248 /*================================================================================================*/
249 /**
250 * @brief   This function returns the MSR register value (32 bits).
251 * @details This function returns the MSR register value (32 bits).
252 *
253 * @param[in]     void        No input parameters
254 * @return        uint32 msr  This function returns the MSR register value (32 bits).
255 *
256 * @pre  None
257 * @post None
258 *
259 */
Mcu_schm_read_msr(void)260 uint32 Mcu_schm_read_msr(void)
261 {
262     uint32 result;
263     __asm volatile("mfmsr %0" : "=r" (result) :);
264     return result;
265 }
266 
267 #endif  /*HighTec compiler only*/
268  /*================================================================================================*/
269 #ifdef _LINARO_C_S32ZE_
270 /**
271 * @brief   This function returns the MSR register value (32 bits).
272 * @details This function returns the MSR register value (32 bits).
273 *
274 * @param[in]     void        No input parameters
275 * @return        uint32 msr  This function returns the MSR register value (32 bits).
276 *
277 * @pre  None
278 * @post None
279 *
280 */
Mcu_schm_read_msr(void)281 uint32 Mcu_schm_read_msr(void)
282 {
283     register uint32 reg_tmp;
284     #if (MCAL_PLATFORM_ARM == MCAL_ARM_AARCH64)
285         __asm volatile( " mrs %x0, DAIF " : "=r" (reg_tmp) );
286     #elif  (MCAL_PLATFORM_ARM == MCAL_ARM_RARCH)
287         __asm volatile( " mrs %0, CPSR " : "=r" (reg_tmp) );
288     #else
289         #if ((defined MCAL_ENABLE_USER_MODE_SUPPORT)&&(!defined MCAL_PLATFORM_ARM_M0PLUS))
290         __asm volatile( " mrs %0, basepri " : "=r" (reg_tmp) );
291         #else
292         __asm volatile( " mrs %0, primask " : "=r" (reg_tmp) );
293         #endif
294     #endif
295     return (uint32)reg_tmp;
296 }
297 #endif   /* _LINARO_C_S32ZE_*/
298 /*================================================================================================*/
299 
300 #ifdef _ARM_DS5_C_S32ZE_
301 /**
302 * @brief   This function returns the MSR register value (32 bits).
303 * @details This function returns the MSR register value (32 bits).
304 *
305 * @param[in]     void        No input parameters
306 * @return        uint32 msr  This function returns the MSR register value (32 bits).
307 *
308 * @pre  None
309 * @post None
310 *
311 */
Mcu_schm_read_msr(void)312 uint32 Mcu_schm_read_msr(void)
313 {
314     register uint32 reg_tmp;
315     #if (MCAL_PLATFORM_ARM == MCAL_ARM_AARCH64)
316         __asm volatile( " mrs %x0, DAIF " : "=r" (reg_tmp) );
317     #elif  (MCAL_PLATFORM_ARM == MCAL_ARM_RARCH)
318         __asm volatile( " mrs %0, CPSR " : "=r" (reg_tmp) );
319     #else
320         #if ((defined MCAL_ENABLE_USER_MODE_SUPPORT)&&(!defined MCAL_PLATFORM_ARM_M0PLUS))
321         __asm volatile( " mrs %0, basepri " : "=r" (reg_tmp) );
322         #else
323         __asm volatile( " mrs %0, primask " : "=r" (reg_tmp) );
324         #endif
325     #endif
326     return (uint32)reg_tmp;
327 }
328 #endif   /* _ARM_DS5_C_S32ZE_ */
329 
330 #ifdef _IAR_C_S32ZE_
331 /**
332 * @brief   This function returns the MSR register value (32 bits).
333 * @details This function returns the MSR register value (32 bits).
334 *
335 * @param[in]     void        No input parameters
336 * @return        uint32 msr  This function returns the MSR register value (32 bits).
337 *
338 * @pre  None
339 * @post None
340 *
341 */
Mcu_schm_read_msr(void)342 uint32 Mcu_schm_read_msr(void)
343 {
344     register uint32 reg_tmp;
345 
346 #if ((defined MCAL_ENABLE_USER_MODE_SUPPORT)&&(!defined MCAL_PLATFORM_ARM_M0PLUS))
347    __asm volatile( " mrs %0, basepri " : "=r" (reg_tmp) );
348 #else
349    __asm volatile( " mrs %0, primask " : "=r" (reg_tmp) );
350 #endif
351 
352     return (uint32)reg_tmp;
353 }
354 #endif   /* _IAR_C_S32ZE_ */
355 
356 #define RTE_STOP_SEC_CODE
357 #include "Rte_MemMap.h"
358 
359 /*==================================================================================================
360 *                                        GLOBAL FUNCTIONS
361 ==================================================================================================*/
362 #define RTE_START_SEC_CODE
363 #include "Rte_MemMap.h"
364 
SchM_Enter_Mcu_MCU_EXCLUSIVE_AREA_00(void)365 void SchM_Enter_Mcu_MCU_EXCLUSIVE_AREA_00(void)
366 {
367     uint32 msr;
368     uint32 u32CoreId = (uint32)OsIf_GetCoreID();
369 
370     if(0UL == reentry_guard_MCU_EXCLUSIVE_AREA_00[u32CoreId])
371     {
372 #if (defined MCAL_ENABLE_USER_MODE_SUPPORT)
373         msr = OsIf_Trusted_Call_Return(Mcu_schm_read_msr);
374 #else
375         msr = Mcu_schm_read_msr();  /*read MSR (to store interrupts state)*/
376 #endif /* MCAL_ENABLE_USER_MODE_SUPPORT */
377         if (ISR_ON(msr)) /*if MSR[EE] = 0, skip calling Suspend/Resume AllInterrupts*/
378         {
379             OsIf_SuspendAllInterrupts();
380 #ifdef _ARM_DS5_C_S32ZE_
381             ASM_KEYWORD(" nop ");/* Compiler fix - forces the CSPID instruction to be generated with -02, -Ospace are selected*/
382 #endif
383         }
384         msr_MCU_EXCLUSIVE_AREA_00[u32CoreId] = msr;
385     }
386     reentry_guard_MCU_EXCLUSIVE_AREA_00[u32CoreId]++;
387 }
388 
SchM_Exit_Mcu_MCU_EXCLUSIVE_AREA_00(void)389 void SchM_Exit_Mcu_MCU_EXCLUSIVE_AREA_00(void)
390 {
391     uint32 u32CoreId = (uint32)OsIf_GetCoreID();
392 
393     reentry_guard_MCU_EXCLUSIVE_AREA_00[u32CoreId]--;
394     if ((ISR_ON(msr_MCU_EXCLUSIVE_AREA_00[u32CoreId]))&&(0UL == reentry_guard_MCU_EXCLUSIVE_AREA_00[u32CoreId]))         /*if interrupts were enabled*/
395     {
396         OsIf_ResumeAllInterrupts();
397 #ifdef _ARM_DS5_C_S32ZE_
398         ASM_KEYWORD(" nop ");/* Compiler fix - forces the CSPID instruction to be generated with -02, -Ospace are selected*/
399 #endif
400     }
401 }
402 
SchM_Enter_Mcu_MCU_EXCLUSIVE_AREA_01(void)403 void SchM_Enter_Mcu_MCU_EXCLUSIVE_AREA_01(void)
404 {
405     uint32 msr;
406     uint32 u32CoreId = (uint32)OsIf_GetCoreID();
407 
408     if(0UL == reentry_guard_MCU_EXCLUSIVE_AREA_01[u32CoreId])
409     {
410 #if (defined MCAL_ENABLE_USER_MODE_SUPPORT)
411         msr = OsIf_Trusted_Call_Return(Mcu_schm_read_msr);
412 #else
413         msr = Mcu_schm_read_msr();  /*read MSR (to store interrupts state)*/
414 #endif /* MCAL_ENABLE_USER_MODE_SUPPORT */
415         if (ISR_ON(msr)) /*if MSR[EE] = 0, skip calling Suspend/Resume AllInterrupts*/
416         {
417             OsIf_SuspendAllInterrupts();
418 #ifdef _ARM_DS5_C_S32ZE_
419             ASM_KEYWORD(" nop ");/* Compiler fix - forces the CSPID instruction to be generated with -02, -Ospace are selected*/
420 #endif
421         }
422         msr_MCU_EXCLUSIVE_AREA_01[u32CoreId] = msr;
423     }
424     reentry_guard_MCU_EXCLUSIVE_AREA_01[u32CoreId]++;
425 }
426 
SchM_Exit_Mcu_MCU_EXCLUSIVE_AREA_01(void)427 void SchM_Exit_Mcu_MCU_EXCLUSIVE_AREA_01(void)
428 {
429     uint32 u32CoreId = (uint32)OsIf_GetCoreID();
430 
431     reentry_guard_MCU_EXCLUSIVE_AREA_01[u32CoreId]--;
432     if ((ISR_ON(msr_MCU_EXCLUSIVE_AREA_01[u32CoreId]))&&(0UL == reentry_guard_MCU_EXCLUSIVE_AREA_01[u32CoreId]))         /*if interrupts were enabled*/
433     {
434         OsIf_ResumeAllInterrupts();
435 #ifdef _ARM_DS5_C_S32ZE_
436         ASM_KEYWORD(" nop ");/* Compiler fix - forces the CSPID instruction to be generated with -02, -Ospace are selected*/
437 #endif
438     }
439 }
440 
SchM_Enter_Mcu_MCU_EXCLUSIVE_AREA_02(void)441 void SchM_Enter_Mcu_MCU_EXCLUSIVE_AREA_02(void)
442 {
443     uint32 msr;
444     uint32 u32CoreId = (uint32)OsIf_GetCoreID();
445 
446     if(0UL == reentry_guard_MCU_EXCLUSIVE_AREA_02[u32CoreId])
447     {
448 #if (defined MCAL_ENABLE_USER_MODE_SUPPORT)
449         msr = OsIf_Trusted_Call_Return(Mcu_schm_read_msr);
450 #else
451         msr = Mcu_schm_read_msr();  /*read MSR (to store interrupts state)*/
452 #endif /* MCAL_ENABLE_USER_MODE_SUPPORT */
453         if (ISR_ON(msr)) /*if MSR[EE] = 0, skip calling Suspend/Resume AllInterrupts*/
454         {
455             OsIf_SuspendAllInterrupts();
456 #ifdef _ARM_DS5_C_S32ZE_
457             ASM_KEYWORD(" nop ");/* Compiler fix - forces the CSPID instruction to be generated with -02, -Ospace are selected*/
458 #endif
459         }
460         msr_MCU_EXCLUSIVE_AREA_02[u32CoreId] = msr;
461     }
462     reentry_guard_MCU_EXCLUSIVE_AREA_02[u32CoreId]++;
463 }
464 
SchM_Exit_Mcu_MCU_EXCLUSIVE_AREA_02(void)465 void SchM_Exit_Mcu_MCU_EXCLUSIVE_AREA_02(void)
466 {
467     uint32 u32CoreId = (uint32)OsIf_GetCoreID();
468 
469     reentry_guard_MCU_EXCLUSIVE_AREA_02[u32CoreId]--;
470     if ((ISR_ON(msr_MCU_EXCLUSIVE_AREA_02[u32CoreId]))&&(0UL == reentry_guard_MCU_EXCLUSIVE_AREA_02[u32CoreId]))         /*if interrupts were enabled*/
471     {
472         OsIf_ResumeAllInterrupts();
473 #ifdef _ARM_DS5_C_S32ZE_
474         ASM_KEYWORD(" nop ");/* Compiler fix - forces the CSPID instruction to be generated with -02, -Ospace are selected*/
475 #endif
476     }
477 }
478 
479 
480 #ifdef MCAL_TESTING_ENVIRONMENT
481 /**
482 @brief   This function checks that all entered exclusive areas were also exited.
483 @details This function checks that all entered exclusive areas were also exited. The check
484          is done by verifying that all reentry_guard_* static variables are back to the
485          zero value.
486 
487 @param[in]     void       No input parameters
488 @return        void       This function does not return a value. Test asserts are used instead.
489 
490 @pre  None
491 @post None
492 
493 @remarks Covers
494 @remarks Implements
495 */
SchM_Check_mcu(void)496 void SchM_Check_mcu(void)
497 {
498     uint32 u32CoreId = (uint32)OsIf_GetCoreID();
499 
500     EU_ASSERT(0UL == reentry_guard_MCU_EXCLUSIVE_AREA_00[u32CoreId]);
501     reentry_guard_MCU_EXCLUSIVE_AREA_00[u32CoreId] = 0UL; /*reset reentry_guard_MCU_EXCLUSIVE_AREA_00 for the next test in the suite*/
502 
503     EU_ASSERT(0UL == reentry_guard_MCU_EXCLUSIVE_AREA_01[u32CoreId]);
504     reentry_guard_MCU_EXCLUSIVE_AREA_01[u32CoreId] = 0UL; /*reset reentry_guard_MCU_EXCLUSIVE_AREA_01 for the next test in the suite*/
505 
506     EU_ASSERT(0UL == reentry_guard_MCU_EXCLUSIVE_AREA_02[u32CoreId]);
507     reentry_guard_MCU_EXCLUSIVE_AREA_02[u32CoreId] = 0UL; /*reset reentry_guard_MCU_EXCLUSIVE_AREA_02 for the next test in the suite*/
508 
509 
510 }
511 #endif /*MCAL_TESTING_ENVIRONMENT*/
512 
513 #define RTE_STOP_SEC_CODE
514 #include "Rte_MemMap.h"
515 
516 #ifdef __cplusplus
517 }
518 #endif
519 
520 /** @} */
521