mperror.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * This file is part of the MicroPython project, http://micropython.org/
  3. *
  4. * The MIT License (MIT)
  5. *
  6. * Copyright (c) 2013, 2014 Damien P. George
  7. * Copyright (c) 2015 Daniel Campora
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a copy
  10. * of this software and associated documentation files (the "Software"), to deal
  11. * in the Software without restriction, including without limitation the rights
  12. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. * copies of the Software, and to permit persons to whom the Software is
  14. * furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included in
  17. * all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. * THE SOFTWARE.
  26. */
  27. #include <stdio.h>
  28. #include <stdint.h>
  29. #include <string.h>
  30. #include "py/mpconfig.h"
  31. #include "py/obj.h"
  32. #include "py/runtime.h"
  33. #include "py/mphal.h"
  34. #include "hw_ints.h"
  35. #include "hw_types.h"
  36. #include "hw_gpio.h"
  37. #include "hw_memmap.h"
  38. #include "hw_gprcm.h"
  39. #include "hw_common_reg.h"
  40. #include "pin.h"
  41. #include "gpio.h"
  42. #ifndef BOOTLOADER
  43. #include "pybpin.h"
  44. #include "pins.h"
  45. #endif
  46. #include "rom_map.h"
  47. #include "prcm.h"
  48. #include "pybuart.h"
  49. #include "utils.h"
  50. #include "mperror.h"
  51. /******************************************************************************
  52. DEFINE CONSTANTS
  53. ******************************************************************************/
  54. #define MPERROR_TOOGLE_MS (50)
  55. #define MPERROR_SIGNAL_ERROR_MS (1200)
  56. #define MPERROR_HEARTBEAT_ON_MS (80)
  57. #define MPERROR_HEARTBEAT_OFF_MS (3920)
  58. /******************************************************************************
  59. DECLARE PRIVATE DATA
  60. ******************************************************************************/
  61. struct mperror_heart_beat {
  62. uint32_t off_time;
  63. uint32_t on_time;
  64. bool beating;
  65. bool enabled;
  66. bool do_disable;
  67. } mperror_heart_beat = {.off_time = 0, .on_time = 0, .beating = false, .enabled = false, .do_disable = false};
  68. /******************************************************************************
  69. DEFINE PUBLIC FUNCTIONS
  70. ******************************************************************************/
  71. void mperror_init0 (void) {
  72. #ifdef BOOTLOADER
  73. // enable the system led and the safe boot pin peripheral clocks
  74. MAP_PRCMPeripheralClkEnable(MICROPY_SYS_LED_PRCM, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
  75. MAP_PRCMPeripheralClkEnable(MICROPY_SAFE_BOOT_PRCM, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
  76. // configure the safe boot pin
  77. MAP_PinTypeGPIO(MICROPY_SAFE_BOOT_PIN_NUM, PIN_MODE_0, false);
  78. MAP_PinConfigSet(MICROPY_SAFE_BOOT_PIN_NUM, PIN_STRENGTH_4MA, PIN_TYPE_STD_PD);
  79. MAP_GPIODirModeSet(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN, GPIO_DIR_MODE_IN);
  80. // configure the bld
  81. MAP_PinTypeGPIO(MICROPY_SYS_LED_PIN_NUM, PIN_MODE_0, false);
  82. MAP_PinConfigSet(MICROPY_SYS_LED_PIN_NUM, PIN_STRENGTH_6MA, PIN_TYPE_STD);
  83. MAP_GPIODirModeSet(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, GPIO_DIR_MODE_OUT);
  84. #else
  85. // configure the system led
  86. pin_config ((pin_obj_t *)&MICROPY_SYS_LED_GPIO, PIN_MODE_0, GPIO_DIR_MODE_OUT, PIN_TYPE_STD, 0, PIN_STRENGTH_6MA);
  87. #endif
  88. mperror_heart_beat.enabled = true;
  89. mperror_heartbeat_switch_off();
  90. }
  91. void mperror_bootloader_check_reset_cause (void) {
  92. // if we are recovering from a WDT reset, trigger
  93. // a hibernate cycle for a clean boot
  94. if (MAP_PRCMSysResetCauseGet() == PRCM_WDT_RESET) {
  95. HWREG(0x400F70B8) = 1;
  96. UtilsDelay(800000/5);
  97. HWREG(0x400F70B0) = 1;
  98. UtilsDelay(800000/5);
  99. HWREG(0x4402E16C) |= 0x2;
  100. UtilsDelay(800);
  101. HWREG(0x4402F024) &= 0xF7FFFFFF;
  102. // since the reset cause will be changed, we must store the right reason
  103. // so that the application knows it when booting for the next time
  104. PRCMSetSpecialBit(PRCM_WDT_RESET_BIT);
  105. MAP_PRCMHibernateWakeupSourceEnable(PRCM_HIB_SLOW_CLK_CTR);
  106. // set the sleep interval to 10ms
  107. MAP_PRCMHibernateIntervalSet(330);
  108. MAP_PRCMHibernateEnter();
  109. }
  110. }
  111. void mperror_deinit_sfe_pin (void) {
  112. // disable the pull-down
  113. MAP_PinConfigSet(MICROPY_SAFE_BOOT_PIN_NUM, PIN_STRENGTH_4MA, PIN_TYPE_STD);
  114. }
  115. void mperror_signal_error (void) {
  116. uint32_t count = 0;
  117. while ((MPERROR_TOOGLE_MS * count++) < MPERROR_SIGNAL_ERROR_MS) {
  118. // toogle the led
  119. MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, ~MAP_GPIOPinRead(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN));
  120. UtilsDelay(UTILS_DELAY_US_TO_COUNT(MPERROR_TOOGLE_MS * 1000));
  121. }
  122. }
  123. void mperror_heartbeat_switch_off (void) {
  124. if (mperror_heart_beat.enabled) {
  125. mperror_heart_beat.on_time = 0;
  126. mperror_heart_beat.off_time = 0;
  127. MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, 0);
  128. }
  129. }
  130. void mperror_heartbeat_signal (void) {
  131. if (mperror_heart_beat.do_disable) {
  132. mperror_heart_beat.do_disable = false;
  133. } else if (mperror_heart_beat.enabled) {
  134. if (!mperror_heart_beat.beating) {
  135. if ((mperror_heart_beat.on_time = mp_hal_ticks_ms()) - mperror_heart_beat.off_time > MPERROR_HEARTBEAT_OFF_MS) {
  136. MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, MICROPY_SYS_LED_PORT_PIN);
  137. mperror_heart_beat.beating = true;
  138. }
  139. } else {
  140. if ((mperror_heart_beat.off_time = mp_hal_ticks_ms()) - mperror_heart_beat.on_time > MPERROR_HEARTBEAT_ON_MS) {
  141. MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, 0);
  142. mperror_heart_beat.beating = false;
  143. }
  144. }
  145. }
  146. }
  147. void NORETURN __fatal_error(const char *msg) {
  148. #ifdef DEBUG
  149. if (msg != NULL) {
  150. // wait for 20ms
  151. UtilsDelay(UTILS_DELAY_US_TO_COUNT(20000));
  152. mp_hal_stdout_tx_str("\r\nFATAL ERROR:");
  153. mp_hal_stdout_tx_str(msg);
  154. mp_hal_stdout_tx_str("\r\n");
  155. }
  156. #endif
  157. // signal the crash with the system led
  158. MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, MICROPY_SYS_LED_PORT_PIN);
  159. for ( ;; ) {__WFI();}
  160. }
  161. void __assert_func(const char *file, int line, const char *func, const char *expr) {
  162. (void) func;
  163. printf("Assertion failed: %s, file %s, line %d\n", expr, file, line);
  164. __fatal_error(NULL);
  165. }
  166. void nlr_jump_fail(void *val) {
  167. #ifdef DEBUG
  168. char msg[64];
  169. snprintf(msg, sizeof(msg), "uncaught exception %p\n", val);
  170. __fatal_error(msg);
  171. #else
  172. __fatal_error(NULL);
  173. #endif
  174. }
  175. void mperror_enable_heartbeat (bool enable) {
  176. if (enable) {
  177. #ifndef BOOTLOADER
  178. // configure the led again
  179. pin_config ((pin_obj_t *)&MICROPY_SYS_LED_GPIO, PIN_MODE_0, GPIO_DIR_MODE_OUT, PIN_TYPE_STD, 0, PIN_STRENGTH_6MA);
  180. #endif
  181. mperror_heart_beat.enabled = true;
  182. mperror_heart_beat.do_disable = false;
  183. mperror_heartbeat_switch_off();
  184. } else {
  185. mperror_heart_beat.do_disable = true;
  186. mperror_heart_beat.enabled = false;
  187. }
  188. }
  189. bool mperror_is_heartbeat_enabled (void) {
  190. return mperror_heart_beat.enabled;
  191. }