test_reset_reason.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. #include "unity.h"
  2. #include "esp_system.h"
  3. #include "esp_task_wdt.h"
  4. #include "esp_attr.h"
  5. #include "soc/rtc_cntl_reg.h"
  6. #include "driver/timer.h"
  7. #include "rom/rtc.h"
  8. #define RTC_BSS_ATTR __attribute__((section(".rtc.bss")))
  9. #define CHECK_VALUE 0x89abcdef
  10. static __NOINIT_ATTR uint32_t s_noinit_val;
  11. static RTC_NOINIT_ATTR uint32_t s_rtc_noinit_val;
  12. static RTC_DATA_ATTR uint32_t s_rtc_data_val;
  13. static RTC_BSS_ATTR uint32_t s_rtc_bss_val;
  14. /* There is no practical difference between placing something into RTC_DATA and
  15. * RTC_RODATA. This only checks a usage pattern where the variable has a non-zero
  16. * initializer (should be initialized by the bootloader).
  17. */
  18. static RTC_RODATA_ATTR uint32_t s_rtc_rodata_val = CHECK_VALUE;
  19. static RTC_FAST_ATTR uint32_t s_rtc_force_fast_val;
  20. static RTC_SLOW_ATTR uint32_t s_rtc_force_slow_val;
  21. static void setup_values()
  22. {
  23. s_noinit_val = CHECK_VALUE;
  24. s_rtc_noinit_val = CHECK_VALUE;
  25. s_rtc_data_val = CHECK_VALUE;
  26. s_rtc_bss_val = CHECK_VALUE;
  27. TEST_ASSERT_EQUAL_HEX32_MESSAGE(CHECK_VALUE, s_rtc_rodata_val,
  28. "s_rtc_rodata_val should already be set up");
  29. s_rtc_force_fast_val = CHECK_VALUE;
  30. s_rtc_force_slow_val = CHECK_VALUE;
  31. }
  32. /* This test needs special test runners: rev1 silicon, and SPI flash with
  33. * fast start-up time. Otherwise reset reason will be RTCWDT_RESET.
  34. */
  35. TEST_CASE("reset reason ESP_RST_POWERON", "[reset][ignore]")
  36. {
  37. TEST_ASSERT_EQUAL(ESP_RST_POWERON, esp_reset_reason());
  38. }
  39. static void do_deep_sleep()
  40. {
  41. setup_values();
  42. esp_sleep_enable_timer_wakeup(10000);
  43. esp_deep_sleep_start();
  44. }
  45. static void check_reset_reason_deep_sleep()
  46. {
  47. TEST_ASSERT_EQUAL(ESP_RST_DEEPSLEEP, esp_reset_reason());
  48. TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_rtc_noinit_val);
  49. TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_rtc_data_val);
  50. TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_rtc_bss_val);
  51. TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_rtc_rodata_val);
  52. TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_rtc_force_fast_val);
  53. TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_rtc_force_slow_val);
  54. }
  55. TEST_CASE_MULTIPLE_STAGES("reset reason ESP_RST_DEEPSLEEP", "[reset_reason][reset=DEEPSLEEP_RESET]",
  56. do_deep_sleep,
  57. check_reset_reason_deep_sleep);
  58. static void do_exception()
  59. {
  60. setup_values();
  61. *(int*) (0x40000001) = 0;
  62. }
  63. static void do_abort()
  64. {
  65. setup_values();
  66. abort();
  67. }
  68. static void check_reset_reason_panic()
  69. {
  70. TEST_ASSERT_EQUAL(ESP_RST_PANIC, esp_reset_reason());
  71. TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_noinit_val);
  72. TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_rtc_noinit_val);
  73. TEST_ASSERT_EQUAL_HEX32(0, s_rtc_data_val);
  74. TEST_ASSERT_EQUAL_HEX32(0, s_rtc_bss_val);
  75. TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_rtc_rodata_val);
  76. TEST_ASSERT_EQUAL_HEX32(0, s_rtc_force_fast_val);
  77. TEST_ASSERT_EQUAL_HEX32(0, s_rtc_force_slow_val);
  78. }
  79. TEST_CASE_MULTIPLE_STAGES("reset reason ESP_RST_PANIC after exception", "[reset_reason][reset=LoadStoreError,SW_CPU_RESET]",
  80. do_exception,
  81. check_reset_reason_panic);
  82. TEST_CASE_MULTIPLE_STAGES("reset reason ESP_RST_PANIC after abort", "[reset_reason][reset=abort,SW_CPU_RESET]",
  83. do_abort,
  84. check_reset_reason_panic);
  85. static void do_restart()
  86. {
  87. setup_values();
  88. esp_restart();
  89. }
  90. #if portNUM_PROCESSORS > 1
  91. static void do_restart_from_app_cpu()
  92. {
  93. setup_values();
  94. xTaskCreatePinnedToCore((TaskFunction_t) &do_restart, "restart", 2048, NULL, 5, NULL, 1);
  95. vTaskDelay(2);
  96. }
  97. #endif
  98. static void check_reset_reason_sw()
  99. {
  100. TEST_ASSERT_EQUAL(ESP_RST_SW, esp_reset_reason());
  101. TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_noinit_val);
  102. TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_rtc_noinit_val);
  103. TEST_ASSERT_EQUAL_HEX32(0, s_rtc_data_val);
  104. TEST_ASSERT_EQUAL_HEX32(0, s_rtc_bss_val);
  105. TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_rtc_rodata_val);
  106. TEST_ASSERT_EQUAL_HEX32(0, s_rtc_force_fast_val);
  107. TEST_ASSERT_EQUAL_HEX32(0, s_rtc_force_slow_val);
  108. }
  109. TEST_CASE_MULTIPLE_STAGES("reset reason ESP_RST_SW after restart", "[reset_reason][reset=SW_CPU_RESET]",
  110. do_restart,
  111. check_reset_reason_sw);
  112. #if portNUM_PROCESSORS > 1
  113. TEST_CASE_MULTIPLE_STAGES("reset reason ESP_RST_SW after restart from APP CPU", "[reset_reason][reset=SW_CPU_RESET]",
  114. do_restart_from_app_cpu,
  115. check_reset_reason_sw);
  116. #endif
  117. static void do_int_wdt()
  118. {
  119. portENTER_CRITICAL_NESTED();
  120. while(1);
  121. }
  122. static void do_int_wdt_hw()
  123. {
  124. XTOS_SET_INTLEVEL(XCHAL_NMILEVEL);
  125. while(1);
  126. }
  127. static void check_reset_reason_int_wdt()
  128. {
  129. TEST_ASSERT_EQUAL(ESP_RST_INT_WDT, esp_reset_reason());
  130. }
  131. TEST_CASE_MULTIPLE_STAGES("reset reason ESP_RST_INT_WDT after interrupt watchdog (panic)",
  132. "[reset_reason][reset=Interrupt wdt timeout on CPU0,SW_CPU_RESET]",
  133. do_int_wdt,
  134. check_reset_reason_int_wdt);
  135. TEST_CASE_MULTIPLE_STAGES("reset reason ESP_RST_INT_WDT after interrupt watchdog (hw)",
  136. "[reset_reason][reset=TG1WDT_SYS_RESET]",
  137. do_int_wdt_hw,
  138. check_reset_reason_int_wdt);
  139. static void do_task_wdt()
  140. {
  141. setup_values();
  142. esp_task_wdt_init(1, true);
  143. esp_task_wdt_add(xTaskGetIdleTaskHandleForCPU(0));
  144. while(1);
  145. }
  146. static void check_reset_reason_task_wdt()
  147. {
  148. TEST_ASSERT_EQUAL(ESP_RST_TASK_WDT, esp_reset_reason());
  149. TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_noinit_val);
  150. TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_rtc_noinit_val);
  151. TEST_ASSERT_EQUAL_HEX32(0, s_rtc_data_val);
  152. TEST_ASSERT_EQUAL_HEX32(0, s_rtc_bss_val);
  153. TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_rtc_rodata_val);
  154. TEST_ASSERT_EQUAL_HEX32(0, s_rtc_force_fast_val);
  155. TEST_ASSERT_EQUAL_HEX32(0, s_rtc_force_slow_val);
  156. }
  157. TEST_CASE_MULTIPLE_STAGES("reset reason ESP_RST_TASK_WDT after task watchdog",
  158. "[reset_reason][reset=abort,SW_CPU_RESET]",
  159. do_task_wdt,
  160. check_reset_reason_task_wdt);
  161. static void do_rtc_wdt()
  162. {
  163. WRITE_PERI_REG(RTC_CNTL_WDTWPROTECT_REG, RTC_CNTL_WDT_WKEY_VALUE);
  164. REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_SYS_RESET_LENGTH, 7);
  165. REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_STG0, RTC_WDT_STG_SEL_RESET_SYSTEM);
  166. WRITE_PERI_REG(RTC_CNTL_WDTCONFIG1_REG, 10000);
  167. REG_SET_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_FLASHBOOT_MOD_EN);
  168. while(1);
  169. }
  170. static void check_reset_reason_any_wdt()
  171. {
  172. TEST_ASSERT_EQUAL(ESP_RST_WDT, esp_reset_reason());
  173. }
  174. TEST_CASE_MULTIPLE_STAGES("reset reason ESP_RST_WDT after RTC watchdog",
  175. "[reset_reason][reset=RTCWDT_RTC_RESET]",
  176. do_rtc_wdt,
  177. check_reset_reason_any_wdt);
  178. static void do_brownout()
  179. {
  180. setup_values();
  181. printf("Manual test: lower the supply voltage to cause brownout\n");
  182. vTaskSuspend(NULL);
  183. }
  184. static void check_reset_reason_brownout()
  185. {
  186. TEST_ASSERT_EQUAL(ESP_RST_BROWNOUT, esp_reset_reason());
  187. TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_noinit_val);
  188. TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_rtc_noinit_val);
  189. TEST_ASSERT_EQUAL_HEX32(0, s_rtc_data_val);
  190. TEST_ASSERT_EQUAL_HEX32(0, s_rtc_bss_val);
  191. TEST_ASSERT_EQUAL_HEX32(CHECK_VALUE, s_rtc_rodata_val);
  192. TEST_ASSERT_EQUAL_HEX32(0, s_rtc_force_fast_val);
  193. TEST_ASSERT_EQUAL_HEX32(0, s_rtc_force_slow_val);
  194. }
  195. TEST_CASE_MULTIPLE_STAGES("reset reason ESP_RST_BROWNOUT after brownout event",
  196. "[reset_reason][ignore][reset=SW_CPU_RESET]",
  197. do_brownout,
  198. check_reset_reason_brownout);
  199. // The following test cases are used to check if the timer_group fix works.
  200. // Some applications use a software reset, at the reset time, timer_group happens to generate an interrupt.
  201. // but software reset does not clear interrupt status, this is not safe for application when enable the interrupt of timer_group.
  202. // This case will check under this fix, whether the interrupt status is cleared after timer_group initialization.
  203. static void timer_group_test_init(void)
  204. {
  205. static const uint32_t time_ms = 100; //Alarm value 100ms.
  206. static const uint16_t timer_div = 10; //Timer prescaler
  207. static const uint32_t ste_val = time_ms * (TIMER_BASE_CLK / timer_div / 1000);
  208. timer_config_t config = {
  209. .divider = timer_div,
  210. .counter_dir = TIMER_COUNT_UP,
  211. .counter_en = TIMER_PAUSE,
  212. .alarm_en = TIMER_ALARM_EN,
  213. .intr_type = TIMER_INTR_LEVEL,
  214. .auto_reload = true,
  215. };
  216. timer_init(TIMER_GROUP_0, TIMER_0, &config);
  217. timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0x00000000ULL);
  218. timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, ste_val);
  219. //Now the timer is ready.
  220. //We only need to check the interrupt status and don't have to register a interrupt routine.
  221. }
  222. static void timer_group_test_first_stage(void)
  223. {
  224. RESET_REASON rst_res = rtc_get_reset_reason(0);
  225. if(rst_res != POWERON_RESET){
  226. printf("Not power on reset\n");
  227. }
  228. TEST_ASSERT_EQUAL(POWERON_RESET, rst_res);
  229. static uint8_t loop_cnt = 0;
  230. timer_group_test_init();
  231. //Start timer
  232. timer_start(TIMER_GROUP_0, TIMER_0);
  233. //Waiting for timer_group to generate an interrupt
  234. while( !TIMERG0.int_raw.t0 && loop_cnt++ < 100) {
  235. vTaskDelay(200);
  236. }
  237. //TIMERG0.int_raw.t0 == 1 means an interruption has occurred
  238. TEST_ASSERT_EQUAL(1, TIMERG0.int_raw.t0);
  239. esp_restart();
  240. }
  241. static void timer_group_test_second_stage(void)
  242. {
  243. RESET_REASON rst_res = rtc_get_reset_reason(0);
  244. if(rst_res != SW_CPU_RESET){
  245. printf("Not software reset\n");
  246. }
  247. TEST_ASSERT_EQUAL(SW_CPU_RESET, rst_res);
  248. timer_group_test_init();
  249. //After the timer_group is initialized, TIMERG0.int_raw.t0 should be cleared.
  250. TEST_ASSERT_EQUAL(0, TIMERG0.int_raw.t0);
  251. }
  252. TEST_CASE_MULTIPLE_STAGES("timer_group software reset test",
  253. "[intr_status][intr_status = 0]",
  254. timer_group_test_first_stage,
  255. timer_group_test_second_stage);
  256. /* Not tested here: ESP_RST_SDIO */