]> begriffs open source - cmsis/blob - CMSIS/CoreValidation/Source/CV_CoreFunc.c
CoreValidation: Fixed Validation test for Cortex-M33 without DSP on GCC.
[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 process 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 /**
258 \brief Test case: TC_CoreFunc_PRIMASK
259 \details
260 - Check if __get_PRIMASK and __set_PRIMASK instrinsic can be used to manipulate PRIMASK.
261 - Check if __enable_irq and __disable_irq are reflected in PRIMASK.
262 */
263 void TC_CoreFunc_PRIMASK (void) {  
264   uint32_t orig = __get_PRIMASK();
265   
266   // toggle primask
267   uint32_t primask = (orig & ~0x01U) | (~orig & 0x01U);
268   
269   __set_PRIMASK(primask);
270   uint32_t result = __get_PRIMASK();
271     
272   ASSERT_TRUE(result == primask);
273   
274   __disable_irq();
275   result = __get_PRIMASK();
276   ASSERT_TRUE((result & 0x01U) == 1U);
277
278   __enable_irq();
279   result = __get_PRIMASK();
280   ASSERT_TRUE((result & 0x01U) == 0U);
281
282   __disable_irq();
283   result = __get_PRIMASK();
284   ASSERT_TRUE((result & 0x01U) == 1U);
285
286   __set_PRIMASK(orig); 
287 }
288
289 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
290 #if ((defined (__ARM_ARCH_7M__      ) && (__ARM_ARCH_7M__      == 1)) || \
291      (defined (__ARM_ARCH_7EM__     ) && (__ARM_ARCH_7EM__     == 1)) || \
292      (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))    )
293
294 /**
295 \brief Test case: TC_CoreFunc_FAULTMASK
296 \details
297 - Check if __get_FAULTMASK and __set_FAULTMASK instrinsic can be used to manipulate FAULTMASK.
298 - Check if __enable_fault_irq and __disable_fault_irq are reflected in FAULTMASK.
299 */
300 void TC_CoreFunc_FAULTMASK (void) {  
301   uint32_t orig = __get_FAULTMASK();
302   
303   // toggle faultmask
304   uint32_t faultmask = (orig & ~0x01U) | (~orig & 0x01U);
305   
306   __set_FAULTMASK(faultmask);
307   uint32_t result = __get_FAULTMASK();
308     
309   ASSERT_TRUE(result == faultmask);
310   
311   __disable_fault_irq();
312   result = __get_FAULTMASK();
313   ASSERT_TRUE((result & 0x01U) == 1U);
314
315   __enable_fault_irq();
316   result = __get_FAULTMASK();
317   ASSERT_TRUE((result & 0x01U) == 0U);
318
319   __disable_fault_irq();
320   result = __get_FAULTMASK();
321   ASSERT_TRUE((result & 0x01U) == 1U);
322
323   __set_FAULTMASK(orig);
324 }
325
326 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
327 /**
328 \brief Test case: TC_CoreFunc_BASEPRI
329 \details
330 - Check if __get_BASEPRI and __set_BASEPRI instrinsic can be used to manipulate BASEPRI.
331 - Check if __set_BASEPRI_MAX instrinsic can be used to manipulate BASEPRI.
332 */
333 void TC_CoreFunc_BASEPRI(void) {  
334   uint32_t orig = __get_BASEPRI();
335   
336   uint32_t basepri = ~orig & 0x80U;
337   __set_BASEPRI(basepri);
338   uint32_t result = __get_BASEPRI();
339   
340   ASSERT_TRUE(result == basepri);
341   
342   __set_BASEPRI(orig);
343
344   __set_BASEPRI_MAX(basepri);
345   result = __get_BASEPRI();
346   
347   ASSERT_TRUE(result == basepri);
348 }
349 #endif
350
351 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
352 #if ((defined (__ARM_ARCH_7EM__     ) && (__ARM_ARCH_7EM__     == 1)) || \
353      (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))    )
354
355 /**
356 \brief Test case: TC_CoreFunc_BASEPRI
357 \details
358 - Check if __get_FPSCR and __set_FPSCR intrinsics can be used
359 */
360 void TC_CoreFunc_FPSCR(void) {  
361   uint32_t fpscr = __get_FPSCR();
362   __ISB();
363   __DSB();
364
365   __set_FPSCR(~fpscr);
366   __ISB();
367   __DSB();
368
369   uint32_t result = __get_FPSCR();
370     
371   __set_FPSCR(fpscr);
372
373 #if (defined (__FPU_USED   ) && (__FPU_USED    == 1U))
374   ASSERT_TRUE(result != fpscr);
375 #else
376   (void)result;
377 #endif
378 }
379 #endif