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