ustimer.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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 "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. #define MAP_SIZE 4096UL
  21. #define MAP_MASK (MAP_SIZE - 1)
  22. int g_ustimer_fd = -1;
  23. unsigned g_ustimer_mapped_size;
  24. void *g_ustimer_map_base, *g_ustimer_virt_addr;
  25. /******************************************************************************
  26. 函数名称: ustimer_init
  27. 函数版本: 01.01
  28. 创建作者: zhaoyang
  29. 创建日期: 2025-07-28
  30. 函数说明: 使用timer2做为延时函数参考定时器并注册
  31. 参数说明: 无
  32. 返回值: 无
  33. 修改记录:
  34. */
  35. int ustimer_init(void)
  36. {
  37. void *temp_ccu_base, *temp_virt_l_base, *temp_virt_h_base, *temp_virt_ctl_base;
  38. unsigned long read_result;
  39. off_t target;
  40. unsigned page_size, offset_in_page;
  41. unsigned width = 8 * sizeof(int);
  42. target = TIMER_BASE;
  43. // 获取页面大小
  44. g_ustimer_mapped_size = page_size = sysconf(_SC_PAGESIZE);
  45. offset_in_page = (unsigned)target & (page_size - 1);
  46. if (offset_in_page + width > page_size) {
  47. /* This access spans pages.
  48. * Must map two pages to make it possible: */
  49. g_ustimer_mapped_size *= 2;
  50. }
  51. g_ustimer_fd = open("/dev/mem", O_RDWR | O_SYNC);
  52. if (g_ustimer_fd < 0)
  53. {
  54. printf("open(/dev/mem) failed.\n");
  55. return -1;
  56. }
  57. fflush(stdout);
  58. 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));
  59. if (g_ustimer_map_base == (void *)-1)
  60. {
  61. printf ("NULL pointer!\n");
  62. }
  63. else
  64. {
  65. printf ("map Successfull!\n");
  66. }
  67. fflush(stdout);
  68. g_ustimer_virt_addr = (char*)g_ustimer_map_base + offset_in_page;
  69. printf("g_ustimer_virt_addr: %p %p %x\n", g_ustimer_virt_addr, g_ustimer_map_base, offset_in_page);
  70. // Init timer ccu clock
  71. /* set TMR2 clock source to HOSC, 8 pre-division */
  72. temp_ccu_base = g_ccu_map_base + 0x0808;
  73. read_result = *(volatile u_int32_t*)(temp_ccu_base);
  74. read_result &= ~((0x01 << 24) | 7);
  75. read_result |= (1 << 31) | 3;
  76. *(volatile u_int32_t*)(temp_ccu_base) = read_result;
  77. // Enable timer2
  78. /* set timer intervalue */
  79. temp_virt_l_base = (char*)g_ustimer_map_base + 0x64;
  80. temp_virt_h_base = (char*)g_ustimer_map_base + 0x6C;
  81. *(volatile u_int32_t*)(temp_virt_l_base) = 0xFFFFFFFF;
  82. *(volatile u_int32_t*)(temp_virt_h_base) = 0xFFFFFF;
  83. /* set mode to auto reload */
  84. temp_virt_ctl_base = (char*)g_ustimer_map_base + 0x60;
  85. read_result = *(volatile u_int32_t*)(temp_virt_ctl_base);
  86. read_result &= TIMER_CTL_PERIODIC;
  87. *(volatile u_int32_t*)(temp_virt_ctl_base) = (read_result | TIMER_CTL_AUTORELOAD | TIMER_CTL_ENABLE);
  88. // read_result = *(volatile u_int32_t*)g_ustimer_virt_addr;
  89. // printf("ustimer_init res: 0x%08lx\n", read_result);
  90. return 0;
  91. }
  92. /******************************************************************************
  93. 函数名称: ustimer_exit
  94. 函数版本: 01.01
  95. 创建作者: zhaoyang
  96. 创建日期: 2025-07-28
  97. 函数说明: 用户定时器注销
  98. 参数说明: 无
  99. 返回值: 无
  100. 修改记录:
  101. */
  102. int ustimer_exit(void)
  103. {
  104. if (g_ustimer_fd >= 0)
  105. {
  106. close(g_ustimer_fd);
  107. g_ustimer_fd = -1;
  108. }
  109. if (munmap(g_ustimer_map_base, g_ustimer_mapped_size) == -1) {
  110. printf("munmap failed!");
  111. return -1;
  112. }
  113. return 0;
  114. }
  115. /******************************************************************************
  116. 函数名称: ustimer_get_origin
  117. 函数版本: 01.01
  118. 创建作者: zhaoyang
  119. 创建日期: 2025-07-28
  120. 函数说明: 得到当前时刻定时器的值,用作ustimer_get_duration、
  121. ustimer_delay_origin函数的origin参数。
  122. 参数说明: 无
  123. 返回值: 当前时刻定时器的值。
  124. 修改记录:
  125. */
  126. unsigned long ustimer_get_origin(void)
  127. {
  128. void *temp_virt_l_base, *temp_virt_h_base;
  129. u_int64_t val_low, val_high;
  130. if (!g_ustimer_map_base) {
  131. return 0;
  132. }
  133. temp_virt_l_base = (char*)g_ustimer_map_base + 0x68;
  134. temp_virt_h_base = (char*)g_ustimer_map_base + 0x70;
  135. val_low = (~*(volatile u_int32_t*)temp_virt_l_base) & TIMER_VL_MASK;
  136. val_high = (~*(volatile u_int32_t*)temp_virt_h_base) & TIMER_VH_MASK;
  137. return ((val_high << TIMER_VH_OFFSET) | val_low)/3;
  138. }