hw_timer.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /******************************************************************************
  2. * Copyright 2013-2014 Espressif Systems (Wuxi)
  3. *
  4. * FileName: hw_time.c
  5. *
  6. * Description: hw_time driver
  7. *
  8. * Modification history:
  9. * 2014/5/1, v1.0 create this file.
  10. *******************************************************************************/
  11. #include "ets_sys.h"
  12. #include "os_type.h"
  13. #include "osapi.h"
  14. #if 1
  15. #define US_TO_RTC_TIMER_TICKS(t) \
  16. ((t) ? \
  17. (((t) > 0x35A) ? \
  18. (((t)>>2) * ((APB_CLK_FREQ>>4)/250000) + ((t)&0x3) * ((APB_CLK_FREQ>>4)/1000000)) : \
  19. (((t) *(APB_CLK_FREQ>>4)) / 1000000)) : \
  20. 0)
  21. #define FRC1_ENABLE_TIMER BIT7
  22. #define FRC1_AUTO_LOAD BIT6
  23. //TIMER PREDIVED MODE
  24. typedef enum {
  25. DIVDED_BY_1 = 0, //timer clock
  26. DIVDED_BY_16 = 4, //divided by 16
  27. DIVDED_BY_256 = 8, //divided by 256
  28. } TIMER_PREDIVED_MODE;
  29. typedef enum { //timer interrupt mode
  30. TM_LEVEL_INT = 1, // level interrupt
  31. TM_EDGE_INT = 0, //edge interrupt
  32. } TIMER_INT_MODE;
  33. typedef enum {
  34. FRC1_SOURCE = 0,
  35. NMI_SOURCE = 1,
  36. } FRC1_TIMER_SOURCE_TYPE;
  37. static void (* user_hw_timer_cb)(void) = NULL;
  38. static u8 TimeType = 0;
  39. static u8 AutoLoad = 0;
  40. static u8 Cando = 0;
  41. static void hw_timer_isr_cb(void)
  42. {
  43. //if(user_hw_timer_cb!=NULL)
  44. // (*(user_hw_timer_cb))();
  45. if(AutoLoad == 1)
  46. {
  47. if (user_hw_timer_cb != NULL) {
  48. (*user_hw_timer_cb)();
  49. }
  50. }
  51. else if(AutoLoad == 0)
  52. {
  53. if(Cando)
  54. {
  55. Cando = 0;
  56. if (user_hw_timer_cb != NULL) {
  57. (*user_hw_timer_cb)();
  58. }
  59. }
  60. }
  61. }
  62. /******************************************************************************
  63. * FunctionName : hw_timer_arm
  64. * Description : set a trigger timer delay for this timer.
  65. * Parameters : uint32 val :
  66. in autoload mode
  67. 50 ~ 0x7fffff; for FRC1 source.
  68. 100 ~ 0x7fffff; for NMI source.
  69. in non autoload mode:
  70. 10 ~ 0x7fffff;
  71. * Returns : NONE
  72. *******************************************************************************/
  73. void hw_timer_arm(u32 val)
  74. {
  75. RTC_REG_WRITE(FRC1_LOAD_ADDRESS, US_TO_RTC_TIMER_TICKS(val));
  76. if(AutoLoad == 0)
  77. {
  78. Cando = 1;
  79. }
  80. }
  81. /******************************************************************************
  82. * FunctionName : hw_timer_set_func
  83. * Description : set the func, when trigger timer is up.
  84. * Parameters : void (* user_hw_timer_cb_set)(void):
  85. timer callback function,
  86. * Returns : NONE
  87. *******************************************************************************/
  88. void hw_timer_set_func(void (* user_hw_timer_cb_set)(void))
  89. {
  90. user_hw_timer_cb = user_hw_timer_cb_set;
  91. }
  92. /******************************************************************************
  93. * FunctionName : hw_timer_init
  94. * Description : initilize the hardware isr timer
  95. * Parameters :
  96. FRC1_TIMER_SOURCE_TYPE source_type:
  97. FRC1_SOURCE, timer use frc1 isr as isr source.
  98. NMI_SOURCE, timer use nmi isr as isr source.
  99. u8 req:
  100. 0, not autoload,
  101. 1, autoload mode,
  102. * Returns : NONE
  103. *******************************************************************************/
  104. void ICACHE_FLASH_ATTR hw_timer_init(FRC1_TIMER_SOURCE_TYPE source_type,u8 req)
  105. {
  106. if(req == 1){
  107. RTC_REG_WRITE(FRC1_CTRL_ADDRESS, FRC1_AUTO_LOAD|
  108. DIVDED_BY_16
  109. | FRC1_ENABLE_TIMER
  110. | TM_EDGE_INT);
  111. AutoLoad = 1;
  112. }
  113. else{
  114. RTC_REG_WRITE(FRC1_CTRL_ADDRESS,
  115. DIVDED_BY_16
  116. | FRC1_ENABLE_TIMER
  117. | TM_EDGE_INT);
  118. AutoLoad = 0;
  119. }
  120. if(source_type == NMI_SOURCE)
  121. {
  122. // #define NMI_SOURCE_SEL_REG 0x3ff00000
  123. // WRITE_PERI_REG(NMI_SOURCE_SEL_REG, (READ_PERI_REG(NMI_SOURCE_SEL_REG)&~0x1F)|(0x1+0x7*2) );
  124. // NmiTimSetFunc(hw_timer_isr_cb);
  125. ETS_FRC_TIMER1_NMI_INTR_ATTACH(hw_timer_isr_cb);
  126. TimeType = 1;
  127. }
  128. else{
  129. ETS_FRC_TIMER1_INTR_ATTACH( hw_timer_isr_cb,NULL);
  130. TimeType = 0;
  131. }
  132. TM1_EDGE_INT_ENABLE();
  133. ETS_FRC1_INTR_ENABLE();
  134. }
  135. void hw_timer_stop(void)
  136. {
  137. //RTC_REG_WRITE(FRC1_CTRL_ADDRESS,DIVDED_BY_16 | FRC1_ENABLE_TIMER | TM_EDGE_INT);
  138. os_printf("hw tim stop\n");
  139. // RemoveNmiISR();
  140. hw_timer_init(1, 0);
  141. // hw_timer_set_func(NULL);
  142. //hw_timer_arm(150);
  143. }
  144. //-------------------------------Test Code Below--------------------------------------
  145. #if 0
  146. Example1:
  147. #define REG_READ(_r) (*(volatile uint32 *)(_r))
  148. #define WDEV_NOW()\
  149. REG_READ(0x3ff20c00)
  150. static u32 tick_now2 = 0;
  151. void hw_test_timer_cb(void)
  152. {
  153. static uint16 j = 0;
  154. j++;
  155. if( (WDEV_NOW() - tick_now2) >= 1000000 )
  156. {
  157. static u32 idx = 1;
  158. tick_now2 = WDEV_NOW();
  159. os_printf("b%u:%d\n",idx++,j);
  160. j = 0;
  161. }
  162. //hw_timer_arm(50);
  163. }
  164. typedef enum {
  165. FRC1_SOURCE = 0,
  166. NMI_SOURCE = 1,
  167. } FRC1_TIMER_SOURCE_TYPE;
  168. void ICACHE_FLASH_ATTR user_init(void)
  169. {
  170. hw_timer_init(FRC1_SOURCE,1); //hw_timer_init(NMI_SOURCE,1);
  171. hw_timer_set_func(hw_test_timer_cb);
  172. hw_timer_arm(100);
  173. }
  174. Example2:
  175. /*
  176. Do not use ICACHE_FLASH_ATTR before this ISR Callback
  177. static void ICACHE_FLASH_ATTR stepper_timer_cb(void) is WRONG
  178. */
  179. static void stepper_timer_cb(void)
  180. {
  181. static u16 j=100;
  182. if(j-- ==0)
  183. {ets_printf("z%u\n",j); j=100;}
  184. hw_timer_arm(2500);
  185. }
  186. void ICACHE_FLASH_ATTR user_init(void)
  187. {
  188. hw_timer_init(0,0);
  189. hw_timer_set_func(stepper_timer_cb);
  190. hw_timer_arm(2500);
  191. }
  192. #endif
  193. /*
  194. NOTE:
  195. 1 if use nmi source, for autoload timer , the timer setting val can't be less than 100.
  196. 2 if use nmi source, this timer has highest priority, can interrupt other isr.
  197. 3 if use frc1 source, this timer can't interrupt other isr.
  198. */
  199. #endif