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