app_error.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /* Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved.
  2. *
  3. * The information contained herein is property of Nordic Semiconductor ASA.
  4. * Terms and conditions of usage are described in detail in NORDIC
  5. * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
  6. *
  7. * Licensees are granted free, non-transferable use of the information. NO
  8. * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
  9. * the file.
  10. *
  11. */
  12. /** @file
  13. *
  14. * @defgroup app_error Common application error handler
  15. * @{
  16. * @ingroup app_common
  17. *
  18. * @brief Common application error handler.
  19. */
  20. #include "nrf.h"
  21. #include <stdio.h>
  22. #include "app_error.h"
  23. #include "nordic_common.h"
  24. #include "sdk_errors.h"
  25. #include "nrf_log.h"
  26. #include "flash.h"
  27. #ifdef DEBUG
  28. #include "bsp.h"
  29. #endif
  30. #define RESET_BUF_LEN 16
  31. __align(4) uint8_t reset_buf[RESET_BUF_LEN] = {0};
  32. /**@brief Function for error handling, which is called when an error has occurred.
  33. *
  34. * @warning This handler is an example only and does not fit a final product. You need to analyze
  35. * how your product is supposed to react in case of error.
  36. *
  37. * @param[in] error_code Error code supplied to the handler.
  38. * @param[in] line_num Line number where the handler is called.
  39. * @param[in] p_file_name Pointer to the file name.
  40. */
  41. /*lint -save -e14 */
  42. void app_error_handler(ret_code_t error_code, uint32_t line_num, const uint8_t * p_file_name)
  43. {
  44. error_info_t error_info =
  45. {
  46. .line_num = line_num,
  47. .p_file_name = p_file_name,
  48. .err_code = error_code,
  49. };
  50. //add reset reason in flash
  51. reset_buf[0] = (uint8_t)(line_num >> 24);
  52. reset_buf[1] = (uint8_t)(line_num >> 16);
  53. reset_buf[2] = (uint8_t)(line_num >> 8);
  54. reset_buf[3] = (uint8_t)line_num;
  55. reset_buf[4] = (uint8_t)(error_code >> 24);
  56. reset_buf[5] = (uint8_t)(error_code >> 16);
  57. reset_buf[6] = (uint8_t)(error_code >> 8);
  58. reset_buf[7] = (uint8_t)error_code;
  59. reset_buf[8] = (uint8_t)((uint32_t)p_file_name >> 24);
  60. reset_buf[9] = (uint8_t)((uint32_t)p_file_name >> 16);
  61. reset_buf[10] = (uint8_t)((uint32_t)p_file_name >> 8);
  62. reset_buf[11] = (uint8_t)((uint32_t)p_file_name);
  63. reset_buf[12] = *(p_file_name+9);
  64. reset_buf[13] = *(p_file_name+10);
  65. reset_buf[14] = *(p_file_name+11);
  66. reset_buf[15] = *(p_file_name+12);
  67. reset_data_flash_update(reset_buf,RESET_BUF_LEN,4);
  68. //add reset reason in flash
  69. app_error_fault_handler(NRF_FAULT_ID_SDK_ERROR, 0, (uint32_t)(&error_info));
  70. UNUSED_VARIABLE(error_info);
  71. }
  72. /*lint -save -e14 */
  73. void app_error_handler_bare(ret_code_t error_code)
  74. {
  75. error_info_t error_info =
  76. {
  77. .line_num = 0,
  78. .p_file_name = NULL,
  79. .err_code = error_code,
  80. };
  81. app_error_fault_handler(NRF_FAULT_ID_SDK_ERROR, 0, (uint32_t)(&error_info));
  82. UNUSED_VARIABLE(error_info);
  83. }
  84. void app_error_save_and_stop(uint32_t id, uint32_t pc, uint32_t info)
  85. {
  86. /* static error variables - in order to prevent removal by optimizers */
  87. static volatile struct
  88. {
  89. uint32_t fault_id;
  90. uint32_t pc;
  91. uint32_t error_info;
  92. assert_info_t * p_assert_info;
  93. error_info_t * p_error_info;
  94. ret_code_t err_code;
  95. uint32_t line_num;
  96. const uint8_t * p_file_name;
  97. } m_error_data = {0};
  98. // The following variable helps Keil keep the call stack visible, in addition, it can be set to
  99. // 0 in the debugger to continue executing code after the error check.
  100. volatile bool loop = true;
  101. UNUSED_VARIABLE(loop);
  102. m_error_data.fault_id = id;
  103. m_error_data.pc = pc;
  104. m_error_data.error_info = info;
  105. switch (id)
  106. {
  107. case NRF_FAULT_ID_SDK_ASSERT:
  108. m_error_data.p_assert_info = (assert_info_t *)info;
  109. m_error_data.line_num = m_error_data.p_assert_info->line_num;
  110. m_error_data.p_file_name = m_error_data.p_assert_info->p_file_name;
  111. break;
  112. case NRF_FAULT_ID_SDK_ERROR:
  113. m_error_data.p_error_info = (error_info_t *)info;
  114. m_error_data.err_code = m_error_data.p_error_info->err_code;
  115. m_error_data.line_num = m_error_data.p_error_info->line_num;
  116. m_error_data.p_file_name = m_error_data.p_error_info->p_file_name;
  117. break;
  118. }
  119. UNUSED_VARIABLE(m_error_data);
  120. // If printing is disrupted, remove the irq calls, or set the loop variable to 0 in the debugger.
  121. __disable_irq();
  122. while(loop);
  123. __enable_irq();
  124. }
  125. /*lint -restore */