/************************************************************************** * Description: handles reinitializing the device after a few seconds * Returns: none * Notes: gives the device enough time to acknowledge the RD request **************************************************************************/ static void reinit_task(void) { BACNET_REINITIALIZED_STATE state = BACNET_REINIT_IDLE; state = Device_Reinitialized_State(); if (state == BACNET_REINIT_IDLE) { /* set timer to never expire */ timer_interval_infinity(&Reinit_Timer); } else if (timer_interval_active(&Reinit_Timer)) { if (timer_interval_expired(&Reinit_Timer)) { /* reset MCU via watchdog timeout */ wdt_reset_mcu(); } } else { timer_interval_start_seconds(&Reinit_Timer, 3); } }
/** \brief Main function. */ int main(void) { uint8_t i; /* Initialize the board hardware and system clocks. */ board_init(); sysclk_init(); /* Detection of all RESET excepted WDT RESET. */ if (reset_cause_get_causes() & ~CHIP_RESET_CAUSE_WDT) { /* Wait for 2 s. */ delay_ms(2000); state_flag = START_OF_PROG; reset_cause_clear_causes( CHIP_RESET_CAUSE_POR | CHIP_RESET_CAUSE_EXTRST | CHIP_RESET_CAUSE_BOD_CPU | CHIP_RESET_CAUSE_OCD | CHIP_RESET_CAUSE_SOFT | CHIP_RESET_CAUSE_SPIKE); } else { reset_cause_clear_causes(CHIP_RESET_CAUSE_WDT); } while (true) { led_display(state_flag); switch (state_flag) { case START_OF_PROG: /* Writing test. */ wdt_set_timeout_period(WDT_TIMEOUT_PERIOD_8CLK); if (wdt_get_timeout_period() != WDT_TIMEOUT_PERIOD_8CLK) { state_flag = ERROR_STATE; break; } wdt_set_timeout_period(WDT_TIMEOUT_PERIOD_250CLK); if (wdt_get_timeout_period() != WDT_TIMEOUT_PERIOD_250CLK) { state_flag = ERROR_STATE; break; } /* Wait for 2 s. */ delay_ms(2000); state_flag = WDT_MCU_RESET; break; case WDT_MCU_RESET: /* Wait for 2 s. */ delay_ms(2000); state_flag = REFRESH_NO_WIN; wdt_reset_mcu(); break; case REFRESH_NO_WIN: /* Enable WDT 500 ms. */ wdt_set_timeout_period(WDT_TIMEOUT_PERIOD_500CLK); wdt_enable(); for (i = 0; i < 8; i++) { /* Wait for 8x 250 ms = 2 s. */ delay_ms(250); wdt_reset(); } wdt_disable(); state_flag = REFRESH_WINDOW; break; case REFRESH_WINDOW: /* Enable Window 250 ms & WDT 500 ms. */ wdt_set_timeout_period(WDT_TIMEOUT_PERIOD_500CLK); wdt_enable(); if (!(wdt_set_window_period(WDT_WINDOW_PERIOD_250CLK))) { state_flag = ERROR_STATE; break; } if (!(wdt_enable_window_mode())) { state_flag = ERROR_STATE; break; } for (i = 0; i < 4; i++) { /* Wait for 500 ms. */ delay_ms(500); wdt_reset(); } wdt_disable(); state_flag = WDT_RST_NO_WIN; break; case WDT_RST_NO_WIN: state_flag = WDT_RST_WINDOW; /* Enable WDT 2 s. */ wdt_set_timeout_period(WDT_TIMEOUT_PERIOD_2KCLK); wdt_enable(); while (true) { /* Wait for Watchdog reset. */ } break; case WDT_RST_WINDOW: state_flag = WDT_RST_RFSH_W; /* Enable Window 1 s & WDT 1 s. */ wdt_set_timeout_period(WDT_TIMEOUT_PERIOD_1KCLK); wdt_enable(); if (!(wdt_set_window_period(WDT_WINDOW_PERIOD_1KCLK))) { state_flag = ERROR_STATE; break; } if (!(wdt_enable_window_mode())) { state_flag = ERROR_STATE; break; } while (true) { /* Wait for Watchdog reset. */ } break; case WDT_RST_RFSH_W: state_flag = END_OF_PROG; /* Enable Window 4 s & WDT 250 ms. */ wdt_set_timeout_period(WDT_TIMEOUT_PERIOD_250CLK); wdt_enable(); if (!(wdt_set_window_period(WDT_WINDOW_PERIOD_4KCLK))) { state_flag = ERROR_STATE; break; } if (!(wdt_enable_window_mode())) { state_flag = ERROR_STATE; break; } /* Wait for 2 s. */ delay_ms(2000); wdt_reset(); while (true) { /* Wait for Watchdog reset. */ } break; case ERROR_STATE: while (true) { led_display(ERROR_STATE); /* Wait for 500 ms. */ delay_ms(500); /* Blinking. */ led_display(~ERROR_STATE); /* Wait for 500 ms. */ delay_ms(500); } break; case END_OF_PROG: default: /* Wait for 2 s. */ delay_ms(2000); reset_do_soft_reset(); break; } } }
/** * \brief Main function. */ int main(void) { uint8_t key; /* Initialize the SAM system. */ sysclk_init(); board_init(); /* Initialize the UART console. */ configure_console(); /* Output example information. */ puts(STRING_HEADER); puts("------ Please select which reset is to be generated ----------\r\n" " c: Generate core BOD reset\r\n" " i: Generate I/O BOD reset\r\n" " w: Generate watchdog reset\r\n" " s: Generate system reset \r"); if (reset_cause_is_power_on_reset()) { LED_On(LED0); } if (reset_cause_is_cpu_brown_out_detected()) { puts("-- Reset Cause is Core browm out reset --\r"); } if (reset_cause_is_io_brown_out_detected()) { puts("-- Reset Cause is I/O brown out reset --\r"); } if (reset_cause_is_ocd()) { puts("-- Reset Cause is system reset request --\r"); } if (reset_cause_is_external_reset()) { puts("-- Reset Cause is external reset --\r"); } if (reset_cause_is_watchdog()) { puts("-- Reset Cause is watchdog reset --\r"); } while(1) { scanf("%c", (char *)&key); switch (key) { case 'c': puts("-- Please press reset button --\r"); BSCIF->BSCIF_BOD18CTRL = BSCIF_BOD18CTRL_EN | BSCIF_BOD18CTRL_ACTION(1) | BSCIF_BOD18CTRL_HYST | BSCIF_BOD18CTRL_FCD; BSCIF->BSCIF_BOD18LEVEL |= BSCIF_BOD18LEVEL_VAL(0x3F); break; case 'i': puts("-- Please press reset button --\r"); BSCIF->BSCIF_BOD33CTRL = BSCIF_BOD33CTRL_EN | BSCIF_BOD33CTRL_ACTION(1) | BSCIF_BOD33CTRL_HYST | BSCIF_BOD33CTRL_FCD; BSCIF->BSCIF_BOD33LEVEL = BSCIF_BOD33LEVEL_VAL(0x3F); break; case 'w': wdt_reset_mcu(); break; case 's': reset_do_soft_reset(); break; } } }
/** * \brief Test watchdog for all cases. * * \note Because MCU will be reset serval times druing the test, * to simplify the design, only one test case but with many test stages. * * \param test Current test case. */ static void run_wdt_test_all(const struct test_case *test) { struct wdt_dev_inst wdt_inst; struct wdt_config wdt_cfg; uint32_t wdt_window_ms = 0; uint32_t wdt_timeout_ms = 0; uint32_t wdt_ut_stage; /* Get test stage */ wdt_ut_stage = (uint32_t)(*(uint32_t *)WDT_UT_TAG_ADDR); if (is_wdt_reset()) { /* Check if the reset is as expected */ switch (wdt_ut_stage) { case WDT_UT_STAGE_START: test_assert_true(test, 0, "Unexpected watchdog reset at start stage!"); break; case WDT_UT_STAGE_RST_MCU: /* Move to next stage */ wdt_ut_stage = WDT_UT_STAGE_BM_NORMAL; flashcalw_memcpy((void *)WDT_UT_TAG_ADDR, &wdt_ut_stage, 4, true); break; case WDT_UT_STAGE_BM_NORMAL: test_assert_true(test, 0, "Unexpected watchdog reset at basic mode!"); break; case WDT_UT_STAGE_BM_TIMEOUT_RST: /* Move to next stage */ wdt_ut_stage = WDT_UT_STAGE_WM_NORMAL; flashcalw_memcpy((void *)WDT_UT_TAG_ADDR, &wdt_ut_stage, 4, true); break; case WDT_UT_STAGE_WM_NORMAL: test_assert_true(test, 0, "Unexpected watchdog reset at window mode!"); break; case WDT_UT_STAGE_WM_TIMEBAN_RST: /* Move to next stage */ wdt_ut_stage = WDT_UT_STAGE_WM_TIMEOUT_RST; flashcalw_memcpy((void *)WDT_UT_TAG_ADDR, &wdt_ut_stage, 4, true); break; case WDT_UT_STAGE_WM_TIMEOUT_RST: /* Move to next stage */ wdt_ut_stage = WDT_UT_STAGE_END; flashcalw_memcpy((void *)WDT_UT_TAG_ADDR, &wdt_ut_stage, 4, true); break; case WDT_UT_STAGE_END: test_assert_true(test, 0, "Unexpected watchdog reset at end stage!"); break; default: test_assert_true(test, 0, "Unexpected watchdog reset!"); break; } } else { /* First WDT unit test start at here, set stage flag */ wdt_ut_stage = WDT_UT_STAGE_START; flashcalw_memcpy((void *)WDT_UT_TAG_ADDR, &wdt_ut_stage, 4, true); } /* * ---- Test reset MCU by the WDT ---- */ if (wdt_ut_stage == WDT_UT_STAGE_START) { bool ret; /* Move to next stage */ wdt_ut_stage = WDT_UT_STAGE_RST_MCU; flashcalw_memcpy((void *)WDT_UT_TAG_ADDR, &wdt_ut_stage, 4, true); /* Reset MCU by the watchdog. */ ret = wdt_reset_mcu(); test_assert_false(test, ret, "Can't reset MCU by the WDT: failed!"); /* The code should not go to here */ test_assert_true(test, 0, "Reset MCU by the WDT: failed!"); } /* * ---- Test the WDT in basic mode ---- */ if ((wdt_ut_stage & WDT_UT_STAGE_MASK) == WDT_UT_STAGE_BM) { /* * Intialize the watchdog in basic mode: * - Use default configuration. * - But change timeout period to 0.57s * (Ttimeout = 2pow(PSEL+1) / Fclk_cnt = 65535 / 115000). */ wdt_get_config_defaults(&wdt_cfg); wdt_cfg.timeout_period = WDT_PERIOD_65536_CLK; wdt_timeout_ms = 570; wdt_init(&wdt_inst, WDT, &wdt_cfg); wdt_enable(&wdt_inst); wdt_clear(&wdt_inst); mdelay(wdt_timeout_ms / 2); wdt_clear(&wdt_inst); /* The code should reach here */ test_assert_true(test, 1, "Clear the WDT in basic mode: passed."); /* Move to next stage */ wdt_ut_stage = WDT_UT_STAGE_BM_TIMEOUT_RST; flashcalw_memcpy((void *)WDT_UT_TAG_ADDR, &wdt_ut_stage, 4, true); /* Wait for the WDT reset */ mdelay(wdt_timeout_ms * 2); /* The code should not go to here, disable watchdog for default */ wdt_disable(&wdt_inst); test_assert_true(test, 0, "No WDT reset happened in basic mode!"); } /* * ---- Test the WDT in window mode ---- */ if ((wdt_ut_stage & WDT_UT_STAGE_MASK) == WDT_UT_STAGE_WM) { /* Enable WDT clock source if need */ if (BPM->BPM_PMCON & BPM_PMCON_CK32S) { /* Enable 32K RC oscillator */ if (!osc_is_ready(OSC_ID_RC32K)) { osc_enable(OSC_ID_RC32K); osc_wait_ready(OSC_ID_RC32K); } } else { /* Enable external OSC32 oscillator */ if (!osc_is_ready(OSC_ID_OSC32)) { osc_enable(OSC_ID_OSC32); osc_wait_ready(OSC_ID_OSC32); } } /* * Intialize the watchdog in window mode: * - Use 32K oscillator as WDT clock source. * - Set timeout/timeban period to 0.5s * (Ttimeout = 2pow(PSEL+1) / Fclk_cnt = 16384 / 32768). */ wdt_get_config_defaults(&wdt_cfg); wdt_cfg.wdt_mode = WDT_MODE_WINDOW; wdt_cfg.clk_src = WDT_CLK_SRC_32K; wdt_cfg.window_period = WDT_PERIOD_16384_CLK; wdt_cfg.timeout_period = WDT_PERIOD_16384_CLK; wdt_window_ms = 500; wdt_timeout_ms = 500; wdt_init(&wdt_inst, WDT, &wdt_cfg); wdt_enable(&wdt_inst); mdelay(wdt_window_ms + wdt_timeout_ms / 10); wdt_clear(&wdt_inst); /* The code should reach here */ test_assert_true(test, 1, "Clear the WDT in window mode: passed."); if (wdt_ut_stage == WDT_UT_STAGE_WM_NORMAL) { /* Move to next stage */ wdt_ut_stage = WDT_UT_STAGE_WM_TIMEBAN_RST; flashcalw_memcpy((void *)WDT_UT_TAG_ADDR, &wdt_ut_stage, 4, true); /* Clear the WDT in time ban window */ wdt_clear(&wdt_inst); /* The WDT reset should happen */ mdelay(50); } else if (wdt_ut_stage == WDT_UT_STAGE_WM_TIMEOUT_RST) { /* Wait for the WDT reset when timeout */ mdelay(wdt_window_ms); mdelay(wdt_timeout_ms * 2); } /* The code should not go to here, disable watchdog for default */ wdt_disable(&wdt_inst); test_assert_true(test, 0, "No WDT reset happened in window mode!"); } /* * ---- Check if all test are OK ---- */ if (wdt_ut_stage == WDT_UT_STAGE_END) { test_assert_true(test, 1, "All test stages done for WDT."); /* Clear flash content */ wdt_ut_stage = 0xFFFFFFFFu; flashcalw_memcpy((void *)WDT_UT_TAG_ADDR, &wdt_ut_stage, 4, true); } else { test_assert_true(test, 0, "WDT test stopped with unexpected stages."); } }
/** \brief Main function. */ int main(void) { uint8_t delay_counter; volatile uint16_t delay; /* Initialize the board. * The board-specific conf_board.h file contains the configuration of * the board initialization. */ sysclk_init(); board_init(); /* Detection of all RESET except WDT RESET. */ if ((reset_cause_get_causes() & CHIP_RESET_CAUSE_WDT) != CHIP_RESET_CAUSE_WDT) { state_flag = START_OF_PROG; reset_cause_clear_causes(CHIP_RESET_CAUSE_POR | CHIP_RESET_CAUSE_EXTRST | CHIP_RESET_CAUSE_BOD_CPU); } else { reset_cause_clear_causes(CHIP_RESET_CAUSE_WDT); } wdt_disable(); while (true) { switch (state_flag) { case START_OF_PROG: /* Writing test. */ wdt_set_timeout_period(WDT_TIMEOUT_PERIOD_2KCLK); if (wdt_get_timeout_period() != WDT_TIMEOUT_PERIOD_2KCLK) { state_flag = ERROR_STATE; break; } wdt_set_timeout_period(WDT_TIMEOUT_PERIOD_1024KCLK); if (wdt_get_timeout_period() != WDT_TIMEOUT_PERIOD_1024KCLK) { state_flag = ERROR_STATE; break; } /* Wait for 2 s. */ delay = 2000; delay_ms(delay); state_flag = WDT_MCU_RESET; break; case WDT_MCU_RESET: state_flag = REFRESH_WDT; wdt_reset_mcu(); break; case REFRESH_WDT: /* Enable WDT 500 ms. */ wdt_set_timeout_period(WDT_TIMEOUT_PERIOD_64KCLK); wdt_enable(SYSTEM_RESET_MODE); if (wdt_get_timeout_period() != WDT_TIMEOUT_PERIOD_64KCLK) { state_flag = ERROR_STATE; break; } for (delay_counter = 0; delay_counter < 8; delay_counter++) { /* Wait for 8x 250 ms = 2 s. */ delay = 250; delay_ms(delay); wdt_reset(); } wdt_disable(); state_flag = WDT_RST; break; case WDT_RST: state_flag = WDT_INTERRUPT; /* Enable WDT 2 s. */ wdt_set_timeout_period(WDT_TIMEOUT_PERIOD_256KCLK); wdt_enable(SYSTEM_RESET_MODE); if (wdt_get_timeout_period() != WDT_TIMEOUT_PERIOD_256KCLK) { state_flag = ERROR_STATE; break; } while (true) { /* Wait for Watchdog reset. */ } /* No break is needed */ case WDT_INTERRUPT: /* Enable WDT 250 ms. */ wdt_set_timeout_period(WDT_TIMEOUT_PERIOD_32KCLK); wdt_set_interrupt_callback(wdt_timer_callback); wdt_enable(INTERRUPT_MODE); if (wdt_get_timeout_period() != WDT_TIMEOUT_PERIOD_32KCLK) { state_flag = ERROR_STATE; break; } cpu_irq_enable(); /* Wait for interrupt to get triggered */ delay = 400; delay_ms(delay); wdt_disable(); break; case WDT_RST_INTERRUPT: /* Enable WDT 125 ms. */ wdt_set_timeout_period(WDT_TIMEOUT_PERIOD_16KCLK); wdt_set_interrupt_callback(wdt_timer_callback); wdt_enable(INTERRUPT_SYSTEM_RESET_MODE); if (wdt_get_timeout_period() != WDT_TIMEOUT_PERIOD_16KCLK) { state_flag = ERROR_STATE; break; } /* Wait for 200 ms. */ delay = 200; delay_ms(delay); wdt_reset(); while (true) { /* Wait for Watchdog reset. */ } /* No break is needed */ case ERROR_STATE: wdt_disable(); while (true) { LED_On(LED_PIN); /* Wait for 500 ms. */ delay = 500; delay_ms(delay); /* Blinking. */ LED_Off(LED_PIN); /* Wait for 500 ms. */ delay = 500; delay_ms(delay); } /* No break is needed */ case END_OF_PROG: default: LED_On(LED_PIN); while (true) { } /* No break is needed */ } } }