ostimer_lpc2xxx.c

Go to the documentation of this file.
00001 /****************************************************************************
00002 *  This file is part of the Ethernut port for the LPC2XXX
00003 *
00004 *  Copyright (c) 2005 by Michael Fischer. All rights reserved.
00005 *
00006 *  Redistribution and use in source and binary forms, with or without 
00007 *  modification, are permitted provided that the following conditions 
00008 *  are met:
00009 *  
00010 *  1. Redistributions of source code must retain the above copyright 
00011 *     notice, this list of conditions and the following disclaimer.
00012 *  2. Redistributions in binary form must reproduce the above copyright
00013 *     notice, this list of conditions and the following disclaimer in the 
00014 *     documentation and/or other materials provided with the distribution.
00015 *  3. Neither the name of the author nor the names of its contributors may 
00016 *     be used to endorse or promote products derived from this software 
00017 *     without specific prior written permission.
00018 *
00019 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
00020 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
00021 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
00022 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
00023 *  THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
00024 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
00025 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 
00026 *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
00027 *  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
00028 *  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
00029 *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
00030 *  SUCH DAMAGE.
00031 *
00032 ****************************************************************************
00033 *
00034 *  History:
00035 *
00036 *  24.09.05  mifi   First Version
00037 *                   The CrossWorks for ARM toolchain will be used. Some of 
00038 *                   this functions looks similar like my ARM uC/OS port for 
00039 *                   CrossWorks because I have done it before (AN-1711B).
00040 *                   For some bit definition and information, take a look
00041 *                   in the LPC2119/2129/2194/2292/2294 user manual 2004 May 03.
00042 ****************************************************************************/
00043 
00044 #include <cfg/arch.h>
00045 #include <arch/arm/lpc2xxx.h>
00046 #include <dev/irqreg.h>
00047 
00048 #ifndef NUT_TICK_FREQ
00049 #define NUT_TICK_FREQ 1000UL
00050 #endif
00051 
00052 /*
00053  * This is the input frequency of 
00054  * the OLIMEX LPC-E2294 eval board.
00055  */
00056 #define CLK_IN        14745600UL
00057 
00058 /*
00059  * Some stuff for the interrupt handler
00060  */
00061 typedef  void (*PFNCT)(void);
00062 static PFNCT NutOSTimerTickHandler = NULL;
00063 
00064 /*
00065  * Return the frequency of the peripheral clk
00066  */
00067 static u_long GetPeripheralClk (void)
00068 {
00069     u_long          msel;
00070     volatile u_long vpbdiv;
00071     u_long          CPUClkFreq;
00072     u_long          PeripheralClkFreq;
00073 
00074     msel       = (u_long)(PLLCFG & 0x1F);
00075     CPUClkFreq = CLK_IN * (msel + 1);
00076 
00077     /*
00078      * See errata:
00079      * August 5, 2005
00080      * Version 1.8
00081      * LPC2294
00082      *
00083      * VPBDIV.1 Incorrect read of VPBDIV
00084      */
00085     vpbdiv = (u_long)(VPBDIV & 0x03);
00086     vpbdiv = (u_long)(VPBDIV & 0x03);
00087     switch (vpbdiv) {
00088         case 0:  PeripheralClkFreq = CPUClkFreq / 4;  break;
00089         case 1:  PeripheralClkFreq = CPUClkFreq;      break;
00090         case 2:  PeripheralClkFreq = CPUClkFreq / 2;  break;
00091         default: PeripheralClkFreq = CPUClkFreq / 4;  break;
00092     }
00093     
00094     return (PeripheralClkFreq);
00095 }
00096 
00097 /*
00098  * This is our timer #0 ISR Handler
00099  */
00100 static void TimerTickISRHandler (void)
00101 {
00102     /*
00103      * Clear interrupt
00104      */ 
00105     T0IR = 0xFF;
00106     
00107     if (NutOSTimerTickHandler != NULL) {    
00108         (*NutOSTimerTickHandler)();    
00109     }    
00110     
00111     /*
00112      * Update the priority hardware.
00113      */                                             
00114     VICVectAddr = 0;
00115 }
00116 
00117 
00131 void NutDelay(u_char ms)
00132 {
00133     int i;
00134 
00135     while (ms--) {
00136         for (i = 893; i--; ) {
00137             _NOP();
00138         }
00139     }
00140 }
00141 
00153 void NutRegisterTimer(void (*handler) (void *))
00154 {
00155     /* 
00156      * Save the new handler.
00157      */
00158     NutOSTimerTickHandler = (PFNCT)handler;
00159 
00160     /* 
00161      * Disable timer.
00162      */
00163     T0TCR = 0;
00164     
00165     /* 
00166      * TC is incrementet on every pclk.
00167      */
00168     T0PC  = 0;
00169     
00170     /* 
00171      * Set match register.
00172      */
00173     T0MR0 = (GetPeripheralClk() / NUT_TICK_FREQ);
00174     
00175     /* 
00176      * An interrupt is generated when MR0 matches the value in TC.
00177      * The TC will be reset if MR0 matches it.
00178      */
00179     T0MCR = 3;
00180     
00181     /*
00182      * Capture feature is disabled.
00183      */
00184     T0CCR = 0;
00185     
00186     /*
00187      * No external match.
00188      */
00189     T0EMR = 0;
00190     
00191     /*
00192      * Enable timer.
00193      */
00194     T0TCR = 1;
00195 
00196     /* 
00197      * VIC TIMER #0 Initialization
00198      */
00199     VICVectAddr2  = (u_long)TimerTickISRHandler;
00200     VICVectCntl2  = 0x20 | VIC_TIMER0;
00201 }
00202 
00203 
00209 u_long NutGetCpuClock(void)
00210 {
00211     u_long msel;
00212     u_long CPUClkFreq;
00213 
00214     msel       = (u_long)(PLLCFG & 0x1F);
00215     CPUClkFreq = CLK_IN * (msel + 1);
00216 
00217     return CPUClkFreq;
00218 }
00219 
00225 u_long NutGetTickClock(void)
00226 {
00227     return NUT_TICK_FREQ;
00228 }
00229 
00233 u_long NutTimerMillisToTicks(u_long ms)
00234 {
00235     u_long x;
00236 
00237     x = ms * NutGetTickClock() / 1000UL;
00238     if (x == 0) {
00239         x = 1;
00240     }
00241     
00242     return (x);
00243 }

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/