ostimer_lpc2xxx.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /****************************************************************************
  2. * This file is part of the Ethernut port for the LPC2XXX
  3. *
  4. * Copyright (c) 2005 by Michael Fischer. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the author nor the names of its contributors may
  16. * be used to endorse or promote products derived from this software
  17. * without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  23. * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  24. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  25. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  26. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  27. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  28. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  29. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. *
  32. ****************************************************************************
  33. *
  34. * History:
  35. *
  36. * 24.09.05 mifi First Version
  37. * The CrossWorks for ARM toolchain will be used. Some of
  38. * this functions looks similar like my ARM uC/OS port for
  39. * CrossWorks because I have done it before (AN-1711B).
  40. * For some bit definition and information, take a look
  41. * in the LPC2119/2129/2194/2292/2294 user manual 2004 May 03.
  42. ****************************************************************************/
  43. #include <cfg/arch.h>
  44. #include <arch/arm/lpc2xxx.h>
  45. #include <dev/irqreg.h>
  46. #ifndef NUT_TICK_FREQ
  47. #define NUT_TICK_FREQ 1000UL
  48. #endif
  49. /*
  50. * This is the input frequency of
  51. * the OLIMEX LPC-E2294 eval board.
  52. */
  53. #define CLK_IN 14745600UL
  54. /*
  55. * Some stuff for the interrupt handler
  56. */
  57. typedef void (*PFNCT)(void);
  58. static PFNCT NutOSTimerTickHandler = NULL;
  59. /*
  60. * Return the frequency of the peripheral clk
  61. */
  62. static uint32_t GetPeripheralClk (void)
  63. {
  64. uint32_t msel;
  65. volatile uint32_t vpbdiv;
  66. uint32_t CPUClkFreq;
  67. uint32_t PeripheralClkFreq;
  68. msel = (uint32_t)(PLLCFG & 0x1F);
  69. CPUClkFreq = CLK_IN * (msel + 1);
  70. /*
  71. * See errata:
  72. * August 5, 2005
  73. * Version 1.8
  74. * LPC2294
  75. *
  76. * VPBDIV.1 Incorrect read of VPBDIV
  77. */
  78. vpbdiv = (uint32_t)(VPBDIV & 0x03);
  79. vpbdiv = (uint32_t)(VPBDIV & 0x03);
  80. switch (vpbdiv) {
  81. case 0: PeripheralClkFreq = CPUClkFreq / 4; break;
  82. case 1: PeripheralClkFreq = CPUClkFreq; break;
  83. case 2: PeripheralClkFreq = CPUClkFreq / 2; break;
  84. default: PeripheralClkFreq = CPUClkFreq / 4; break;
  85. }
  86. return (PeripheralClkFreq);
  87. }
  88. /*
  89. * This is our timer #0 ISR Handler
  90. */
  91. static void TimerTickISRHandler (void)
  92. {
  93. /*
  94. * Clear interrupt
  95. */
  96. T0IR = 0xFF;
  97. if (NutOSTimerTickHandler != NULL) {
  98. (*NutOSTimerTickHandler)();
  99. }
  100. /*
  101. * Update the priority hardware.
  102. */
  103. VICVectAddr = 0;
  104. }
  105. /*!
  106. * \brief Initialize system timer.
  107. *
  108. * This function is automatically called by Nut/OS
  109. * during system initialization.
  110. *
  111. * Nut/OS uses on-chip timer 0 for its timer services.
  112. * Applications should not modify any registers of this
  113. * timer, but make use of the Nut/OS timer API. Timer 1
  114. * and timer 2 are available to applications.
  115. */
  116. void NutRegisterTimer(void (*handler) (void *))
  117. {
  118. /*
  119. * Save the new handler.
  120. */
  121. NutOSTimerTickHandler = (PFNCT)handler;
  122. /*
  123. * Disable timer.
  124. */
  125. T0TCR = 0;
  126. /*
  127. * TC is incrementet on every pclk.
  128. */
  129. T0PC = 0;
  130. /*
  131. * Set match register.
  132. */
  133. T0MR0 = (GetPeripheralClk() / NUT_TICK_FREQ);
  134. /*
  135. * An interrupt is generated when MR0 matches the value in TC.
  136. * The TC will be reset if MR0 matches it.
  137. */
  138. T0MCR = 3;
  139. /*
  140. * Capture feature is disabled.
  141. */
  142. T0CCR = 0;
  143. /*
  144. * No external match.
  145. */
  146. T0EMR = 0;
  147. /*
  148. * Enable timer.
  149. */
  150. T0TCR = 1;
  151. /*
  152. * VIC TIMER #0 Initialization
  153. */
  154. VICVectAddr2 = (uint32_t)TimerTickISRHandler;
  155. VICVectCntl2 = 0x20 | VIC_TIMER0;
  156. }
  157. /*!
  158. * \brief Return the CPU clock in Hertz.
  159. *
  160. * \return CPU clock frequency in Hertz.
  161. */
  162. uint32_t NutArchClockGet(int idx)
  163. {
  164. uint32_t msel;
  165. uint32_t CPUClkFreq;
  166. msel = (uint32_t)(PLLCFG & 0x1F);
  167. CPUClkFreq = CLK_IN * (msel + 1);
  168. return CPUClkFreq;
  169. }
  170. /*!
  171. * \brief Return the number of system ticks per second.
  172. *
  173. * \return System tick frequency in Hertz.
  174. */
  175. uint32_t NutGetTickClock(void)
  176. {
  177. return NUT_TICK_FREQ;
  178. }
  179. /*!
  180. * \brief Calculate system ticks for a given number of milliseconds.
  181. */
  182. uint32_t NutTimerMillisToTicks(uint32_t ms)
  183. {
  184. #if (NUT_TICK_FREQ % 1000)
  185. if (ms >= 0x3E8000UL)
  186. return (ms / 1000UL) * NUT_TICK_FREQ;
  187. return (ms * NUT_TICK_FREQ + 999UL) / 1000UL;
  188. #else
  189. return ms * (NUT_TICK_FREQ / 1000UL);
  190. #endif
  191. }