PageRenderTime 41ms CodeModel.GetById 26ms app.highlight 11ms RepoModel.GetById 0ms app.codeStats 1ms

/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
 58#include "TCPIP Stack/TCPIP.h"
 59
 60// Internal counter to store Ticks.  This variable is incremented in an ISR and 
 61// therefore must be marked volatile to prevent the compiler optimizer from 
 62// reordering code to use this value in the main context while interrupts are 
 63// disabled.
 64static volatile DWORD dwInternalTicks = 0;
 65
 66// 6-byte value to store Ticks.  Allows for use over longer periods of time.
 67static BYTE vTickReading[6];
 68
 69static void GetTickCopy(void);
 70
 71
 72/*****************************************************************************
 73  Function:
 74	void TickInit(void)
 75
 76  Summary:
 77	Initializes the Tick manager module.
 78
 79  Description:
 80	Configures the Tick module and any necessary hardware resources.
 81
 82  Precondition:
 83	None
 84
 85  Parameters:
 86	None
 87
 88  Returns:
 89  	None
 90  	
 91  Remarks:
 92	This function is called only one during lifetime of the application.
 93  ***************************************************************************/
 94void TickInit(void)
 95{
 96#if defined(__18CXX)
 97	// Use Timer0 for 8 bit processors
 98    // Initialize the time
 99    TMR0H = 0;
100    TMR0L = 0;
101
102	// Set up the timer interrupt
103	INTCON2bits.TMR0IP = 0;		// Low priority
104    INTCONbits.TMR0IF = 0;
105    INTCONbits.TMR0IE = 1;		// Enable interrupt
106
107    // Timer0 on, 16-bit, internal timer, 1:256 prescalar
108    T0CON = 0x87;
109
110#else
111	// Use Timer 1 for 16-bit and 32-bit processors
112	// 1:256 prescale
113	T1CONbits.TCKPS = 3;
114	// Base
115	PR1 = 0xFFFF;
116	// Clear counter
117	TMR1 = 0;
118
119	// Enable timer interrupt
120	#if defined(__C30__)
121		IPC0bits.T1IP = 2;	// Interrupt priority 2 (low)
122		IFS0bits.T1IF = 0;
123		IEC0bits.T1IE = 1;
124	#else
125		IPC1bits.T1IP = 2;	// Interrupt priority 2 (low)
126		IFS0CLR = _IFS0_T1IF_MASK;
127		IEC0SET = _IEC0_T1IE_MASK;
128	#endif
129
130	// Start timer
131	T1CONbits.TON = 1;
132#endif
133}
134
135/*****************************************************************************
136  Function:
137	static void GetTickCopy(void)
138
139  Summary:
140	Reads the tick value.
141
142  Description:
143	This function performs an interrupt-safe and synchronized read of the 
144	48-bit Tick value.
145
146  Precondition:
147	None
148
149  Parameters:
150	None
151
152  Returns:
153  	None
154  ***************************************************************************/
155static void GetTickCopy(void)
156{
157	// Perform an Interrupt safe and synchronized read of the 48-bit 
158	// tick value
159#if defined(__18CXX)
160	do
161	{
162		INTCONbits.TMR0IE = 1;		// Enable interrupt
163		Nop();
164		INTCONbits.TMR0IE = 0;		// Disable interrupt
165		vTickReading[0] = TMR0L;
166		vTickReading[1] = TMR0H;
167		*((DWORD*)&vTickReading[2]) = dwInternalTicks;
168	} while(INTCONbits.TMR0IF);
169	INTCONbits.TMR0IE = 1;			// Enable interrupt
170#elif defined(__C30__)
171	do
172	{
173		DWORD dwTempTicks;
174		
175		IEC0bits.T1IE = 1;			// Enable interrupt
176		Nop();
177		IEC0bits.T1IE = 0;			// Disable interrupt
178
179		// Get low 2 bytes
180		((WORD*)vTickReading)[0] = TMR1;
181		
182		// Correct corner case where interrupt increments byte[4+] but 
183		// TMR1 hasn't rolled over to 0x0000 yet
184		dwTempTicks = dwInternalTicks;
185		if(((WORD*)vTickReading)[0] == 0xFFFFu)
186			dwTempTicks--;
187		
188		// Get high 4 bytes
189		vTickReading[2] = ((BYTE*)&dwTempTicks)[0];
190		vTickReading[3] = ((BYTE*)&dwTempTicks)[1];
191		vTickReading[4] = ((BYTE*)&dwTempTicks)[2];
192		vTickReading[5] = ((BYTE*)&dwTempTicks)[3];
193	} while(IFS0bits.T1IF);
194	IEC0bits.T1IE = 1;				// Enable interrupt
195#else	// PIC32
196	do
197	{
198		DWORD dwTempTicks;
199		
200		IEC0SET = _IEC0_T1IE_MASK;	// Enable interrupt
201		Nop();
202		IEC0CLR = _IEC0_T1IE_MASK;	// Disable interrupt
203		
204		// Get low 2 bytes
205		((volatile WORD*)vTickReading)[0] = TMR1;
206		
207		// Correct corner case where interrupt increments byte[4+] but 
208		// TMR1 hasn't rolled over to 0x0000 yet
209		dwTempTicks = dwInternalTicks;
210
211		// PIC32MX3XX/4XX devices trigger the timer interrupt when TMR1 == PR1 
212		// (TMR1 prescalar is 0x00), requiring us to undo the ISR's increment 
213		// of the upper 32 bits of our 48 bit timer in the special case when 
214		// TMR1 == PR1 == 0xFFFF.  For other PIC32 families, the ISR is 
215		// triggered when TMR1 increments from PR1 to 0x0000, making no special 
216		// corner case.
217		#if __PIC32_FEATURE_SET__ <= 460
218			if(((WORD*)vTickReading)[0] == 0xFFFFu)
219				dwTempTicks--;
220		#elif !defined(__PIC32_FEATURE_SET__)
221			#error __PIC32_FEATURE_SET__ macro must be defined.  You need to download a newer C32 compiler version.
222		#endif
223		
224		// Get high 4 bytes
225		vTickReading[2] = ((BYTE*)&dwTempTicks)[0];
226		vTickReading[3] = ((BYTE*)&dwTempTicks)[1];
227		vTickReading[4] = ((BYTE*)&dwTempTicks)[2];
228		vTickReading[5] = ((BYTE*)&dwTempTicks)[3];
229	} while(IFS0bits.T1IF);
230	IEC0SET = _IEC0_T1IE_MASK;		// Enable interrupt
231#endif
232}
233
234
235/*****************************************************************************
236  Function:
237	DWORD TickGet(void)
238
239  Summary:
240	Obtains the current Tick value.
241
242  Description:
243	This function retrieves the current Tick value, allowing timing and
244	measurement code to be written in a non-blocking fashion.  This function
245	retrieves the least significant 32 bits of the internal tick counter, 
246	and is useful for measuring time increments ranging from a few 
247	microseconds to a few hours.  Use TickGetDiv256 or TickGetDiv64K for
248	longer periods of time.
249
250  Precondition:
251	None
252
253  Parameters:
254	None
255
256  Returns:
257  	Lower 32 bits of the current Tick value.
258  ***************************************************************************/
259DWORD TickGet(void)
260{
261	GetTickCopy();
262	return *((DWORD*)&vTickReading[0]);
263}
264
265/*****************************************************************************
266  Function:
267	DWORD TickGetDiv256(void)
268
269  Summary:
270	Obtains the current Tick value divided by 256.
271
272  Description:
273	This function retrieves the current Tick value, allowing timing and
274	measurement code to be written in a non-blocking fashion.  This function
275	retrieves the middle 32 bits of the internal tick counter, 
276	and is useful for measuring time increments ranging from a few 
277	minutes to a few weeks.  Use TickGet for shorter periods or TickGetDiv64K
278	for longer ones.
279
280  Precondition:
281	None
282
283  Parameters:
284	None
285
286  Returns:
287  	Middle 32 bits of the current Tick value.
288  ***************************************************************************/
289DWORD TickGetDiv256(void)
290{
291	DWORD dw;
292
293	GetTickCopy();
294	((BYTE*)&dw)[0] = vTickReading[1];	// Note: This copy must be done one 
295	((BYTE*)&dw)[1] = vTickReading[2];	// byte at a time to prevent misaligned 
296	((BYTE*)&dw)[2] = vTickReading[3];	// memory reads, which will reset the PIC.
297	((BYTE*)&dw)[3] = vTickReading[4];
298	
299	return dw;
300}
301
302/*****************************************************************************
303  Function:
304	DWORD TickGetDiv64K(void)
305
306  Summary:
307	Obtains the current Tick value divided by 64K.
308
309  Description:
310	This function retrieves the current Tick value, allowing timing and
311	measurement code to be written in a non-blocking fashion.  This function
312	retrieves the most significant 32 bits of the internal tick counter, 
313	and is useful for measuring time increments ranging from a few 
314	days to a few years, or for absolute time measurements.  Use TickGet or
315	TickGetDiv256 for shorter periods of time.
316
317  Precondition:
318	None
319
320  Parameters:
321	None
322
323  Returns:
324  	Upper 32 bits of the current Tick value.
325  ***************************************************************************/
326DWORD TickGetDiv64K(void)
327{
328	DWORD dw;
329
330	GetTickCopy();
331	((BYTE*)&dw)[0] = vTickReading[2];	// Note: This copy must be done one 
332	((BYTE*)&dw)[1] = vTickReading[3];	// byte at a time to prevent misaligned 
333	((BYTE*)&dw)[2] = vTickReading[4];	// memory reads, which will reset the PIC.
334	((BYTE*)&dw)[3] = vTickReading[5];
335	
336	return dw;
337}
338
339
340/*****************************************************************************
341  Function:
342	DWORD TickConvertToMilliseconds(DWORD dwTickValue)
343
344  Summary:
345	Converts a Tick value or difference to milliseconds.
346
347  Description:
348	This function converts a Tick value or difference to milliseconds.  For
349	example, TickConvertToMilliseconds(32768) returns 1000 when a 32.768kHz 
350	clock with no prescaler drives the Tick module interrupt.
351
352  Precondition:
353	None
354
355  Parameters:
356	dwTickValue	- Value to convert to milliseconds
357
358  Returns:
359  	Input value expressed in milliseconds.
360
361  Remarks:
362	This function performs division on DWORDs, which is slow.  Avoid using
363	it unless you absolutely must (such as displaying data to a user).  For
364	timeout comparisons, compare the current value to a multiple or fraction 
365	of TICK_SECOND, which will be calculated only once at compile time.
366  ***************************************************************************/
367DWORD TickConvertToMilliseconds(DWORD dwTickValue)
368{
369	return (dwTickValue+(TICKS_PER_SECOND/2000ul))/((DWORD)(TICKS_PER_SECOND/1000ul));
370}
371
372
373/*****************************************************************************
374  Function:
375	void TickUpdate(void)
376
377  Description:
378	Updates the tick value when an interrupt occurs.
379
380  Precondition:
381	None
382
383  Parameters:
384	None
385
386  Returns:
387  	None
388  ***************************************************************************/
389#if defined(__18CXX)
390void TickUpdate(void)
391{
392    if(INTCONbits.TMR0IF)
393    {
394		// Increment internal high tick counter
395		dwInternalTicks++;
396
397		// Reset interrupt flag
398        INTCONbits.TMR0IF = 0;
399    }
400}
401
402/*****************************************************************************
403  Function:
404	void _ISR _T1Interrupt(void)
405
406  Description:
407	Updates the tick value when an interrupt occurs.
408
409  Precondition:
410	None
411
412  Parameters:
413	None
414
415  Returns:
416  	None
417  ***************************************************************************/
418#elif defined(__PIC32MX__)
419void __attribute((interrupt(ipl2), vector(_TIMER_1_VECTOR), nomips16)) _T1Interrupt(void)
420{
421	// Increment internal high tick counter
422	dwInternalTicks++;
423
424	// Reset interrupt flag
425	IFS0CLR = _IFS0_T1IF_MASK;
426}
427#else
428#if defined(__PCD__)  //__CCS__ __PCH__ __PCD__ ccs added
429#int_timer1 NOCLEAR
430void _T1Interrupt(void)
431#elif __C30_VERSION__ >= 300
432void _ISR __attribute__((__no_auto_psv__)) _T1Interrupt(void)
433#else
434void _ISR _T1Interrupt(void)
435#endif
436{
437	// Increment internal high tick counter
438	dwInternalTicks++;
439
440	// Reset interrupt flag
441	IFS0bits.T1IF = 0;
442}
443#endif