2018-07-29 14:17:09 +03:00
# include "unity.h"
# include "esp_system.h"
# include "esp_task_wdt.h"
# include "esp_attr.h"
2019-05-13 18:02:45 +08:00
# include "soc/rtc_periph.h"
2018-12-06 19:27:52 +08:00
# include "driver/timer.h"
2019-03-14 17:29:32 +08:00
# include "esp32/rom/rtc.h"
2019-04-03 13:17:38 +08:00
# include "esp_sleep.h"
2018-07-29 14:17:09 +03:00
# define RTC_BSS_ATTR __attribute__((section(".rtc.bss")))
2018-09-29 13:53:37 +08:00
# define CHECK_VALUE 0x89abcdef
2018-07-29 14:17:09 +03:00
static __NOINIT_ATTR uint32_t s_noinit_val ;
static RTC_NOINIT_ATTR uint32_t s_rtc_noinit_val ;
static RTC_DATA_ATTR uint32_t s_rtc_data_val ;
static RTC_BSS_ATTR uint32_t s_rtc_bss_val ;
2018-09-29 13:53:37 +08:00
/* There is no practical difference between placing something into RTC_DATA and
* RTC_RODATA. This only checks a usage pattern where the variable has a non-zero
* initializer (should be initialized by the bootloader).
*/
static RTC_RODATA_ATTR uint32_t s_rtc_rodata_val = CHECK_VALUE ;
static RTC_FAST_ATTR uint32_t s_rtc_force_fast_val ;
static RTC_SLOW_ATTR uint32_t s_rtc_force_slow_val ;
2018-07-29 14:17:09 +03:00
2019-07-16 16:33:30 +07:00
static void setup_values ( void )
2018-07-29 14:17:09 +03:00
{
s_noinit_val = CHECK_VALUE ;
s_rtc_noinit_val = CHECK_VALUE ;
s_rtc_data_val = CHECK_VALUE ;
s_rtc_bss_val = CHECK_VALUE ;
2018-09-29 13:53:37 +08:00
TEST_ASSERT_EQUAL_HEX32_MESSAGE ( CHECK_VALUE , s_rtc_rodata_val ,
" s_rtc_rodata_val should already be set up " ) ;
s_rtc_force_fast_val = CHECK_VALUE ;
s_rtc_force_slow_val = CHECK_VALUE ;
2018-07-29 14:17:09 +03:00
}
/* This test needs special test runners: rev1 silicon, and SPI flash with
* fast start-up time. Otherwise reset reason will be RTCWDT_RESET.
*/
TEST_CASE ( " reset reason ESP_RST_POWERON " , " [reset][ignore] " )
{
TEST_ASSERT_EQUAL ( ESP_RST_POWERON , esp_reset_reason ( ) ) ;
}
2019-07-16 16:33:30 +07:00
static void do_deep_sleep ( void )
2018-07-29 14:17:09 +03:00
{
setup_values ( ) ;
esp_sleep_enable_timer_wakeup ( 10000 ) ;
esp_deep_sleep_start ( ) ;
}
2019-07-16 16:33:30 +07:00
static void check_reset_reason_deep_sleep ( void )
2018-07-29 14:17:09 +03:00
{
TEST_ASSERT_EQUAL ( ESP_RST_DEEPSLEEP , esp_reset_reason ( ) ) ;
TEST_ASSERT_EQUAL_HEX32 ( CHECK_VALUE , s_rtc_noinit_val ) ;
TEST_ASSERT_EQUAL_HEX32 ( CHECK_VALUE , s_rtc_data_val ) ;
TEST_ASSERT_EQUAL_HEX32 ( CHECK_VALUE , s_rtc_bss_val ) ;
2018-09-29 13:53:37 +08:00
TEST_ASSERT_EQUAL_HEX32 ( CHECK_VALUE , s_rtc_rodata_val ) ;
TEST_ASSERT_EQUAL_HEX32 ( CHECK_VALUE , s_rtc_force_fast_val ) ;
TEST_ASSERT_EQUAL_HEX32 ( CHECK_VALUE , s_rtc_force_slow_val ) ;
2018-07-29 14:17:09 +03:00
}
TEST_CASE_MULTIPLE_STAGES ( " reset reason ESP_RST_DEEPSLEEP " , " [reset_reason][reset=DEEPSLEEP_RESET] " ,
do_deep_sleep ,
check_reset_reason_deep_sleep ) ;
2019-07-16 16:33:30 +07:00
static void do_exception ( void )
2018-07-29 14:17:09 +03:00
{
setup_values ( ) ;
* ( int * ) ( 0x40000001 ) = 0 ;
}
2019-07-16 16:33:30 +07:00
static void do_abort ( void )
2018-07-29 14:17:09 +03:00
{
setup_values ( ) ;
abort ( ) ;
}
2019-07-16 16:33:30 +07:00
static void check_reset_reason_panic ( void )
2018-07-29 14:17:09 +03:00
{
TEST_ASSERT_EQUAL ( ESP_RST_PANIC , esp_reset_reason ( ) ) ;
TEST_ASSERT_EQUAL_HEX32 ( CHECK_VALUE , s_noinit_val ) ;
TEST_ASSERT_EQUAL_HEX32 ( CHECK_VALUE , s_rtc_noinit_val ) ;
TEST_ASSERT_EQUAL_HEX32 ( 0 , s_rtc_data_val ) ;
TEST_ASSERT_EQUAL_HEX32 ( 0 , s_rtc_bss_val ) ;
2018-09-29 13:53:37 +08:00
TEST_ASSERT_EQUAL_HEX32 ( CHECK_VALUE , s_rtc_rodata_val ) ;
TEST_ASSERT_EQUAL_HEX32 ( 0 , s_rtc_force_fast_val ) ;
TEST_ASSERT_EQUAL_HEX32 ( 0 , s_rtc_force_slow_val ) ;
2018-07-29 14:17:09 +03:00
}
TEST_CASE_MULTIPLE_STAGES ( " reset reason ESP_RST_PANIC after exception " , " [reset_reason][reset=LoadStoreError,SW_CPU_RESET] " ,
do_exception ,
check_reset_reason_panic ) ;
TEST_CASE_MULTIPLE_STAGES ( " reset reason ESP_RST_PANIC after abort " , " [reset_reason][reset=abort,SW_CPU_RESET] " ,
do_abort ,
check_reset_reason_panic ) ;
2019-07-16 16:33:30 +07:00
static void do_restart ( void )
2018-07-29 14:17:09 +03:00
{
setup_values ( ) ;
esp_restart ( ) ;
}
# if portNUM_PROCESSORS > 1
2019-07-16 16:33:30 +07:00
static void do_restart_from_app_cpu ( void )
2018-07-29 14:17:09 +03:00
{
setup_values ( ) ;
xTaskCreatePinnedToCore ( ( TaskFunction_t ) & do_restart , " restart " , 2048 , NULL , 5 , NULL , 1 ) ;
vTaskDelay ( 2 ) ;
}
# endif
2019-07-16 16:33:30 +07:00
static void check_reset_reason_sw ( void )
2018-07-29 14:17:09 +03:00
{
TEST_ASSERT_EQUAL ( ESP_RST_SW , esp_reset_reason ( ) ) ;
TEST_ASSERT_EQUAL_HEX32 ( CHECK_VALUE , s_noinit_val ) ;
TEST_ASSERT_EQUAL_HEX32 ( CHECK_VALUE , s_rtc_noinit_val ) ;
TEST_ASSERT_EQUAL_HEX32 ( 0 , s_rtc_data_val ) ;
TEST_ASSERT_EQUAL_HEX32 ( 0 , s_rtc_bss_val ) ;
2018-09-29 13:53:37 +08:00
TEST_ASSERT_EQUAL_HEX32 ( CHECK_VALUE , s_rtc_rodata_val ) ;
TEST_ASSERT_EQUAL_HEX32 ( 0 , s_rtc_force_fast_val ) ;
TEST_ASSERT_EQUAL_HEX32 ( 0 , s_rtc_force_slow_val ) ;
2018-07-29 14:17:09 +03:00
}
TEST_CASE_MULTIPLE_STAGES ( " reset reason ESP_RST_SW after restart " , " [reset_reason][reset=SW_CPU_RESET] " ,
do_restart ,
check_reset_reason_sw ) ;
# if portNUM_PROCESSORS > 1
TEST_CASE_MULTIPLE_STAGES ( " reset reason ESP_RST_SW after restart from APP CPU " , " [reset_reason][reset=SW_CPU_RESET] " ,
do_restart_from_app_cpu ,
check_reset_reason_sw ) ;
# endif
2019-07-16 16:33:30 +07:00
static void do_int_wdt ( void )
2018-07-29 14:17:09 +03:00
{
2019-05-06 10:59:43 +08:00
setup_values ( ) ;
2018-07-29 14:17:09 +03:00
portENTER_CRITICAL_NESTED ( ) ;
while ( 1 ) ;
}
2019-07-16 16:33:30 +07:00
static void do_int_wdt_hw ( void )
2018-07-29 14:17:09 +03:00
{
2019-05-06 10:59:43 +08:00
setup_values ( ) ;
2018-07-29 14:17:09 +03:00
XTOS_SET_INTLEVEL ( XCHAL_NMILEVEL ) ;
while ( 1 ) ;
}
2019-07-16 16:33:30 +07:00
static void check_reset_reason_int_wdt ( void )
2018-07-29 14:17:09 +03:00
{
TEST_ASSERT_EQUAL ( ESP_RST_INT_WDT , esp_reset_reason ( ) ) ;
2019-05-06 10:59:43 +08:00
TEST_ASSERT_EQUAL_HEX32 ( CHECK_VALUE , s_rtc_noinit_val ) ;
2018-07-29 14:17:09 +03:00
}
TEST_CASE_MULTIPLE_STAGES ( " reset reason ESP_RST_INT_WDT after interrupt watchdog (panic) " ,
" [reset_reason][reset=Interrupt wdt timeout on CPU0,SW_CPU_RESET] " ,
do_int_wdt ,
check_reset_reason_int_wdt ) ;
TEST_CASE_MULTIPLE_STAGES ( " reset reason ESP_RST_INT_WDT after interrupt watchdog (hw) " ,
" [reset_reason][reset=TG1WDT_SYS_RESET] " ,
do_int_wdt_hw ,
check_reset_reason_int_wdt ) ;
2019-07-16 16:33:30 +07:00
static void do_task_wdt ( void )
2018-07-29 14:17:09 +03:00
{
setup_values ( ) ;
esp_task_wdt_init ( 1 , true ) ;
esp_task_wdt_add ( xTaskGetIdleTaskHandleForCPU ( 0 ) ) ;
while ( 1 ) ;
}
2019-07-16 16:33:30 +07:00
static void check_reset_reason_task_wdt ( void )
2018-07-29 14:17:09 +03:00
{
TEST_ASSERT_EQUAL ( ESP_RST_TASK_WDT , esp_reset_reason ( ) ) ;
TEST_ASSERT_EQUAL_HEX32 ( CHECK_VALUE , s_noinit_val ) ;
TEST_ASSERT_EQUAL_HEX32 ( CHECK_VALUE , s_rtc_noinit_val ) ;
TEST_ASSERT_EQUAL_HEX32 ( 0 , s_rtc_data_val ) ;
TEST_ASSERT_EQUAL_HEX32 ( 0 , s_rtc_bss_val ) ;
2018-09-29 13:53:37 +08:00
TEST_ASSERT_EQUAL_HEX32 ( CHECK_VALUE , s_rtc_rodata_val ) ;
TEST_ASSERT_EQUAL_HEX32 ( 0 , s_rtc_force_fast_val ) ;
TEST_ASSERT_EQUAL_HEX32 ( 0 , s_rtc_force_slow_val ) ;
2018-07-29 14:17:09 +03:00
}
TEST_CASE_MULTIPLE_STAGES ( " reset reason ESP_RST_TASK_WDT after task watchdog " ,
" [reset_reason][reset=abort,SW_CPU_RESET] " ,
do_task_wdt ,
check_reset_reason_task_wdt ) ;
2019-07-16 16:33:30 +07:00
static void do_rtc_wdt ( void )
2018-07-29 14:17:09 +03:00
{
2019-05-06 10:59:43 +08:00
setup_values ( ) ;
2018-07-29 14:17:09 +03:00
WRITE_PERI_REG ( RTC_CNTL_WDTWPROTECT_REG , RTC_CNTL_WDT_WKEY_VALUE ) ;
REG_SET_FIELD ( RTC_CNTL_WDTCONFIG0_REG , RTC_CNTL_WDT_SYS_RESET_LENGTH , 7 ) ;
REG_SET_FIELD ( RTC_CNTL_WDTCONFIG0_REG , RTC_CNTL_WDT_STG0 , RTC_WDT_STG_SEL_RESET_SYSTEM ) ;
WRITE_PERI_REG ( RTC_CNTL_WDTCONFIG1_REG , 10000 ) ;
REG_SET_BIT ( RTC_CNTL_WDTCONFIG0_REG , RTC_CNTL_WDT_FLASHBOOT_MOD_EN ) ;
while ( 1 ) ;
}
2019-07-16 16:33:30 +07:00
static void check_reset_reason_any_wdt ( void )
2018-07-29 14:17:09 +03:00
{
TEST_ASSERT_EQUAL ( ESP_RST_WDT , esp_reset_reason ( ) ) ;
2019-05-06 10:59:43 +08:00
TEST_ASSERT_EQUAL_HEX32 ( CHECK_VALUE , s_rtc_noinit_val ) ;
2018-07-29 14:17:09 +03:00
}
TEST_CASE_MULTIPLE_STAGES ( " reset reason ESP_RST_WDT after RTC watchdog " ,
" [reset_reason][reset=RTCWDT_RTC_RESET] " ,
do_rtc_wdt ,
check_reset_reason_any_wdt ) ;
2019-07-16 16:33:30 +07:00
static void do_brownout ( void )
2018-07-29 14:17:09 +03:00
{
setup_values ( ) ;
printf ( " Manual test: lower the supply voltage to cause brownout \n " ) ;
vTaskSuspend ( NULL ) ;
}
2019-07-16 16:33:30 +07:00
static void check_reset_reason_brownout ( void )
2018-07-29 14:17:09 +03:00
{
TEST_ASSERT_EQUAL ( ESP_RST_BROWNOUT , esp_reset_reason ( ) ) ;
TEST_ASSERT_EQUAL_HEX32 ( CHECK_VALUE , s_noinit_val ) ;
TEST_ASSERT_EQUAL_HEX32 ( CHECK_VALUE , s_rtc_noinit_val ) ;
TEST_ASSERT_EQUAL_HEX32 ( 0 , s_rtc_data_val ) ;
TEST_ASSERT_EQUAL_HEX32 ( 0 , s_rtc_bss_val ) ;
2018-09-29 13:53:37 +08:00
TEST_ASSERT_EQUAL_HEX32 ( CHECK_VALUE , s_rtc_rodata_val ) ;
TEST_ASSERT_EQUAL_HEX32 ( 0 , s_rtc_force_fast_val ) ;
TEST_ASSERT_EQUAL_HEX32 ( 0 , s_rtc_force_slow_val ) ;
2018-07-29 14:17:09 +03:00
}
TEST_CASE_MULTIPLE_STAGES ( " reset reason ESP_RST_BROWNOUT after brownout event " ,
" [reset_reason][ignore][reset=SW_CPU_RESET] " ,
do_brownout ,
check_reset_reason_brownout ) ;
2018-12-06 19:27:52 +08:00
2020-05-16 17:52:33 +08:00
# ifdef CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
# ifndef CONFIG_FREERTOS_UNICORE
# include "xt_instr_macros.h"
# include "xtensa/config/specreg.h"
static int size_stack = 1024 * 3 ;
static StackType_t * start_addr_stack ;
static int fibonacci ( int n , void * func ( void ) )
{
int tmp1 = n , tmp2 = n ;
uint32_t base , start ;
RSR ( WINDOWBASE , base ) ;
RSR ( WINDOWSTART , start ) ;
printf ( " WINDOWBASE = %-2d WINDOWSTART = 0x%x \n " , base , start ) ;
if ( n < = 1 ) {
StackType_t * last_addr_stack = get_sp ( ) ;
StackType_t * used_stack = ( StackType_t * ) ( start_addr_stack - last_addr_stack ) ;
printf ( " addr_stack = %p, used[%p]/all[0x%x] space in stack \n " , last_addr_stack , used_stack , size_stack ) ;
func ( ) ;
return n ;
}
int fib = fibonacci ( n - 1 , func ) + fibonacci ( n - 2 , func ) ;
printf ( " fib = %d \n " , ( tmp1 - tmp2 ) + fib ) ;
return fib ;
}
static void test_task ( void * func )
{
start_addr_stack = get_sp ( ) ;
if ( esp_ptr_external_ram ( start_addr_stack ) ) {
printf ( " restart_task: uses external stack, addr_stack = %p \n " , start_addr_stack ) ;
} else {
printf ( " restart_task: uses internal stack, addr_stack = %p \n " , start_addr_stack ) ;
}
fibonacci ( 35 , func ) ;
}
static void func_do_exception ( void )
{
* ( ( int * ) 0 ) = 0 ;
}
static void init_restart_task ( void )
{
StackType_t * stack_for_task = ( StackType_t * ) heap_caps_calloc ( 1 , size_stack , MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT ) ;
printf ( " init_task: current addr_stack = %p, stack_for_task = %p \n " , get_sp ( ) , stack_for_task ) ;
static StaticTask_t task_buf ;
xTaskCreateStaticPinnedToCore ( test_task , " test_task " , size_stack , esp_restart , 5 , stack_for_task , & task_buf , 1 ) ;
while ( 1 ) { } ;
}
static void init_task_do_exception ( void )
{
StackType_t * stack_for_task = ( StackType_t * ) heap_caps_calloc ( 1 , size_stack , MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT ) ;
printf ( " init_task: current addr_stack = %p, stack_for_task = %p \n " , get_sp ( ) , stack_for_task ) ;
static StaticTask_t task_buf ;
xTaskCreateStaticPinnedToCore ( test_task , " test_task " , size_stack , func_do_exception , 5 , stack_for_task , & task_buf , 1 ) ;
while ( 1 ) { } ;
}
static void test1_finish ( void )
{
TEST_ASSERT_EQUAL ( ESP_RST_SW , esp_reset_reason ( ) ) ;
printf ( " test - OK \n " ) ;
}
static void test2_finish ( void )
{
TEST_ASSERT_EQUAL ( ESP_RST_PANIC , esp_reset_reason ( ) ) ;
printf ( " test - OK \n " ) ;
}
TEST_CASE_MULTIPLE_STAGES ( " reset reason ESP_RST_SW after restart in a task with spiram stack " , " [spiram_stack][reset=SW_CPU_RESET] " ,
init_restart_task ,
test1_finish ) ;
TEST_CASE_MULTIPLE_STAGES ( " reset reason ESP_RST_PANIC after an exception in a task with spiram stack " , " [spiram_stack][reset=StoreProhibited,SW_CPU_RESET] " ,
init_task_do_exception ,
test2_finish ) ;
# endif // CONFIG_FREERTOS_UNICORE
# endif // CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
2018-07-29 14:17:09 +03:00
/* Not tested here: ESP_RST_SDIO */