bsp_ustimer.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /******************************************************************************
  2. 版权所有: @copyright (C) 2024-2034 HaiYang Technology Corp. All rights reserved.
  3. 文件名称: ustimer.c
  4. 文件版本: 01.01
  5. 创建作者: zhaoyang
  6. 创建日期: 2025-07-28
  7. 功能说明: us定时器模块驱动程序。目前使用了TIM2定时器,作为延时函数的参考定时器用。
  8. TIM2的时钟周期为1/3us。延时函数的最大时间长度为1431.6557653秒。
  9. 其它说明:
  10. 修改记录:
  11. */
  12. #include "bsp_ustimer.h"
  13. #include <stdlib.h>
  14. #include <fcntl.h>
  15. #include <sys/types.h>
  16. #include <unistd.h>
  17. #include <stdio.h>
  18. #include <sys/mman.h>
  19. #include "bsp_ccu.h"
  20. #include "rt_types.h"
  21. #define MAP_SIZE 4096UL
  22. #define MAP_MASK (MAP_SIZE - 1)
  23. #define BSP_USTIMER_DELAY_MAX_US (10UL * 60 * BSP_USTIMER_SEC) // 10分钟
  24. int g_ustimer_fd = -1;
  25. unsigned g_ustimer_mapped_size;
  26. void *g_ustimer_map_base, *g_ustimer_virt_addr;
  27. /******************************************************************************
  28. 函数名称: bsp_ustimer_init
  29. 函数版本: 01.01
  30. 创建作者: zhaoyang
  31. 创建日期: 2025-07-28
  32. 函数说明: 使用timer2做为延时函数参考定时器并注册
  33. 参数说明: 无
  34. 返回值: 无
  35. 修改记录:
  36. */
  37. int bsp_ustimer_init(void)
  38. {
  39. void *temp_ccu_base, *temp_virt_l_base, *temp_virt_h_base, *temp_virt_ctl_base;
  40. unsigned long read_result;
  41. off_t target;
  42. unsigned page_size, offset_in_page;
  43. unsigned width = 8 * sizeof(int);
  44. target = TIMER_BASE;
  45. // 获取页面大小
  46. g_ustimer_mapped_size = page_size = sysconf(_SC_PAGESIZE);
  47. offset_in_page = (unsigned)target & (page_size - 1);
  48. if (offset_in_page + width > page_size)
  49. {
  50. /* This access spans pages.
  51. * Must map two pages to make it possible: */
  52. g_ustimer_mapped_size *= 2;
  53. }
  54. g_ustimer_fd = open("/dev/mem", O_RDWR | O_SYNC);
  55. if (g_ustimer_fd < 0)
  56. {
  57. printf("open(/dev/mem) failed.\n");
  58. return -1;
  59. }
  60. fflush(stdout);
  61. g_ustimer_map_base = mmap(NULL, g_ustimer_mapped_size, PROT_READ | PROT_WRITE, MAP_SHARED, g_ustimer_fd, target & ~(off_t)(page_size - 1));
  62. if (g_ustimer_map_base == (void *)-1)
  63. {
  64. printf("NULL pointer!\n");
  65. }
  66. else
  67. {
  68. printf("BSP ustimer map Successfull!\n");
  69. }
  70. fflush(stdout);
  71. g_ustimer_virt_addr = (char *)g_ustimer_map_base + offset_in_page;
  72. // printf("g_ustimer_virt_addr: %p %p %x\n", g_ustimer_virt_addr, g_ustimer_map_base, offset_in_page);
  73. // Init timer ccu clock
  74. /* set TMR2 clock source to HOSC, 8 pre-division */
  75. temp_ccu_base = g_ccu_map_base + 0x0808;
  76. read_result = *(volatile u_int32_t *)(temp_ccu_base);
  77. read_result &= ~((0x01 << 24) | 7);
  78. read_result |= (1 << 31) | 3;
  79. *(volatile u_int32_t *)(temp_ccu_base) = read_result;
  80. // Enable timer2
  81. /* set timer intervalue */
  82. temp_virt_l_base = (char *)g_ustimer_map_base + 0x64;
  83. temp_virt_h_base = (char *)g_ustimer_map_base + 0x6C;
  84. *(volatile u_int32_t *)(temp_virt_l_base) = 0xFFFFFFFF;
  85. *(volatile u_int32_t *)(temp_virt_h_base) = 0xFFFFFF;
  86. /* set mode to auto reload */
  87. temp_virt_ctl_base = (char *)g_ustimer_map_base + 0x60;
  88. read_result = *(volatile u_int32_t *)(temp_virt_ctl_base);
  89. read_result &= TIMER_CTL_PERIODIC;
  90. *(volatile u_int32_t *)(temp_virt_ctl_base) = (read_result | TIMER_CTL_AUTORELOAD | TIMER_CTL_ENABLE);
  91. // read_result = *(volatile u_int32_t*)g_ustimer_virt_addr;
  92. // printf("ustimer_init res: 0x%08lx\n", read_result);
  93. return 0;
  94. }
  95. /******************************************************************************
  96. 函数名称: bsp_ustimer_exit
  97. 函数版本: 01.01
  98. 创建作者: zhaoyang
  99. 创建日期: 2025-07-28
  100. 函数说明: 用户定时器注销
  101. 参数说明: 无
  102. 返回值: 无
  103. 修改记录:
  104. */
  105. int bsp_ustimer_exit(void)
  106. {
  107. if (g_ustimer_fd >= 0)
  108. {
  109. close(g_ustimer_fd);
  110. g_ustimer_fd = -1;
  111. }
  112. if (munmap(g_ustimer_map_base, g_ustimer_mapped_size) == -1)
  113. {
  114. printf("munmap failed!");
  115. return -1;
  116. }
  117. return 0;
  118. }
  119. /******************************************************************************
  120. 函数名称: bsp_ustimer_get_origin
  121. 函数版本: 01.01
  122. 创建作者: zhaoyang
  123. 创建日期: 2025-07-28
  124. 函数说明: 得到当前时刻定时器的值,用作ustimer_get_duration、
  125. ustimer_delay_origin函数的origin参数。
  126. 参数说明: 无
  127. 返回值: 当前时刻定时器的值。
  128. 修改记录:
  129. */
  130. unsigned long bsp_ustimer_get_origin(void)
  131. {
  132. void *temp_virt_l_base, *temp_virt_h_base;
  133. u_int64_t val_low, val_high;
  134. if (!g_ustimer_map_base)
  135. {
  136. return 0;
  137. }
  138. temp_virt_l_base = (char *)g_ustimer_map_base + 0x68;
  139. temp_virt_h_base = (char *)g_ustimer_map_base + 0x70;
  140. val_low = (~*(volatile u_int32_t *)temp_virt_l_base) & TIMER_VL_MASK;
  141. val_high = (~*(volatile u_int32_t *)temp_virt_h_base) & TIMER_VH_MASK;
  142. return ((val_high << TIMER_VH_OFFSET) | val_low) / 3;
  143. }
  144. /******************************************************************************
  145. 函数名称: bsp_ustimer_get_duration
  146. 函数版本: 01.01
  147. 创建作者: zhaoyang
  148. 创建日期: 2025-07-28
  149. 函数说明: 得到当前时刻相对于指定时间原点的时间间隔,以us为单位。
  150. 参数说明: origin: 时间原点,以us为单位。
  151. 返回值: 当前时刻相对于原点的的时间间隔。
  152. 修改记录:
  153. */
  154. unsigned long bsp_ustimer_get_duration(unsigned long origin)
  155. {
  156. if (!g_ustimer_map_base)
  157. return 0;
  158. // 返回差值(根据C语言算法,会自动处理回绕问题)
  159. return bsp_ustimer_get_origin() - origin;
  160. }
  161. /******************************************************************************
  162. 函数名称: bsp_ustimer_delay_origin
  163. 函数版本: 01.01
  164. 创建作者: zhaoyang
  165. 创建日期: 2025-07-28
  166. 函数说明: 以us为单位的延时函数。最大延时值为1小时(3600000000us)和
  167. ustimer_delay函数不同的是bsp_ustimer_delay_origin函数的延时计算的时间
  168. 原点为origin,而不是函数被调用的时刻。当这个函数退出时,会确保延时
  169. 大于等于设定值。如果需要高精度的延时,调用这个函数时应先屏蔽中断。
  170. 参数说明:
  171. origin: 延时计算的时间原点,以us为单位,通常通过ustimer_get_origin函数获得。
  172. us: 延时us数。
  173. 返回值:
  174. 0: 成功
  175. 其它: 失败
  176. 修改记录:
  177. */
  178. unsigned long bsp_ustimer_delay_origin(unsigned long origin, unsigned long us)
  179. {
  180. if (!g_ustimer_map_base)
  181. return 0;
  182. // 检查参数
  183. if (us > BSP_USTIMER_DELAY_MAX_US)
  184. return -1;
  185. // 循环等待
  186. while (us > (bsp_ustimer_get_origin() - origin))
  187. ;
  188. return 0;
  189. }
  190. /******************************************************************************
  191. 函数名称: ustimer_delay
  192. 函数版本: 01.01
  193. 创建作者: zhaoyang
  194. 创建日期: 2025-07-28
  195. 函数说明: 以us为单位的延时函数。最大延时值为1小时(3600000000us)。
  196. 当这个函数退出时,会确保延时大于等于设定值。如果需要高精度的延时,
  197. 调用这个函数时应先屏蔽中断。
  198. 参数说明:
  199. us: 延时us数。
  200. 返回值:
  201. 0: 成功
  202. 其它: 失败
  203. 修改记录:
  204. */
  205. unsigned long bsp_ustimer_delay(unsigned long us)
  206. {
  207. u64 origin;
  208. if (!g_ustimer_map_base)
  209. return 0;
  210. // 检查参数
  211. if (us > BSP_USTIMER_DELAY_MAX_US)
  212. return -1;
  213. origin = bsp_ustimer_get_origin();
  214. bsp_ustimer_delay_origin(origin, us);
  215. return 0;
  216. }