timer.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956
  1. /*
  2. * Copyright (C) 2001-2006 by egnite Software GmbH. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the copyright holders nor the names of
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  24. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  25. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  26. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  27. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. *
  30. * For additional information see http://www.ethernut.de/
  31. */
  32. /*!
  33. * \file os/timer.c
  34. * \brief System timer support.
  35. *
  36. * This kernel module contains the hardware independent system timer routines.
  37. *
  38. * \verbatim
  39. *
  40. * $Log$
  41. * Revision 1.39 2009/03/05 22:16:57 freckle
  42. * use __NUT_EMULATION instead of __APPLE__, __linux__, or __CYGWIN__
  43. *
  44. * Revision 1.38 2009/01/19 18:55:12 haraldkipp
  45. * Added stack checking code.
  46. *
  47. * Revision 1.37 2009/01/17 15:37:52 haraldkipp
  48. * Added some NUTASSERT macros to check function parameters.
  49. *
  50. * Revision 1.36 2008/08/22 09:25:35 haraldkipp
  51. * Clock value caching and new functions NutArchClockGet, NutClockGet and
  52. * NutClockSet added.
  53. *
  54. * Revision 1.35 2008/08/11 07:00:34 haraldkipp
  55. * BSD types replaced by stdint types (feature request #1282721).
  56. *
  57. * Revision 1.34 2008/07/29 07:28:17 haraldkipp
  58. * Late timer destroy, hopefully solves bug #2029411.
  59. *
  60. * Revision 1.33 2008/07/08 08:25:05 haraldkipp
  61. * NutDelay is no more architecture specific.
  62. * Number of loops per millisecond is configurable or will be automatically
  63. * determined.
  64. * A new function NutMicroDelay provides shorter delays.
  65. *
  66. * Revision 1.32 2007/05/29 16:31:25 freckle
  67. * corrected comment
  68. *
  69. * Revision 1.31 2006/07/26 11:16:12 haraldkipp
  70. * NutSleep() didn't take the difference between timer creation time and
  71. * last timer elapsed processing into account. This may resulted in shorter
  72. * sleep time. Thanks to Andras Albert for this fix.
  73. *
  74. * Revision 1.30 2006/06/28 14:42:28 haraldkipp
  75. * Event and timer handling re-design, again.
  76. * Time-out timers are now released early.
  77. * The timer list is now double linked to reduce removal time.
  78. * Internally timeout condition is now flagged by setting the timer handle
  79. * to SIGNALED.
  80. * The documentation had been updated.
  81. * NUTDEBUG code requires some updates. Temporarly removed.
  82. * LGPL copyright removed after all the initial sources had been finally
  83. * replaced by BSDL'ed code.
  84. * Variable nut_ticks_resume is used in NutTimerProcessElapsed() only. Moved
  85. * there.
  86. *
  87. * Revision 1.29 2006/01/26 15:34:49 going_nuts
  88. * adapted to new interrupt handling scheme for unix emulation
  89. * now uses Unix timer and runs without interrupts unless you emulate other hardware
  90. *
  91. * Revision 1.28 2005/08/03 14:43:54 freckle
  92. * made nut_tick public
  93. *
  94. * Revision 1.27 2005/07/26 16:01:19 haraldkipp
  95. * Cygwin added.
  96. * Platform dependent code is now located in arch/(target)/ostimer.c.
  97. *
  98. * Revision 1.26 2005/07/21 15:31:04 freckle
  99. * rewrote timer handling. timer interrupt handler only updates nut_ticks now
  100. *
  101. * Revision 1.25 2005/07/20 09:26:34 haraldkipp
  102. * Use native heap calls to avoid dependencies
  103. *
  104. * Revision 1.24 2005/07/15 14:44:46 freckle
  105. * corrected NutGetMillis, update comments
  106. *
  107. * Revision 1.23 2005/07/12 16:37:02 freckle
  108. * made NutTimerInsert public
  109. *
  110. * Revision 1.22 2005/07/12 16:26:04 freckle
  111. * extracted timer creation from NutTimerStartTicks into NutTimerCreate
  112. *
  113. * Revision 1.21 2005/07/12 15:23:40 olereinhardt
  114. * Added NULL pointer checks in NutTimerProcessElapsed(void)
  115. *
  116. * Revision 1.20 2005/07/12 15:10:43 freckle
  117. * removed critical section in NutSleep
  118. *
  119. * Revision 1.19 2005/07/07 12:43:49 freckle
  120. * removed stopped timers in NutTimerProcessElapsed
  121. *
  122. * Revision 1.18 2005/06/14 19:04:44 freckle
  123. * Fixed NutTimerStopAsync(): it now removes callback ptr => timer stop
  124. *
  125. * Revision 1.17 2005/06/12 16:53:01 haraldkipp
  126. * Major redesing to reduce interrupt latency.
  127. * Much better seperation of hardware dependent and independent parts.
  128. *
  129. * Revision 1.16 2005/05/27 17:30:27 drsung
  130. * Platform dependant files were moved to /arch directory.
  131. *
  132. * Revision 1.15 2005/02/21 12:37:57 phblum
  133. * Removed tabs and added semicolons after NUTTRACER macros
  134. *
  135. * Revision 1.14 2005/02/16 19:53:27 haraldkipp
  136. * Ready-to-run queue handling removed from interrupt context.
  137. *
  138. * Revision 1.13 2005/02/10 07:06:51 hwmaier
  139. * Changes to incorporate support for AT90CAN128 CPU
  140. *
  141. * Revision 1.12 2005/01/24 22:34:40 freckle
  142. * Added new tracer by Phlipp Blum <blum@tik.ee.ethz.ch>
  143. *
  144. * Revision 1.11 2005/01/19 17:59:43 freckle
  145. * Improved interrupt performance by reducing some critical section
  146. *
  147. * Revision 1.10 2005/01/13 18:51:23 haraldkipp
  148. * Moved ms62_5 counter to nutinit.c to make sure this is located in internal
  149. * RAM (AVR platforms). This fixes the wrong baudrate bug for applications
  150. * occupying all internal RAM.
  151. *
  152. * Optimized some timer handling.
  153. *
  154. * Revision 1.9 2005/01/02 10:07:10 haraldkipp
  155. * Replaced platform dependant formats in debug outputs.
  156. *
  157. * Revision 1.8 2004/09/08 10:53:25 haraldkipp
  158. * os/timer.c
  159. *
  160. * Revision 1.7 2004/04/07 12:13:58 haraldkipp
  161. * Matthias Ringwald's *nix emulation added
  162. *
  163. * Revision 1.6 2004/03/19 09:05:12 jdubiec
  164. * Fixed format strings declarations for AVR.
  165. *
  166. * Revision 1.5 2004/03/16 16:48:45 haraldkipp
  167. * Added Jan Dubiec's H8/300 port.
  168. *
  169. * Revision 1.4 2004/02/01 18:49:48 haraldkipp
  170. * Added CPU family support
  171. *
  172. * Revision 1.3 2003/11/03 16:34:21 haraldkipp
  173. * New API returns system uptime in miliseconds
  174. *
  175. * Revision 1.2 2003/10/13 10:17:11 haraldkipp
  176. * Seconds counter added
  177. *
  178. * Revision 1.1.1.1 2003/05/09 14:41:55 haraldkipp
  179. * Initial using 3.2.1
  180. *
  181. * Revision 1.24 2003/05/06 18:56:58 harald
  182. * Allow compilation without clock crystal
  183. *
  184. * Revision 1.23 2003/04/21 17:09:19 harald
  185. * *** empty log message ***
  186. *
  187. * Revision 1.22 2003/03/31 14:39:54 harald
  188. * *** empty log message ***
  189. *
  190. * Revision 1.21 2003/02/04 18:15:57 harald
  191. * Version 3 released
  192. *
  193. * Revision 1.20 2003/01/14 16:58:41 harald
  194. * Tick counter added.
  195. *
  196. * Revision 1.19 2002/10/29 15:37:55 harald
  197. * Some compilers refuse fixed crystal source
  198. *
  199. * Revision 1.18 2002/09/15 17:08:07 harald
  200. * *** empty log message ***
  201. *
  202. * Revision 1.17 2002/08/08 17:32:44 harald
  203. * Imagecraft support by Klaus Ummenhofer
  204. *
  205. * Revision 1.16 2002/06/26 17:29:45 harald
  206. * First pre-release with 2.4 stack
  207. *
  208. * \endverbatim
  209. */
  210. #include <cfg/os.h>
  211. #include <dev/irqreg.h>
  212. #include <sys/types.h>
  213. #include <sys/atom.h>
  214. #include <sys/heap.h>
  215. #include <sys/thread.h>
  216. #include <sys/timer.h>
  217. #include <sys/time.h>
  218. #include <sys/nutdebug.h>
  219. #include <time.h>
  220. #ifdef NUTDEBUG
  221. #include <sys/osdebug.h>
  222. #endif
  223. #ifdef NUTTRACER
  224. #include <sys/tracer.h>
  225. #endif
  226. #ifdef __NUT_EMULATION__
  227. static struct timeval timeStart;
  228. #endif
  229. #ifndef NUT_TICK_FREQ
  230. #define NUT_TICK_FREQ 1000UL
  231. #endif
  232. #include <string.h>
  233. #if defined(__AVR_LIBC_VERSION__)
  234. #include <util/delay_basic.h>
  235. #endif
  236. /*!
  237. * \addtogroup xgTimer
  238. */
  239. /*@{*/
  240. /*!
  241. * \brief Double linked list of all system timers.
  242. */
  243. NUTTIMERINFO *nutTimerList;
  244. /*
  245. * Last processing time of elapsed timers.
  246. */
  247. static uint32_t nut_ticks_resume;
  248. /*!
  249. * \brief System tick counter
  250. */
  251. volatile uint32_t nut_ticks = 0;
  252. #ifndef NUT_USE_OLD_TIME_API
  253. /*!
  254. * \brief System time
  255. */
  256. volatile struct timeval system_time = {0, 0};
  257. /*!
  258. * \brief microseconds per system tick
  259. */
  260. uint32_t systick_us = 0;
  261. #endif
  262. // volatile uint32_t nut_tick_dist[32];
  263. static uint32_t clock_cache[NUT_HWCLK_MAX + 1];
  264. #if defined(__CORTEX__)
  265. uint32_t _us_to_systicks_512;
  266. #elif defined(__AVR_LIBC_VERSION__)
  267. uint16_t _delay_loop_2_mult;
  268. #else
  269. /*!
  270. * \brief Loops per microsecond.
  271. */
  272. #if defined(NUT_DELAYLOOPS)
  273. uint32_t nut_delay_loops = NUT_DELAYLOOPS;
  274. #else
  275. uint32_t nut_delay_loops;
  276. #endif
  277. #endif
  278. /*!
  279. * \brief Related CPU frequency for loops per microsecond.
  280. */
  281. //Not Used uint32_t nut_delay_loops_clk;
  282. /*!
  283. * \brief System timer interrupt handler.
  284. */
  285. #ifndef __NUT_EMULATION__
  286. #if defined(USE_TIMER)
  287. SIGNAL( SIG_TIMER )
  288. #else
  289. void NutTimerIntr(void *arg)
  290. #endif
  291. {
  292. nut_ticks++;
  293. #ifndef NUT_USE_OLD_TIME_API
  294. system_time.tv_usec += systick_us;
  295. if (system_time.tv_usec > 1000000) {
  296. system_time.tv_sec ++;
  297. system_time.tv_usec -= 1000000;
  298. }
  299. #endif
  300. // nut_tick_dist[TCNT0]++;
  301. #ifdef NUTDEBUG_CHECK_STACKMIN
  302. if((nut_ticks % 1000) == 0) {
  303. NUTTHREADINFO *tdp = NutThreadStackCheck(NUTDEBUG_CHECK_STACKMIN);
  304. if (tdp) {
  305. NUTFATAL(tdp->td_name, __FILE__, __LINE__, "more stack space");
  306. }
  307. }
  308. #endif
  309. }
  310. #endif
  311. /*!
  312. * \brief Initialize system timer.
  313. *
  314. * This function is automatically called by Nut/OS during system
  315. * initialization. It calls the hardware dependent layer to initialize
  316. * the timer hardware, registers a timer interrupt handler and eventual
  317. * precalculates constants used in delay loops.
  318. */
  319. void NutTimerInit(void)
  320. {
  321. #ifdef __NUT_EMULATION__
  322. gettimeofday( &timeStart, NULL );
  323. #else
  324. NutRegisterTimer(NutTimerIntr);
  325. #ifndef NUT_USE_OLD_TIME_API
  326. systick_us = 1000000 / NutGetTickClock();
  327. #endif
  328. NutEnableTimerIrq();
  329. //Not Used /* Remember the CPU clock for which the loop counter is valid. */
  330. //Not Used nut_delay_loops_clk = NutGetCpuClock();
  331. #if defined(__CORTEX__)
  332. if (SysTick->LOAD < 0x00800000)
  333. _us_to_systicks_512 = ((SysTick->LOAD +1) << 9)/NUT_TICK_FREQ;
  334. else
  335. _us_to_systicks_512 = ((SysTick->LOAD +1)/NUT_TICK_FREQ) << 9;
  336. #elif defined(__AVR_LIBC_VERSION__)
  337. _delay_loop_2_mult = NutGetCpuClock()/(4000000 >> 8);
  338. #elif !defined(NUT_DELAYLOOPS)
  339. {
  340. /* Wait for the next tick. */
  341. uint32_t cnt = NutGetTickCount();
  342. while (cnt == NutGetTickCount());
  343. /* Wait for the next tick, counting loops. */
  344. cnt = NutGetTickCount();
  345. while (cnt == NutGetTickCount()) {
  346. nut_delay_loops++;
  347. }
  348. nut_delay_loops *= 137UL;
  349. nut_delay_loops /= 25UL;
  350. }
  351. #endif
  352. #endif
  353. }
  354. /*!
  355. * \brief Loop for a specified number of microseconds.
  356. *
  357. * This routine can be used for short delays below the system tick
  358. * time, mainly when driving external hardware, where the resolution
  359. * of NutSleep() wouldn't fit or a thread switch would be undesirable.
  360. * In all other cases NutSleep() should be used.
  361. *
  362. * This call will not release the CPU and will not switch to another
  363. * thread. However, interrupts are not disabled and introduce some
  364. * jitter.
  365. *
  366. * On AVR neither _delay_loop_2() and NUT_DELAYLOOPS is defined, the
  367. * deviation may be greater than 10%.
  368. *
  369. * For delays below 100 microseconds, the deviation may increase above
  370. * 200%. In any case the delay should always be at least as large as
  371. * specified. If in doubt, use a simple port bit toggle routine to
  372. * check the result with an oscilloscope or frequency counter and adjust
  373. * NUT_DELAYLOOPS accordingly.
  374. *
  375. * In any case, if you need exact timing, use timer/counter hardware
  376. * instead.
  377. *
  378. * \param us Delay time in microseconds. Do not use values larger than 10ms
  379. * to prevent integer overflows on fast CPUs
  380. *
  381. * \todo Overflow handling.
  382. */
  383. void NutMicroDelay(uint32_t us)
  384. {
  385. #ifdef __NUT_EMULATION__
  386. usleep(us);
  387. #elif defined(__CORTEX__)
  388. int32_t start_ticks;
  389. int32_t current_ticks, summed_ticks=0;
  390. int32_t end_ticks;
  391. start_ticks = SysTick->VAL;
  392. /* Good for up to 42 ms with 200 MHz Systick Clock*/
  393. end_ticks = (us * _us_to_systicks_512) >> 9;
  394. /* Systick counts backwards! */
  395. while (summed_ticks < end_ticks)
  396. {
  397. current_ticks = SysTick->VAL;
  398. summed_ticks += start_ticks - current_ticks ;
  399. if (current_ticks > start_ticks)
  400. summed_ticks += (SysTick->LOAD +1);
  401. start_ticks = current_ticks;
  402. }
  403. #elif defined(__AVR_LIBC_VERSION__)
  404. /* Use avr-libc provided _delay_loop_2 that takes 4 clocks per unit
  405. *
  406. * Try to keep the overhead low, so use a precalculated, scaled value
  407. * Use 16-bit math is possible
  408. *
  409. * Loop overhead is constant in clock cycles, so values determined
  410. * on AT90CAN128 at 16 MHz with gcc-4.3.3. and -Os vs -O0 should fit
  411. * for other frequencies too.
  412. *
  413. * Scale factor keeps error < 0.8 % for f > 1e6
  414. */
  415. #define MAX_AVR_FREQ 20000000
  416. #if defined(__OPTIMIZE__)
  417. #define LOOP_OFFSET_16 15
  418. #define LOOP_OFFSET_32 48
  419. #else
  420. #define LOOP_OFFSET_16 31
  421. #define LOOP_OFFSET_32 56
  422. #endif
  423. if (us < (0xffff/(MAX_AVR_FREQ/(4000000 >> 8)))) {
  424. uint16_t dly16 = ((uint16_t)us * _delay_loop_2_mult) >> 8;
  425. if (dly16 <= LOOP_OFFSET_16)
  426. return;
  427. dly16 -= LOOP_OFFSET_16;
  428. _delay_loop_2(dly16);
  429. }
  430. else {
  431. uint32_t dly32 = (us * _delay_loop_2_mult)>>8;
  432. if (dly32 <= LOOP_OFFSET_32)
  433. return;
  434. dly32 -= LOOP_OFFSET_32;
  435. while (dly32 > 0xffff)
  436. {
  437. /* _delay_loop_2(0) does 0x10000 loops*/
  438. _delay_loop_2(0);
  439. dly32 -= 0x10000;
  440. }
  441. if(dly32)
  442. _delay_loop_2(dly32);
  443. }
  444. #else
  445. register uint32_t cnt = nut_delay_loops * us / 1000;
  446. while (cnt--) {
  447. _NOP();
  448. }
  449. #endif
  450. }
  451. /*!
  452. * \brief Loop for a specified number of milliseconds.
  453. *
  454. * This call will not release the CPU and will not switch to another
  455. * thread. Because of absent thread switching, the delay time is more
  456. * exact than with NutSleep().
  457. *
  458. * \param ms Delay time in milliseconds, maximum is 255.
  459. *
  460. * \deprecated New applications should use NutMicroDelay().
  461. */
  462. void NutDelay(uint8_t ms)
  463. {
  464. while (ms--){
  465. NutMicroDelay(1000);
  466. }
  467. }
  468. /*!
  469. * \brief Insert a new timer in the global timer list.
  470. *
  471. * Applications should not call this function.
  472. *
  473. * \param tn Pointer to the timer structure to insert.
  474. *
  475. * \todo Make this local function static.
  476. */
  477. void NutTimerInsert(NUTTIMERINFO * tn)
  478. {
  479. NUTTIMERINFO *tnp;
  480. NUTASSERT(tn != NULL);
  481. tn->tn_prev = NULL;
  482. for (tnp = nutTimerList; tnp; tnp = tnp->tn_next) {
  483. if (tn->tn_ticks_left < tnp->tn_ticks_left) {
  484. tnp->tn_ticks_left -= tn->tn_ticks_left;
  485. break;
  486. }
  487. tn->tn_ticks_left -= tnp->tn_ticks_left;
  488. tn->tn_prev = tnp;
  489. }
  490. tn->tn_next = tnp;
  491. if (tn->tn_next) {
  492. tn->tn_next->tn_prev = tn;
  493. }
  494. if (tn->tn_prev) {
  495. tn->tn_prev->tn_next = tn;
  496. }
  497. else {
  498. nutTimerList = tn;
  499. }
  500. }
  501. /*!
  502. * \brief Process elapsed timers.
  503. *
  504. * This routine is called during context switch processing.
  505. * Applications should not use this function.
  506. */
  507. void NutTimerProcessElapsed(void)
  508. {
  509. NUTTIMERINFO *tn;
  510. uint32_t ticks;
  511. uint32_t ticks_new;
  512. // calculate ticks since last call
  513. ticks = NutGetTickCount();
  514. ticks_new = ticks - nut_ticks_resume;
  515. nut_ticks_resume = ticks;
  516. // process timers
  517. while (nutTimerList && ticks_new){
  518. tn = nutTimerList;
  519. // subtract time
  520. if (ticks_new < tn->tn_ticks_left) {
  521. tn->tn_ticks_left -= ticks_new;
  522. ticks_new = 0;
  523. } else {
  524. ticks_new -= tn->tn_ticks_left;
  525. tn->tn_ticks_left = 0;
  526. }
  527. // elapsed
  528. if (tn->tn_ticks_left == 0){
  529. // callback
  530. if (tn->tn_callback) {
  531. (*tn->tn_callback) (tn, (void *) tn->tn_arg);
  532. }
  533. // remove from list
  534. nutTimerList = nutTimerList->tn_next;
  535. if (nutTimerList) {
  536. nutTimerList->tn_prev = NULL;
  537. }
  538. if ((tn->tn_ticks_left = tn->tn_ticks) == 0) {
  539. NutHeapFree(tn);
  540. }
  541. else {
  542. // re-insert
  543. NutTimerInsert(tn);
  544. }
  545. }
  546. }
  547. }
  548. /*!
  549. * \brief Create a new system timer.
  550. *
  551. * Applications should not call this function.
  552. *
  553. * \param ticks Specifies the timer interval in system ticks.
  554. * \param callback Identifies the function to be called on each
  555. * timer interval.
  556. * \param arg The argument passed to the callback function.
  557. * \param flags If set to TM_ONESHOT, the timer will be stopped
  558. * after the first interval. Set to 0 for periodic
  559. * timers.
  560. *
  561. * \return Timer handle if successfull, 0 otherwise. The handle
  562. * may be used to release the timer by calling TimerStop.
  563. *
  564. * \todo Make this local function static or directly integrate it into
  565. * NutTimerStartTicks().
  566. */
  567. NUTTIMERINFO * NutTimerCreate(uint32_t ticks, void (*callback) (HANDLE, void *), void *arg, uint8_t flags)
  568. {
  569. NUTTIMERINFO *tn;
  570. tn = NutHeapAlloc(sizeof(NUTTIMERINFO));
  571. if (tn) {
  572. tn->tn_ticks_left = ticks + NutGetTickCount() - nut_ticks_resume;
  573. /*
  574. * Periodic timers will reload the tick counter on each timer
  575. * intervall.
  576. */
  577. if (flags & TM_ONESHOT) {
  578. tn->tn_ticks = 0;
  579. } else {
  580. tn->tn_ticks = ticks;
  581. }
  582. /* Set callback and callback argument. */
  583. tn->tn_callback = callback;
  584. tn->tn_arg = arg;
  585. }
  586. return tn;
  587. }
  588. /*!
  589. * \brief Start a system timer.
  590. *
  591. * The function returns immediately, while the timer runs asynchronously in
  592. * the background.
  593. *
  594. * The timer counts for a specified number of ticks, then calls the callback
  595. * routine with a given argument.
  596. *
  597. * Even after the timer elapsed, the callback function is not executed
  598. * before the currently running thread is ready to give up the CPU. Thus,
  599. * system timers may not fulfill the required accuracy. For precise or
  600. * high resolution timing, native timer interrupt routines are a better
  601. * choice.
  602. *
  603. * \param ticks Specifies the timer interval in system ticks.
  604. * \param callback Identifies the function to be called on each
  605. * timer interval.
  606. * \param arg The argument passed to the callback function.
  607. * \param flags If set to TM_ONESHOT, the timer will be stopped
  608. * after the first interval. Set to 0 for periodic
  609. * timers.
  610. *
  611. * \return Timer handle if successfull, 0 otherwise. The handle
  612. * may be used to stop the timer by calling TimerStop.
  613. */
  614. HANDLE NutTimerStartTicks(uint32_t ticks, void (*callback) (HANDLE, void *), void *arg, uint8_t flags)
  615. {
  616. NUTTIMERINFO *tn;
  617. tn = NutTimerCreate( ticks, callback, arg, flags);
  618. if (tn) {
  619. /* Add the timer to the list. */
  620. NutTimerInsert(tn);
  621. }
  622. return tn;
  623. }
  624. /*!
  625. * \brief Start a system timer.
  626. *
  627. * The function returns immediately, while the timer runs
  628. * asynchronously in the background.
  629. *
  630. * The timer counts for a specified number of milliseconds,
  631. * then calls the callback routine with a given argument.
  632. *
  633. * Even after the timer elapsed, the callback function is not executed
  634. * before the currently running thread is ready to give up the CPU. Thus,
  635. * system timers may not fulfill the required accuracy. For precise or
  636. * high resolution timing, native timer interrupt routines are a better
  637. * choice.
  638. *
  639. * \param ms Specifies the timer interval in milliseconds. The
  640. * resolution is limited to the granularity of the system
  641. * timer.
  642. * \param callback Identifies the function to be called on each
  643. * timer interval.
  644. * \param arg The argument passed to the callback function.
  645. * \param flags If set to TM_ONESHOT, the timer will be stopped
  646. * after the first interval. Set to 0 for periodic
  647. * timers.
  648. *
  649. * \return Timer handle if successfull, 0 otherwise. The handle
  650. * may be used to stop the timer by calling TimerStop.
  651. */
  652. HANDLE NutTimerStart(uint32_t ms, void (*callback) (HANDLE, void *), void *arg, uint8_t flags)
  653. {
  654. return NutTimerStartTicks(NutTimerMillisToTicks(ms), callback, arg, flags);
  655. }
  656. /*!
  657. * \brief Temporarily suspends the current thread.
  658. *
  659. * Causes the current thread to wait for a specified interval or,
  660. * if the specified interval is zero, to give up the CPU for
  661. * another thread with higher or same priority.
  662. *
  663. * This function may switch to another application thread, that
  664. * got the same or a higher priority and is ready to run.
  665. *
  666. * \note Threads may sleep longer than the specified number of
  667. * milliseconds, depending on the number of threads
  668. * with higher or equal priority, which are ready to run.
  669. *
  670. * \param ms Milliseconds to sleep. If 0, the current thread will not
  671. * sleep, but may give up the CPU. The resolution is limited
  672. * to the granularity of the system timer.
  673. *
  674. * \todo Code size can be reduced by trying to create the timer before
  675. * removing the thread from the run queue.
  676. */
  677. void NutSleep(uint32_t ms)
  678. {
  679. if (ms) {
  680. /* remove running thread from runQueue */
  681. NutThreadRemoveQueue(runningThread, &runQueue);
  682. runningThread->td_state = TDS_SLEEP;
  683. if ((runningThread->td_timer = NutTimerStart(ms, NutThreadWake, runningThread, TM_ONESHOT)) != 0) {
  684. #ifdef NUTTRACER
  685. TRACE_ADD_ITEM(TRACE_TAG_THREAD_SLEEP,(int)runningThread);
  686. #endif
  687. NutThreadResume();
  688. } else
  689. {
  690. /* timer creation failed, restore queues */
  691. runningThread->td_queue = &runQueue;
  692. runningThread->td_qnxt = runQueue;
  693. runningThread->td_state = TDS_RUNNING;
  694. runQueue = runningThread;
  695. }
  696. } else
  697. NutThreadYield();
  698. }
  699. /*!
  700. * \brief Stop a specified timer.
  701. *
  702. * Only periodic timers need to be stopped. One-shot timers
  703. * are automatically stopped by the timer management after
  704. * ther first timer interval. Anyway, long running one-shot
  705. * timers may be stopped to release the occupied memory.
  706. *
  707. * \param handle Identifies the timer to be stopped. This handle must
  708. * have been created by calling NutTimerStart() or
  709. * NutTimerStartTicks().
  710. */
  711. void NutTimerStop(HANDLE handle)
  712. {
  713. NUTTIMERINFO *tn = (NUTTIMERINFO *)handle;
  714. NUTASSERT(tn != NULL);
  715. /* Disable periodic operation and callback. */
  716. tn->tn_ticks = 0;
  717. tn->tn_callback = NULL;
  718. /* If not already elapsed, expire the timer. */
  719. if (tn->tn_ticks_left) {
  720. if (tn->tn_prev) {
  721. tn->tn_prev->tn_next = tn->tn_next;
  722. }
  723. else {
  724. nutTimerList = tn->tn_next;
  725. }
  726. if (tn->tn_next) {
  727. tn->tn_next->tn_prev = tn->tn_prev;
  728. tn->tn_next->tn_ticks_left += tn->tn_ticks_left;
  729. }
  730. tn->tn_ticks_left = 0;
  731. NutTimerInsert(tn);
  732. }
  733. }
  734. /*!
  735. * \brief Return the number of system timer ticks.
  736. *
  737. * This function returns the number of system ticks since the system was
  738. * started.
  739. *
  740. * \return Number of ticks.
  741. */
  742. uint32_t NutGetTickCount(void)
  743. {
  744. uint32_t rc;
  745. #ifdef __NUT_EMULATION__
  746. struct timeval timeNow;
  747. gettimeofday( &timeNow, NULL );
  748. rc = (timeNow.tv_sec - timeStart.tv_sec) * 1000;
  749. rc += (timeNow.tv_usec - timeStart.tv_usec) / 1000;
  750. #else
  751. #ifndef __CORTEX__
  752. NutEnterCritical();
  753. rc = nut_ticks;
  754. NutExitCritical();
  755. #else
  756. /* LST verification shows single atomic access to get this value.
  757. * So no additional atomic forcing operations needed here with Cortex.
  758. */
  759. // TODO: Check with other ARM architectures.
  760. rc = nut_ticks;
  761. #endif
  762. #endif
  763. return rc;
  764. }
  765. /*!
  766. * \brief Return the seconds counter value.
  767. *
  768. * This function returns the value of a counter, which is incremented
  769. * every second. During system start, the counter is cleared to zero.
  770. *
  771. * \note There is intentionally no provision to modify the seconds counter.
  772. * Callers can rely on a continuous update and use this value for
  773. * system tick independend timeout calculations. Applications,
  774. * which want to use this counter for date and time functions,
  775. * should use an offset value.
  776. *
  777. * \return Value of the seconds counter.
  778. */
  779. uint32_t NutGetSeconds(void)
  780. {
  781. #ifdef NUT_USE_OLD_TIME_API
  782. return NutGetTickCount() / NutGetTickClock();
  783. #else
  784. return system_time.tv_sec;
  785. #endif
  786. }
  787. /*!
  788. * \brief Return the milliseconds counter value.
  789. *
  790. * This function returns the value of a counter, which is incremented
  791. * every system timer tick. During system start, the counter is cleared
  792. * to zero and will overflow with the 32 bit tick counter (4294967296).
  793. * With the default 1024 ticks/s this will happen after 49.71 days.
  794. * The resolution is also given by the system ticks.
  795. *
  796. * \note There is intentionally no provision to modify the seconds counter.
  797. * Callers can rely on a continuous update and use this value for
  798. * system tick independend timeout calculations.
  799. * Depending on
  800. *
  801. * \return Value of the seconds counter.
  802. */
  803. uint32_t NutGetMillis(void)
  804. {
  805. #ifdef NUT_USE_OLD_TIME_API
  806. // carefully stay within 32 bit values
  807. uint32_t ticks = NutGetTickCount();
  808. uint32_t seconds = ticks / NutGetTickClock();
  809. ticks -= seconds * NutGetTickClock();
  810. return seconds * 1000 + (ticks * 1000 ) / NutGetTickClock();
  811. #else
  812. return system_time.tv_sec * 1000 + system_time.tv_usec / 1000;
  813. #endif
  814. }
  815. /*!
  816. * \brief Return the specified clock frequency.
  817. *
  818. * If only 1 hardware clock is defined, then this function is mapped
  819. * to NutGetCpuClock().
  820. *
  821. * The number of available hardware clocks depends on the target harware
  822. * and is specified by NUT_HWCLK_MAX + 1.
  823. *
  824. * \param idx Index of the hardware clock. Can be any of the following:
  825. * - NUT_HWCLK_CPU
  826. * - NUT_HWCLK_PERIPHERAL
  827. *
  828. * \return CPU clock frequency in Hertz.
  829. */
  830. #if NUT_HWCLK_MAX
  831. uint32_t NutClockGet(int idx)
  832. {
  833. if (clock_cache[idx] == 0) {
  834. clock_cache[idx] = NutArchClockGet(idx) | NUT_CACHE_LVALID;
  835. }
  836. return clock_cache[idx] & ~NUT_CACHE_LVALID;
  837. }
  838. #endif
  839. /*!
  840. * \brief Set the specified clock frequency.
  841. *
  842. * In the future this may be used to set any hardware clock.
  843. * For now, this simply clears the clock value cache and must
  844. * be called after changing any clock frequency.
  845. *
  846. * \param idx Index of the hardware clock, currently ignored.
  847. * Set to -1 (all clocks) to maintain upward compatibility.
  848. * \param freq Clock frequency in Hertz, currently ignored.
  849. * Set to NUT_CACHE_LVALID (release cached value) to maintain
  850. * upward compatibility.
  851. *
  852. * \return Always 0.
  853. */
  854. int NutClockSet(int idx, uint32_t freq)
  855. {
  856. /* Clear all cached values. */
  857. memset(clock_cache, 0, sizeof(clock_cache));
  858. return 0;
  859. }
  860. /*!
  861. * \brief Return the CPU clock frequency.
  862. *
  863. * Same as NutClockGet(NUT_HWCLK_CPU) but faster, specially when
  864. * NUT_CPU_FREQ is defined.
  865. *
  866. * \return CPU clock frequency in Hertz.
  867. */
  868. #if !defined(NutGetCpuClock)
  869. uint32_t NutGetCpuClock(void)
  870. {
  871. #ifdef NUT_CPU_FREQ
  872. /* Keep this code small! Can we use a preprocessor
  873. ** macro to define NutGetCpuClock() as NUT_CPU_FREQ? */
  874. return NUT_CPU_FREQ;
  875. #else /* !NUT_CPU_FREQ */
  876. /* Keep this code fast for the normal case, where the
  877. ** cached value is valid. */
  878. if (clock_cache[NUT_HWCLK_CPU]) {
  879. return clock_cache[NUT_HWCLK_CPU] & ~NUT_CACHE_LVALID;
  880. }
  881. #if NUT_HWCLK_MAX
  882. return NutClockGet(NUT_HWCLK_CPU);
  883. #else /* !NUT_HWCLK_MAX */
  884. clock_cache[NUT_HWCLK_CPU] = NutArchClockGet(NUT_HWCLK_CPU) | NUT_CACHE_LVALID;
  885. return clock_cache[NUT_HWCLK_CPU] & ~NUT_CACHE_LVALID;
  886. #endif /* !NUT_HWCLK_MAX */
  887. #endif /* !NUT_CPU_FREQ */
  888. }
  889. #endif /* !NutGetCpuClock */
  890. /*@}*/