CV_CoreFunc.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  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__) || defined(__ARM_ARCH_8M_BASE__))
  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 main 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. #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
  204. (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
  205. /**
  206. \brief Test case: TC_CoreFunc_PSPLIM
  207. \details
  208. - Check if __get_PSPLIM and __set_PSPLIM instrinsic can be used to manipulate process stack pointer limit.
  209. */
  210. void TC_CoreFunc_PSPLIM (void) {
  211. // don't use stack for this variables
  212. static uint32_t orig;
  213. static uint32_t psplim;
  214. static uint32_t result;
  215. orig = __get_PSPLIM();
  216. psplim = orig + 0x12345678U;
  217. __set_PSPLIM(psplim);
  218. result = __get_PSPLIM();
  219. __set_PSPLIM(orig);
  220. #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
  221. (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
  222. // without main extensions, the non-secure PSPLIM is RAZ/WI
  223. ASSERT_TRUE(result == 0U);
  224. #else
  225. ASSERT_TRUE(result == psplim);
  226. #endif
  227. }
  228. /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
  229. /**
  230. \brief Test case: TC_CoreFunc_PSPLIM_NS
  231. \details
  232. - Check if __TZ_get_PSPLIM_NS and __TZ_set_PSPLIM_NS instrinsic can be used to manipulate process stack pointer limit.
  233. */
  234. void TC_CoreFunc_PSPLIM_NS (void) {
  235. #if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3))
  236. uint32_t orig;
  237. uint32_t psplim;
  238. uint32_t result;
  239. orig = __TZ_get_PSPLIM_NS();
  240. psplim = orig + 0x12345678U;
  241. __TZ_set_PSPLIM_NS(psplim);
  242. result = __TZ_get_PSPLIM_NS();
  243. __TZ_set_PSPLIM_NS(orig);
  244. #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
  245. // without main extensions, the non-secure PSPLIM is RAZ/WI
  246. ASSERT_TRUE(result == 0U);
  247. #else
  248. ASSERT_TRUE(result == psplim);
  249. #endif
  250. #endif
  251. }
  252. /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
  253. /**
  254. \brief Test case: TC_CoreFunc_MSPLIM
  255. \details
  256. - Check if __get_MSPLIM and __set_MSPLIM instrinsic can be used to manipulate main stack pointer limit.
  257. */
  258. void TC_CoreFunc_MSPLIM (void) {
  259. // don't use stack for this variables
  260. static uint32_t orig;
  261. static uint32_t msplim;
  262. static uint32_t result;
  263. static uint32_t ctrl;
  264. ctrl = __get_CONTROL();
  265. __set_CONTROL(ctrl | CONTROL_SPSEL_Msk); // switch to PSP
  266. orig = __get_MSPLIM();
  267. msplim = orig + 0x12345678U;
  268. __set_MSPLIM(msplim);
  269. result = __get_MSPLIM();
  270. __set_MSPLIM(orig);
  271. __set_CONTROL(ctrl);
  272. #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
  273. (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
  274. // without main extensions, the non-secure MSPLIM is RAZ/WI
  275. ASSERT_TRUE(result == 0U);
  276. #else
  277. ASSERT_TRUE(result == msplim);
  278. #endif
  279. }
  280. #endif
  281. /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
  282. /**
  283. \brief Test case: TC_CoreFunc_MSPLIM_NS
  284. \details
  285. - Check if __TZ_get_MSPLIM_NS and __TZ_set_MSPLIM_NS instrinsic can be used to manipulate process stack pointer limit.
  286. */
  287. void TC_CoreFunc_MSPLIM_NS (void) {
  288. #if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3))
  289. uint32_t orig;
  290. uint32_t msplim;
  291. uint32_t result;
  292. orig = __TZ_get_MSPLIM_NS();
  293. msplim = orig + 0x12345678U;
  294. __TZ_set_MSPLIM_NS(msplim);
  295. result = __TZ_get_MSPLIM_NS();
  296. __TZ_set_MSPLIM_NS(orig);
  297. #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
  298. // without main extensions, the non-secure PSPLIM is RAZ/WI
  299. ASSERT_TRUE(result == 0U);
  300. #else
  301. ASSERT_TRUE(result == msplim);
  302. #endif
  303. #endif
  304. }
  305. /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
  306. /**
  307. \brief Test case: TC_CoreFunc_PRIMASK
  308. \details
  309. - Check if __get_PRIMASK and __set_PRIMASK instrinsic can be used to manipulate PRIMASK.
  310. - Check if __enable_irq and __disable_irq are reflected in PRIMASK.
  311. */
  312. void TC_CoreFunc_PRIMASK (void) {
  313. uint32_t orig = __get_PRIMASK();
  314. // toggle primask
  315. uint32_t primask = (orig & ~0x01U) | (~orig & 0x01U);
  316. __set_PRIMASK(primask);
  317. uint32_t result = __get_PRIMASK();
  318. ASSERT_TRUE(result == primask);
  319. __disable_irq();
  320. result = __get_PRIMASK();
  321. ASSERT_TRUE((result & 0x01U) == 1U);
  322. __enable_irq();
  323. result = __get_PRIMASK();
  324. ASSERT_TRUE((result & 0x01U) == 0U);
  325. __disable_irq();
  326. result = __get_PRIMASK();
  327. ASSERT_TRUE((result & 0x01U) == 1U);
  328. __set_PRIMASK(orig);
  329. }
  330. /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
  331. #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
  332. (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
  333. (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) )
  334. /**
  335. \brief Test case: TC_CoreFunc_FAULTMASK
  336. \details
  337. - Check if __get_FAULTMASK and __set_FAULTMASK instrinsic can be used to manipulate FAULTMASK.
  338. - Check if __enable_fault_irq and __disable_fault_irq are reflected in FAULTMASK.
  339. */
  340. void TC_CoreFunc_FAULTMASK (void) {
  341. uint32_t orig = __get_FAULTMASK();
  342. // toggle faultmask
  343. uint32_t faultmask = (orig & ~0x01U) | (~orig & 0x01U);
  344. __set_FAULTMASK(faultmask);
  345. uint32_t result = __get_FAULTMASK();
  346. ASSERT_TRUE(result == faultmask);
  347. __disable_fault_irq();
  348. result = __get_FAULTMASK();
  349. ASSERT_TRUE((result & 0x01U) == 1U);
  350. __enable_fault_irq();
  351. result = __get_FAULTMASK();
  352. ASSERT_TRUE((result & 0x01U) == 0U);
  353. __disable_fault_irq();
  354. result = __get_FAULTMASK();
  355. ASSERT_TRUE((result & 0x01U) == 1U);
  356. __set_FAULTMASK(orig);
  357. }
  358. /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
  359. /**
  360. \brief Test case: TC_CoreFunc_BASEPRI
  361. \details
  362. - Check if __get_BASEPRI and __set_BASEPRI instrinsic can be used to manipulate BASEPRI.
  363. - Check if __set_BASEPRI_MAX instrinsic can be used to manipulate BASEPRI.
  364. */
  365. void TC_CoreFunc_BASEPRI(void) {
  366. uint32_t orig = __get_BASEPRI();
  367. uint32_t basepri = ~orig & 0x80U;
  368. __set_BASEPRI(basepri);
  369. uint32_t result = __get_BASEPRI();
  370. ASSERT_TRUE(result == basepri);
  371. __set_BASEPRI(orig);
  372. __set_BASEPRI_MAX(basepri);
  373. result = __get_BASEPRI();
  374. ASSERT_TRUE(result == basepri);
  375. }
  376. #endif
  377. /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
  378. #if ((defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
  379. (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) )
  380. /**
  381. \brief Test case: TC_CoreFunc_BASEPRI
  382. \details
  383. - Check if __get_FPSCR and __set_FPSCR intrinsics can be used
  384. */
  385. void TC_CoreFunc_FPSCR(void) {
  386. uint32_t fpscr = __get_FPSCR();
  387. __ISB();
  388. __DSB();
  389. __set_FPSCR(~fpscr);
  390. __ISB();
  391. __DSB();
  392. uint32_t result = __get_FPSCR();
  393. __set_FPSCR(fpscr);
  394. #if (defined (__FPU_USED ) && (__FPU_USED == 1U))
  395. ASSERT_TRUE(result != fpscr);
  396. #else
  397. (void)result;
  398. #endif
  399. }
  400. #endif