hal_base.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. /* SPDX-License-Identifier: BSD-3-Clause */
  2. /*
  3. * Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
  4. */
  5. #include "hal_base.h"
  6. /** @addtogroup RK_HAL_Driver
  7. * @{
  8. */
  9. /** @addtogroup HAL_BASE
  10. * @{
  11. */
  12. /** @defgroup HAL_BASE_How_To_Use How To Use
  13. * @{
  14. HAL system support is including delay system, HAL tick system and global system clock,
  15. HAL system tick setting:
  16. - Attach HAL_IncTick() to system tick interrupt handler;
  17. - Notify the HAL system the system's tick frequency by calling HAL_SetTickFreq() unless
  18. it is the same as default value HAL_TICK_FREQ_1KHZ;
  19. - If you need a more accurate delay system, specify SYS_TIMER in hal_conf.h.
  20. Init HAL system:
  21. - Initialize the HAL system by calling HAL_Init():
  22. Reset when SOC system is changed:
  23. - Update system with new core clock and new SysTick clock source by calling HAL_SystemCoreClockUpdate();
  24. APIs:
  25. - Get system time by calling HAL_GetTick();
  26. - Delay for a certain length of time, HAL_DelayMs(), HAL_DelayUs(), and HAL_CPUDelayUs().
  27. - Blocking for a certain period of time to continuously query HW status, use HAL_GetTick()
  28. to do timeout, this will be more accurate.
  29. @} */
  30. /** @defgroup HAL_BASE_Private_Definition Private Definition
  31. * @{
  32. */
  33. /********************* Private MACRO Definition ******************************/
  34. #define HAL_TICK_FREQ_DEFAULT HAL_TICK_FREQ_1KHZ
  35. /********************* Private Structure Definition **************************/
  36. /********************* Private Variable Definition ***************************/
  37. static __IO uint32_t uwTick;
  38. static eHAL_tickFreq uwTickFreq = HAL_TICK_FREQ_DEFAULT;
  39. /********************* Private Function Definition ***************************/
  40. #if defined(__CORTEX_A) || defined(__CORTEX_M)
  41. #if __CORTEX_M == 0U || !defined(__GNUC__)
  42. static void CPUCycleLoop(uint32_t cycles)
  43. {
  44. uint32_t count;
  45. if (cycles < 100U) {
  46. return;
  47. }
  48. count = cycles / 3;
  49. while (count-- > 0) {
  50. __asm volatile ("nop");
  51. }
  52. }
  53. #else
  54. static void CPUCycleLoop(uint32_t cycles)
  55. {
  56. __ASM volatile (
  57. "mov r0, %0\n\t"
  58. "adds r0, r0, #2\n\t" // 1 2 Round to the nearest multiple of 4.
  59. "lsrs r0, r0, #2\n\t" // 1 2 Divide by 4 and set flags.
  60. "beq 2f\n\t" // 2 2 Skip if 0.
  61. ".align 4\n\t"
  62. "1:\n\t"
  63. "adds r0, r0, #1\n\t" // 1 2 Increment the counter.
  64. "subs r0, r0, #2\n\t" // 1 2 Decrement the counter by 2.
  65. "bne 1b\n\t" // (1)2 2 2 CPU cycles (if branch is taken).
  66. "nop\n\t" // 1 2 Loop alignment padding.
  67. "2:"
  68. : : "r" (cycles)
  69. );
  70. }
  71. #endif
  72. #elif defined(__RISC_V)
  73. static void CPUCycleLoop(uint32_t cycles)
  74. {
  75. asm volatile (
  76. "mv a0, %0\n\t"
  77. "addi a0, a0, 2\n\t" // 1 2 Round to the nearest multiple of 4.
  78. "li a1, 4\n\t"
  79. "div a0, a0, a1\n\t" // 1 2 Divide by 4 and set flags.
  80. "li a1, 2\n\t"
  81. "bnez a0, 1f\n\t" // 2 2 Skip if 0.
  82. "j 2f\n\t"
  83. ".align 6\n\t"
  84. "1:\n\t"
  85. "addi a0, a0, 1\n\t" // 1 2 Increment the counter.
  86. "sub a0, a0, a1\n\t" // 1 2 Decrement the counter by 2.
  87. "bnez a0, 1b\n\t" // (1)2 2 2 CPU cycles (if branch is taken).
  88. "nop\n\t" // 1 2 Loop alignment padding.
  89. "2:"
  90. : : "r" (cycles)
  91. );
  92. }
  93. #endif
  94. #if defined(SYS_TIMER) && defined(HAL_TIMER_MODULE_ENABLED)
  95. __STATIC_FORCEINLINE HAL_Status TimerDelayUs(uint32_t us)
  96. {
  97. uint64_t count, from, now, pass;
  98. from = HAL_TIMER_GetCount(SYS_TIMER);
  99. count = PLL_INPUT_OSC_RATE / 1000000 * us;
  100. do {
  101. now = HAL_TIMER_GetCount(SYS_TIMER);
  102. pass = now > from ? now - from : from - now;
  103. } while (pass < count);
  104. return HAL_OK;
  105. }
  106. #endif
  107. /** @} */
  108. /********************* Public Function Definition ***************************/
  109. /** @defgroup HAL_BASE_Exported_Functions_Group4 Init and DeInit Functions
  110. This section provides functions allowing to init and deinit the module:
  111. * @{
  112. */
  113. /**
  114. * @brief Init HAL driver basic code.
  115. * @return HAL_OK.
  116. */
  117. HAL_Status HAL_Init(void)
  118. {
  119. #ifdef __CORTEX_M
  120. #ifdef HAL_NVIC_MODULE_ENABLED
  121. /* Set Interrupt Group Priority */
  122. HAL_NVIC_Init();
  123. /* Set Interrupt Group Priority */
  124. HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_DEFAULT);
  125. #endif
  126. #endif
  127. #if defined(SYS_TIMER) && defined(HAL_TIMER_MODULE_ENABLED)
  128. HAL_TIMER_SysTimerInit(SYS_TIMER);
  129. #endif
  130. #ifdef RK_BSP_TEMP
  131. #ifdef HAL_PINCTRL_MODULE_ENABLED
  132. HAL_PINCTRL_Init();
  133. #endif
  134. #endif
  135. return HAL_OK;
  136. }
  137. /**
  138. * @brief HAL system update with new core clock and systick clock source.
  139. * @param hz: new core clock.
  140. * @param clkSource: new systick clock source.
  141. * @return HAL_OK.
  142. */
  143. HAL_Status HAL_SystemCoreClockUpdate(uint32_t hz, eHAL_systickClkSource clkSource)
  144. {
  145. uint32_t rate = hz;
  146. HAL_Status ret = HAL_OK;
  147. #if defined(__CORTEX_M) && defined(HAL_SYSTICK_MODULE_ENABLED)
  148. ret = HAL_SYSTICK_CLKSourceConfig(clkSource);
  149. if (ret == HAL_OK && clkSource == HAL_SYSTICK_CLKSRC_EXT) {
  150. rate = PLL_INPUT_OSC_RATE;
  151. }
  152. HAL_SYSTICK_Config(rate / (1000 / HAL_GetTickFreq()));
  153. ret = HAL_OK;
  154. #endif
  155. if (ret == HAL_OK) {
  156. SystemCoreClock = rate; /* Update global SystemCoreClock */
  157. }
  158. return ret;
  159. }
  160. /**
  161. * @brief HAL deinit.
  162. * @return HAL_Status: HAL_OK.
  163. */
  164. HAL_Status HAL_DeInit(void)
  165. {
  166. /* TO-DO */
  167. return HAL_OK;
  168. }
  169. /** @} */
  170. /** @defgroup HAL_BASE_Exported_Functions_Group5 Other Functions
  171. * @{
  172. */
  173. /**
  174. * @brief Count plus tickFreq when interrupt occurs.
  175. * @return HAL_Status: HAL_OK.
  176. */
  177. HAL_Status HAL_IncTick(void)
  178. {
  179. uwTick += uwTickFreq;
  180. return HAL_OK;
  181. }
  182. /**
  183. * @brief Provides tick value in millisecond.
  184. * @return uint32_t: tick value in millisecond.
  185. * @attention this API allow direct use in the HAL layer.
  186. */
  187. uint32_t HAL_GetTick(void)
  188. {
  189. #if defined(SYS_TIMER) && defined(HAL_TIMER_MODULE_ENABLED)
  190. uint64_t tick = HAL_TIMER_GetCount(SYS_TIMER);
  191. uint32_t base = PLL_INPUT_OSC_RATE / 1000;
  192. if (tick >> 62) {
  193. tick = ~tick;
  194. }
  195. return (uint32_t)HAL_DivU64(tick, base);
  196. #else
  197. return uwTick;
  198. #endif
  199. }
  200. /**
  201. * @brief Provides system timer count.
  202. * @return uint64_t: timer count.
  203. * @attention this API allow direct use in the HAL layer.
  204. */
  205. uint64_t HAL_GetSysTimerCount(void)
  206. {
  207. #if defined(SYS_TIMER) && defined(HAL_TIMER_MODULE_ENABLED)
  208. uint64_t count = HAL_TIMER_GetCount(SYS_TIMER);
  209. if (count >> 62) {
  210. count = ~count;
  211. }
  212. return count;
  213. #else
  214. return 0LLU;
  215. #endif
  216. }
  217. /**
  218. * @brief Set new tick frequency.
  219. * @return HAL_Status.
  220. */
  221. HAL_Status HAL_SetTickFreq(eHAL_tickFreq freq)
  222. {
  223. HAL_ASSERT(IS_TICKFREQ(freq));
  224. uwTickFreq = freq;
  225. return HAL_OK;
  226. }
  227. /**
  228. * @brief Return tick frequency.
  229. * @return uint32_t: tick period in Hz.
  230. * @attention this API allow direct use in the HAL layer.
  231. */
  232. eHAL_tickFreq HAL_GetTickFreq(void)
  233. {
  234. return uwTickFreq;
  235. }
  236. /**
  237. * @brief SysTick mdelay.
  238. * @param ms: mdelay count.
  239. * @return HAL_Status: HAL_OK.
  240. * @attention this API allow direct use in the HAL layer. Blocking for a
  241. * certain period of time to continuously query HW status, use HAL_GetTick
  242. * to do timeout, that will be more accurate.
  243. */
  244. __WEAK HAL_Status HAL_DelayMs(uint32_t ms)
  245. {
  246. for (uint32_t i = 0; i < ms; i++) {
  247. HAL_DelayUs(1000);
  248. }
  249. return HAL_OK;
  250. }
  251. /**
  252. * @brief SysTick udelay.
  253. * @param us: udelay count.
  254. * @return HAL_Status: HAL_OK.
  255. * @attention this API allow direct use in the HAL layer. The longer the delay,
  256. * the more accurate. Actual delay is greater than the parameter.
  257. */
  258. HAL_Status HAL_DelayUs(uint32_t us)
  259. {
  260. #if defined(SYS_TIMER) && defined(HAL_TIMER_MODULE_ENABLED)
  261. return TimerDelayUs(us);
  262. #else
  263. return HAL_CPUDelayUs(us);
  264. #endif
  265. }
  266. /**
  267. * @brief CPU loop udelay.
  268. * @param us: udelay count.
  269. * @return HAL_Status: HAL_OK.
  270. * @attention this API allow direct use in the HAL layer. The longer the delay,
  271. * the more accurate. Actual delay is greater than the parameter.
  272. * During delay, CPU rate change result in delay imprecise, so call it in
  273. * following case:
  274. * 1.IRQ disable
  275. * 2.CRU code
  276. */
  277. HAL_Status HAL_CPUDelayUs(uint32_t us)
  278. {
  279. volatile uint32_t cycles;
  280. #if (__CORTEX_M == 0)
  281. cycles = (uint32_t)HAL_DivU64((uint64_t)SystemCoreClock, 1000000) * us; /* Add few cycles penalty */
  282. #else
  283. cycles = SystemCoreClock / 1000000 * us; /* Add few cycles penalty */
  284. #endif
  285. CPUCycleLoop(cycles);
  286. return HAL_OK;
  287. }
  288. /** @} */
  289. /** @} */
  290. /** @} */