1
0

ls1c_timer.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /*
  2. * Copyright (c) 2006-2018, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * first version
  9. */
  10. // 硬件定时器源码
  11. #include <ls1c.h>
  12. #include "ls1c_public.h"
  13. #include "ls1c_pin.h"
  14. #include "ls1c_clock.h"
  15. #include "ls1c_regs.h"
  16. #include "ls1c_pwm.h"
  17. #include "ls1c_timer.h"
  18. // 定时器中计数器(CNTR、HRC和LRC)的最大值
  19. #define TIMER_COUNTER_MAX (0xffffff)
  20. /*
  21. * 获取指定定时器的寄存器基地址
  22. * @timer 硬件定时器
  23. * @ret 基地址
  24. */
  25. unsigned int timer_get_reg_base(ls1c_timer_t timer)
  26. {
  27. unsigned int reg_base = 0;
  28. switch (timer)
  29. {
  30. case TIMER_PWM0:
  31. reg_base = LS1C_REG_BASE_PWM0;
  32. break;
  33. case TIMER_PWM1:
  34. reg_base = LS1C_REG_BASE_PWM1;
  35. break;
  36. case TIMER_PWM2:
  37. reg_base = LS1C_REG_BASE_PWM2;
  38. break;
  39. case TIMER_PWM3:
  40. reg_base = LS1C_REG_BASE_PWM3;
  41. break;
  42. }
  43. return reg_base;
  44. }
  45. /*
  46. * 初始化定时器,并开始定时
  47. * @timer_info 定时器和定时时间信息
  48. */
  49. void timer_init(timer_info_t *timer_info)
  50. {
  51. unsigned int timer_reg_base = 0; // 寄存器基地址
  52. unsigned long timer_clk = 0; // 硬件定时器的时钟
  53. unsigned long tmp;
  54. unsigned int ctrl = 0; // 控制寄存器中的控制信息
  55. // 判断入参
  56. if (NULL == timer_info)
  57. {
  58. return ;
  59. }
  60. /*
  61. * 把定时时间换算为计数器的值
  62. * 计数器值 = 定时器的时钟 * 定时时间(单位ns) / 1000000000
  63. * 龙芯1c的定时器时钟为APB时钟,达到126Mhz,
  64. * 为避免计算过程发生溢出,这里采用手动优化上面的计算式,也可以采用浮点运算
  65. */
  66. timer_clk = clk_get_apb_rate();
  67. tmp = (timer_clk / 1000000) * (timer_info->time_ns / 1000); // 将1000000000拆分为1000000和1000
  68. tmp = MIN(tmp, TIMER_COUNTER_MAX);
  69. // 控制寄存器信息
  70. ctrl = (1 << LS1C_PWM_INT_LRC_EN)
  71. | (0 << LS1C_PWM_INT_HRC_EN)
  72. | (0 << LS1C_PWM_CNTR_RST)
  73. | (0 << LS1C_PWM_INT_SR)
  74. | (1 << LS1C_PWM_INTEN)
  75. | (1 << LS1C_PWM_SINGLE)
  76. | (1 << LS1C_PWM_OE)
  77. | (1 << LS1C_PWM_CNT_EN);
  78. // 设置各个寄存器
  79. timer_reg_base = timer_get_reg_base(timer_info->timer); // 获取寄存器基地址
  80. reg_write_32(0, (volatile unsigned int *)(timer_reg_base + LS1C_PWM_HRC));
  81. reg_write_32(tmp--, (volatile unsigned int *)(timer_reg_base + LS1C_PWM_LRC));
  82. reg_write_32(0, (volatile unsigned int *)(timer_reg_base + LS1C_PWM_CNTR));
  83. reg_write_32(ctrl, (volatile unsigned int *)(timer_reg_base + LS1C_PWM_CTRL));
  84. return ;
  85. }
  86. /*
  87. * 判断指定定时器是否超时(实现定时)
  88. * @timer_info 定时器
  89. * @ret TRUE or FALSE
  90. */
  91. BOOL timer_is_time_out(timer_info_t *timer_info)
  92. {
  93. unsigned int timer_reg_base = 0; // 寄存器基地址
  94. unsigned int ctrl; // 控制寄存器的值
  95. // 判断入参
  96. if (NULL == timer_info)
  97. {
  98. return FALSE;
  99. }
  100. // 读取控制寄存器
  101. timer_reg_base = timer_get_reg_base(timer_info->timer);
  102. ctrl = reg_read_32((volatile unsigned int *)(timer_reg_base + LS1C_PWM_CTRL));
  103. // 判断中断状态位
  104. if (ctrl & (1 << LS1C_PWM_INT_SR))
  105. {
  106. return TRUE;
  107. }
  108. else
  109. {
  110. return FALSE;
  111. }
  112. }
  113. /*
  114. * 停止定时器
  115. * @timer_info 定时器
  116. */
  117. void timer_stop(timer_info_t *timer_info)
  118. {
  119. unsigned int timer_reg_base = 0;
  120. // 判断入参
  121. if (NULL == timer_info)
  122. {
  123. return ;
  124. }
  125. timer_reg_base = timer_get_reg_base(timer_info->timer);
  126. reg_write_32(0, (volatile unsigned int *)(timer_reg_base + LS1C_PWM_CTRL));
  127. return ;
  128. }
  129. /*
  130. * 获取定时器从初始化到现在的时间(实现计时功能),单位ns
  131. * @timer_info 硬件定时器
  132. * @ret 时间,单位ns
  133. */
  134. unsigned long timer_get_time_ns(timer_info_t *timer_info)
  135. {
  136. unsigned int timer_reg_base = 0;
  137. unsigned int cntr = 0; // 寄存器CNTR的值
  138. unsigned long time_ns = 0; // 时间,单位ns
  139. unsigned long timer_clk = 0; // 定时器时钟
  140. // 读取寄存器CNTR的值
  141. timer_reg_base = timer_get_reg_base(timer_info->timer);
  142. cntr = reg_read_32((volatile unsigned int *)(timer_reg_base + LS1C_PWM_CNTR));
  143. /*
  144. * 将CNTR值换算为时间,单位us
  145. * 时间 = (计数器值CNTR * 1000000000) / 定时器时钟频率
  146. * 为避免产生溢出,手动优化上式为 时间 = (计数器值CNTR * 1000) / (定时器时钟频率 / 1000000)
  147. */
  148. timer_clk = clk_get_apb_rate();
  149. time_ns = (cntr * 1000 ) / (timer_clk /1000000);
  150. // printf("[%s] time_us=%lu, cntr=%d, timer_clk=%d\n", __FUNCTION__, time_ns, cntr, timer_clk);
  151. return time_ns;
  152. }
  153. /*
  154. * 打印timer相关寄存器的值
  155. * @timer_info 硬件定时器
  156. */
  157. void timer_print_regs(timer_info_t *timer_info)
  158. {
  159. unsigned int timer_reg_base = 0;
  160. timer_reg_base = timer_get_reg_base(timer_info->timer);
  161. printf("CNTR=0x%x, HRC=0x%x, LRC=0x%x, CTRL=0x%x\n",
  162. reg_read_32((volatile unsigned int *)(timer_reg_base + LS1C_PWM_CNTR)),
  163. reg_read_32((volatile unsigned int *)(timer_reg_base + LS1C_PWM_HRC)),
  164. reg_read_32((volatile unsigned int *)(timer_reg_base + LS1C_PWM_LRC)),
  165. reg_read_32((volatile unsigned int *)(timer_reg_base + LS1C_PWM_CTRL)));
  166. return ;
  167. }
  168. /*
  169. * 定时器中断清
  170. * @timer_info 定时器信息
  171. */
  172. void timer_int_clr(timer_info_t *timer_info)
  173. {
  174. unsigned int timer_reg_base = 0; // 寄存器基地址
  175. unsigned int ctrl ;
  176. // 判断入参
  177. if (NULL == timer_info)
  178. {
  179. return ;
  180. }
  181. timer_reg_base = timer_get_reg_base(timer_info->timer); // 获取寄存器基地址
  182. ctrl = reg_read_32((volatile unsigned int *)(timer_reg_base + LS1C_PWM_CTRL));
  183. ctrl = ctrl | (1<<LS1C_PWM_INT_SR) ;
  184. reg_write_32(ctrl , (volatile unsigned int *)(timer_reg_base + LS1C_PWM_CTRL));
  185. ctrl = ctrl & (~(1<<LS1C_PWM_INT_SR)) ;
  186. reg_write_32(ctrl , (volatile unsigned int *)(timer_reg_base + LS1C_PWM_CTRL));
  187. return ;
  188. }
  189. /*
  190. * 定时器计数清
  191. * @timer_info 定时器信息
  192. */
  193. void timer_cnt_clr(timer_info_t *timer_info)
  194. {
  195. unsigned int timer_reg_base = 0; // 寄存器基地址
  196. unsigned int ctrl ;
  197. // 判断入参
  198. if (NULL == timer_info)
  199. {
  200. return ;
  201. }
  202. timer_reg_base = timer_get_reg_base(timer_info->timer); // 获取寄存器基地址
  203. ctrl = reg_read_32((volatile unsigned int *)(timer_reg_base + LS1C_PWM_CTRL));
  204. ctrl = ctrl | (1<<LS1C_PWM_CNTR_RST);
  205. reg_write_32(ctrl , (volatile unsigned int *)(timer_reg_base + LS1C_PWM_CTRL));
  206. ctrl = ctrl & (~(1<<LS1C_PWM_CNTR_RST)) ;
  207. reg_write_32(ctrl , (volatile unsigned int *)(timer_reg_base + LS1C_PWM_CTRL));
  208. return ;
  209. }
  210. /*
  211. * 初始化定时器,并开始中断定时
  212. * @timer_info 定时器和定时时间信息
  213. * @hrc 高中断 lrc 低中断 为1打开,为0关闭
  214. */
  215. void timer_int_init(timer_info_t *timer_info, int hrc, int lrc)
  216. {
  217. unsigned int timer_reg_base = 0; // 寄存器基地址
  218. unsigned long timer_clk = 0; // 硬件定时器的时钟
  219. unsigned long h_value, l_value;
  220. unsigned int ctrl = 0; // 控制寄存器中的控制信息
  221. // 判断入参
  222. if (NULL == timer_info)
  223. {
  224. return ;
  225. }
  226. /*
  227. * 把定时时间换算为计数器的值
  228. * 计数器值 = 定时器的时钟 * 定时时间(单位ns) / 1000000000
  229. * 龙芯1c的定时器时钟为APB时钟,达到126Mhz,
  230. * 为避免计算过程发生溢出,这里采用手动优化上面的计算式,也可以采用浮点运算
  231. */
  232. timer_clk = clk_get_apb_rate();
  233. l_value = (timer_clk / 1000000) * (timer_info->time_ns / 1000); // 将1000000000拆分为1000000和1000
  234. l_value = MIN(l_value, TIMER_COUNTER_MAX);
  235. h_value = (timer_clk / 1000000) * (timer_info->time_h_ns / 1000); // 将1000000000拆分为1000000和1000
  236. h_value = MIN(h_value, l_value);
  237. // 控制寄存器信息
  238. ctrl = (lrc << LS1C_PWM_INT_LRC_EN)
  239. | (hrc << LS1C_PWM_INT_HRC_EN)
  240. | (0 << LS1C_PWM_CNTR_RST)
  241. | (0 << LS1C_PWM_INT_SR)
  242. | (1 << LS1C_PWM_INTEN)
  243. | (1 << LS1C_PWM_SINGLE)
  244. | (1 << LS1C_PWM_OE)
  245. | (1 << LS1C_PWM_CNT_EN);
  246. // 设置各个寄存器
  247. timer_reg_base = timer_get_reg_base(timer_info->timer); // 获取寄存器基地址
  248. reg_write_32(0, (volatile unsigned int *)(timer_reg_base + LS1C_PWM_HRC));
  249. reg_write_32(l_value--, (volatile unsigned int *)(timer_reg_base + LS1C_PWM_LRC));
  250. reg_write_32(h_value--, (volatile unsigned int *)(timer_reg_base + LS1C_PWM_HRC));
  251. reg_write_32(0, (volatile unsigned int *)(timer_reg_base + LS1C_PWM_CNTR));
  252. reg_write_32(ctrl, (volatile unsigned int *)(timer_reg_base + LS1C_PWM_CTRL));
  253. return ;
  254. }