/CCS_5 C code/TCPIP/Tick.c
https://gitlab.com/ammar.rajab1/ENC28J60-LAN · C · 443 lines · 141 code · 37 blank · 265 comment · 8 complexity · aecbee3c375d4a60758c36bb80c3d488 MD5 · raw file
- /*********************************************************************
- *
- * Tick Manager for Timekeeping
- *
- *********************************************************************
- * FileName: Tick.c
- * Dependencies: Timer 0 (PIC18) or Timer 1 (PIC24F, PIC24H,
- * dsPIC30F, dsPIC33F, PIC32)
- * Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
- * Compiler: Microchip C32 v1.10b or higher
- * Microchip C30 v3.12 or higher
- * Microchip C18 v3.30 or higher
- * HI-TECH PICC-18 PRO 9.63PL2 or higher
- * Company: Microchip Technology, Inc.
- *
- * Software License Agreement
- *
- * Copyright (C) 2002-2010 Microchip Technology Inc. All rights
- * reserved.
- *
- * Microchip licenses to you the right to use, modify, copy, and
- * distribute:
- * (i) the Software when embedded on a Microchip microcontroller or
- * digital signal controller product ("Device") which is
- * integrated into Licensee's product; or
- * (ii) ONLY the Software driver source files ENC28J60.c, ENC28J60.h,
- * ENCX24J600.c and ENCX24J600.h ported to a non-Microchip device
- * used in conjunction with a Microchip ethernet controller for
- * the sole purpose of interfacing with the ethernet controller.
- *
- * You should refer to the license agreement accompanying this
- * Software for additional information regarding your rights and
- * obligations.
- *
- * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
- * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
- * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
- * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
- * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
- * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
- * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
- * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
- *
- *
- * Author Date Comment
- *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * Nilesh Rajbharti 6/28/01 Original (Rev 1.0)
- * Nilesh Rajbharti 2/9/02 Cleanup
- * Nilesh Rajbharti 5/22/02 Rev 2.0 (See version.log for detail)
- * Howard Schlunder 6/13/07 Changed to use timer without
- * writing for perfect accuracy.
- ********************************************************************/
- #define __TICK_C
-
- #include "TCPIP Stack/TCPIP.h"
-
- // Internal counter to store Ticks. This variable is incremented in an ISR and
- // therefore must be marked volatile to prevent the compiler optimizer from
- // reordering code to use this value in the main context while interrupts are
- // disabled.
- static volatile DWORD dwInternalTicks = 0;
-
- // 6-byte value to store Ticks. Allows for use over longer periods of time.
- static BYTE vTickReading[6];
-
- static void GetTickCopy(void);
-
-
- /*****************************************************************************
- Function:
- void TickInit(void)
-
- Summary:
- Initializes the Tick manager module.
-
- Description:
- Configures the Tick module and any necessary hardware resources.
-
- Precondition:
- None
-
- Parameters:
- None
-
- Returns:
- None
-
- Remarks:
- This function is called only one during lifetime of the application.
- ***************************************************************************/
- void TickInit(void)
- {
- #if defined(__18CXX)
- // Use Timer0 for 8 bit processors
- // Initialize the time
- TMR0H = 0;
- TMR0L = 0;
-
- // Set up the timer interrupt
- INTCON2bits.TMR0IP = 0; // Low priority
- INTCONbits.TMR0IF = 0;
- INTCONbits.TMR0IE = 1; // Enable interrupt
-
- // Timer0 on, 16-bit, internal timer, 1:256 prescalar
- T0CON = 0x87;
-
- #else
- // Use Timer 1 for 16-bit and 32-bit processors
- // 1:256 prescale
- T1CONbits.TCKPS = 3;
- // Base
- PR1 = 0xFFFF;
- // Clear counter
- TMR1 = 0;
-
- // Enable timer interrupt
- #if defined(__C30__)
- IPC0bits.T1IP = 2; // Interrupt priority 2 (low)
- IFS0bits.T1IF = 0;
- IEC0bits.T1IE = 1;
- #else
- IPC1bits.T1IP = 2; // Interrupt priority 2 (low)
- IFS0CLR = _IFS0_T1IF_MASK;
- IEC0SET = _IEC0_T1IE_MASK;
- #endif
-
- // Start timer
- T1CONbits.TON = 1;
- #endif
- }
-
- /*****************************************************************************
- Function:
- static void GetTickCopy(void)
-
- Summary:
- Reads the tick value.
-
- Description:
- This function performs an interrupt-safe and synchronized read of the
- 48-bit Tick value.
-
- Precondition:
- None
-
- Parameters:
- None
-
- Returns:
- None
- ***************************************************************************/
- static void GetTickCopy(void)
- {
- // Perform an Interrupt safe and synchronized read of the 48-bit
- // tick value
- #if defined(__18CXX)
- do
- {
- INTCONbits.TMR0IE = 1; // Enable interrupt
- Nop();
- INTCONbits.TMR0IE = 0; // Disable interrupt
- vTickReading[0] = TMR0L;
- vTickReading[1] = TMR0H;
- *((DWORD*)&vTickReading[2]) = dwInternalTicks;
- } while(INTCONbits.TMR0IF);
- INTCONbits.TMR0IE = 1; // Enable interrupt
- #elif defined(__C30__)
- do
- {
- DWORD dwTempTicks;
-
- IEC0bits.T1IE = 1; // Enable interrupt
- Nop();
- IEC0bits.T1IE = 0; // Disable interrupt
-
- // Get low 2 bytes
- ((WORD*)vTickReading)[0] = TMR1;
-
- // Correct corner case where interrupt increments byte[4+] but
- // TMR1 hasn't rolled over to 0x0000 yet
- dwTempTicks = dwInternalTicks;
- if(((WORD*)vTickReading)[0] == 0xFFFFu)
- dwTempTicks--;
-
- // Get high 4 bytes
- vTickReading[2] = ((BYTE*)&dwTempTicks)[0];
- vTickReading[3] = ((BYTE*)&dwTempTicks)[1];
- vTickReading[4] = ((BYTE*)&dwTempTicks)[2];
- vTickReading[5] = ((BYTE*)&dwTempTicks)[3];
- } while(IFS0bits.T1IF);
- IEC0bits.T1IE = 1; // Enable interrupt
- #else // PIC32
- do
- {
- DWORD dwTempTicks;
-
- IEC0SET = _IEC0_T1IE_MASK; // Enable interrupt
- Nop();
- IEC0CLR = _IEC0_T1IE_MASK; // Disable interrupt
-
- // Get low 2 bytes
- ((volatile WORD*)vTickReading)[0] = TMR1;
-
- // Correct corner case where interrupt increments byte[4+] but
- // TMR1 hasn't rolled over to 0x0000 yet
- dwTempTicks = dwInternalTicks;
-
- // PIC32MX3XX/4XX devices trigger the timer interrupt when TMR1 == PR1
- // (TMR1 prescalar is 0x00), requiring us to undo the ISR's increment
- // of the upper 32 bits of our 48 bit timer in the special case when
- // TMR1 == PR1 == 0xFFFF. For other PIC32 families, the ISR is
- // triggered when TMR1 increments from PR1 to 0x0000, making no special
- // corner case.
- #if __PIC32_FEATURE_SET__ <= 460
- if(((WORD*)vTickReading)[0] == 0xFFFFu)
- dwTempTicks--;
- #elif !defined(__PIC32_FEATURE_SET__)
- #error __PIC32_FEATURE_SET__ macro must be defined. You need to download a newer C32 compiler version.
- #endif
-
- // Get high 4 bytes
- vTickReading[2] = ((BYTE*)&dwTempTicks)[0];
- vTickReading[3] = ((BYTE*)&dwTempTicks)[1];
- vTickReading[4] = ((BYTE*)&dwTempTicks)[2];
- vTickReading[5] = ((BYTE*)&dwTempTicks)[3];
- } while(IFS0bits.T1IF);
- IEC0SET = _IEC0_T1IE_MASK; // Enable interrupt
- #endif
- }
-
-
- /*****************************************************************************
- Function:
- DWORD TickGet(void)
-
- Summary:
- Obtains the current Tick value.
-
- Description:
- This function retrieves the current Tick value, allowing timing and
- measurement code to be written in a non-blocking fashion. This function
- retrieves the least significant 32 bits of the internal tick counter,
- and is useful for measuring time increments ranging from a few
- microseconds to a few hours. Use TickGetDiv256 or TickGetDiv64K for
- longer periods of time.
-
- Precondition:
- None
-
- Parameters:
- None
-
- Returns:
- Lower 32 bits of the current Tick value.
- ***************************************************************************/
- DWORD TickGet(void)
- {
- GetTickCopy();
- return *((DWORD*)&vTickReading[0]);
- }
-
- /*****************************************************************************
- Function:
- DWORD TickGetDiv256(void)
-
- Summary:
- Obtains the current Tick value divided by 256.
-
- Description:
- This function retrieves the current Tick value, allowing timing and
- measurement code to be written in a non-blocking fashion. This function
- retrieves the middle 32 bits of the internal tick counter,
- and is useful for measuring time increments ranging from a few
- minutes to a few weeks. Use TickGet for shorter periods or TickGetDiv64K
- for longer ones.
-
- Precondition:
- None
-
- Parameters:
- None
-
- Returns:
- Middle 32 bits of the current Tick value.
- ***************************************************************************/
- DWORD TickGetDiv256(void)
- {
- DWORD dw;
-
- GetTickCopy();
- ((BYTE*)&dw)[0] = vTickReading[1]; // Note: This copy must be done one
- ((BYTE*)&dw)[1] = vTickReading[2]; // byte at a time to prevent misaligned
- ((BYTE*)&dw)[2] = vTickReading[3]; // memory reads, which will reset the PIC.
- ((BYTE*)&dw)[3] = vTickReading[4];
-
- return dw;
- }
-
- /*****************************************************************************
- Function:
- DWORD TickGetDiv64K(void)
-
- Summary:
- Obtains the current Tick value divided by 64K.
-
- Description:
- This function retrieves the current Tick value, allowing timing and
- measurement code to be written in a non-blocking fashion. This function
- retrieves the most significant 32 bits of the internal tick counter,
- and is useful for measuring time increments ranging from a few
- days to a few years, or for absolute time measurements. Use TickGet or
- TickGetDiv256 for shorter periods of time.
-
- Precondition:
- None
-
- Parameters:
- None
-
- Returns:
- Upper 32 bits of the current Tick value.
- ***************************************************************************/
- DWORD TickGetDiv64K(void)
- {
- DWORD dw;
-
- GetTickCopy();
- ((BYTE*)&dw)[0] = vTickReading[2]; // Note: This copy must be done one
- ((BYTE*)&dw)[1] = vTickReading[3]; // byte at a time to prevent misaligned
- ((BYTE*)&dw)[2] = vTickReading[4]; // memory reads, which will reset the PIC.
- ((BYTE*)&dw)[3] = vTickReading[5];
-
- return dw;
- }
-
-
- /*****************************************************************************
- Function:
- DWORD TickConvertToMilliseconds(DWORD dwTickValue)
-
- Summary:
- Converts a Tick value or difference to milliseconds.
-
- Description:
- This function converts a Tick value or difference to milliseconds. For
- example, TickConvertToMilliseconds(32768) returns 1000 when a 32.768kHz
- clock with no prescaler drives the Tick module interrupt.
-
- Precondition:
- None
-
- Parameters:
- dwTickValue - Value to convert to milliseconds
-
- Returns:
- Input value expressed in milliseconds.
-
- Remarks:
- This function performs division on DWORDs, which is slow. Avoid using
- it unless you absolutely must (such as displaying data to a user). For
- timeout comparisons, compare the current value to a multiple or fraction
- of TICK_SECOND, which will be calculated only once at compile time.
- ***************************************************************************/
- DWORD TickConvertToMilliseconds(DWORD dwTickValue)
- {
- return (dwTickValue+(TICKS_PER_SECOND/2000ul))/((DWORD)(TICKS_PER_SECOND/1000ul));
- }
-
-
- /*****************************************************************************
- Function:
- void TickUpdate(void)
-
- Description:
- Updates the tick value when an interrupt occurs.
-
- Precondition:
- None
-
- Parameters:
- None
-
- Returns:
- None
- ***************************************************************************/
- #if defined(__18CXX)
- void TickUpdate(void)
- {
- if(INTCONbits.TMR0IF)
- {
- // Increment internal high tick counter
- dwInternalTicks++;
-
- // Reset interrupt flag
- INTCONbits.TMR0IF = 0;
- }
- }
-
- /*****************************************************************************
- Function:
- void _ISR _T1Interrupt(void)
-
- Description:
- Updates the tick value when an interrupt occurs.
-
- Precondition:
- None
-
- Parameters:
- None
-
- Returns:
- None
- ***************************************************************************/
- #elif defined(__PIC32MX__)
- void __attribute((interrupt(ipl2), vector(_TIMER_1_VECTOR), nomips16)) _T1Interrupt(void)
- {
- // Increment internal high tick counter
- dwInternalTicks++;
-
- // Reset interrupt flag
- IFS0CLR = _IFS0_T1IF_MASK;
- }
- #else
- #if defined(__PCD__) //__CCS__ __PCH__ __PCD__ ccs added
- #int_timer1 NOCLEAR
- void _T1Interrupt(void)
- #elif __C30_VERSION__ >= 300
- void _ISR __attribute__((__no_auto_psv__)) _T1Interrupt(void)
- #else
- void _ISR _T1Interrupt(void)
- #endif
- {
- // Increment internal high tick counter
- dwInternalTicks++;
-
- // Reset interrupt flag
- IFS0bits.T1IF = 0;
- }
- #endif