PageRenderTime 46ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/CCS_5 C code/TCPIP/Tick.c

https://gitlab.com/ammar.rajab1/ENC28J60-LAN
C | 443 lines | 141 code | 37 blank | 265 comment | 5 complexity | aecbee3c375d4a60758c36bb80c3d488 MD5 | raw file
  1. /*********************************************************************
  2. *
  3. * Tick Manager for Timekeeping
  4. *
  5. *********************************************************************
  6. * FileName: Tick.c
  7. * Dependencies: Timer 0 (PIC18) or Timer 1 (PIC24F, PIC24H,
  8. * dsPIC30F, dsPIC33F, PIC32)
  9. * Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
  10. * Compiler: Microchip C32 v1.10b or higher
  11. * Microchip C30 v3.12 or higher
  12. * Microchip C18 v3.30 or higher
  13. * HI-TECH PICC-18 PRO 9.63PL2 or higher
  14. * Company: Microchip Technology, Inc.
  15. *
  16. * Software License Agreement
  17. *
  18. * Copyright (C) 2002-2010 Microchip Technology Inc. All rights
  19. * reserved.
  20. *
  21. * Microchip licenses to you the right to use, modify, copy, and
  22. * distribute:
  23. * (i) the Software when embedded on a Microchip microcontroller or
  24. * digital signal controller product ("Device") which is
  25. * integrated into Licensee's product; or
  26. * (ii) ONLY the Software driver source files ENC28J60.c, ENC28J60.h,
  27. * ENCX24J600.c and ENCX24J600.h ported to a non-Microchip device
  28. * used in conjunction with a Microchip ethernet controller for
  29. * the sole purpose of interfacing with the ethernet controller.
  30. *
  31. * You should refer to the license agreement accompanying this
  32. * Software for additional information regarding your rights and
  33. * obligations.
  34. *
  35. * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
  36. * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
  37. * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
  38. * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  39. * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
  40. * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
  41. * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
  42. * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
  43. * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
  44. * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
  45. * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
  46. *
  47. *
  48. * Author Date Comment
  49. *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  50. * Nilesh Rajbharti 6/28/01 Original (Rev 1.0)
  51. * Nilesh Rajbharti 2/9/02 Cleanup
  52. * Nilesh Rajbharti 5/22/02 Rev 2.0 (See version.log for detail)
  53. * Howard Schlunder 6/13/07 Changed to use timer without
  54. * writing for perfect accuracy.
  55. ********************************************************************/
  56. #define __TICK_C
  57. #include "TCPIP Stack/TCPIP.h"
  58. // Internal counter to store Ticks. This variable is incremented in an ISR and
  59. // therefore must be marked volatile to prevent the compiler optimizer from
  60. // reordering code to use this value in the main context while interrupts are
  61. // disabled.
  62. static volatile DWORD dwInternalTicks = 0;
  63. // 6-byte value to store Ticks. Allows for use over longer periods of time.
  64. static BYTE vTickReading[6];
  65. static void GetTickCopy(void);
  66. /*****************************************************************************
  67. Function:
  68. void TickInit(void)
  69. Summary:
  70. Initializes the Tick manager module.
  71. Description:
  72. Configures the Tick module and any necessary hardware resources.
  73. Precondition:
  74. None
  75. Parameters:
  76. None
  77. Returns:
  78. None
  79. Remarks:
  80. This function is called only one during lifetime of the application.
  81. ***************************************************************************/
  82. void TickInit(void)
  83. {
  84. #if defined(__18CXX)
  85. // Use Timer0 for 8 bit processors
  86. // Initialize the time
  87. TMR0H = 0;
  88. TMR0L = 0;
  89. // Set up the timer interrupt
  90. INTCON2bits.TMR0IP = 0; // Low priority
  91. INTCONbits.TMR0IF = 0;
  92. INTCONbits.TMR0IE = 1; // Enable interrupt
  93. // Timer0 on, 16-bit, internal timer, 1:256 prescalar
  94. T0CON = 0x87;
  95. #else
  96. // Use Timer 1 for 16-bit and 32-bit processors
  97. // 1:256 prescale
  98. T1CONbits.TCKPS = 3;
  99. // Base
  100. PR1 = 0xFFFF;
  101. // Clear counter
  102. TMR1 = 0;
  103. // Enable timer interrupt
  104. #if defined(__C30__)
  105. IPC0bits.T1IP = 2; // Interrupt priority 2 (low)
  106. IFS0bits.T1IF = 0;
  107. IEC0bits.T1IE = 1;
  108. #else
  109. IPC1bits.T1IP = 2; // Interrupt priority 2 (low)
  110. IFS0CLR = _IFS0_T1IF_MASK;
  111. IEC0SET = _IEC0_T1IE_MASK;
  112. #endif
  113. // Start timer
  114. T1CONbits.TON = 1;
  115. #endif
  116. }
  117. /*****************************************************************************
  118. Function:
  119. static void GetTickCopy(void)
  120. Summary:
  121. Reads the tick value.
  122. Description:
  123. This function performs an interrupt-safe and synchronized read of the
  124. 48-bit Tick value.
  125. Precondition:
  126. None
  127. Parameters:
  128. None
  129. Returns:
  130. None
  131. ***************************************************************************/
  132. static void GetTickCopy(void)
  133. {
  134. // Perform an Interrupt safe and synchronized read of the 48-bit
  135. // tick value
  136. #if defined(__18CXX)
  137. do
  138. {
  139. INTCONbits.TMR0IE = 1; // Enable interrupt
  140. Nop();
  141. INTCONbits.TMR0IE = 0; // Disable interrupt
  142. vTickReading[0] = TMR0L;
  143. vTickReading[1] = TMR0H;
  144. *((DWORD*)&vTickReading[2]) = dwInternalTicks;
  145. } while(INTCONbits.TMR0IF);
  146. INTCONbits.TMR0IE = 1; // Enable interrupt
  147. #elif defined(__C30__)
  148. do
  149. {
  150. DWORD dwTempTicks;
  151. IEC0bits.T1IE = 1; // Enable interrupt
  152. Nop();
  153. IEC0bits.T1IE = 0; // Disable interrupt
  154. // Get low 2 bytes
  155. ((WORD*)vTickReading)[0] = TMR1;
  156. // Correct corner case where interrupt increments byte[4+] but
  157. // TMR1 hasn't rolled over to 0x0000 yet
  158. dwTempTicks = dwInternalTicks;
  159. if(((WORD*)vTickReading)[0] == 0xFFFFu)
  160. dwTempTicks--;
  161. // Get high 4 bytes
  162. vTickReading[2] = ((BYTE*)&dwTempTicks)[0];
  163. vTickReading[3] = ((BYTE*)&dwTempTicks)[1];
  164. vTickReading[4] = ((BYTE*)&dwTempTicks)[2];
  165. vTickReading[5] = ((BYTE*)&dwTempTicks)[3];
  166. } while(IFS0bits.T1IF);
  167. IEC0bits.T1IE = 1; // Enable interrupt
  168. #else // PIC32
  169. do
  170. {
  171. DWORD dwTempTicks;
  172. IEC0SET = _IEC0_T1IE_MASK; // Enable interrupt
  173. Nop();
  174. IEC0CLR = _IEC0_T1IE_MASK; // Disable interrupt
  175. // Get low 2 bytes
  176. ((volatile WORD*)vTickReading)[0] = TMR1;
  177. // Correct corner case where interrupt increments byte[4+] but
  178. // TMR1 hasn't rolled over to 0x0000 yet
  179. dwTempTicks = dwInternalTicks;
  180. // PIC32MX3XX/4XX devices trigger the timer interrupt when TMR1 == PR1
  181. // (TMR1 prescalar is 0x00), requiring us to undo the ISR's increment
  182. // of the upper 32 bits of our 48 bit timer in the special case when
  183. // TMR1 == PR1 == 0xFFFF. For other PIC32 families, the ISR is
  184. // triggered when TMR1 increments from PR1 to 0x0000, making no special
  185. // corner case.
  186. #if __PIC32_FEATURE_SET__ <= 460
  187. if(((WORD*)vTickReading)[0] == 0xFFFFu)
  188. dwTempTicks--;
  189. #elif !defined(__PIC32_FEATURE_SET__)
  190. #error __PIC32_FEATURE_SET__ macro must be defined. You need to download a newer C32 compiler version.
  191. #endif
  192. // Get high 4 bytes
  193. vTickReading[2] = ((BYTE*)&dwTempTicks)[0];
  194. vTickReading[3] = ((BYTE*)&dwTempTicks)[1];
  195. vTickReading[4] = ((BYTE*)&dwTempTicks)[2];
  196. vTickReading[5] = ((BYTE*)&dwTempTicks)[3];
  197. } while(IFS0bits.T1IF);
  198. IEC0SET = _IEC0_T1IE_MASK; // Enable interrupt
  199. #endif
  200. }
  201. /*****************************************************************************
  202. Function:
  203. DWORD TickGet(void)
  204. Summary:
  205. Obtains the current Tick value.
  206. Description:
  207. This function retrieves the current Tick value, allowing timing and
  208. measurement code to be written in a non-blocking fashion. This function
  209. retrieves the least significant 32 bits of the internal tick counter,
  210. and is useful for measuring time increments ranging from a few
  211. microseconds to a few hours. Use TickGetDiv256 or TickGetDiv64K for
  212. longer periods of time.
  213. Precondition:
  214. None
  215. Parameters:
  216. None
  217. Returns:
  218. Lower 32 bits of the current Tick value.
  219. ***************************************************************************/
  220. DWORD TickGet(void)
  221. {
  222. GetTickCopy();
  223. return *((DWORD*)&vTickReading[0]);
  224. }
  225. /*****************************************************************************
  226. Function:
  227. DWORD TickGetDiv256(void)
  228. Summary:
  229. Obtains the current Tick value divided by 256.
  230. Description:
  231. This function retrieves the current Tick value, allowing timing and
  232. measurement code to be written in a non-blocking fashion. This function
  233. retrieves the middle 32 bits of the internal tick counter,
  234. and is useful for measuring time increments ranging from a few
  235. minutes to a few weeks. Use TickGet for shorter periods or TickGetDiv64K
  236. for longer ones.
  237. Precondition:
  238. None
  239. Parameters:
  240. None
  241. Returns:
  242. Middle 32 bits of the current Tick value.
  243. ***************************************************************************/
  244. DWORD TickGetDiv256(void)
  245. {
  246. DWORD dw;
  247. GetTickCopy();
  248. ((BYTE*)&dw)[0] = vTickReading[1]; // Note: This copy must be done one
  249. ((BYTE*)&dw)[1] = vTickReading[2]; // byte at a time to prevent misaligned
  250. ((BYTE*)&dw)[2] = vTickReading[3]; // memory reads, which will reset the PIC.
  251. ((BYTE*)&dw)[3] = vTickReading[4];
  252. return dw;
  253. }
  254. /*****************************************************************************
  255. Function:
  256. DWORD TickGetDiv64K(void)
  257. Summary:
  258. Obtains the current Tick value divided by 64K.
  259. Description:
  260. This function retrieves the current Tick value, allowing timing and
  261. measurement code to be written in a non-blocking fashion. This function
  262. retrieves the most significant 32 bits of the internal tick counter,
  263. and is useful for measuring time increments ranging from a few
  264. days to a few years, or for absolute time measurements. Use TickGet or
  265. TickGetDiv256 for shorter periods of time.
  266. Precondition:
  267. None
  268. Parameters:
  269. None
  270. Returns:
  271. Upper 32 bits of the current Tick value.
  272. ***************************************************************************/
  273. DWORD TickGetDiv64K(void)
  274. {
  275. DWORD dw;
  276. GetTickCopy();
  277. ((BYTE*)&dw)[0] = vTickReading[2]; // Note: This copy must be done one
  278. ((BYTE*)&dw)[1] = vTickReading[3]; // byte at a time to prevent misaligned
  279. ((BYTE*)&dw)[2] = vTickReading[4]; // memory reads, which will reset the PIC.
  280. ((BYTE*)&dw)[3] = vTickReading[5];
  281. return dw;
  282. }
  283. /*****************************************************************************
  284. Function:
  285. DWORD TickConvertToMilliseconds(DWORD dwTickValue)
  286. Summary:
  287. Converts a Tick value or difference to milliseconds.
  288. Description:
  289. This function converts a Tick value or difference to milliseconds. For
  290. example, TickConvertToMilliseconds(32768) returns 1000 when a 32.768kHz
  291. clock with no prescaler drives the Tick module interrupt.
  292. Precondition:
  293. None
  294. Parameters:
  295. dwTickValue - Value to convert to milliseconds
  296. Returns:
  297. Input value expressed in milliseconds.
  298. Remarks:
  299. This function performs division on DWORDs, which is slow. Avoid using
  300. it unless you absolutely must (such as displaying data to a user). For
  301. timeout comparisons, compare the current value to a multiple or fraction
  302. of TICK_SECOND, which will be calculated only once at compile time.
  303. ***************************************************************************/
  304. DWORD TickConvertToMilliseconds(DWORD dwTickValue)
  305. {
  306. return (dwTickValue+(TICKS_PER_SECOND/2000ul))/((DWORD)(TICKS_PER_SECOND/1000ul));
  307. }
  308. /*****************************************************************************
  309. Function:
  310. void TickUpdate(void)
  311. Description:
  312. Updates the tick value when an interrupt occurs.
  313. Precondition:
  314. None
  315. Parameters:
  316. None
  317. Returns:
  318. None
  319. ***************************************************************************/
  320. #if defined(__18CXX)
  321. void TickUpdate(void)
  322. {
  323. if(INTCONbits.TMR0IF)
  324. {
  325. // Increment internal high tick counter
  326. dwInternalTicks++;
  327. // Reset interrupt flag
  328. INTCONbits.TMR0IF = 0;
  329. }
  330. }
  331. /*****************************************************************************
  332. Function:
  333. void _ISR _T1Interrupt(void)
  334. Description:
  335. Updates the tick value when an interrupt occurs.
  336. Precondition:
  337. None
  338. Parameters:
  339. None
  340. Returns:
  341. None
  342. ***************************************************************************/
  343. #elif defined(__PIC32MX__)
  344. void __attribute((interrupt(ipl2), vector(_TIMER_1_VECTOR), nomips16)) _T1Interrupt(void)
  345. {
  346. // Increment internal high tick counter
  347. dwInternalTicks++;
  348. // Reset interrupt flag
  349. IFS0CLR = _IFS0_T1IF_MASK;
  350. }
  351. #else
  352. #if defined(__PCD__) //__CCS__ __PCH__ __PCD__ ccs added
  353. #int_timer1 NOCLEAR
  354. void _T1Interrupt(void)
  355. #elif __C30_VERSION__ >= 300
  356. void _ISR __attribute__((__no_auto_psv__)) _T1Interrupt(void)
  357. #else
  358. void _ISR _T1Interrupt(void)
  359. #endif
  360. {
  361. // Increment internal high tick counter
  362. dwInternalTicks++;
  363. // Reset interrupt flag
  364. IFS0bits.T1IF = 0;
  365. }
  366. #endif