]> begriffs open source - cmsis/blob - CMSIS/CoreValidation/Source/CV_CoreFunc.c
DoxyGen: remind users to enable trace before using PMU
[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 - 2021 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   extern const VECTOR_TABLE_Type __VECTOR_TABLE[48];
198   static VECTOR_TABLE_Type vectors[sizeof(__VECTOR_TABLE)/sizeof(__VECTOR_TABLE[0])] __ALIGNED(512);
199
200   memcpy(vectors, __VECTOR_TABLE, sizeof(__VECTOR_TABLE));
201   
202   const uint32_t orig_vtor = SCB->VTOR;
203   const uint32_t vtor = ((uint32_t)vectors) & SCB_VTOR_TBLOFF_Msk;
204   SCB->VTOR = vtor;
205
206   ASSERT_TRUE(vtor == SCB->VTOR);
207
208   /* check exception vectors */
209   extern void HardFault_Handler(void);
210   extern void SVC_Handler(void);
211   extern void PendSV_Handler(void);
212   extern void SysTick_Handler(void);
213
214   ASSERT_TRUE(NVIC_GetVector(HardFault_IRQn) == (uint32_t)HardFault_Handler);
215   ASSERT_TRUE(NVIC_GetVector(SVCall_IRQn) == (uint32_t)SVC_Handler);
216   ASSERT_TRUE(NVIC_GetVector(PendSV_IRQn) == (uint32_t)PendSV_Handler);
217   ASSERT_TRUE(NVIC_GetVector(SysTick_IRQn) == (uint32_t)SysTick_Handler);
218
219   /* reconfigure WDT IRQ vector */
220   extern void Interrupt0_Handler(void);
221
222   const uint32_t wdtvec = NVIC_GetVector(Interrupt0_IRQn);
223   ASSERT_TRUE(wdtvec == (uint32_t)Interrupt0_Handler);
224
225   NVIC_SetVector(Interrupt0_IRQn, wdtvec + 32U);
226
227   ASSERT_TRUE(NVIC_GetVector(Interrupt0_IRQn) == (wdtvec + 32U));
228
229   /* restore vector table */
230   SCB->VTOR = orig_vtor;
231 #endif
232 }
233
234 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
235 /**
236 \brief Test case: TC_CoreFunc_GetCtrl
237 \details
238 - Check if __set_CONTROL and __get_CONTROL() sets/gets control register
239 */
240 void TC_CoreFunc_Control (void) {
241   // don't use stack for this variables
242   static uint32_t orig;
243   static uint32_t ctrl;
244   static uint32_t result;
245
246   orig = __get_CONTROL();
247   ctrl = orig;
248   result = UINT32_MAX;
249
250 #ifdef CONTROL_SPSEL_Msk
251   // SPSEL set to 0 (MSP)
252   ASSERT_TRUE((ctrl & CONTROL_SPSEL_Msk) == 0U);
253
254   // SPSEL set to 1 (PSP)
255   ctrl |= CONTROL_SPSEL_Msk;
256
257   // Move MSP to PSP
258   __set_PSP(__get_MSP());
259 #endif
260
261   __set_CONTROL(ctrl);
262   __ISB();
263
264   result = __get_CONTROL();
265
266   __set_CONTROL(orig);
267   __ISB();
268
269   ASSERT_TRUE(result == ctrl);
270   ASSERT_TRUE(__get_CONTROL() == orig);
271 }
272
273 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
274 /**
275 \brief Test case: TC_CoreFunc_IPSR
276 \details
277 - Check if __get_IPSR intrinsic is available
278 - Check if __get_xPSR intrinsic is available
279 - Result differentiates between thread and exception modes
280 */
281 void TC_CoreFunc_IPSR (void) {
282   uint32_t result = __get_IPSR();
283   ASSERT_TRUE(result == 0U); // Thread Mode
284
285   result = __get_xPSR();
286   ASSERT_TRUE((result & xPSR_ISR_Msk) == 0U); // Thread Mode
287
288   TST_IRQHandler = TC_CoreFunc_IPSR_IRQHandler;
289   irqIPSR = 0U;
290   irqXPSR = 0U;
291
292   NVIC_ClearPendingIRQ(Interrupt0_IRQn);
293   NVIC_EnableIRQ(Interrupt0_IRQn);
294   __enable_irq();
295
296   NVIC_SetPendingIRQ(Interrupt0_IRQn);
297   for(uint32_t i = 10U; i > 0U; --i) {}
298
299   __disable_irq();
300   NVIC_DisableIRQ(Interrupt0_IRQn);
301
302   ASSERT_TRUE(irqIPSR != 0U); // Exception Mode
303   ASSERT_TRUE((irqXPSR & xPSR_ISR_Msk) != 0U); // Exception Mode
304 }
305
306 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
307
308 #if defined(__CC_ARM)
309 #define SUBS(Rd, Rm, Rn) __ASM volatile("SUBS " # Rd ", " # Rm ", " # Rn)
310 #define ADDS(Rd, Rm, Rn) __ASM volatile("ADDS " # Rd ", " # Rm ", " # Rn)
311 #elif defined( __GNUC__ )  && (!defined(__ARMCC_VERSION))  && (defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_8M_BASE__))
312 #define SUBS(Rd, Rm, Rn) __ASM volatile("SUB %0, %1, %2" : "=r"(Rd) : "r"(Rm), "r"(Rn) : "cc")
313 #define ADDS(Rd, Rm, Rn) __ASM volatile("ADD %0, %1, %2" : "=r"(Rd) : "r"(Rm), "r"(Rn) : "cc")
314 #elif defined(_lint)
315 //lint -save -e(9026) allow function-like macro
316 #define SUBS(Rd, Rm, Rn) ((Rd) = (Rm) - (Rn))
317 #define ADDS(Rd, Rm, Rn) ((Rd) = (Rm) + (Rn))
318 //lint -restore
319 #else
320 #define SUBS(Rd, Rm, Rn) __ASM volatile("SUBS %0, %1, %2" : "=r"(Rd) : "r"(Rm), "r"(Rn) : "cc")
321 #define ADDS(Rd, Rm, Rn) __ASM volatile("ADDS %0, %1, %2" : "=r"(Rd) : "r"(Rm), "r"(Rn) : "cc")
322 #endif
323
324 /**
325 \brief Test case: TC_CoreFunc_APSR
326 \details
327 - Check if __get_APSR intrinsic is available
328 - Check if __get_xPSR intrinsic is available
329 - Check negative, zero and overflow flags
330 */
331 void TC_CoreFunc_APSR (void) {
332   volatile uint32_t result;
333   //lint -esym(838, Rm) unused values
334   //lint -esym(438, Rm) unused values
335
336   // Check negative flag
337   volatile int32_t Rm = 5;
338   volatile int32_t Rn = 7;
339   SUBS(Rm, Rm, Rn);
340   result  = __get_APSR();
341   ASSERT_TRUE((result & APSR_N_Msk) == APSR_N_Msk);
342
343   Rm = 5;
344   Rn = 7;
345   SUBS(Rm, Rm, Rn);
346   result  = __get_xPSR();
347   ASSERT_TRUE((result & xPSR_N_Msk) == xPSR_N_Msk);
348
349   // Check zero and compare flag
350   Rm = 5;
351   SUBS(Rm, Rm, Rm);
352   result  = __get_APSR();
353   ASSERT_TRUE((result & APSR_Z_Msk) == APSR_Z_Msk);
354   ASSERT_TRUE((result & APSR_C_Msk) == APSR_C_Msk);
355
356   Rm = 5;
357   SUBS(Rm, Rm, Rm);
358   result  = __get_xPSR();
359   ASSERT_TRUE((result & xPSR_Z_Msk) == xPSR_Z_Msk);
360   ASSERT_TRUE((result & APSR_C_Msk) == APSR_C_Msk);
361
362   // Check overflow flag
363   Rm = 5;
364   Rn = INT32_MAX;
365   ADDS(Rm, Rm, Rn);
366   result  = __get_APSR();
367   ASSERT_TRUE((result & APSR_V_Msk) == APSR_V_Msk);
368
369   Rm = 5;
370   Rn = INT32_MAX;
371   ADDS(Rm, Rm, Rn);
372   result  = __get_xPSR();
373   ASSERT_TRUE((result & xPSR_V_Msk) == xPSR_V_Msk);
374 }
375
376 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
377 /**
378 \brief Test case: TC_CoreFunc_PSP
379 \details
380 - Check if __get_PSP and __set_PSP intrinsic can be used to manipulate process stack pointer.
381 */
382 void TC_CoreFunc_PSP (void) {
383   // don't use stack for this variables
384   static uint32_t orig;
385   static uint32_t psp;
386   static uint32_t result;
387
388   orig = __get_PSP();
389
390   psp = orig + 0x12345678U;
391   __set_PSP(psp);
392
393   result = __get_PSP();
394
395   __set_PSP(orig);
396
397   ASSERT_TRUE(result == psp);
398 }
399
400 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
401 /**
402 \brief Test case: TC_CoreFunc_MSP
403 \details
404 - Check if __get_MSP and __set_MSP intrinsic can be used to manipulate main stack pointer.
405 */
406 void TC_CoreFunc_MSP (void) {
407   // don't use stack for this variables
408   static uint32_t orig;
409   static uint32_t msp;
410   static uint32_t result;
411   static uint32_t ctrl;
412
413   ctrl = __get_CONTROL();
414   orig = __get_MSP();
415
416   __set_PSP(orig);
417   __set_CONTROL(ctrl | CONTROL_SPSEL_Msk); // switch to PSP
418
419   msp = orig + 0x12345678U;
420   __set_MSP(msp);
421
422   result = __get_MSP();
423
424   __set_MSP(orig);
425
426   __set_CONTROL(ctrl);
427
428   ASSERT_TRUE(result == msp);
429 }
430
431 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
432 /**
433 \brief Test case: TC_CoreFunc_PSPLIM
434 \details
435 - Check if __get_PSPLIM and __set_PSPLIM intrinsic can be used to manipulate process stack pointer limit.
436 */
437 void TC_CoreFunc_PSPLIM (void) {
438 #if ((defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) || \
439      (defined (__ARM_ARCH_8M_MAIN__   ) && (__ARM_ARCH_8M_MAIN__   == 1)) || \
440      (defined (__ARM_ARCH_8M_BASE__   ) && (__ARM_ARCH_8M_BASE__   == 1))    )
441   // don't use stack for this variables
442   static uint32_t orig;
443   static uint32_t psplim;
444   static uint32_t result;
445
446   orig = __get_PSPLIM();
447
448   psplim = orig + 0x12345678U;
449   __set_PSPLIM(psplim);
450
451   result = __get_PSPLIM();
452
453   __set_PSPLIM(orig);
454
455 #if (!(defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) && \
456      !(defined (__ARM_ARCH_8M_MAIN__   ) && (__ARM_ARCH_8M_MAIN__   == 1)) && \
457      (!defined (__ARM_FEATURE_CMSE     ) || (__ARM_FEATURE_CMSE      < 3))    )
458   // without main extensions, the non-secure PSPLIM is RAZ/WI
459   ASSERT_TRUE(result == 0U);
460 #else
461   ASSERT_TRUE(result == psplim);
462 #endif
463
464 #endif
465 }
466
467 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
468 /**
469 \brief Test case: TC_CoreFunc_PSPLIM_NS
470 \details
471 - Check if __TZ_get_PSPLIM_NS and __TZ_set_PSPLIM_NS intrinsic can be used to manipulate process stack pointer limit.
472 */
473 void TC_CoreFunc_PSPLIM_NS (void) {
474 #if ((defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) || \
475      (defined (__ARM_ARCH_8M_MAIN__   ) && (__ARM_ARCH_8M_MAIN__   == 1)) || \
476      (defined (__ARM_ARCH_8M_BASE__   ) && (__ARM_ARCH_8M_BASE__   == 1))    )
477
478 #if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3))
479   uint32_t orig;
480   uint32_t psplim;
481   uint32_t result;
482
483   orig = __TZ_get_PSPLIM_NS();
484
485   psplim = orig + 0x12345678U;
486   __TZ_set_PSPLIM_NS(psplim);
487
488   result = __TZ_get_PSPLIM_NS();
489
490   __TZ_set_PSPLIM_NS(orig);
491
492 #if (!(defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) && \
493      !(defined (__ARM_ARCH_8M_MAIN__   ) && (__ARM_ARCH_8M_MAIN__   == 1))    )
494   // without main extensions, the non-secure PSPLIM is RAZ/WI
495   ASSERT_TRUE(result == 0U);
496 #else
497   ASSERT_TRUE(result == psplim);
498 #endif
499 #endif
500
501 #endif
502 }
503
504 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
505 /**
506 \brief Test case: TC_CoreFunc_MSPLIM
507 \details
508 - Check if __get_MSPLIM and __set_MSPLIM intrinsic can be used to manipulate main stack pointer limit.
509 */
510 void TC_CoreFunc_MSPLIM (void) {
511 #if ((defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) || \
512      (defined (__ARM_ARCH_8M_MAIN__   ) && (__ARM_ARCH_8M_MAIN__   == 1)) || \
513      (defined (__ARM_ARCH_8M_BASE__   ) && (__ARM_ARCH_8M_BASE__   == 1))    )
514   // don't use stack for this variables
515   static uint32_t orig;
516   static uint32_t msplim;
517   static uint32_t result;
518   static uint32_t ctrl;
519
520   ctrl = __get_CONTROL();
521   __set_CONTROL(ctrl | CONTROL_SPSEL_Msk); // switch to PSP
522
523   orig = __get_MSPLIM();
524
525   msplim = orig + 0x12345678U;
526   __set_MSPLIM(msplim);
527
528   result = __get_MSPLIM();
529
530   __set_MSPLIM(orig);
531
532   __set_CONTROL(ctrl);
533
534 #if (!(defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) && \
535      !(defined (__ARM_ARCH_8M_MAIN__   ) && (__ARM_ARCH_8M_MAIN__   == 1)) && \
536      (!defined (__ARM_FEATURE_CMSE     ) || (__ARM_FEATURE_CMSE      < 3))    )
537   // without main extensions, the non-secure MSPLIM is RAZ/WI
538   ASSERT_TRUE(result == 0U);
539 #else
540   ASSERT_TRUE(result == msplim);
541 #endif
542
543 #endif
544 }
545
546 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
547 /**
548 \brief Test case: TC_CoreFunc_MSPLIM_NS
549 \details
550 - Check if __TZ_get_MSPLIM_NS and __TZ_set_MSPLIM_NS intrinsic can be used to manipulate process stack pointer limit.
551 */
552 void TC_CoreFunc_MSPLIM_NS (void) {
553 #if ((defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) || \
554      (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
555      (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1))    )
556
557 #if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3))
558   uint32_t orig;
559   uint32_t msplim;
560   uint32_t result;
561
562   orig = __TZ_get_MSPLIM_NS();
563
564   msplim = orig + 0x12345678U;
565   __TZ_set_MSPLIM_NS(msplim);
566
567   result = __TZ_get_MSPLIM_NS();
568
569   __TZ_set_MSPLIM_NS(orig);
570
571 #if (!(defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) && \
572      !(defined (__ARM_ARCH_8M_MAIN__   ) && (__ARM_ARCH_8M_MAIN__   == 1))    )
573   // without main extensions, the non-secure MSPLIM is RAZ/WI
574   ASSERT_TRUE(result == 0U);
575 #else
576   ASSERT_TRUE(result == msplim);
577 #endif
578 #endif
579
580 #endif
581 }
582
583 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
584 /**
585 \brief Test case: TC_CoreFunc_PRIMASK
586 \details
587 - Check if __get_PRIMASK and __set_PRIMASK intrinsic can be used to manipulate PRIMASK.
588 - Check if __enable_irq and __disable_irq are reflected in PRIMASK.
589 */
590 void TC_CoreFunc_PRIMASK (void) {
591   uint32_t orig = __get_PRIMASK();
592
593   // toggle primask
594   uint32_t primask = (orig & ~0x01U) | (~orig & 0x01U);
595
596   __set_PRIMASK(primask);
597   uint32_t result = __get_PRIMASK();
598
599   ASSERT_TRUE(result == primask);
600
601   __disable_irq();
602   result = __get_PRIMASK();
603   ASSERT_TRUE((result & 0x01U) == 1U);
604
605   __enable_irq();
606   result = __get_PRIMASK();
607   ASSERT_TRUE((result & 0x01U) == 0U);
608
609   __disable_irq();
610   result = __get_PRIMASK();
611   ASSERT_TRUE((result & 0x01U) == 1U);
612
613   __set_PRIMASK(orig);
614 }
615
616 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
617 /**
618 \brief Test case: TC_CoreFunc_FAULTMASK
619 \details
620 - Check if __get_FAULTMASK and __set_FAULTMASK intrinsic can be used to manipulate FAULTMASK.
621 - Check if __enable_fault_irq and __disable_fault_irq are reflected in FAULTMASK.
622 */
623 void TC_CoreFunc_FAULTMASK (void) {
624 #if ((defined (__ARM_ARCH_7M__        ) && (__ARM_ARCH_7M__        == 1)) || \
625      (defined (__ARM_ARCH_7EM__       ) && (__ARM_ARCH_7EM__       == 1)) || \
626      (defined (__ARM_ARCH_8M_MAIN__   ) && (__ARM_ARCH_8M_MAIN__   == 1)) || \
627      (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1))    )
628
629   uint32_t orig = __get_FAULTMASK();
630
631   // toggle faultmask
632   uint32_t faultmask = (orig & ~0x01U) | (~orig & 0x01U);
633
634   __set_FAULTMASK(faultmask);
635   uint32_t result = __get_FAULTMASK();
636
637   ASSERT_TRUE(result == faultmask);
638
639   __disable_fault_irq();
640   result = __get_FAULTMASK();
641   ASSERT_TRUE((result & 0x01U) == 1U);
642
643   __enable_fault_irq();
644   result = __get_FAULTMASK();
645   ASSERT_TRUE((result & 0x01U) == 0U);
646
647   __disable_fault_irq();
648   result = __get_FAULTMASK();
649   ASSERT_TRUE((result & 0x01U) == 1U);
650
651   __set_FAULTMASK(orig);
652
653 #endif
654 }
655
656 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
657 /**
658 \brief Test case: TC_CoreFunc_BASEPRI
659 \details
660 - Check if __get_BASEPRI and __set_BASEPRI intrinsic can be used to manipulate BASEPRI.
661 - Check if __set_BASEPRI_MAX intrinsic can be used to manipulate BASEPRI.
662 */
663 void TC_CoreFunc_BASEPRI(void) {
664 #if ((defined (__ARM_ARCH_7M__        ) && (__ARM_ARCH_7M__        == 1)) || \
665      (defined (__ARM_ARCH_7EM__       ) && (__ARM_ARCH_7EM__       == 1)) || \
666      (defined (__ARM_ARCH_8M_MAIN__   ) && (__ARM_ARCH_8M_MAIN__   == 1)) || \
667      (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1))    )
668
669   uint32_t orig = __get_BASEPRI();
670
671   uint32_t basepri = ~orig & 0x80U;
672   __set_BASEPRI(basepri);
673   uint32_t result = __get_BASEPRI();
674
675   ASSERT_TRUE(result == basepri);
676
677   __set_BASEPRI(orig);
678
679   __set_BASEPRI_MAX(basepri);
680   result = __get_BASEPRI();
681
682   ASSERT_TRUE(result == basepri);
683
684 #endif
685 }
686
687 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
688 /**
689 \brief Test case: TC_CoreFunc_FPUType
690 \details
691 Check SCB_GetFPUType returns information.
692 */
693 void TC_CoreFunc_FPUType(void) {
694   uint32_t fpuType = SCB_GetFPUType();
695 #if defined(__FPU_PRESENT) && (__FPU_PRESENT != 0)
696   ASSERT_TRUE(fpuType > 0U);
697 #else
698   ASSERT_TRUE(fpuType  == 0U);
699 #endif
700 }
701
702 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
703 /**
704 \brief Test case: TC_CoreFunc_FPSCR
705 \details
706 - Check if __get_FPSCR and __set_FPSCR intrinsics can be used
707 */
708 void TC_CoreFunc_FPSCR(void) {
709   uint32_t fpscr = __get_FPSCR();
710   __ISB();
711   __DSB();
712
713   __set_FPSCR(~fpscr);
714   __ISB();
715   __DSB();
716
717   uint32_t result = __get_FPSCR();
718
719   __set_FPSCR(fpscr);
720
721 #if (defined (__FPU_USED   ) && (__FPU_USED    == 1U))
722   ASSERT_TRUE(result != fpscr);
723 #else
724   ASSERT_TRUE(result == 0U);
725 #endif
726 }