timer.c
上传用户:mhstny
上传日期:2022-08-05
资源大小:793k
文件大小:6k
源码类别:

微处理器开发

开发平台:

Unix_Linux

  1. #include "def.h"
  2. #include "2410addr.h"
  3. #include "2410slib.h"
  4. #include "2410lib.h"
  5. #include "2410slib.h"
  6. #include "timer.h"
  7. #define EXT_XTAL_FREQ 12000000
  8. #define BIOS_TIMER_FREQ 100
  9. U32 SYS_FCLK, SYS_HCLK, SYS_PCLK;
  10. static U8 sCLKDIVN, SlowMode;
  11. static U8 chg_os_timer, os_timer_run, chg_bios_timer, bios_timer_run;
  12. static U16 os_timer_rld, bios_timer_rld;
  13. static U16 Timer4Cnt, Timer4Freq;
  14. static U16 DoBiosEvent;
  15. static void SetHclkPclk()
  16. {
  17. if(sCLKDIVN&2)
  18. SYS_HCLK = SYS_FCLK>>1;
  19. else
  20. SYS_HCLK = SYS_FCLK;
  21. if(sCLKDIVN&1)
  22. SYS_PCLK = SYS_HCLK>>1;
  23. else
  24. SYS_PCLK = SYS_HCLK;
  25. }
  26. U8 SetSysFclk(U32 val)
  27. {
  28. U32 i, freq;
  29. U8 mdiv, pdiv, sdiv;
  30. if(SlowMode)
  31. return FALSE;
  32. mdiv = (val>>12)&0xff;
  33. pdiv = (val>>4)&0x3f;
  34. sdiv = val&0x3;
  35. i = (pdiv+2);
  36. while(sdiv--)
  37. i *= 2;
  38. freq = ((mdiv+8)*EXT_XTAL_FREQ)/i;
  39. if(freq>=(3*EXT_XTAL_FREQ)) {
  40. rMPLLCON = val;
  41. SYS_FCLK = freq;
  42. SetHclkPclk();
  43. if(os_timer_run) {
  44. os_timer_rld = SYS_PCLK/(8*4*Timer4Freq)-1;
  45. chg_os_timer = 1;
  46. }
  47. if(bios_timer_run) {
  48. bios_timer_rld = SYS_PCLK/(8*4*BIOS_TIMER_FREQ)-1;
  49. chg_bios_timer = 1;
  50. }
  51. return TRUE;
  52. }
  53. return FALSE;
  54. }
  55. void SetClockDivider(int hdivn, int pdivn)
  56. {
  57.      // hdivn,pdivn FCLK:HCLK:PCLK
  58.      //     0,0         1:1:1 
  59.      //     0,1         1:1:2 
  60.      //     1,0         1:2:2
  61.      //     1,1         1:2:4
  62.     if(SlowMode)
  63.      return;
  64.      
  65. hdivn &= 1;
  66. pdivn &= 1;
  67. sCLKDIVN = (hdivn<<1)|pdivn;
  68. rCLKDIVN = sCLKDIVN;
  69.     if(hdivn)
  70.         MMU_SetAsyncBusMode();
  71.     else 
  72.         MMU_SetFastBusMode();
  73.         
  74. SetHclkPclk();
  75. }
  76. void ChangeSlowMode(U16 mode)
  77. {
  78. static U32 save_clk, save_div;
  79. U8 div;
  80. if(mode&CLKSLOW_SLOW_BIT) { //enter slow mode
  81. div = mode&7;
  82. save_clk = SYS_FCLK;
  83. save_div = sCLKDIVN;
  84. if(div)
  85. SYS_FCLK = EXT_XTAL_FREQ/(2*div);
  86. else
  87. SYS_FCLK = EXT_XTAL_FREQ;
  88. SetClockDivider(0, 0);
  89. rCLKSLOW = mode;
  90. SlowMode = 1;
  91. } else { //exit slow mode
  92. SlowMode = 0; //clear SlowMode before SetClockDivider
  93. mode &= ~CLKSLOW_MPLL_OFF; //must enable MPLL
  94. SYS_FCLK = save_clk;
  95. SetClockDivider(save_div>>1, save_div);
  96. rCLKSLOW = mode;
  97. }
  98. }
  99. /**************************************************************/
  100. static void __irq ISR_Timer4(void)
  101. {
  102. // ClearPending(BIT_TIMER4);
  103. register i;
  104. rSRCPND = BIT_TIMER4;
  105. rINTPND = BIT_TIMER4;
  106. i = rINTPND;
  107. /*
  108. Timer4Cnt--;
  109. if(!Timer4Cnt) {
  110. Timer4Cnt = Timer4Freq;
  111. led ^= 0xf;
  112. Led_Display(led);
  113. }
  114. */
  115. if(chg_os_timer) {
  116. chg_os_timer = 0;
  117. rTCNTB4 = os_timer_rld;
  118. rTCON  &= 0xff0fffff; //stop Timer4
  119. rTCON  |= 0x00700000; //auto-reload, update TCNTB4, start Timer4
  120. rTCON  &= 0xffdfffff;
  121. }
  122. }
  123. U32 OpenOsTimer(U16 OSTimer)
  124. {
  125. Timer4Freq = 1000/OSTimer;
  126. Timer4Cnt  = Timer4Freq;
  127. rTCFG0 &= 0xffff00ff;
  128. rTCFG0 |= 7<<8; //8 prescaler
  129. rTCFG1 &= 0xfff0ffff;
  130. rTCFG1 |= 1<<16; //mux = 1/4
  131. rTCNTB4 = SYS_PCLK/(8*4*Timer4Freq)-1;
  132. rTCON  &= 0xff0fffff; //stop Timer4
  133. rTCON  |= 0x00700000; //auto-reload, update TCNTB4, start Timer4
  134. rTCON  &= 0xffdfffff;
  135. os_timer_run = 1;
  136. pISR_TIMER4  = (U32)ISR_Timer4;
  137. ClearPending(BIT_TIMER4);
  138. EnableIrq(BIT_TIMER4);
  139. return 14;
  140. }
  141. __inline void ClearOsTimerPnd(void)
  142. {
  143. // ClearPending(BIT_TIMER4);
  144. register i;
  145. rSRCPND = BIT_TIMER4;
  146. rINTPND = BIT_TIMER4;
  147. i = rINTPND;
  148. }
  149. /*********************************************************/
  150. static struct{
  151. U16 cnt;
  152. U16 rld;
  153. void (*proc)(U32);
  154. }BiosTimerEvent[MaxBiosTimerEvent];
  155. static U16 bios_tick_run = 0;
  156. static U32 bios_tick_cnt;
  157. static __irq void ISR_Timer3(void)
  158. {
  159. U32 i;
  160. register r;
  161. // ClearPending(BIT_TIMER3);
  162. rSRCPND = BIT_TIMER3;
  163. rINTPND = BIT_TIMER3;
  164. r = rINTPND;
  165. if(chg_bios_timer) {
  166. chg_bios_timer = 0;
  167. rTCNTB3 = bios_timer_rld;
  168. rTCON  &= 0xfff0ffff;
  169. rTCON  |= 0x000b0000;
  170. rTCON  &= 0xfffdffff;
  171. }
  172. bios_tick_cnt++; //whenever bios_tick_run is 1 or 0, bios_tick_cnt++
  173. for(i=0; i<MaxBiosTimerEvent; i++) {
  174. if(BiosTimerEvent[i].proc) {
  175. BiosTimerEvent[i].cnt--;
  176. if(!BiosTimerEvent[i].cnt) {
  177. BiosTimerEvent[i].cnt = BiosTimerEvent[i].rld;
  178. (*BiosTimerEvent[i].proc)(i);
  179. }
  180. }
  181. }
  182. if(!(DoBiosEvent||bios_tick_run)) {
  183. bios_timer_run = 0;
  184. DisableIrq(BIT_TIMER3);
  185. }
  186. }
  187. static void OpenBiosTimer(void)
  188. {
  189. U16 i;
  190. if(!bios_timer_run) {
  191. DoBiosEvent = 0;
  192. for(i=0; i<MaxBiosTimerEvent; i++) {
  193. BiosTimerEvent[i].proc = 0;
  194. }
  195. if(!os_timer_run) {
  196. rTCFG0 &= 0xffff00ff;
  197. rTCFG0 |= 7<<8; //8 prescaler
  198. }
  199. rTCFG1 &= 0xffff0fff;
  200. rTCFG1 |= 1<<12; //mux = 1/4
  201. rTCNTB3 = SYS_PCLK/(8*4*BIOS_TIMER_FREQ)-1;
  202. rTCON  &= 0xfff0ffff;
  203. rTCON  |= 0x000b0000;
  204. rTCON  &= 0xfffdffff;
  205. bios_timer_run = 1;
  206. pISR_TIMER3    = (U32)ISR_Timer3;
  207. ClearPending(BIT_TIMER3);
  208. EnableIrq(BIT_TIMER3);
  209. }
  210. }
  211. int RequestBiosTimerEvent(U16 rld, void (*proc)(U32))
  212. {
  213. int i=-1;
  214. U32 r;
  215. EnterCritical(&r);
  216. if(!bios_timer_run)
  217. OpenBiosTimer();
  218. for(i=0; i<MaxBiosTimerEvent; i++)
  219. if(!BiosTimerEvent[i].proc) {
  220. BiosTimerEvent[i].cnt  = rld;
  221. BiosTimerEvent[i].rld  = rld;
  222. BiosTimerEvent[i].proc = proc;
  223. DoBiosEvent++;
  224. break;
  225. }
  226. ExitCritical(&r);
  227. return i;
  228. }
  229. void ReleaseBiosTimerEvent(U16 number)
  230. {
  231. U32 r;
  232. EnterCritical(&r);
  233. if((number<MaxBiosTimerEvent)&&(BiosTimerEvent[number].proc)) {
  234. BiosTimerEvent[number].proc = 0;
  235. if(DoBiosEvent)
  236. DoBiosEvent--;
  237. }
  238. ExitCritical(&r);
  239. }
  240. void RtcOpenTick(void)
  241. {
  242. if(!bios_timer_run)
  243. OpenBiosTimer();
  244. if(!bios_tick_run)
  245. bios_tick_cnt = 0;
  246. bios_tick_run = 1;
  247. }
  248. void RtcCloseTick(void)
  249. {
  250. bios_tick_run = 0;
  251. }
  252. BYTE RtcReadTick(U32 *pTicks)
  253. {
  254. BYTE r;
  255. if(!bios_tick_run) {
  256. *pTicks = 0;
  257. return 0;
  258. }
  259. r = (bios_tick_cnt!=*pTicks);
  260. *pTicks = bios_tick_cnt;
  261. return r;
  262. }