EDF - OnePIC MCU  v1.1.0
source/Microchip/Common/TimeDelay.c
Go to the documentation of this file.
00001 /******************************************************************************
00002 
00003 File Name:       TimeDelay.c
00004 Dependencies:    None
00005 Processor:       PIC18/PIC24/dsPIC30/dsPIC33/PIC32
00006 Compiler:        C30 v3.12
00007 Company:         Microchip Technology, Inc.
00008 
00009 Copyright (C) 2010 Microchip Technology Inc.  All rights reserved.
00010 
00011 Microchip licenses to you the right to use, modify, copy and distribute 
00012 Software only when embedded on a Microchip microcontroller or digital signal 
00013 controller that is integrated into your product or third party product 
00014 (pursuant to the sublicense terms in the accompanying license agreement).  
00015 
00016 You should refer to the license agreement accompanying this Software for 
00017 additional information regarding your rights and obligations.
00018 
00019 SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
00020 EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF 
00021 MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. 
00022 IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER 
00023 CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR 
00024 OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES 
00025 INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR 
00026 CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF 
00027 SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES 
00028 (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
00029 
00030 Author          Date    Comments
00031 --------------------------------------------------------------------------------
00032 AKN     2009.10.14      FILE CREATED
00033 AKN     2009.10.15      CHANGED C18 DELAY ROUTINE TO DECREMENT ENTIRE NUMBER OF CYCLES
00034 AKN     2009.10.19      CHANGED C30 DELAY ROUTINE TO MATCH C18 IMPLEMENTATION
00035 AKN     2009.10.26      ADDED C32 DELAY ROUTINE TO MATCH C18 IMPLEMENTATION
00036 AKN     2009.10.27      CONSOLIDATED C30 AND C32 IMPLEMENTATIONS, ADDED PADDING TO
00037                 MAKE C30 DELAYS MORE ACCURATE
00038 PAT     2010.01.26      CONVERTED LOCALS TO VOLATILE 
00039 PAT     2010.03.07      ADDED include "Compiler.h"
00040  *******************************************************************************/
00041 
00046 #if defined(__PIC32MX__)
00047 #include <plib.h>
00048 #endif
00049 #include "bsp.h"
00050 #include "Compiler.h"
00051 //#include "HardwareProfile.h"
00052 
00053 #include "TimeDelay.h" 
00054 
00059 void Delay10us(UINT32 tenMicroSecondCounter) {
00060     volatile INT32 cyclesRequiredForEntireDelay;
00061 #if defined (__PICC__)
00062     uint8_t i;
00063     for (i = 0; i != tenMicroSecondCounter; i++)
00064             __delay_us(10);
00065 //    if (GetInstructionClock() <= 2500000) {
00066 //
00067 //    }
00068 #elif defined(__18CXX)
00069 
00070     if (GetInstructionClock() <= 2500000) //for all FCY speeds under 2MHz (FOSC <= 10MHz)
00071     {
00072         //26 cycles burned through this path (includes return to caller).
00073         //For FOSC == 1MHZ, it takes 104us.
00074         //For FOSC == 4MHZ, it takes 26us
00075         //For FOSC == 8MHZ, it takes 13us.
00076         //For FOSC == 10MHZ, it takes 10.5us.
00077     } else {
00078         //14 cycles burned to this point.
00079 
00080         //We want to pre-calculate number of cycles required to delay 10us * tenMicroSecondCounter using a 1 cycle granule.
00081         cyclesRequiredForEntireDelay = (INT32) (GetInstructionClock() / 100000) * tenMicroSecondCounter;
00082 
00083         //We subtract all the cycles used up until we reach the while loop below, where each loop cycle count is subtracted.
00084         //Also we subtract the 22 cycle function return.
00085         cyclesRequiredForEntireDelay -= (153 + 22);
00086 
00087         if (cyclesRequiredForEntireDelay <= 45) {
00088             // If we have exceeded the cycle count already, bail! Best compromise between FOSC == 12MHz and FOSC == 24MHz.
00089         } else {
00090             //Try as you may, you can't get out of this heavier-duty case under 30us. ;]
00091 
00092             while (cyclesRequiredForEntireDelay > 0) //153 cycles used to this point.
00093             {
00094                 Nop(); //Delay one instruction cycle at a time, not absolutely necessary.
00095                 cyclesRequiredForEntireDelay -= 42; //Subtract cycles burned while doing each delay stage, 42 in this case.
00096             }
00097         }
00098     }
00099 
00100 #elif defined(__C30__) || defined(__PIC32MX__)
00101 
00102     if (GetInstructionClock() <= 500000) //for all FCY speeds under 500KHz (FOSC <= 1MHz)
00103     {
00104         //10 cycles burned through this path (includes return to caller).
00105         //For FOSC == 1MHZ, it takes 5us.
00106         //For FOSC == 4MHZ, it takes 0.5us
00107         //For FOSC == 8MHZ, it takes 0.25us.
00108         //For FOSC == 10MHZ, it takes 0.2us.
00109     } else {
00110         //7 cycles burned to this point.
00111 
00112         //We want to pre-calculate number of cycles required to delay 10us * tenMicroSecondCounter using a 1 cycle granule.
00113         cyclesRequiredForEntireDelay = (INT32) (GetInstructionClock() / 100000) * tenMicroSecondCounter;
00114 
00115 #if defined(__C30__)
00116         //We subtract all the cycles used up until we reach the while loop below, where each loop cycle count is subtracted.
00117         //Also we subtract the 5 cycle function return.
00118         cyclesRequiredForEntireDelay -= 44; //(29 + 5) + 10 cycles padding
00119 #elif defined(__PIC32MX__)
00120         //We subtract all the cycles used up until we reach the while loop below, where each loop cycle count is subtracted.
00121         //Also we subtract the 5 cycle function return.
00122         cyclesRequiredForEntireDelay -= 24; //(19 + 5)
00123 #endif
00124 
00125         if (cyclesRequiredForEntireDelay <= 0) {
00126             // If we have exceeded the cycle count already, bail!
00127         } else {
00128             while (cyclesRequiredForEntireDelay > 0) //19 cycles used to this point.
00129             {
00130 #if defined(__C30__)
00131                 cyclesRequiredForEntireDelay -= 11; //Subtract cycles burned while doing each delay stage, 12 in this case. Add one cycle as padding.
00132 #elif defined(__PIC32MX__)
00133                 cyclesRequiredForEntireDelay -= 8; //Subtract cycles burned while doing each delay stage, 8 in this case.
00134 #endif
00135             }
00136         }
00137     }
00138 #endif
00139 }
00140 
00145 void DelayMs(UINT16 ms) {
00146 #if defined(__PICC__)
00147     uint16_t i;
00148     for (i = ms; i != 0; i--)
00149         __delay_ms(1);
00150     //    INT32 cyclesRequiredForEntireDelay;
00151     //    // We want to pre-calculate number of cycles required to delay 1ms, using a 1 cycle granule.
00152     //    cyclesRequiredForEntireDelay = (unsigned long) (GetInstructionClock() / 1000) * ms;
00153     //
00154     //    // We subtract all the cycles used up until we reach the while loop below, where each loop cycle count is subtracted.
00155     //    // Also we subtract the 22 cycle function return.
00156     //    cyclesRequiredForEntireDelay -= (148 + 22);
00157     //
00158     //    if (cyclesRequiredForEntireDelay <= (170 + 25)) {
00159     //        return; // If we have exceeded the cycle count already, bail!
00160     //    } else {
00161     //        while (cyclesRequiredForEntireDelay > 0) //148 cycles used to this point.
00162     //        {
00163     //            NOP(); // Delay one instruction cycle at a time, not absolutely necessary.
00164     //            cyclesRequiredForEntireDelay -= 26; // Subtract cycles burned while doing each delay stage, 39 in this case.
00165     //        }
00166     //    }
00167 #elif defined(__18CXX)
00168 
00169     INT32 cyclesRequiredForEntireDelay;
00170 
00171     // We want to pre-calculate number of cycles required to delay 1ms, using a 1 cycle granule.
00172     cyclesRequiredForEntireDelay = (signed long) (GetInstructionClock() / 1000) * ms;
00173 
00174     // We subtract all the cycles used up until we reach the while loop below, where each loop cycle count is subtracted.
00175     // Also we subtract the 22 cycle function return.
00176     cyclesRequiredForEntireDelay -= (148 + 22);
00177 
00178     if (cyclesRequiredForEntireDelay <= (170 + 25)) {
00179         return; // If we have exceeded the cycle count already, bail!
00180     } else {
00181         while (cyclesRequiredForEntireDelay > 0) //148 cycles used to this point.
00182         {
00183             Nop(); // Delay one instruction cycle at a time, not absolutely necessary.
00184             cyclesRequiredForEntireDelay -= 39; // Subtract cycles burned while doing each delay stage, 39 in this case.
00185         }
00186     }
00187 
00188 
00189 #elif defined(__C30__) || defined(__PIC32MX__)
00190 
00191     volatile UINT8 i;
00192 
00193     while (ms--) {
00194         i = 4;
00195         while (i--) {
00196             Delay10us(25);
00197         }
00198     }
00199 #endif
00200 }
00201