fsl_common_arm.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /*
  2. * Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
  3. * Copyright 2016-2021 NXP
  4. * All rights reserved.
  5. *
  6. * SPDX-License-Identifier: BSD-3-Clause
  7. */
  8. #include "fsl_common.h"
  9. /* Component ID definition, used by tools. */
  10. #ifndef FSL_COMPONENT_ID
  11. #define FSL_COMPONENT_ID "platform.drivers.common_arm"
  12. #endif
  13. #ifndef __GIC_PRIO_BITS
  14. #if defined(ENABLE_RAM_VECTOR_TABLE)
  15. uint32_t InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler)
  16. {
  17. #ifdef __VECTOR_TABLE
  18. #undef __VECTOR_TABLE
  19. #endif
  20. /* Addresses for VECTOR_TABLE and VECTOR_RAM come from the linker file */
  21. #if defined(__CC_ARM) || defined(__ARMCC_VERSION)
  22. extern uint32_t Image$$VECTOR_ROM$$Base[];
  23. extern uint32_t Image$$VECTOR_RAM$$Base[];
  24. extern uint32_t Image$$RW_m_data$$Base[];
  25. #define __VECTOR_TABLE Image$$VECTOR_ROM$$Base
  26. #define __VECTOR_RAM Image$$VECTOR_RAM$$Base
  27. #define __RAM_VECTOR_TABLE_SIZE (((uint32_t)Image$$RW_m_data$$Base - (uint32_t)Image$$VECTOR_RAM$$Base))
  28. #elif defined(__ICCARM__)
  29. extern uint32_t __RAM_VECTOR_TABLE_SIZE[];
  30. extern uint32_t __VECTOR_TABLE[];
  31. extern uint32_t __VECTOR_RAM[];
  32. #elif defined(__GNUC__)
  33. extern uint32_t __VECTOR_TABLE[];
  34. extern uint32_t __VECTOR_RAM[];
  35. extern uint32_t __RAM_VECTOR_TABLE_SIZE_BYTES[];
  36. uint32_t __RAM_VECTOR_TABLE_SIZE = (uint32_t)(__RAM_VECTOR_TABLE_SIZE_BYTES);
  37. #endif /* defined(__CC_ARM) || defined(__ARMCC_VERSION) */
  38. uint32_t n;
  39. uint32_t ret;
  40. uint32_t irqMaskValue;
  41. irqMaskValue = DisableGlobalIRQ();
  42. if (SCB->VTOR != (uint32_t)__VECTOR_RAM)
  43. {
  44. /* Copy the vector table from ROM to RAM */
  45. for (n = 0; n < ((uint32_t)__RAM_VECTOR_TABLE_SIZE) / sizeof(uint32_t); n++)
  46. {
  47. __VECTOR_RAM[n] = __VECTOR_TABLE[n];
  48. }
  49. /* Point the VTOR to the position of vector table */
  50. SCB->VTOR = (uint32_t)__VECTOR_RAM;
  51. }
  52. ret = __VECTOR_RAM[(int32_t)irq + 16];
  53. /* make sure the __VECTOR_RAM is noncachable */
  54. __VECTOR_RAM[(int32_t)irq + 16] = irqHandler;
  55. EnableGlobalIRQ(irqMaskValue);
  56. return ret;
  57. }
  58. #endif /* ENABLE_RAM_VECTOR_TABLE. */
  59. #endif /* __GIC_PRIO_BITS. */
  60. #if (defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0))
  61. /*
  62. * When FSL_FEATURE_POWERLIB_EXTEND is defined to non-zero value,
  63. * powerlib should be used instead of these functions.
  64. */
  65. #if !(defined(FSL_FEATURE_POWERLIB_EXTEND) && (FSL_FEATURE_POWERLIB_EXTEND != 0))
  66. /*
  67. * When the SYSCON STARTER registers are discontinuous, these functions are
  68. * implemented in fsl_power.c.
  69. */
  70. #if !(defined(FSL_FEATURE_SYSCON_STARTER_DISCONTINUOUS) && FSL_FEATURE_SYSCON_STARTER_DISCONTINUOUS)
  71. void EnableDeepSleepIRQ(IRQn_Type interrupt)
  72. {
  73. uint32_t intNumber = (uint32_t)interrupt;
  74. uint32_t index = 0;
  75. while (intNumber >= 32u)
  76. {
  77. index++;
  78. intNumber -= 32u;
  79. }
  80. SYSCON->STARTERSET[index] = 1UL << intNumber;
  81. (void)EnableIRQ(interrupt); /* also enable interrupt at NVIC */
  82. }
  83. void DisableDeepSleepIRQ(IRQn_Type interrupt)
  84. {
  85. uint32_t intNumber = (uint32_t)interrupt;
  86. (void)DisableIRQ(interrupt); /* also disable interrupt at NVIC */
  87. uint32_t index = 0;
  88. while (intNumber >= 32u)
  89. {
  90. index++;
  91. intNumber -= 32u;
  92. }
  93. SYSCON->STARTERCLR[index] = 1UL << intNumber;
  94. }
  95. #endif /* FSL_FEATURE_SYSCON_STARTER_DISCONTINUOUS */
  96. #endif /* FSL_FEATURE_POWERLIB_EXTEND */
  97. #endif /* FSL_FEATURE_SOC_SYSCON_COUNT */
  98. #if defined(SDK_DELAY_USE_DWT) && defined(DWT)
  99. /* Use WDT. */
  100. static void enableCpuCycleCounter(void)
  101. {
  102. /* Make sure the DWT trace fucntion is enabled. */
  103. if (CoreDebug_DEMCR_TRCENA_Msk != (CoreDebug_DEMCR_TRCENA_Msk & CoreDebug->DEMCR))
  104. {
  105. CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
  106. }
  107. /* CYCCNT not supported on this device. */
  108. assert(DWT_CTRL_NOCYCCNT_Msk != (DWT->CTRL & DWT_CTRL_NOCYCCNT_Msk));
  109. /* Read CYCCNT directly if CYCCENT has already been enabled, otherwise enable CYCCENT first. */
  110. if (DWT_CTRL_CYCCNTENA_Msk != (DWT_CTRL_CYCCNTENA_Msk & DWT->CTRL))
  111. {
  112. DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
  113. }
  114. }
  115. static uint32_t getCpuCycleCount(void)
  116. {
  117. return DWT->CYCCNT;
  118. }
  119. #else /* defined(SDK_DELAY_USE_DWT) && defined(DWT) */
  120. /* Use software loop. */
  121. #if defined(__CC_ARM) /* This macro is arm v5 specific */
  122. /* clang-format off */
  123. __ASM static void DelayLoop(uint32_t count)
  124. {
  125. loop
  126. SUBS R0, R0, #1
  127. CMP R0, #0
  128. BNE loop
  129. BX LR
  130. }
  131. /* clang-format on */
  132. #elif defined(__ARMCC_VERSION) || defined(__ICCARM__) || defined(__GNUC__)
  133. /* Cortex-M0 has a smaller instruction set, SUBS isn't supported in thumb-16 mode reported from __GNUC__ compiler,
  134. * use SUB and CMP here for compatibility */
  135. static void DelayLoop(uint32_t count)
  136. {
  137. __ASM volatile(" MOV R0, %0" : : "r"(count));
  138. __ASM volatile(
  139. "loop: \n"
  140. #if defined(__GNUC__) && !defined(__ARMCC_VERSION)
  141. " SUB R0, R0, #1 \n"
  142. #else
  143. " SUBS R0, R0, #1 \n"
  144. #endif
  145. " CMP R0, #0 \n"
  146. " BNE loop \n"
  147. :
  148. :
  149. : "r0");
  150. }
  151. #endif /* defined(__CC_ARM) */
  152. #endif /* defined(SDK_DELAY_USE_DWT) && defined(DWT) */
  153. /*!
  154. * @brief Delay at least for some time.
  155. * Please note that, if not uses DWT, this API will use while loop for delay, different run-time environments have
  156. * effect on the delay time. If precise delay is needed, please enable DWT delay. The two parmeters delayTime_us and
  157. * coreClock_Hz have limitation. For example, in the platform with 1GHz coreClock_Hz, the delayTime_us only supports
  158. * up to 4294967 in current code. If long time delay is needed, please implement a new delay function.
  159. *
  160. * @param delayTime_us Delay time in unit of microsecond.
  161. * @param coreClock_Hz Core clock frequency with Hz.
  162. */
  163. void SDK_DelayAtLeastUs(uint32_t delayTime_us, uint32_t coreClock_Hz)
  164. {
  165. uint64_t count;
  166. if (delayTime_us > 0U)
  167. {
  168. count = USEC_TO_COUNT(delayTime_us, coreClock_Hz);
  169. assert(count <= UINT32_MAX);
  170. #if defined(SDK_DELAY_USE_DWT) && defined(DWT) /* Use DWT for better accuracy */
  171. enableCpuCycleCounter();
  172. /* Calculate the count ticks. */
  173. count += getCpuCycleCount();
  174. if (count > UINT32_MAX)
  175. {
  176. count -= UINT32_MAX;
  177. /* Wait for cyccnt overflow. */
  178. while (count < getCpuCycleCount())
  179. {
  180. }
  181. }
  182. /* Wait for cyccnt reach count value. */
  183. while (count > getCpuCycleCount())
  184. {
  185. }
  186. #else
  187. /* Divide value may be different in various environment to ensure delay is precise.
  188. * Every loop count includes three instructions, due to Cortex-M7 sometimes executes
  189. * two instructions in one period, through test here set divide 1.5. Other M cores use
  190. * divide 4. By the way, divide 1.5 or 4 could let the count lose precision, but it does
  191. * not matter because other instructions outside while loop is enough to fill the time.
  192. */
  193. #if (__CORTEX_M == 7)
  194. count = count / 3U * 2U;
  195. #else
  196. count = count / 4U;
  197. #endif
  198. DelayLoop((uint32_t)count);
  199. #endif /* defined(SDK_DELAY_USE_DWT) && defined(DWT) */
  200. }
  201. }