bsp_ustimer.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  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. /* This access spans pages.
  50. * Must map two pages to make it possible: */
  51. g_ustimer_mapped_size *= 2;
  52. }
  53. g_ustimer_fd = open("/dev/mem", O_RDWR | O_SYNC);
  54. if (g_ustimer_fd < 0)
  55. {
  56. printf("open(/dev/mem) failed.\n");
  57. return -1;
  58. }
  59. fflush(stdout);
  60. 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));
  61. if (g_ustimer_map_base == (void *)-1)
  62. {
  63. printf ("NULL pointer!\n");
  64. }
  65. else
  66. {
  67. printf ("BSP ustimer map Successfull!\n");
  68. }
  69. fflush(stdout);
  70. g_ustimer_virt_addr = (char*)g_ustimer_map_base + offset_in_page;
  71. // printf("g_ustimer_virt_addr: %p %p %x\n", g_ustimer_virt_addr, g_ustimer_map_base, offset_in_page);
  72. // Init timer ccu clock
  73. /* set TMR2 clock source to HOSC, 8 pre-division */
  74. temp_ccu_base = g_ccu_map_base + 0x0808;
  75. read_result = *(volatile u_int32_t*)(temp_ccu_base);
  76. read_result &= ~((0x01 << 24) | 7);
  77. read_result |= (1 << 31) | 3;
  78. *(volatile u_int32_t*)(temp_ccu_base) = read_result;
  79. // Enable timer2
  80. /* set timer intervalue */
  81. temp_virt_l_base = (char*)g_ustimer_map_base + 0x64;
  82. temp_virt_h_base = (char*)g_ustimer_map_base + 0x6C;
  83. *(volatile u_int32_t*)(temp_virt_l_base) = 0xFFFFFFFF;
  84. *(volatile u_int32_t*)(temp_virt_h_base) = 0xFFFFFF;
  85. /* set mode to auto reload */
  86. temp_virt_ctl_base = (char*)g_ustimer_map_base + 0x60;
  87. read_result = *(volatile u_int32_t*)(temp_virt_ctl_base);
  88. read_result &= TIMER_CTL_PERIODIC;
  89. *(volatile u_int32_t*)(temp_virt_ctl_base) = (read_result | TIMER_CTL_AUTORELOAD | TIMER_CTL_ENABLE);
  90. // read_result = *(volatile u_int32_t*)g_ustimer_virt_addr;
  91. // printf("ustimer_init res: 0x%08lx\n", read_result);
  92. return 0;
  93. }
  94. /******************************************************************************
  95. 函数名称: bsp_ustimer_exit
  96. 函数版本: 01.01
  97. 创建作者: zhaoyang
  98. 创建日期: 2025-07-28
  99. 函数说明: 用户定时器注销
  100. 参数说明: 无
  101. 返回值: 无
  102. 修改记录:
  103. */
  104. int bsp_ustimer_exit(void)
  105. {
  106. if (g_ustimer_fd >= 0)
  107. {
  108. close(g_ustimer_fd);
  109. g_ustimer_fd = -1;
  110. }
  111. if (munmap(g_ustimer_map_base, g_ustimer_mapped_size) == -1) {
  112. printf("munmap failed!");
  113. return -1;
  114. }
  115. return 0;
  116. }
  117. /******************************************************************************
  118. 函数名称: bsp_ustimer_get_origin
  119. 函数版本: 01.01
  120. 创建作者: zhaoyang
  121. 创建日期: 2025-07-28
  122. 函数说明: 得到当前时刻定时器的值,用作ustimer_get_duration、
  123. ustimer_delay_origin函数的origin参数。
  124. 参数说明: 无
  125. 返回值: 当前时刻定时器的值。
  126. 修改记录:
  127. */
  128. unsigned long bsp_ustimer_get_origin(void)
  129. {
  130. void *temp_virt_l_base, *temp_virt_h_base;
  131. u_int64_t val_low, val_high;
  132. if (!g_ustimer_map_base) {
  133. return 0;
  134. }
  135. temp_virt_l_base = (char*)g_ustimer_map_base + 0x68;
  136. temp_virt_h_base = (char*)g_ustimer_map_base + 0x70;
  137. val_low = (~*(volatile u_int32_t*)temp_virt_l_base) & TIMER_VL_MASK;
  138. val_high = (~*(volatile u_int32_t*)temp_virt_h_base) & TIMER_VH_MASK;
  139. return ((val_high << TIMER_VH_OFFSET) | val_low)/3;
  140. }
  141. /******************************************************************************
  142. 函数名称: bsp_ustimer_get_duration
  143. 函数版本: 01.01
  144. 创建作者: zhaoyang
  145. 创建日期: 2025-07-28
  146. 函数说明: 得到当前时刻相对于指定时间原点的时间间隔,以us为单位。
  147. 参数说明: origin: 时间原点,以us为单位。
  148. 返回值: 当前时刻相对于原点的的时间间隔。
  149. 修改记录:
  150. */
  151. unsigned long bsp_ustimer_get_duration(unsigned long origin)
  152. {
  153. if(!g_ustimer_map_base)
  154. return 0;
  155. // 返回差值(根据C语言算法,会自动处理回绕问题)
  156. return bsp_ustimer_get_origin() - origin;
  157. }
  158. /******************************************************************************
  159. 函数名称: bsp_ustimer_delay_origin
  160. 函数版本: 01.01
  161. 创建作者: zhaoyang
  162. 创建日期: 2025-07-28
  163. 函数说明: 以us为单位的延时函数。最大延时值为1小时(3600000000us)和
  164. ustimer_delay函数不同的是bsp_ustimer_delay_origin函数的延时计算的时间
  165. 原点为origin,而不是函数被调用的时刻。当这个函数退出时,会确保延时
  166. 大于等于设定值。如果需要高精度的延时,调用这个函数时应先屏蔽中断。
  167. 参数说明:
  168. origin: 延时计算的时间原点,以us为单位,通常通过ustimer_get_origin函数获得。
  169. us: 延时us数。
  170. 返回值:
  171. 0: 成功
  172. 其它: 失败
  173. 修改记录:
  174. */
  175. unsigned long bsp_ustimer_delay_origin(unsigned long origin,unsigned long us)
  176. {
  177. if(!g_ustimer_map_base)
  178. return 0;
  179. //检查参数
  180. if(us > BSP_USTIMER_DELAY_MAX_US)
  181. return -1;
  182. // 循环等待
  183. while (us > (bsp_ustimer_get_origin() - origin))
  184. ;
  185. return 0;
  186. }
  187. /******************************************************************************
  188. 函数名称: ustimer_delay
  189. 函数版本: 01.01
  190. 创建作者: zhaoyang
  191. 创建日期: 2025-07-28
  192. 函数说明: 以us为单位的延时函数。最大延时值为1小时(3600000000us)。
  193. 当这个函数退出时,会确保延时大于等于设定值。如果需要高精度的延时,
  194. 调用这个函数时应先屏蔽中断。
  195. 参数说明:
  196. us: 延时us数。
  197. 返回值:
  198. 0: 成功
  199. 其它: 失败
  200. 修改记录:
  201. */
  202. unsigned long bsp_ustimer_delay(unsigned long us)
  203. {
  204. u64 origin;
  205. if(!g_ustimer_map_base)
  206. return 0;
  207. //检查参数
  208. if(us > BSP_USTIMER_DELAY_MAX_US)
  209. return -1;
  210. origin = bsp_ustimer_get_origin();
  211. bsp_ustimer_delay_origin(origin, us);
  212. return 0;
  213. }