]> begriffs open source - cmsis/blob - CMSIS/CoreValidation/Source/CV_CoreFunc.c
Code Coding rules for CMSIS-RTOS2 added.
[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 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(WDT_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(WDT_IRQn);
56   ASSERT_TRUE(NVIC_GetEnableIRQ(WDT_IRQn) != 0U);
57   
58   // Clear its pending state
59   NVIC_ClearPendingIRQ(WDT_IRQn);
60   ASSERT_TRUE(NVIC_GetPendingIRQ(WDT_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(WDT_IRQn);
71   for(uint32_t i = 10U; i > 0U; --i) {}
72
73   // Interrupt is not taken
74   ASSERT_TRUE(irqTaken == 0U);
75   ASSERT_TRUE(NVIC_GetPendingIRQ(WDT_IRQn) != 0U);
76 #if defined(__CORTEX_M) && (__CORTEX_M > 0)
77   ASSERT_TRUE(NVIC_GetActive(WDT_IRQn) == 0U);
78 #endif
79
80   // Globally enable interrupt servicing
81   __enable_irq();
82
83   for(uint32_t i = 10U; i > 0U; --i) {}
84
85   // Interrupt was taken
86   ASSERT_TRUE(irqTaken == 1U);
87 #if defined(__CORTEX_M) && (__CORTEX_M > 0)
88   ASSERT_TRUE(irqActive != 0U);
89   ASSERT_TRUE(NVIC_GetActive(WDT_IRQn) == 0U);
90 #endif
91
92   // Interrupt it not pending anymore.
93   ASSERT_TRUE(NVIC_GetPendingIRQ(WDT_IRQn) == 0U);
94
95   // Disable interrupt
96   NVIC_DisableIRQ(WDT_IRQn);
97   ASSERT_TRUE(NVIC_GetEnableIRQ(WDT_IRQn) == 0U);
98
99   // Set interrupt pending
100   NVIC_SetPendingIRQ(WDT_IRQn);
101   for(uint32_t i = 10U; i > 0U; --i) {}
102
103   // Interrupt is not taken again
104   ASSERT_TRUE(irqTaken == 1U);
105   ASSERT_TRUE(NVIC_GetPendingIRQ(WDT_IRQn) != 0U);
106   
107   // Clear interrupt pending
108   NVIC_ClearPendingIRQ(WDT_IRQn);
109   for(uint32_t i = 10U; i > 0U; --i) {}
110
111   // Interrupt it not pending anymore.
112   ASSERT_TRUE(NVIC_GetPendingIRQ(WDT_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_GetCtrl
121 \details
122 - Check if __set_CONTROL and __get_CONTROL() sets/gets control register
123 */
124 void TC_CoreFunc_Control (void) {
125   // don't use stack for this variables
126   static uint32_t orig;
127   static uint32_t ctrl;
128   static uint32_t result;
129
130   orig = __get_CONTROL();
131   ctrl = orig;
132   result = UINT32_MAX;
133
134 #ifdef CONTROL_SPSEL_Msk
135   // toggle SPSEL
136   ctrl = (ctrl & ~CONTROL_SPSEL_Msk) | (~ctrl & CONTROL_SPSEL_Msk);
137 #endif
138
139   __set_CONTROL(ctrl);
140   __ISB();
141
142   result = __get_CONTROL();
143
144   __set_CONTROL(orig);
145   __ISB();
146
147   ASSERT_TRUE(result == ctrl);
148   ASSERT_TRUE(__get_CONTROL() == orig);
149 }
150
151 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
152 /**
153 \brief Test case: TC_CoreFunc_IPSR
154 \details
155 - Check if __get_IPSR intrinsic is available
156 - Check if __get_xPSR intrinsic is available
157 - Result differentiates between thread and exception modes
158 */
159 void TC_CoreFunc_IPSR (void) {
160   uint32_t result = __get_IPSR();
161   ASSERT_TRUE(result == 0U); // Thread Mode
162
163   result = __get_xPSR();
164   ASSERT_TRUE((result & xPSR_ISR_Msk) == 0U); // Thread Mode
165
166   TST_IRQHandler = TC_CoreFunc_IPSR_IRQHandler;
167   irqIPSR = 0U;
168   irqXPSR = 0U;
169
170   NVIC_ClearPendingIRQ(WDT_IRQn);
171   NVIC_EnableIRQ(WDT_IRQn);
172   __enable_irq();
173
174   NVIC_SetPendingIRQ(WDT_IRQn);
175   for(uint32_t i = 10U; i > 0U; --i) {}
176
177   __disable_irq();
178   NVIC_DisableIRQ(WDT_IRQn);
179
180   ASSERT_TRUE(irqIPSR != 0U); // Exception Mode
181   ASSERT_TRUE((irqXPSR & xPSR_ISR_Msk) != 0U); // Exception Mode
182 }
183
184 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
185
186 #if defined(__CC_ARM)
187 #define SUBS(Rd, Rm, Rn) __ASM("SUBS " # Rd ", " # Rm ", " # Rn)
188 #define ADDS(Rd, Rm, Rn) __ASM("ADDS " # Rd ", " # Rm ", " # Rn)
189 #elif defined( __GNUC__ )  && (defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_8M_BASE__))
190 #define SUBS(Rd, Rm, Rn) __ASM("SUB %0, %1, %2" : "=r"(Rd) : "r"(Rm), "r"(Rn) : "cc")
191 #define ADDS(Rd, Rm, Rn) __ASM("ADD %0, %1, %2" : "=r"(Rd) : "r"(Rm), "r"(Rn) : "cc")
192 #elif defined(_lint)
193 //lint -save -e(9026) allow function-like macro
194 #define SUBS(Rd, Rm, Rn) ((Rd) = (Rm) - (Rn))
195 #define ADDS(Rd, Rm, Rn) ((Rd) = (Rm) + (Rn))
196 //lint -restore
197 #else
198 #define SUBS(Rd, Rm, Rn) __ASM("SUBS %0, %1, %2" : "=r"(Rd) : "r"(Rm), "r"(Rn) : "cc")
199 #define ADDS(Rd, Rm, Rn) __ASM("ADDS %0, %1, %2" : "=r"(Rd) : "r"(Rm), "r"(Rn) : "cc")
200 #endif
201
202 /**
203 \brief Test case: TC_CoreFunc_APSR
204 \details
205 - Check if __get_APSR intrinsic is available
206 - Check if __get_xPSR intrinsic is available
207 - Check negative, zero and overflow flags
208 */
209 void TC_CoreFunc_APSR (void) {
210   uint32_t result;
211   //lint -esym(838, Rm) unused values
212   //lint -esym(438, Rm) unused values
213
214   // Check negative flag
215   int32_t Rm = 5;
216   int32_t Rn = 7;
217   SUBS(Rm, Rm, Rn);
218   result  = __get_APSR();
219   ASSERT_TRUE((result & APSR_N_Msk) == APSR_N_Msk);
220
221   Rm = 5;
222   Rn = 7;
223   SUBS(Rm, Rm, Rn);
224   result  = __get_xPSR();
225   ASSERT_TRUE((result & xPSR_N_Msk) == xPSR_N_Msk);
226
227   // Check zero and compare flag
228   Rm = 5;
229   SUBS(Rm, Rm, Rm);
230   result  = __get_APSR();
231   ASSERT_TRUE((result & APSR_Z_Msk) == APSR_Z_Msk);
232   ASSERT_TRUE((result & APSR_C_Msk) == APSR_C_Msk);
233
234   Rm = 5;
235   SUBS(Rm, Rm, Rm);
236   result  = __get_xPSR();
237   ASSERT_TRUE((result & xPSR_Z_Msk) == xPSR_Z_Msk);
238   ASSERT_TRUE((result & APSR_C_Msk) == APSR_C_Msk);
239
240   // Check overflow flag
241   Rm = 5;
242   Rn = INT32_MAX;
243   ADDS(Rm, Rm, Rn);
244   result  = __get_APSR();
245   ASSERT_TRUE((result & APSR_V_Msk) == APSR_V_Msk);
246
247   Rm = 5;
248   Rn = INT32_MAX;
249   ADDS(Rm, Rm, Rn);
250   result  = __get_xPSR();
251   ASSERT_TRUE((result & xPSR_V_Msk) == xPSR_V_Msk);
252 }
253
254 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
255 /**
256 \brief Test case: TC_CoreFunc_PSP
257 \details
258 - Check if __get_PSP and __set_PSP intrinsic can be used to manipulate process stack pointer.
259 */
260 void TC_CoreFunc_PSP (void) {
261   // don't use stack for this variables
262   static uint32_t orig;
263   static uint32_t psp;
264   static uint32_t result;
265
266   orig = __get_PSP();
267
268   psp = orig + 0x12345678U;
269   __set_PSP(psp);
270
271   result = __get_PSP();
272
273   __set_PSP(orig);
274
275   ASSERT_TRUE(result == psp);
276 }
277
278 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
279 /**
280 \brief Test case: TC_CoreFunc_MSP
281 \details
282 - Check if __get_MSP and __set_MSP intrinsic can be used to manipulate main stack pointer.
283 */
284 void TC_CoreFunc_MSP (void) {
285   // don't use stack for this variables
286   static uint32_t orig;
287   static uint32_t msp;
288   static uint32_t result;
289   static uint32_t ctrl;
290
291   ctrl = __get_CONTROL();
292   __set_CONTROL(ctrl | CONTROL_SPSEL_Msk); // switch to PSP
293
294   orig = __get_MSP();
295
296   msp = orig + 0x12345678U;
297   __set_MSP(msp);
298
299   result = __get_MSP();
300
301   __set_MSP(orig);
302
303   __set_CONTROL(ctrl);
304
305   ASSERT_TRUE(result == msp);
306 }
307
308 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
309 #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
310      (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1))    )
311
312 /**
313 \brief Test case: TC_CoreFunc_PSPLIM
314 \details
315 - Check if __get_PSPLIM and __set_PSPLIM intrinsic can be used to manipulate process stack pointer limit.
316 */
317 void TC_CoreFunc_PSPLIM (void) {
318   // don't use stack for this variables
319   static uint32_t orig;
320   static uint32_t psplim;
321   static uint32_t result;
322
323   orig = __get_PSPLIM();
324
325   psplim = orig + 0x12345678U;
326   __set_PSPLIM(psplim);
327
328   result = __get_PSPLIM();
329
330   __set_PSPLIM(orig);
331
332 #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
333      (!defined (__ARM_FEATURE_CMSE  ) || (__ARM_FEATURE_CMSE   < 3)))
334   // without main extensions, the non-secure PSPLIM is RAZ/WI
335   ASSERT_TRUE(result == 0U);
336 #else
337   ASSERT_TRUE(result == psplim);
338 #endif
339 }
340
341 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
342 /**
343 \brief Test case: TC_CoreFunc_PSPLIM_NS
344 \details
345 - Check if __TZ_get_PSPLIM_NS and __TZ_set_PSPLIM_NS intrinsic can be used to manipulate process stack pointer limit.
346 */
347 void TC_CoreFunc_PSPLIM_NS (void) {
348 #if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3))
349   uint32_t orig;
350   uint32_t psplim;
351   uint32_t result;
352
353   orig = __TZ_get_PSPLIM_NS();
354
355   psplim = orig + 0x12345678U;
356   __TZ_set_PSPLIM_NS(psplim);
357
358   result = __TZ_get_PSPLIM_NS();
359
360   __TZ_set_PSPLIM_NS(orig);
361
362 #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
363   // without main extensions, the non-secure PSPLIM is RAZ/WI
364   ASSERT_TRUE(result == 0U);
365 #else
366   ASSERT_TRUE(result == psplim);
367 #endif
368 #endif
369 }
370
371 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
372 /**
373 \brief Test case: TC_CoreFunc_MSPLIM
374 \details
375 - Check if __get_MSPLIM and __set_MSPLIM intrinsic can be used to manipulate main stack pointer limit.
376 */
377 void TC_CoreFunc_MSPLIM (void) {
378   // don't use stack for this variables
379   static uint32_t orig;
380   static uint32_t msplim;
381   static uint32_t result;
382   static uint32_t ctrl;
383
384   ctrl = __get_CONTROL();
385   __set_CONTROL(ctrl | CONTROL_SPSEL_Msk); // switch to PSP
386
387   orig = __get_MSPLIM();
388
389   msplim = orig + 0x12345678U;
390   __set_MSPLIM(msplim);
391
392   result = __get_MSPLIM();
393
394   __set_MSPLIM(orig);
395   
396   __set_CONTROL(ctrl);
397
398 #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
399      (!defined (__ARM_FEATURE_CMSE  ) || (__ARM_FEATURE_CMSE   < 3)))
400   // without main extensions, the non-secure MSPLIM is RAZ/WI
401   ASSERT_TRUE(result == 0U);
402 #else
403   ASSERT_TRUE(result == msplim);
404 #endif
405 }
406
407 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
408 /**
409 \brief Test case: TC_CoreFunc_MSPLIM_NS
410 \details
411 - Check if __TZ_get_MSPLIM_NS and __TZ_set_MSPLIM_NS intrinsic can be used to manipulate process stack pointer limit.
412 */
413 void TC_CoreFunc_MSPLIM_NS (void) {
414 #if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3))
415   uint32_t orig;
416   uint32_t msplim;
417   uint32_t result;
418
419   orig = __TZ_get_MSPLIM_NS();
420
421   msplim = orig + 0x12345678U;
422   __TZ_set_MSPLIM_NS(msplim);
423
424   result = __TZ_get_MSPLIM_NS();
425
426   __TZ_set_MSPLIM_NS(orig);
427
428 #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
429   // without main extensions, the non-secure MSPLIM is RAZ/WI
430   ASSERT_TRUE(result == 0U);
431 #else
432   ASSERT_TRUE(result == msplim);
433 #endif
434 #endif
435 }
436
437 #endif
438
439 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
440 /**
441 \brief Test case: TC_CoreFunc_PRIMASK
442 \details
443 - Check if __get_PRIMASK and __set_PRIMASK intrinsic can be used to manipulate PRIMASK.
444 - Check if __enable_irq and __disable_irq are reflected in PRIMASK.
445 */
446 void TC_CoreFunc_PRIMASK (void) {
447   uint32_t orig = __get_PRIMASK();
448
449   // toggle primask
450   uint32_t primask = (orig & ~0x01U) | (~orig & 0x01U);
451
452   __set_PRIMASK(primask);
453   uint32_t result = __get_PRIMASK();
454
455   ASSERT_TRUE(result == primask);
456
457   __disable_irq();
458   result = __get_PRIMASK();
459   ASSERT_TRUE((result & 0x01U) == 1U);
460
461   __enable_irq();
462   result = __get_PRIMASK();
463   ASSERT_TRUE((result & 0x01U) == 0U);
464
465   __disable_irq();
466   result = __get_PRIMASK();
467   ASSERT_TRUE((result & 0x01U) == 1U);
468
469   __set_PRIMASK(orig);
470 }
471
472 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
473 #if ((defined (__ARM_ARCH_7M__      ) && (__ARM_ARCH_7M__      == 1)) || \
474      (defined (__ARM_ARCH_7EM__     ) && (__ARM_ARCH_7EM__     == 1)) || \
475      (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))    )
476
477 /**
478 \brief Test case: TC_CoreFunc_FAULTMASK
479 \details
480 - Check if __get_FAULTMASK and __set_FAULTMASK intrinsic can be used to manipulate FAULTMASK.
481 - Check if __enable_fault_irq and __disable_fault_irq are reflected in FAULTMASK.
482 */
483 void TC_CoreFunc_FAULTMASK (void) {
484   uint32_t orig = __get_FAULTMASK();
485
486   // toggle faultmask
487   uint32_t faultmask = (orig & ~0x01U) | (~orig & 0x01U);
488
489   __set_FAULTMASK(faultmask);
490   uint32_t result = __get_FAULTMASK();
491
492   ASSERT_TRUE(result == faultmask);
493
494   __disable_fault_irq();
495   result = __get_FAULTMASK();
496   ASSERT_TRUE((result & 0x01U) == 1U);
497
498   __enable_fault_irq();
499   result = __get_FAULTMASK();
500   ASSERT_TRUE((result & 0x01U) == 0U);
501
502   __disable_fault_irq();
503   result = __get_FAULTMASK();
504   ASSERT_TRUE((result & 0x01U) == 1U);
505
506   __set_FAULTMASK(orig);
507 }
508
509 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
510 /**
511 \brief Test case: TC_CoreFunc_BASEPRI
512 \details
513 - Check if __get_BASEPRI and __set_BASEPRI intrinsic can be used to manipulate BASEPRI.
514 - Check if __set_BASEPRI_MAX intrinsic can be used to manipulate BASEPRI.
515 */
516 void TC_CoreFunc_BASEPRI(void) {
517   uint32_t orig = __get_BASEPRI();
518
519   uint32_t basepri = ~orig & 0x80U;
520   __set_BASEPRI(basepri);
521   uint32_t result = __get_BASEPRI();
522
523   ASSERT_TRUE(result == basepri);
524
525   __set_BASEPRI(orig);
526
527   __set_BASEPRI_MAX(basepri);
528   result = __get_BASEPRI();
529
530   ASSERT_TRUE(result == basepri);
531 }
532 #endif
533
534 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
535 #if ((defined (__ARM_ARCH_7EM__     ) && (__ARM_ARCH_7EM__     == 1)) || \
536      (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))    )
537
538 /**
539 \brief Test case: TC_CoreFunc_BASEPRI
540 \details
541 - Check if __get_FPSCR and __set_FPSCR intrinsics can be used
542 */
543 void TC_CoreFunc_FPSCR(void) {
544   uint32_t fpscr = __get_FPSCR();
545   __ISB();
546   __DSB();
547
548   __set_FPSCR(~fpscr);
549   __ISB();
550   __DSB();
551
552   uint32_t result = __get_FPSCR();
553
554   __set_FPSCR(fpscr);
555
556 #if (defined (__FPU_USED   ) && (__FPU_USED    == 1U))
557   ASSERT_TRUE(result != fpscr);
558 #else
559   (void)result;
560 #endif
561 }
562 #endif