wdt_at91.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. * Copyright (C) 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. /*
  34. * $Log$
  35. * Revision 1.4 2009/01/17 11:26:37 haraldkipp
  36. * Getting rid of two remaining BSD types in favor of stdint.
  37. * Replaced 'u_int' by 'unsinged int' and 'uptr_t' by 'uintptr_t'.
  38. *
  39. * Revision 1.3 2008/08/11 06:59:13 haraldkipp
  40. * BSD types replaced by stdint types (feature request #1282721).
  41. *
  42. * Revision 1.2 2006/05/25 09:13:22 haraldkipp
  43. * Platform independent watchdog API added.
  44. *
  45. * Revision 1.1 2006/02/23 15:36:35 haraldkipp
  46. * Added support for AT91 watchdog timer.
  47. *
  48. */
  49. #include <sys/timer.h>
  50. #include <dev/watchdog.h>
  51. /*!
  52. * \addtogroup xgNutArchAt91DevWatchDog
  53. */
  54. /*@{*/
  55. #if defined(MCU_AT91R40008)
  56. static ureg_t nested;
  57. #endif
  58. /*!
  59. * \brief Start the AT91 hardware watch dog timer.
  60. *
  61. * For portability, applications should use the platform independent
  62. * \ref xgWatchDog "Watchdog Driver API".
  63. */
  64. uint32_t At91WatchDogStart(uint32_t ms, uint32_t xmode)
  65. {
  66. unsigned int cmval;
  67. #if defined(MCU_AT91R40008)
  68. At91WatchDogDisable();
  69. /*
  70. * The watchdog counts down a 16 bit value, of which the upper
  71. * 4 bits are configurable and the lower 12 bits are set to 1.
  72. * Calculate the number of cycles required to count down the
  73. * upper 4 bits.
  74. */
  75. cmval = ((NutGetCpuClock() / 1000) * ms) >> 13;
  76. /* Check if MCK/8 is slow enough. */
  77. if (cmval < WD_HPCV) {
  78. cmval = (cmval & WD_HPCV) | WD_WDCLKS_MCK8;
  79. }
  80. /* Check if MCK/32 is slow enough. */
  81. else if ((cmval >>= 2) < WD_HPCV) {
  82. cmval = (cmval & WD_HPCV) | WD_WDCLKS_MCK32;
  83. }
  84. /* Check if MCK/128 is slow enough. */
  85. else if ((cmval >>= 2) < WD_HPCV) {
  86. cmval = (cmval & WD_HPCV) | WD_WDCLKS_MCK128;
  87. }
  88. /* Check if MCK/1024 is slow enough. */
  89. else if ((cmval >>= 3) < WD_HPCV) {
  90. cmval = (cmval & WD_HPCV) | WD_WDCLKS_MCK1024;
  91. }
  92. /* Use maximum. */
  93. else {
  94. cmval = WD_HPCV | WD_WDCLKS_MCK1024;
  95. }
  96. outr(WD_CMR, WD_CKEY | cmval);
  97. if (xmode == 0) {
  98. xmode |= WD_RSTEN;
  99. }
  100. At91WatchDogRestart();
  101. outr(WD_OMR, WD_OKEY | WD_WDEN | xmode);
  102. nested = 1;
  103. #elif defined(MCU_AT91SAM7X) || defined(MCU_AT91SAM7S) || defined(MCU_AT91SAM7SE)
  104. /* Compute 12-bit timer value for 32Khz(approx) slow clock divided by 128 */
  105. cmval = (ms * (32000/128)) / 1000;
  106. if(cmval>4095) cmval=4095;
  107. /* if mode=0, Enable watchdog and disable it when debugging (default value) */
  108. if (xmode == 0) {
  109. xmode |= WDT_WDRSTEN|WDT_WDDBGHLT|WDT_WDIDLEHLT;
  110. }
  111. /* Write watchdog, you can do it only one time. Delta fixed to timer value */
  112. outr(WDT_MR, cmval | (cmval<<16) | xmode);
  113. At91WatchDogRestart();
  114. #endif
  115. return ms;
  116. }
  117. /*!
  118. * \brief Re-start the AT91 hardware watch dog timer.
  119. *
  120. * For portability, applications should use the platform independent
  121. * \ref xgWatchDog "Watchdog Driver API".
  122. */
  123. void At91WatchDogRestart(void)
  124. {
  125. #if defined(MCU_AT91R40008)
  126. outr(WD_CR, WD_RSTKEY);
  127. #elif defined(MCU_AT91SAM7X) || defined(MCU_AT91SAM7S) || defined(MCU_AT91SAM7SE)
  128. outr(WDT_CR, WDT_KEY|WDT_WDRSTT);
  129. #endif
  130. }
  131. /*!
  132. * \brief Disable the AT91 hardware watch dog timer.
  133. *
  134. * For portability, applications should use the platform independent
  135. * \ref xgWatchDog "Watchdog Driver API".
  136. */
  137. void At91WatchDogDisable(void)
  138. {
  139. #if defined(MCU_AT91R40008)
  140. if (nested) {
  141. nested++;
  142. }
  143. outr(WD_OMR, WD_OKEY | (inr(WD_OMR) & ~WD_WDEN));
  144. #elif defined(MCU_AT91SAM7X) || defined(MCU_AT91SAM7S) || defined(MCU_AT91SAM7SE)
  145. outr(WDT_MR, WDT_WDDIS);
  146. #endif
  147. }
  148. /*!
  149. * \brief Enable the AT91 hardware watch dog timer.
  150. *
  151. * For portability, applications should use the platform independent
  152. * \ref xgWatchDog "Watchdog Driver API".
  153. */
  154. void At91WatchDogEnable(void)
  155. {
  156. #if defined(MCU_AT91R40008)
  157. if (nested > 1 && --nested == 1) {
  158. At91WatchDogRestart();
  159. outr(WD_OMR, WD_OKEY | inr(WD_OMR) | WD_WDEN);
  160. }
  161. #endif
  162. }
  163. /*@}*/