Nut/OS  4.10.3
API Reference
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 uint32_t GetPeripheralClk (void)
00068 {
00069     uint32_t          msel;
00070     volatile uint32_t vpbdiv;
00071     uint32_t          CPUClkFreq;
00072     uint32_t          PeripheralClkFreq;
00073 
00074     msel       = (uint32_t)(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 = (uint32_t)(VPBDIV & 0x03);
00086     vpbdiv = (uint32_t)(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 
00128 void NutRegisterTimer(void (*handler) (void *))
00129 {
00130     /* 
00131      * Save the new handler.
00132      */
00133     NutOSTimerTickHandler = (PFNCT)handler;
00134 
00135     /* 
00136      * Disable timer.
00137      */
00138     T0TCR = 0;
00139     
00140     /* 
00141      * TC is incrementet on every pclk.
00142      */
00143     T0PC  = 0;
00144     
00145     /* 
00146      * Set match register.
00147      */
00148     T0MR0 = (GetPeripheralClk() / NUT_TICK_FREQ);
00149     
00150     /* 
00151      * An interrupt is generated when MR0 matches the value in TC.
00152      * The TC will be reset if MR0 matches it.
00153      */
00154     T0MCR = 3;
00155     
00156     /*
00157      * Capture feature is disabled.
00158      */
00159     T0CCR = 0;
00160     
00161     /*
00162      * No external match.
00163      */
00164     T0EMR = 0;
00165     
00166     /*
00167      * Enable timer.
00168      */
00169     T0TCR = 1;
00170 
00171     /* 
00172      * VIC TIMER #0 Initialization
00173      */
00174     VICVectAddr2  = (uint32_t)TimerTickISRHandler;
00175     VICVectCntl2  = 0x20 | VIC_TIMER0;
00176 }
00177 
00178 
00184 uint32_t NutArchClockGet(int idx)
00185 {
00186     uint32_t msel;
00187     uint32_t CPUClkFreq;
00188 
00189     msel       = (uint32_t)(PLLCFG & 0x1F);
00190     CPUClkFreq = CLK_IN * (msel + 1);
00191 
00192     return CPUClkFreq;
00193 }
00194 
00200 uint32_t NutGetTickClock(void)
00201 {
00202     return NUT_TICK_FREQ;
00203 }
00204 
00208 uint32_t NutTimerMillisToTicks(uint32_t ms)
00209 {
00210 #if (NUT_TICK_FREQ % 1000)
00211     if (ms >= 0x3E8000UL)
00212         return (ms / 1000UL) * NUT_TICK_FREQ;
00213     return (ms * NUT_TICK_FREQ + 999UL) / 1000UL;
00214 #else
00215     return ms * (NUT_TICK_FREQ / 1000UL);
00216 #endif
00217 }