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