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   __ISB();
299   for(uint32_t i = 10U; i > 0U; --i) {__NOP();}
300 
301   __disable_irq();
302   NVIC_DisableIRQ(Interrupt0_IRQn);
303 
304   ASSERT_TRUE(irqIPSR != 0U); // Exception Mode
305   ASSERT_TRUE((irqXPSR & xPSR_ISR_Msk) != 0U); // Exception Mode
306 }
307 
308 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
309 
310 #if defined(__CC_ARM)
311 #define SUBS(Rd, Rm, Rn) __ASM volatile("SUBS " # Rd ", " # Rm ", " # Rn)
312 #define ADDS(Rd, Rm, Rn) __ASM volatile("ADDS " # Rd ", " # Rm ", " # Rn)
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 */
TC_CoreFunc_APSR(void)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 */
TC_CoreFunc_PSP(void)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 */
TC_CoreFunc_MSP(void)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 */
TC_CoreFunc_PSPLIM(void)436 void TC_CoreFunc_PSPLIM (void) {
437 #if ((defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) || \
438      (defined (__ARM_ARCH_8M_MAIN__   ) && (__ARM_ARCH_8M_MAIN__   == 1)) || \
439      (defined (__ARM_ARCH_8M_BASE__   ) && (__ARM_ARCH_8M_BASE__   == 1))    )
440   // don't use stack for this variables
441   static uint32_t orig;
442   static uint32_t psplim;
443   static uint32_t result;
444 
445   orig = __get_PSPLIM();
446 
447   psplim = orig + 0x12345678U;
448   __set_PSPLIM(psplim);
449 
450   result = __get_PSPLIM();
451 
452   __set_PSPLIM(orig);
453 
454 #if (!(defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) && \
455      !(defined (__ARM_ARCH_8M_MAIN__   ) && (__ARM_ARCH_8M_MAIN__   == 1)) && \
456      (!defined (__ARM_FEATURE_CMSE     ) || (__ARM_FEATURE_CMSE      < 3))    )
457   // without main extensions, the non-secure PSPLIM is RAZ/WI
458   ASSERT_TRUE(result == 0U);
459 #else
460   ASSERT_TRUE(result == psplim);
461 #endif
462 
463 #endif
464 }
465 
466 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
467 /**
468 \brief Test case: TC_CoreFunc_PSPLIM_NS
469 \details
470 - Check if __TZ_get_PSPLIM_NS and __TZ_set_PSPLIM_NS intrinsic can be used to manipulate process stack pointer limit.
471 */
TC_CoreFunc_PSPLIM_NS(void)472 void TC_CoreFunc_PSPLIM_NS (void) {
473 #if ((defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) || \
474      (defined (__ARM_ARCH_8M_MAIN__   ) && (__ARM_ARCH_8M_MAIN__   == 1)) || \
475      (defined (__ARM_ARCH_8M_BASE__   ) && (__ARM_ARCH_8M_BASE__   == 1))    )
476 
477 #if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3))
478   uint32_t orig;
479   uint32_t psplim;
480   uint32_t result;
481 
482   orig = __TZ_get_PSPLIM_NS();
483 
484   psplim = orig + 0x12345678U;
485   __TZ_set_PSPLIM_NS(psplim);
486 
487   result = __TZ_get_PSPLIM_NS();
488 
489   __TZ_set_PSPLIM_NS(orig);
490 
491 #if (!(defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) && \
492      !(defined (__ARM_ARCH_8M_MAIN__   ) && (__ARM_ARCH_8M_MAIN__   == 1))    )
493   // without main extensions, the non-secure PSPLIM is RAZ/WI
494   ASSERT_TRUE(result == 0U);
495 #else
496   ASSERT_TRUE(result == psplim);
497 #endif
498 #endif
499 
500 #endif
501 }
502 
503 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
504 /**
505 \brief Test case: TC_CoreFunc_MSPLIM
506 \details
507 - Check if __get_MSPLIM and __set_MSPLIM intrinsic can be used to manipulate main stack pointer limit.
508 */
TC_CoreFunc_MSPLIM(void)509 void TC_CoreFunc_MSPLIM (void) {
510 #if ((defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) || \
511      (defined (__ARM_ARCH_8M_MAIN__   ) && (__ARM_ARCH_8M_MAIN__   == 1)) || \
512      (defined (__ARM_ARCH_8M_BASE__   ) && (__ARM_ARCH_8M_BASE__   == 1))    )
513   // don't use stack for this variables
514   static uint32_t orig;
515   static uint32_t msplim;
516   static uint32_t result;
517   static uint32_t ctrl;
518 
519   ctrl = __get_CONTROL();
520   __set_CONTROL(ctrl | CONTROL_SPSEL_Msk); // switch to PSP
521 
522   orig = __get_MSPLIM();
523 
524   msplim = orig + 0x12345678U;
525   __set_MSPLIM(msplim);
526 
527   result = __get_MSPLIM();
528 
529   __set_MSPLIM(orig);
530 
531   __set_CONTROL(ctrl);
532 
533 #if (!(defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) && \
534      !(defined (__ARM_ARCH_8M_MAIN__   ) && (__ARM_ARCH_8M_MAIN__   == 1)) && \
535      (!defined (__ARM_FEATURE_CMSE     ) || (__ARM_FEATURE_CMSE      < 3))    )
536   // without main extensions, the non-secure MSPLIM is RAZ/WI
537   ASSERT_TRUE(result == 0U);
538 #else
539   ASSERT_TRUE(result == msplim);
540 #endif
541 
542 #endif
543 }
544 
545 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
546 /**
547 \brief Test case: TC_CoreFunc_MSPLIM_NS
548 \details
549 - Check if __TZ_get_MSPLIM_NS and __TZ_set_MSPLIM_NS intrinsic can be used to manipulate process stack pointer limit.
550 */
TC_CoreFunc_MSPLIM_NS(void)551 void TC_CoreFunc_MSPLIM_NS (void) {
552 #if ((defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) || \
553      (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
554      (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1))    )
555 
556 #if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3))
557   uint32_t orig;
558   uint32_t msplim;
559   uint32_t result;
560 
561   orig = __TZ_get_MSPLIM_NS();
562 
563   msplim = orig + 0x12345678U;
564   __TZ_set_MSPLIM_NS(msplim);
565 
566   result = __TZ_get_MSPLIM_NS();
567 
568   __TZ_set_MSPLIM_NS(orig);
569 
570 #if (!(defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) && \
571      !(defined (__ARM_ARCH_8M_MAIN__   ) && (__ARM_ARCH_8M_MAIN__   == 1))    )
572   // without main extensions, the non-secure MSPLIM is RAZ/WI
573   ASSERT_TRUE(result == 0U);
574 #else
575   ASSERT_TRUE(result == msplim);
576 #endif
577 #endif
578 
579 #endif
580 }
581 
582 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
583 /**
584 \brief Test case: TC_CoreFunc_PRIMASK
585 \details
586 - Check if __get_PRIMASK and __set_PRIMASK intrinsic can be used to manipulate PRIMASK.
587 - Check if __enable_irq and __disable_irq are reflected in PRIMASK.
588 */
TC_CoreFunc_PRIMASK(void)589 void TC_CoreFunc_PRIMASK (void) {
590   uint32_t orig = __get_PRIMASK();
591 
592   // toggle primask
593   uint32_t primask = (orig & ~0x01U) | (~orig & 0x01U);
594 
595   __set_PRIMASK(primask);
596   uint32_t result = __get_PRIMASK();
597   ASSERT_TRUE(result == primask);
598 
599   __disable_irq();
600   result = __get_PRIMASK();
601   ASSERT_TRUE((result & 0x01U) == 1U);
602 
603   __enable_irq();
604   result = __get_PRIMASK();
605   ASSERT_TRUE((result & 0x01U) == 0U);
606 
607   __disable_irq();
608   result = __get_PRIMASK();
609   ASSERT_TRUE((result & 0x01U) == 1U);
610 
611   __set_PRIMASK(orig);
612 }
613 
614 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
615 /**
616 \brief Test case: TC_CoreFunc_FAULTMASK
617 \details
618 - Check if __get_FAULTMASK and __set_FAULTMASK intrinsic can be used to manipulate FAULTMASK.
619 - Check if __enable_fault_irq and __disable_fault_irq are reflected in FAULTMASK.
620 */
TC_CoreFunc_FAULTMASK(void)621 void TC_CoreFunc_FAULTMASK (void) {
622 #if ((defined (__ARM_ARCH_7M__        ) && (__ARM_ARCH_7M__        == 1)) || \
623      (defined (__ARM_ARCH_7EM__       ) && (__ARM_ARCH_7EM__       == 1)) || \
624      (defined (__ARM_ARCH_8M_MAIN__   ) && (__ARM_ARCH_8M_MAIN__   == 1)) || \
625      (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1))    )
626 
627   uint32_t orig = __get_FAULTMASK();
628 
629   // toggle faultmask
630   uint32_t faultmask = (orig & ~0x01U) | (~orig & 0x01U);
631 
632   __set_FAULTMASK(faultmask);
633   uint32_t result = __get_FAULTMASK();
634   ASSERT_TRUE(result == faultmask);
635 
636   __disable_fault_irq();
637   result = __get_FAULTMASK();
638   ASSERT_TRUE((result & 0x01U) == 1U);
639 
640   __enable_fault_irq();
641   result = __get_FAULTMASK();
642   ASSERT_TRUE((result & 0x01U) == 0U);
643 
644   __disable_fault_irq();
645   result = __get_FAULTMASK();
646   ASSERT_TRUE((result & 0x01U) == 1U);
647 
648   __set_FAULTMASK(orig);
649 
650 #endif
651 }
652 
653 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
654 /**
655 \brief Test case: TC_CoreFunc_BASEPRI
656 \details
657 - Check if __get_BASEPRI and __set_BASEPRI intrinsic can be used to manipulate BASEPRI.
658 - Check if __set_BASEPRI_MAX intrinsic can be used to manipulate BASEPRI.
659 */
TC_CoreFunc_BASEPRI(void)660 void TC_CoreFunc_BASEPRI(void) {
661 #if ((defined (__ARM_ARCH_7M__        ) && (__ARM_ARCH_7M__        == 1)) || \
662      (defined (__ARM_ARCH_7EM__       ) && (__ARM_ARCH_7EM__       == 1)) || \
663      (defined (__ARM_ARCH_8M_MAIN__   ) && (__ARM_ARCH_8M_MAIN__   == 1)) || \
664      (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1))    )
665 
666   uint32_t orig = __get_BASEPRI();
667 
668   uint32_t basepri = ~orig & 0x80U;
669   __set_BASEPRI(basepri);
670   uint32_t result = __get_BASEPRI();
671 
672   ASSERT_TRUE(result == basepri);
673 
674   __set_BASEPRI(orig);
675 
676   __set_BASEPRI_MAX(basepri);
677   result = __get_BASEPRI();
678 
679   ASSERT_TRUE(result == basepri);
680 
681 #endif
682 }
683 
684 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
685 /**
686 \brief Test case: TC_CoreFunc_FPUType
687 \details
688 Check SCB_GetFPUType returns information.
689 */
TC_CoreFunc_FPUType(void)690 void TC_CoreFunc_FPUType(void) {
691   uint32_t fpuType = SCB_GetFPUType();
692 #if defined(__FPU_PRESENT) && (__FPU_PRESENT != 0)
693   ASSERT_TRUE(fpuType > 0U);
694 #else
695   ASSERT_TRUE(fpuType  == 0U);
696 #endif
697 }
698 
699 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
700 /**
701 \brief Test case: TC_CoreFunc_FPSCR
702 \details
703 - Check if __get_FPSCR and __set_FPSCR intrinsics can be used
704 */
TC_CoreFunc_FPSCR(void)705 void TC_CoreFunc_FPSCR(void) {
706   uint32_t fpscr = __get_FPSCR();
707   __ISB();
708   __DSB();
709 
710   __set_FPSCR(~fpscr);
711   __ISB();
712   __DSB();
713 
714   uint32_t result = __get_FPSCR();
715 
716   __set_FPSCR(fpscr);
717 
718 #if (defined (__FPU_USED   ) && (__FPU_USED    == 1U))
719   ASSERT_TRUE(result != fpscr);
720 #else
721   ASSERT_TRUE(result == 0U);
722 #endif
723 }
724