]> begriffs open source - cmsis/blob - CMSIS/CoreValidation/Source/CV_CoreFunc.c
Device: Renamed globally exposed interrupt function pointer type.
[cmsis] / CMSIS / CoreValidation / Source / CV_CoreFunc.c
1 /*-----------------------------------------------------------------------------
2  *      Name:         CV_CoreFunc.c
3  *      Purpose:      CMSIS CORE validation tests implementation
4  *-----------------------------------------------------------------------------
5  *      Copyright (c) 2017 - 2019 Arm Limited. All rights reserved.
6  *----------------------------------------------------------------------------*/
7
8 #include "CV_Framework.h"
9 #include "cmsis_cv.h"
10
11 /*-----------------------------------------------------------------------------
12  *      Test implementation
13  *----------------------------------------------------------------------------*/
14
15 static volatile uint32_t irqTaken = 0U;
16 #if defined(__CORTEX_M) && (__CORTEX_M > 0)
17 static volatile uint32_t irqActive = 0U;
18 #endif
19
20 static void TC_CoreFunc_EnDisIRQIRQHandler(void) {
21   ++irqTaken;
22 #if defined(__CORTEX_M) && (__CORTEX_M > 0)
23   irqActive = NVIC_GetActive(Interrupt0_IRQn);
24 #endif
25 }
26
27 static volatile uint32_t irqIPSR = 0U;
28 static volatile uint32_t irqXPSR = 0U;
29
30 static void TC_CoreFunc_IPSR_IRQHandler(void) {
31   irqIPSR = __get_IPSR();
32   irqXPSR = __get_xPSR();
33 }
34
35 /*-----------------------------------------------------------------------------
36  *      Test cases
37  *----------------------------------------------------------------------------*/
38
39 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
40 /**
41 \brief Test case: TC_CoreFunc_EnDisIRQ
42 \details
43 Check expected behavior of interrupt related control functions:
44 - __disable_irq() and __enable_irq()
45 - NVIC_EnableIRQ, NVIC_DisableIRQ,  and NVIC_GetEnableIRQ
46 - NVIC_SetPendingIRQ, NVIC_ClearPendingIRQ, and NVIC_GetPendingIRQ
47 - NVIC_GetActive (not on Cortex-M0/M0+)
48 */
49 void TC_CoreFunc_EnDisIRQ (void)
50 {
51   // Globally disable all interrupt servicing
52   __disable_irq();
53
54   // Enable the interrupt
55   NVIC_EnableIRQ(Interrupt0_IRQn);
56   ASSERT_TRUE(NVIC_GetEnableIRQ(Interrupt0_IRQn) != 0U);
57
58   // Clear its pending state
59   NVIC_ClearPendingIRQ(Interrupt0_IRQn);
60   ASSERT_TRUE(NVIC_GetPendingIRQ(Interrupt0_IRQn) == 0U);
61
62   // Register test interrupt handler.
63   TST_IRQHandler = TC_CoreFunc_EnDisIRQIRQHandler;
64   irqTaken = 0U;
65 #if defined(__CORTEX_M) && (__CORTEX_M > 0)
66   irqActive = UINT32_MAX;
67 #endif
68
69   // Set the interrupt pending state
70   NVIC_SetPendingIRQ(Interrupt0_IRQn);
71   for(uint32_t i = 10U; i > 0U; --i) {}
72
73   // Interrupt is not taken
74   ASSERT_TRUE(irqTaken == 0U);
75   ASSERT_TRUE(NVIC_GetPendingIRQ(Interrupt0_IRQn) != 0U);
76 #if defined(__CORTEX_M) && (__CORTEX_M > 0)
77   ASSERT_TRUE(NVIC_GetActive(Interrupt0_IRQn) == 0U);
78 #endif
79
80   // Globally enable interrupt servicing
81   __enable_irq();
82
83   for(uint32_t i = 10U; i > 0U; --i) {}
84
85   // Interrupt was taken
86   ASSERT_TRUE(irqTaken == 1U);
87 #if defined(__CORTEX_M) && (__CORTEX_M > 0)
88   ASSERT_TRUE(irqActive != 0U);
89   ASSERT_TRUE(NVIC_GetActive(Interrupt0_IRQn) == 0U);
90 #endif
91
92   // Interrupt it not pending anymore.
93   ASSERT_TRUE(NVIC_GetPendingIRQ(Interrupt0_IRQn) == 0U);
94
95   // Disable interrupt
96   NVIC_DisableIRQ(Interrupt0_IRQn);
97   ASSERT_TRUE(NVIC_GetEnableIRQ(Interrupt0_IRQn) == 0U);
98
99   // Set interrupt pending
100   NVIC_SetPendingIRQ(Interrupt0_IRQn);
101   for(uint32_t i = 10U; i > 0U; --i) {}
102
103   // Interrupt is not taken again
104   ASSERT_TRUE(irqTaken == 1U);
105   ASSERT_TRUE(NVIC_GetPendingIRQ(Interrupt0_IRQn) != 0U);
106
107   // Clear interrupt pending
108   NVIC_ClearPendingIRQ(Interrupt0_IRQn);
109   for(uint32_t i = 10U; i > 0U; --i) {}
110
111   // Interrupt it not pending anymore.
112   ASSERT_TRUE(NVIC_GetPendingIRQ(Interrupt0_IRQn) == 0U);
113
114   // Globally disable interrupt servicing
115   __disable_irq();
116 }
117
118 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
119 /**
120 \brief Test case: TC_CoreFunc_IRQPrio
121 \details
122 Check expected behavior of interrupt priority control functions:
123 - NVIC_SetPriority, NVIC_GetPriority
124 */
125 void TC_CoreFunc_IRQPrio (void)
126 {
127   /* Test Exception Priority */
128   uint32_t orig = NVIC_GetPriority(SVCall_IRQn);
129
130   NVIC_SetPriority(SVCall_IRQn, orig+1U);
131   uint32_t prio = NVIC_GetPriority(SVCall_IRQn);
132
133   ASSERT_TRUE(prio == orig+1U);
134
135   NVIC_SetPriority(SVCall_IRQn, orig);
136
137   /* Test Interrupt Priority */
138   orig = NVIC_GetPriority(Interrupt0_IRQn);
139
140   NVIC_SetPriority(Interrupt0_IRQn, orig+1U);
141   prio = NVIC_GetPriority(Interrupt0_IRQn);
142
143   ASSERT_TRUE(prio == orig+1U);
144
145   NVIC_SetPriority(Interrupt0_IRQn, orig);
146 }
147
148 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
149 /** Helper function for TC_CoreFunc_EncDecIRQPrio
150 \details
151 The helper encodes and decodes the given priority configuration.
152 \param[in] prigroup The PRIGROUP setting to be considered for encoding/decoding.
153 \param[in] pre The preempt priority value.
154 \param[in] sub The subpriority value.
155 */
156 static void TC_CoreFunc_EncDecIRQPrio_Step(uint32_t prigroup, uint32_t pre, uint32_t sub) {
157   uint32_t prio = NVIC_EncodePriority(prigroup, pre, sub);
158
159   uint32_t ret_pre = UINT32_MAX;
160   uint32_t ret_sub = UINT32_MAX;
161
162   NVIC_DecodePriority(prio, prigroup, &ret_pre, &ret_sub);
163
164   ASSERT_TRUE(ret_pre == pre);
165   ASSERT_TRUE(ret_sub == sub);
166 }
167
168 /**
169 \brief Test case: TC_CoreFunc_EncDecIRQPrio
170 \details
171 Check expected behavior of interrupt priority encoding/decoding functions:
172 - NVIC_EncodePriority, NVIC_DecodePriority
173 */
174 void TC_CoreFunc_EncDecIRQPrio (void)
175 {
176   /* Check only the valid range of PRIGROUP and preempt-/sub-priority values. */
177   static const uint32_t priobits = (__NVIC_PRIO_BITS > 7U) ? 7U : __NVIC_PRIO_BITS;
178   for(uint32_t prigroup = 7U-priobits; prigroup<7U; prigroup++) {
179     for(uint32_t pre = 0U; pre<(128U>>prigroup); pre++) {
180       for(uint32_t sub = 0U; sub<(256U>>(8U-__NVIC_PRIO_BITS+7U-prigroup)); sub++) {
181         TC_CoreFunc_EncDecIRQPrio_Step(prigroup, pre, sub);
182       }
183     }
184   }
185 }
186
187 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
188 /**
189 \brief Test case: TC_CoreFunc_IRQVect
190 \details
191 Check expected behavior of interrupt vector relocation functions:
192 - NVIC_SetVector, NVIC_GetVector
193 */
194 void TC_CoreFunc_IRQVect(void) {
195 #if defined(__VTOR_PRESENT) && __VTOR_PRESENT
196   /* relocate vector table */
197   static VECTOR_TABLE_Type vectors[sizeof(__VECTOR_TABLE)/sizeof(__VECTOR_TABLE[0])] __ALIGNED(512);
198
199   memcpy(vectors, __VECTOR_TABLE, sizeof(__VECTOR_TABLE));
200   
201   const uint32_t orig_vtor = SCB->VTOR;
202   const uint32_t vtor = ((uint32_t)vectors) & SCB_VTOR_TBLOFF_Msk;
203   SCB->VTOR = vtor;
204
205   ASSERT_TRUE(vtor == SCB->VTOR);
206
207   /* check exception vectors */
208   extern void HardFault_Handler(void);
209   extern void SVC_Handler(void);
210   extern void PendSV_Handler(void);
211   extern void SysTick_Handler(void);
212
213   ASSERT_TRUE(NVIC_GetVector(HardFault_IRQn) == (uint32_t)HardFault_Handler);
214   ASSERT_TRUE(NVIC_GetVector(SVCall_IRQn) == (uint32_t)SVC_Handler);
215   ASSERT_TRUE(NVIC_GetVector(PendSV_IRQn) == (uint32_t)PendSV_Handler);
216   ASSERT_TRUE(NVIC_GetVector(SysTick_IRQn) == (uint32_t)SysTick_Handler);
217
218   /* reconfigure WDT IRQ vector */
219   extern void Interrupt0_Handler(void);
220
221   const uint32_t wdtvec = NVIC_GetVector(Interrupt0_IRQn);
222   ASSERT_TRUE(wdtvec == (uint32_t)Interrupt0_Handler);
223
224   NVIC_SetVector(Interrupt0_IRQn, wdtvec + 32U);
225
226   ASSERT_TRUE(NVIC_GetVector(Interrupt0_IRQn) == (wdtvec + 32U));
227
228   /* restore vector table */
229   SCB->VTOR = orig_vtor;
230 #endif
231 }
232
233 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
234 /**
235 \brief Test case: TC_CoreFunc_GetCtrl
236 \details
237 - Check if __set_CONTROL and __get_CONTROL() sets/gets control register
238 */
239 void TC_CoreFunc_Control (void) {
240   // don't use stack for this variables
241   static uint32_t orig;
242   static uint32_t ctrl;
243   static uint32_t result;
244
245   orig = __get_CONTROL();
246   ctrl = orig;
247   result = UINT32_MAX;
248
249 #ifdef CONTROL_SPSEL_Msk
250   // SPSEL set to 0 (MSP)
251   ASSERT_TRUE((ctrl & CONTROL_SPSEL_Msk) == 0U);
252
253   // SPSEL set to 1 (PSP)
254   ctrl |= CONTROL_SPSEL_Msk;
255
256   // Move MSP to PSP
257   __set_PSP(__get_MSP());
258 #endif
259
260   __set_CONTROL(ctrl);
261   __ISB();
262
263   result = __get_CONTROL();
264
265   __set_CONTROL(orig);
266   __ISB();
267
268   ASSERT_TRUE(result == ctrl);
269   ASSERT_TRUE(__get_CONTROL() == orig);
270 }
271
272 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
273 /**
274 \brief Test case: TC_CoreFunc_IPSR
275 \details
276 - Check if __get_IPSR intrinsic is available
277 - Check if __get_xPSR intrinsic is available
278 - Result differentiates between thread and exception modes
279 */
280 void TC_CoreFunc_IPSR (void) {
281   uint32_t result = __get_IPSR();
282   ASSERT_TRUE(result == 0U); // Thread Mode
283
284   result = __get_xPSR();
285   ASSERT_TRUE((result & xPSR_ISR_Msk) == 0U); // Thread Mode
286
287   TST_IRQHandler = TC_CoreFunc_IPSR_IRQHandler;
288   irqIPSR = 0U;
289   irqXPSR = 0U;
290
291   NVIC_ClearPendingIRQ(Interrupt0_IRQn);
292   NVIC_EnableIRQ(Interrupt0_IRQn);
293   __enable_irq();
294
295   NVIC_SetPendingIRQ(Interrupt0_IRQn);
296   for(uint32_t i = 10U; i > 0U; --i) {}
297
298   __disable_irq();
299   NVIC_DisableIRQ(Interrupt0_IRQn);
300
301   ASSERT_TRUE(irqIPSR != 0U); // Exception Mode
302   ASSERT_TRUE((irqXPSR & xPSR_ISR_Msk) != 0U); // Exception Mode
303 }
304
305 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
306
307 #if defined(__CC_ARM)
308 #define SUBS(Rd, Rm, Rn) __ASM volatile("SUBS " # Rd ", " # Rm ", " # Rn)
309 #define ADDS(Rd, Rm, Rn) __ASM volatile("ADDS " # Rd ", " # Rm ", " # Rn)
310 #elif defined( __GNUC__ )  && (!defined(__ARMCC_VERSION))  && (defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_8M_BASE__))
311 #define SUBS(Rd, Rm, Rn) __ASM volatile("SUB %0, %1, %2" : "=r"(Rd) : "r"(Rm), "r"(Rn) : "cc")
312 #define ADDS(Rd, Rm, Rn) __ASM volatile("ADD %0, %1, %2" : "=r"(Rd) : "r"(Rm), "r"(Rn) : "cc")
313 #elif defined(_lint)
314 //lint -save -e(9026) allow function-like macro
315 #define SUBS(Rd, Rm, Rn) ((Rd) = (Rm) - (Rn))
316 #define ADDS(Rd, Rm, Rn) ((Rd) = (Rm) + (Rn))
317 //lint -restore
318 #else
319 #define SUBS(Rd, Rm, Rn) __ASM volatile("SUBS %0, %1, %2" : "=r"(Rd) : "r"(Rm), "r"(Rn) : "cc")
320 #define ADDS(Rd, Rm, Rn) __ASM volatile("ADDS %0, %1, %2" : "=r"(Rd) : "r"(Rm), "r"(Rn) : "cc")
321 #endif
322
323 /**
324 \brief Test case: TC_CoreFunc_APSR
325 \details
326 - Check if __get_APSR intrinsic is available
327 - Check if __get_xPSR intrinsic is available
328 - Check negative, zero and overflow flags
329 */
330 void TC_CoreFunc_APSR (void) {
331   volatile uint32_t result;
332   //lint -esym(838, Rm) unused values
333   //lint -esym(438, Rm) unused values
334
335   // Check negative flag
336   volatile int32_t Rm = 5;
337   volatile int32_t Rn = 7;
338   SUBS(Rm, Rm, Rn);
339   result  = __get_APSR();
340   ASSERT_TRUE((result & APSR_N_Msk) == APSR_N_Msk);
341
342   Rm = 5;
343   Rn = 7;
344   SUBS(Rm, Rm, Rn);
345   result  = __get_xPSR();
346   ASSERT_TRUE((result & xPSR_N_Msk) == xPSR_N_Msk);
347
348   // Check zero and compare flag
349   Rm = 5;
350   SUBS(Rm, Rm, Rm);
351   result  = __get_APSR();
352   ASSERT_TRUE((result & APSR_Z_Msk) == APSR_Z_Msk);
353   ASSERT_TRUE((result & APSR_C_Msk) == APSR_C_Msk);
354
355   Rm = 5;
356   SUBS(Rm, Rm, Rm);
357   result  = __get_xPSR();
358   ASSERT_TRUE((result & xPSR_Z_Msk) == xPSR_Z_Msk);
359   ASSERT_TRUE((result & APSR_C_Msk) == APSR_C_Msk);
360
361   // Check overflow flag
362   Rm = 5;
363   Rn = INT32_MAX;
364   ADDS(Rm, Rm, Rn);
365   result  = __get_APSR();
366   ASSERT_TRUE((result & APSR_V_Msk) == APSR_V_Msk);
367
368   Rm = 5;
369   Rn = INT32_MAX;
370   ADDS(Rm, Rm, Rn);
371   result  = __get_xPSR();
372   ASSERT_TRUE((result & xPSR_V_Msk) == xPSR_V_Msk);
373 }
374
375 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
376 /**
377 \brief Test case: TC_CoreFunc_PSP
378 \details
379 - Check if __get_PSP and __set_PSP intrinsic can be used to manipulate process stack pointer.
380 */
381 void TC_CoreFunc_PSP (void) {
382   // don't use stack for this variables
383   static uint32_t orig;
384   static uint32_t psp;
385   static uint32_t result;
386
387   orig = __get_PSP();
388
389   psp = orig + 0x12345678U;
390   __set_PSP(psp);
391
392   result = __get_PSP();
393
394   __set_PSP(orig);
395
396   ASSERT_TRUE(result == psp);
397 }
398
399 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
400 /**
401 \brief Test case: TC_CoreFunc_MSP
402 \details
403 - Check if __get_MSP and __set_MSP intrinsic can be used to manipulate main stack pointer.
404 */
405 void TC_CoreFunc_MSP (void) {
406   // don't use stack for this variables
407   static uint32_t orig;
408   static uint32_t msp;
409   static uint32_t result;
410   static uint32_t ctrl;
411
412   ctrl = __get_CONTROL();
413   orig = __get_MSP();
414
415   __set_PSP(orig);
416   __set_CONTROL(ctrl | CONTROL_SPSEL_Msk); // switch to PSP
417
418   msp = orig + 0x12345678U;
419   __set_MSP(msp);
420
421   result = __get_MSP();
422
423   __set_MSP(orig);
424
425   __set_CONTROL(ctrl);
426
427   ASSERT_TRUE(result == msp);
428 }
429
430 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
431 /**
432 \brief Test case: TC_CoreFunc_PSPLIM
433 \details
434 - Check if __get_PSPLIM and __set_PSPLIM intrinsic can be used to manipulate process stack pointer limit.
435 */
436 void TC_CoreFunc_PSPLIM (void) {
437 #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
438      (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1))    )
439   // don't use stack for this variables
440   static uint32_t orig;
441   static uint32_t psplim;
442   static uint32_t result;
443
444   orig = __get_PSPLIM();
445
446   psplim = orig + 0x12345678U;
447   __set_PSPLIM(psplim);
448
449   result = __get_PSPLIM();
450
451   __set_PSPLIM(orig);
452
453 #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
454      (!defined (__ARM_FEATURE_CMSE  ) || (__ARM_FEATURE_CMSE   < 3)))
455   // without main extensions, the non-secure PSPLIM is RAZ/WI
456   ASSERT_TRUE(result == 0U);
457 #else
458   ASSERT_TRUE(result == psplim);
459 #endif
460
461 #endif
462 }
463
464 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
465 /**
466 \brief Test case: TC_CoreFunc_PSPLIM_NS
467 \details
468 - Check if __TZ_get_PSPLIM_NS and __TZ_set_PSPLIM_NS intrinsic can be used to manipulate process stack pointer limit.
469 */
470 void TC_CoreFunc_PSPLIM_NS (void) {
471 #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
472      (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1))    )
473
474 #if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3))
475   uint32_t orig;
476   uint32_t psplim;
477   uint32_t result;
478
479   orig = __TZ_get_PSPLIM_NS();
480
481   psplim = orig + 0x12345678U;
482   __TZ_set_PSPLIM_NS(psplim);
483
484   result = __TZ_get_PSPLIM_NS();
485
486   __TZ_set_PSPLIM_NS(orig);
487
488 #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
489   // without main extensions, the non-secure PSPLIM is RAZ/WI
490   ASSERT_TRUE(result == 0U);
491 #else
492   ASSERT_TRUE(result == psplim);
493 #endif
494 #endif
495
496 #endif
497 }
498
499 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
500 /**
501 \brief Test case: TC_CoreFunc_MSPLIM
502 \details
503 - Check if __get_MSPLIM and __set_MSPLIM intrinsic can be used to manipulate main stack pointer limit.
504 */
505 void TC_CoreFunc_MSPLIM (void) {
506 #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
507      (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1))    )
508   // don't use stack for this variables
509   static uint32_t orig;
510   static uint32_t msplim;
511   static uint32_t result;
512   static uint32_t ctrl;
513
514   ctrl = __get_CONTROL();
515   __set_CONTROL(ctrl | CONTROL_SPSEL_Msk); // switch to PSP
516
517   orig = __get_MSPLIM();
518
519   msplim = orig + 0x12345678U;
520   __set_MSPLIM(msplim);
521
522   result = __get_MSPLIM();
523
524   __set_MSPLIM(orig);
525
526   __set_CONTROL(ctrl);
527
528 #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
529      (!defined (__ARM_FEATURE_CMSE  ) || (__ARM_FEATURE_CMSE   < 3)))
530   // without main extensions, the non-secure MSPLIM is RAZ/WI
531   ASSERT_TRUE(result == 0U);
532 #else
533   ASSERT_TRUE(result == msplim);
534 #endif
535
536 #endif
537 }
538
539 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
540 /**
541 \brief Test case: TC_CoreFunc_MSPLIM_NS
542 \details
543 - Check if __TZ_get_MSPLIM_NS and __TZ_set_MSPLIM_NS intrinsic can be used to manipulate process stack pointer limit.
544 */
545 void TC_CoreFunc_MSPLIM_NS (void) {
546 #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
547      (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1))    )
548
549 #if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3))
550   uint32_t orig;
551   uint32_t msplim;
552   uint32_t result;
553
554   orig = __TZ_get_MSPLIM_NS();
555
556   msplim = orig + 0x12345678U;
557   __TZ_set_MSPLIM_NS(msplim);
558
559   result = __TZ_get_MSPLIM_NS();
560
561   __TZ_set_MSPLIM_NS(orig);
562
563 #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
564   // without main extensions, the non-secure MSPLIM is RAZ/WI
565   ASSERT_TRUE(result == 0U);
566 #else
567   ASSERT_TRUE(result == msplim);
568 #endif
569 #endif
570
571 #endif
572 }
573
574 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
575 /**
576 \brief Test case: TC_CoreFunc_PRIMASK
577 \details
578 - Check if __get_PRIMASK and __set_PRIMASK intrinsic can be used to manipulate PRIMASK.
579 - Check if __enable_irq and __disable_irq are reflected in PRIMASK.
580 */
581 void TC_CoreFunc_PRIMASK (void) {
582   uint32_t orig = __get_PRIMASK();
583
584   // toggle primask
585   uint32_t primask = (orig & ~0x01U) | (~orig & 0x01U);
586
587   __set_PRIMASK(primask);
588   uint32_t result = __get_PRIMASK();
589
590   ASSERT_TRUE(result == primask);
591
592   __disable_irq();
593   result = __get_PRIMASK();
594   ASSERT_TRUE((result & 0x01U) == 1U);
595
596   __enable_irq();
597   result = __get_PRIMASK();
598   ASSERT_TRUE((result & 0x01U) == 0U);
599
600   __disable_irq();
601   result = __get_PRIMASK();
602   ASSERT_TRUE((result & 0x01U) == 1U);
603
604   __set_PRIMASK(orig);
605 }
606
607 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
608 /**
609 \brief Test case: TC_CoreFunc_FAULTMASK
610 \details
611 - Check if __get_FAULTMASK and __set_FAULTMASK intrinsic can be used to manipulate FAULTMASK.
612 - Check if __enable_fault_irq and __disable_fault_irq are reflected in FAULTMASK.
613 */
614 void TC_CoreFunc_FAULTMASK (void) {
615 #if ((defined (__ARM_ARCH_7M__      ) && (__ARM_ARCH_7M__      == 1)) || \
616      (defined (__ARM_ARCH_7EM__     ) && (__ARM_ARCH_7EM__     == 1)) || \
617      (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))    )
618
619   uint32_t orig = __get_FAULTMASK();
620
621   // toggle faultmask
622   uint32_t faultmask = (orig & ~0x01U) | (~orig & 0x01U);
623
624   __set_FAULTMASK(faultmask);
625   uint32_t result = __get_FAULTMASK();
626
627   ASSERT_TRUE(result == faultmask);
628
629   __disable_fault_irq();
630   result = __get_FAULTMASK();
631   ASSERT_TRUE((result & 0x01U) == 1U);
632
633   __enable_fault_irq();
634   result = __get_FAULTMASK();
635   ASSERT_TRUE((result & 0x01U) == 0U);
636
637   __disable_fault_irq();
638   result = __get_FAULTMASK();
639   ASSERT_TRUE((result & 0x01U) == 1U);
640
641   __set_FAULTMASK(orig);
642
643 #endif
644 }
645
646 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
647 /**
648 \brief Test case: TC_CoreFunc_BASEPRI
649 \details
650 - Check if __get_BASEPRI and __set_BASEPRI intrinsic can be used to manipulate BASEPRI.
651 - Check if __set_BASEPRI_MAX intrinsic can be used to manipulate BASEPRI.
652 */
653 void TC_CoreFunc_BASEPRI(void) {
654 #if ((defined (__ARM_ARCH_7M__      ) && (__ARM_ARCH_7M__      == 1)) || \
655      (defined (__ARM_ARCH_7EM__     ) && (__ARM_ARCH_7EM__     == 1)) || \
656      (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))    )
657
658   uint32_t orig = __get_BASEPRI();
659
660   uint32_t basepri = ~orig & 0x80U;
661   __set_BASEPRI(basepri);
662   uint32_t result = __get_BASEPRI();
663
664   ASSERT_TRUE(result == basepri);
665
666   __set_BASEPRI(orig);
667
668   __set_BASEPRI_MAX(basepri);
669   result = __get_BASEPRI();
670
671   ASSERT_TRUE(result == basepri);
672
673 #endif
674 }
675
676 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
677 /**
678 \brief Test case: TC_CoreFunc_FPUType
679 \details
680 Check SCB_GetFPUType returns information.
681 */
682 void TC_CoreFunc_FPUType(void) {
683   uint32_t fpuType = SCB_GetFPUType();
684 #if defined(__FPU_PRESENT) && (__FPU_PRESENT != 0)
685   ASSERT_TRUE(fpuType > 0U);
686 #else
687   ASSERT_TRUE(fpuType  == 0U);
688 #endif
689 }
690
691 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
692 /**
693 \brief Test case: TC_CoreFunc_FPSCR
694 \details
695 - Check if __get_FPSCR and __set_FPSCR intrinsics can be used
696 */
697 void TC_CoreFunc_FPSCR(void) {
698   uint32_t fpscr = __get_FPSCR();
699   __ISB();
700   __DSB();
701
702   __set_FPSCR(~fpscr);
703   __ISB();
704   __DSB();
705
706   uint32_t result = __get_FPSCR();
707
708   __set_FPSCR(fpscr);
709
710 #if (defined (__FPU_USED   ) && (__FPU_USED    == 1U))
711   ASSERT_TRUE(result != fpscr);
712 #else
713   ASSERT_TRUE(result == 0U);
714 #endif
715 }