watchdog.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * Copyright STREAMIT BV, 2010.
  3. *
  4. * Project : SIR
  5. * Module : watchdog
  6. * File name $Workfile: watchdog.c $
  7. * Last Save $Date: 2007/01/16 11:17:24 $
  8. * $Revision: 0.1 $
  9. * Creation Date : 2007/01/16 11:17:25
  10. *
  11. * Description : Watchdog routines for the ATMega128/256
  12. * Inspired by the arch/xxx/dev/watchdog routines in
  13. * NutOS 4.2.1 and higher.
  14. *
  15. */
  16. #define LOG_MODULE LOG_WATCHDOG_MODULE
  17. /*--------------------------------------------------------------------------*/
  18. /* Include files */
  19. /*--------------------------------------------------------------------------*/
  20. #include <stdio.h>
  21. #ifdef __AVR__
  22. #ifdef __GNUC__
  23. #include <avr/wdt.h>
  24. #endif /* #ifdef __GNUC__ */
  25. #endif /* #ifdef __AVR__ */
  26. #include "watchdog.h"
  27. /*--------------------------------------------------------------------------*/
  28. /* Constant definitions */
  29. /*--------------------------------------------------------------------------*/
  30. /*!
  31. * \brief Watchdog oscillator frequency.
  32. */
  33. #ifndef NUT_WDT_FREQ
  34. #define NUT_WDT_FREQ 128000UL
  35. #endif
  36. #ifndef WDTO_15MS
  37. #define WDTO_15MS 0x00
  38. #define WDTO_30MS 0x01
  39. #define WDTO_60MS 0x02
  40. #define WDTO_120MS 0x03
  41. #define WDTO_250MS 0x04
  42. #define WDTO_500MS 0x05
  43. #define WDTO_1S 0x06
  44. #define WDTO_2S 0x07
  45. #define WDTO_4S 0x20
  46. #define WDTO_8S 0x21
  47. #endif /* #ifndef WDTO_15MS */
  48. #define WD_CONTROL WDTCSR
  49. /*--------------------------------------------------------------------------*/
  50. /* Type declarations */
  51. /*--------------------------------------------------------------------------*/
  52. /*--------------------------------------------------------------------------*/
  53. /* Local variables */
  54. /*--------------------------------------------------------------------------*/
  55. /*!\brief Counts nested calls */
  56. static unsigned char g_byNested;
  57. /*!\brief Watchdog Timeout constant */
  58. static unsigned char g_byWdtDivider;
  59. /*--------------------------------------------------------------------------*/
  60. /* Global variables */
  61. /*--------------------------------------------------------------------------*/
  62. /*--------------------------------------------------------------------------*/
  63. /* Local functions */
  64. /*--------------------------------------------------------------------------*/
  65. #ifndef wdt_enable
  66. #define wdt_enable(tmo) \
  67. { \
  68. register u_char s = _BV(WDCE) | _BV(WDE); \
  69. register u_char r = tmo | _BV(WDE); \
  70. asm("in R0, 0x3F\n" \
  71. "cli\n" \
  72. "wdr\n" \
  73. "sts 0x60, %s\n" \
  74. "sts 0x60, %r\n" \
  75. "out 0x3F, R0\n"); \
  76. }
  77. #endif /* #ifndef wdt_enable */
  78. #ifndef wdt_disable
  79. #define wdt_disable() \
  80. { \
  81. asm("in R0, $3F\n" \
  82. "cli\n" \
  83. "wdr\n" \
  84. "in r24,0x34\n" \
  85. "andi r24,0xF7\n" \
  86. "out 0x34,r24\n" \
  87. "lds r24,0x0060\n" \
  88. "ori r24,0x18\n" \
  89. "sts 0x0060,r24\n" \
  90. "clr r2\n" \
  91. "sts 0x0060,r2\n" \
  92. "out 0x3F, R0\n"); \
  93. }
  94. #endif /* #ifndef wdt_disable */
  95. #ifndef wdt_reset
  96. #define wdt_reset() \
  97. { \
  98. _WDR(); \
  99. }
  100. #endif /* #ifndef wdt_reset */
  101. /*--------------------------------------------------------------------------*/
  102. /* Global functions */
  103. /*--------------------------------------------------------------------------*/
  104. void WatchDogStart(unsigned long ms)
  105. {
  106. const unsigned long unPrescaleFactor = 2048UL; // PragmaLab: check datasheet Mega2561
  107. unsigned char byPrescale = 1;
  108. wdt_reset();
  109. /*
  110. * Calculate the needed prescaling for the timer ticks
  111. */
  112. while (((unPrescaleFactor << byPrescale) / (NUT_WDT_FREQ / 1000UL)) < ms)
  113. {
  114. byPrescale++;
  115. }
  116. g_byWdtDivider = byPrescale;
  117. if (g_byWdtDivider > WDTO_8S)
  118. {
  119. // restrict timeout since HW only can handle 8 seconds for Mega256
  120. g_byWdtDivider &= WDTO_8S;
  121. }
  122. wdt_enable(g_byWdtDivider);
  123. g_byNested = 1;
  124. }
  125. void WatchDogRestart(void)
  126. {
  127. wdt_reset();
  128. }
  129. void WatchDogDisable(void)
  130. {
  131. if (g_byNested != 0)
  132. {
  133. g_byNested++;
  134. }
  135. wdt_disable();
  136. }
  137. void WatchDogEnable(void)
  138. {
  139. if (g_byNested > 1 && --g_byNested == 1)
  140. {
  141. wdt_enable(g_byWdtDivider);
  142. }
  143. }