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 }