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 }