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