]> begriffs open source - cmsis/blob - CMSIS/CoreValidation/Source/CV_CoreFunc.c
Initial intros about external CMSIS-components.
[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 - 2023 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) {__NOP();}
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) {__NOP();}
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) {__NOP();}
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) {__NOP();}
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(1024) __NO_INIT;
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) {__NOP();}
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(__ti__)) && (!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_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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 }