CV_CoreFunc.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  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. #include "CV_Framework.h"
  8. #include "cmsis_cv.h"
  9. /*-----------------------------------------------------------------------------
  10. * Test implementation
  11. *----------------------------------------------------------------------------*/
  12. static volatile uint32_t irqTaken = 0U;
  13. static void TC_CoreFunc_EnDisIRQIRQHandler(void) {
  14. ++irqTaken;
  15. }
  16. static volatile uint32_t irqIPSR = 0U;
  17. static volatile uint32_t irqXPSR = 0U;
  18. static void TC_CoreFunc_IPSR_IRQHandler(void) {
  19. irqIPSR = __get_IPSR();
  20. irqXPSR = __get_xPSR();
  21. }
  22. /*-----------------------------------------------------------------------------
  23. * Test cases
  24. *----------------------------------------------------------------------------*/
  25. /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
  26. /**
  27. \brief Test case: TC_CoreFunc_EnDisIRQ
  28. \details
  29. - Check if __disable_irq() and __enable_irq() have expected behaviour.
  30. */
  31. void TC_CoreFunc_EnDisIRQ (void)
  32. {
  33. __disable_irq();
  34. NVIC_EnableIRQ(WDT_IRQn);
  35. NVIC_ClearPendingIRQ(WDT_IRQn);
  36. TST_IRQHandler = TC_CoreFunc_EnDisIRQIRQHandler;
  37. irqTaken = 0U;
  38. NVIC_SetPendingIRQ(WDT_IRQn);
  39. for(uint32_t i = 10U; i > 0U; --i) {}
  40. // Interrupt is not taken
  41. ASSERT_TRUE(irqTaken == 0U);
  42. __enable_irq();
  43. for(uint32_t i = 10U; i > 0U; --i) {}
  44. // Interrupt was taken
  45. ASSERT_TRUE(irqTaken == 1U);
  46. __disable_irq();
  47. NVIC_DisableIRQ(WDT_IRQn);
  48. }
  49. /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
  50. /**
  51. \brief Test case: TC_CoreFunc_GetCtrl
  52. \details
  53. - Check if __set_CONTROL and __get_CONTROL() sets/gets control register
  54. */
  55. void TC_CoreFunc_Control (void) {
  56. // don't use stack for this variables
  57. static uint32_t orig;
  58. static uint32_t ctrl;
  59. static uint32_t result;
  60. orig = __get_CONTROL();
  61. ctrl = orig;
  62. result = UINT32_MAX;
  63. #ifdef CONTROL_SPSEL_Msk
  64. // toggle SPSEL
  65. ctrl = (ctrl & ~CONTROL_SPSEL_Msk) | (~ctrl & CONTROL_SPSEL_Msk);
  66. #endif
  67. __set_CONTROL(ctrl);
  68. __ISB();
  69. result = __get_CONTROL();
  70. __set_CONTROL(orig);
  71. __ISB();
  72. ASSERT_TRUE(result == ctrl);
  73. ASSERT_TRUE(__get_CONTROL() == orig);
  74. }
  75. /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
  76. /**
  77. \brief Test case: TC_CoreFunc_IPSR
  78. \details
  79. - Check if __get_IPSR instrinsic is available
  80. - Check if __get_xPSR instrinsic is available
  81. - Result differentiates between thread and exception modes
  82. */
  83. void TC_CoreFunc_IPSR (void) {
  84. uint32_t result = __get_IPSR();
  85. ASSERT_TRUE(result == 0U); // Thread Mode
  86. result = __get_xPSR();
  87. ASSERT_TRUE((result & xPSR_ISR_Msk) == 0U); // Thread Mode
  88. TST_IRQHandler = TC_CoreFunc_IPSR_IRQHandler;
  89. irqIPSR = 0U;
  90. irqXPSR = 0U;
  91. NVIC_ClearPendingIRQ(WDT_IRQn);
  92. NVIC_EnableIRQ(WDT_IRQn);
  93. __enable_irq();
  94. NVIC_SetPendingIRQ(WDT_IRQn);
  95. for(uint32_t i = 10U; i > 0U; --i) {}
  96. __disable_irq();
  97. NVIC_DisableIRQ(WDT_IRQn);
  98. ASSERT_TRUE(irqIPSR != 0U); // Exception Mode
  99. ASSERT_TRUE((irqXPSR & xPSR_ISR_Msk) != 0U); // Exception Mode
  100. }
  101. /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
  102. #if defined(__CC_ARM)
  103. #define SUBS(Rd, Rm, Rn) __ASM("SUBS " # Rd ", " # Rm ", " # Rn)
  104. #define ADDS(Rd, Rm, Rn) __ASM("ADDS " # Rd ", " # Rm ", " # Rn)
  105. #elif defined( __GNUC__ ) && defined(__ARM_ARCH_6M__)
  106. #define SUBS(Rd, Rm, Rn) __ASM("SUB %0, %1, %2" : "=r"(Rd) : "r"(Rm), "r"(Rn) : "cc")
  107. #define ADDS(Rd, Rm, Rn) __ASM("ADD %0, %1, %2" : "=r"(Rd) : "r"(Rm), "r"(Rn) : "cc")
  108. #elif defined(_lint)
  109. //lint -save -e(9026) allow function-like macro
  110. #define SUBS(Rd, Rm, Rn) ((Rd) = (Rm) - (Rn))
  111. #define ADDS(Rd, Rm, Rn) ((Rd) = (Rm) + (Rn))
  112. //lint -restore
  113. #else
  114. #define SUBS(Rd, Rm, Rn) __ASM("SUBS %0, %1, %2" : "=r"(Rd) : "r"(Rm), "r"(Rn) : "cc")
  115. #define ADDS(Rd, Rm, Rn) __ASM("ADDS %0, %1, %2" : "=r"(Rd) : "r"(Rm), "r"(Rn) : "cc")
  116. #endif
  117. /**
  118. \brief Test case: TC_CoreFunc_APSR
  119. \details
  120. - Check if __get_APSR instrinsic is available
  121. - Check if __get_xPSR instrinsic is available
  122. - Check negative, zero and overflow flags
  123. */
  124. void TC_CoreFunc_APSR (void) {
  125. uint32_t result;
  126. //lint -esym(838, Rm) unused values
  127. //lint -esym(438, Rm) unused values
  128. // Check negative flag
  129. int32_t Rm = 5;
  130. int32_t Rn = 7;
  131. SUBS(Rm, Rm, Rn);
  132. result = __get_APSR();
  133. ASSERT_TRUE((result & APSR_N_Msk) == APSR_N_Msk);
  134. Rm = 5;
  135. Rn = 7;
  136. SUBS(Rm, Rm, Rn);
  137. result = __get_xPSR();
  138. ASSERT_TRUE((result & xPSR_N_Msk) == xPSR_N_Msk);
  139. // Check zero and compare flag
  140. Rm = 5;
  141. SUBS(Rm, Rm, Rm);
  142. result = __get_APSR();
  143. ASSERT_TRUE((result & APSR_Z_Msk) == APSR_Z_Msk);
  144. ASSERT_TRUE((result & APSR_C_Msk) == APSR_C_Msk);
  145. Rm = 5;
  146. SUBS(Rm, Rm, Rm);
  147. result = __get_xPSR();
  148. ASSERT_TRUE((result & xPSR_Z_Msk) == xPSR_Z_Msk);
  149. ASSERT_TRUE((result & APSR_C_Msk) == APSR_C_Msk);
  150. // Check overflow flag
  151. Rm = 5;
  152. Rn = INT32_MAX;
  153. ADDS(Rm, Rm, Rn);
  154. result = __get_APSR();
  155. ASSERT_TRUE((result & APSR_V_Msk) == APSR_V_Msk);
  156. Rm = 5;
  157. Rn = INT32_MAX;
  158. ADDS(Rm, Rm, Rn);
  159. result = __get_xPSR();
  160. ASSERT_TRUE((result & xPSR_V_Msk) == xPSR_V_Msk);
  161. }
  162. /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
  163. /**
  164. \brief Test case: TC_CoreFunc_PSP
  165. \details
  166. - Check if __get_PSP and __set_PSP instrinsic can be used to manipulate process stack pointer.
  167. */
  168. void TC_CoreFunc_PSP (void) {
  169. // don't use stack for this variables
  170. static uint32_t orig;
  171. static uint32_t psp;
  172. static uint32_t result;
  173. orig = __get_PSP();
  174. psp = orig + 0x12345678U;
  175. __set_PSP(psp);
  176. result = __get_PSP();
  177. __set_PSP(orig);
  178. ASSERT_TRUE(result == psp);
  179. }
  180. /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
  181. /**
  182. \brief Test case: TC_CoreFunc_MSP
  183. \details
  184. - Check if __get_MSP and __set_MSP instrinsic can be used to manipulate process stack pointer.
  185. */
  186. void TC_CoreFunc_MSP (void) {
  187. // don't use stack for this variables
  188. static uint32_t orig;
  189. static uint32_t msp;
  190. static uint32_t result;
  191. static uint32_t ctrl;
  192. ctrl = __get_CONTROL();
  193. __set_CONTROL(ctrl | CONTROL_SPSEL_Msk); // switch to PSP
  194. orig = __get_MSP();
  195. msp = orig + 0x12345678U;
  196. __set_MSP(msp);
  197. result = __get_MSP();
  198. __set_MSP(orig);
  199. __set_CONTROL(ctrl);
  200. ASSERT_TRUE(result == msp);
  201. }
  202. /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
  203. /**
  204. \brief Test case: TC_CoreFunc_PRIMASK
  205. \details
  206. - Check if __get_PRIMASK and __set_PRIMASK instrinsic can be used to manipulate PRIMASK.
  207. - Check if __enable_irq and __disable_irq are reflected in PRIMASK.
  208. */
  209. void TC_CoreFunc_PRIMASK (void) {
  210. uint32_t orig = __get_PRIMASK();
  211. // toggle primask
  212. uint32_t primask = (orig & ~0x01U) | (~orig & 0x01U);
  213. __set_PRIMASK(primask);
  214. uint32_t result = __get_PRIMASK();
  215. ASSERT_TRUE(result == primask);
  216. __disable_irq();
  217. result = __get_PRIMASK();
  218. ASSERT_TRUE((result & 0x01U) == 1U);
  219. __enable_irq();
  220. result = __get_PRIMASK();
  221. ASSERT_TRUE((result & 0x01U) == 0U);
  222. __disable_irq();
  223. result = __get_PRIMASK();
  224. ASSERT_TRUE((result & 0x01U) == 1U);
  225. __set_PRIMASK(orig);
  226. }
  227. /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
  228. #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
  229. (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
  230. (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) )
  231. /**
  232. \brief Test case: TC_CoreFunc_FAULTMASK
  233. \details
  234. - Check if __get_FAULTMASK and __set_FAULTMASK instrinsic can be used to manipulate FAULTMASK.
  235. - Check if __enable_fault_irq and __disable_fault_irq are reflected in FAULTMASK.
  236. */
  237. void TC_CoreFunc_FAULTMASK (void) {
  238. uint32_t orig = __get_FAULTMASK();
  239. // toggle faultmask
  240. uint32_t faultmask = (orig & ~0x01U) | (~orig & 0x01U);
  241. __set_FAULTMASK(faultmask);
  242. uint32_t result = __get_FAULTMASK();
  243. ASSERT_TRUE(result == faultmask);
  244. __disable_fault_irq();
  245. result = __get_FAULTMASK();
  246. ASSERT_TRUE((result & 0x01U) == 1U);
  247. __enable_fault_irq();
  248. result = __get_FAULTMASK();
  249. ASSERT_TRUE((result & 0x01U) == 0U);
  250. __disable_fault_irq();
  251. result = __get_FAULTMASK();
  252. ASSERT_TRUE((result & 0x01U) == 1U);
  253. __set_FAULTMASK(orig);
  254. }
  255. /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
  256. /**
  257. \brief Test case: TC_CoreFunc_BASEPRI
  258. \details
  259. - Check if __get_BASEPRI and __set_BASEPRI instrinsic can be used to manipulate BASEPRI.
  260. - Check if __set_BASEPRI_MAX instrinsic can be used to manipulate BASEPRI.
  261. */
  262. void TC_CoreFunc_BASEPRI(void) {
  263. uint32_t orig = __get_BASEPRI();
  264. uint32_t basepri = ~orig & 0x80U;
  265. __set_BASEPRI(basepri);
  266. uint32_t result = __get_BASEPRI();
  267. ASSERT_TRUE(result == basepri);
  268. __set_BASEPRI(orig);
  269. __set_BASEPRI_MAX(basepri);
  270. result = __get_BASEPRI();
  271. ASSERT_TRUE(result == basepri);
  272. }
  273. #endif
  274. /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
  275. #if ((defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
  276. (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) )
  277. /**
  278. \brief Test case: TC_CoreFunc_BASEPRI
  279. \details
  280. - Check if __get_FPSCR and __set_FPSCR intrinsics can be used
  281. */
  282. void TC_CoreFunc_FPSCR(void) {
  283. uint32_t fpscr = __get_FPSCR();
  284. __ISB();
  285. __DSB();
  286. __set_FPSCR(~fpscr);
  287. __ISB();
  288. __DSB();
  289. uint32_t result = __get_FPSCR();
  290. __set_FPSCR(fpscr);
  291. #if (defined (__FPU_USED ) && (__FPU_USED == 1U))
  292. ASSERT_TRUE(result != fpscr);
  293. #endif
  294. }
  295. #endif