default 0x4000 if MEMMAP_TRACEMEM && !MEMMAP_TRACEMEM_TWOBANKS
default 0x0
+# Not implemented and/or needs new silicon rev to work
config MEMMAP_SPISRAM
bool "Use external SPI SRAM chip as main memory"
+ depends on ESP32_NEEDS_NEW_SILICON_REV
default "n"
help
The ESP32 can control an external SPI SRAM chip, adding the memory it contains to the
depends on !ULP_COPROC_ENABLED
+choice ESP32_PANIC
+ prompt "Panic handler behaviour"
+ default FREERTOS_PANIC_PRINT_REBOOT
+ help
+ If FreeRTOS detects unexpected behaviour or an unhandled exception, the panic handler is
+ invoked. Configure the panic handlers action here.
+
+config ESP32_PANIC_PRINT_HALT
+ bool "Print registers and halt"
+ help
+ Outputs the relevant registers over the serial port and halt the
+ processor. Needs a manual reset to restart.
+
+config ESP32_PANIC_PRINT_REBOOT
+ bool "Print registers and reboot"
+ help
+ Outputs the relevant registers over the serial port and immediately
+ reset the processor.
+
+config ESP32_PANIC_SILENT_REBOOT
+ bool "Silent reboot"
+ help
+ Just resets the processor without outputting anything
+
+config ESP32_PANIC_GDBSTUB
+ bool "Invoke GDBStub"
+ help
+ Invoke gdbstub on the serial port, allowing for gdb to attach to it to do a postmortem
+ of the crash.
+endchoice
+
+config ESP32_DEBUG_OCDAWARE
+ bool "Make exception and panic handlers JTAG/OCD aware"
+ default y
+ help
+ The FreeRTOS panic and unhandled exception handers can detect a JTAG OCD debugger and
+ instead of panicking, have the debugger stop on the offending instruction.
+
+
config INT_WDT
bool "Interrupt watchdog"
default y
#endif
esp_set_cpu_freq(); // set CPU frequency configured in menuconfig
uart_div_modify(0, (APB_CLK_FREQ << 4) / 115200);
- ets_setup_syscalls();
- do_global_ctors();
- esp_ipc_init();
- spi_flash_init();
#if CONFIG_BROWNOUT_DET
esp_brownout_init();
#endif
#if CONFIG_INT_WDT
- int_wdt_init();
+ esp_int_wdt_init();
#endif
#if CONFIG_TASK_WDT
- task_wdt_init();
+ esp_task_wdt_init();
#endif
+ ets_setup_syscalls();
+ do_global_ctors();
+ esp_ipc_init();
+ spi_flash_init();
xTaskCreatePinnedToCore(&main_task, "main",
ESP_TASK_MAIN_STACK, NULL,
#include "soc/uart_reg.h"
#include "soc/io_mux_reg.h"
-#include "gdbstub.h"
+#include "esp_gdbstub.h"
//Length of buffer used to reserve GDB commands. Has to be at least able to fit the G command, which
//implies a minimum size of about 320 bytes.
#include <xtensa/config/core.h>
#include "freertos/xtensa_api.h"
-void gdbstubPanicHandler(XtExcFrame *frame);
+void esp_gdbstub_panic_handler(XtExcFrame *frame);
#endif
\ No newline at end of file
* @{
*/
+/*
+This routine enables a watchdog to catch instances of processes disabling
+interrupts for too long, or code within interrupt handlers taking too long.
+It does this by setting up a watchdog which gets fed from the FreeRTOS
+task switch interrupt. When this watchdog times out, initially it will call
+a high-level interrupt routine that will panic FreeRTOS in order to allow
+for forensic examination of the state of the CPU. When this interrupt
+handler is not called and the watchdog times out a second time, it will
+reset the SoC.
+
+This uses the TIMERG1 WDT.
+*/
+
+
/**
- * @brief Initialize the interrupt watchdog. This is called in the init code, no need to
- * call it explicitly.
+ * @brief Initialize the interrupt watchdog. This is called in the init code if
+ * the interrupt watchdog is enabled in menuconfig.
*
* @param null
*
* @return null
*/
-void int_wdt_init();
+void esp_int_wdt_init();
/**
#ifndef __ASSEMBLER__
-void setBreakpointIfJtag(void *fn);
+void esp_set_breakpoint_if_jtag(void *fn);
#endif
* @{
*/
+/*
+This routine enables a more general-purpose task watchdog: tasks can individually
+feed the watchdog and the watchdog will bark if one or more tasks haven't fed the
+watchdog within the specified time. Optionally, the idle tasks can also configured
+to feed the watchdog in a similar fashion, to detect CPU starvation.
+
+This uses the TIMERG0 WDT.
+*/
+
+
/**
- * @brief Initialize the task watchdog. This is called in the init code, no need to
- * call it explicitly.
+ * @brief Initialize the task watchdog. This is called in the init code, if the
+ * task watchdog is enabled in menuconfig.
*
* @param null
*
* @return null
*/
-void task_wdt_init();
+void esp_task_wdt_init();
/**
* @brief Feed the watchdog. After the first feeding session, the watchdog will expect the calling
* @return null
*/
-void task_wdt_feed();
+void esp_task_wdt_feed();
/**
*
* @return null
*/
-void task_wdt_delete();
+void esp_task_wdt_delete();
/**
* @}
#ifndef _SOC_RTC_CNTL_REG_H_
#define _SOC_RTC_CNTL_REG_H_
+#define WDT_WRITE_KEY 0x50D83AA1
+
#include "soc.h"
#define RTC_CNTL_OPTIONS0_REG (DR_REG_RTCCNTL_BASE + 0x0)
#define __TIMG_REG_H__
#include "soc.h"
+#define WDT_WRITE_KEY 0x50D83AA1
+
#define REG_TIMG_BASE(i) (DR_REG_TIMERGROUP0_BASE + i*0x1000)
#define TIMG_T0CONFIG_REG(i) (REG_TIMG_BASE(i) + 0x0000)
/* TIMG_T0_EN : R/W ;bitpos:[31] ;default: 1'h0 ; */
// limitations under the License.
-/*
-This routine enables a watchdog to catch instances of processes disabling
-interrupts for too long, or code within interrupt handlers taking too long.
-It does this by setting up a watchdog which gets fed from the FreeRTOS
-task switch interrupt. When this watchdog times out, initially it will call
-a high-level interrupt routine that will panic FreeRTOS in order to allow
-for forensic examination of the state of the CPU. When this interrupt
-handler is not called and the watchdog times out a second time, it will
-reset the SoC.
-
-This uses the TIMERG1 WDT.
-*/
#include "sdkconfig.h"
#include <stdint.h>
#include "esp_err.h"
#include "esp_intr.h"
#include "soc/timer_group_struct.h"
+#include "soc/timer_group_reg.h"
#include "esp_int_wdt.h"
#define WDT_INT_NUM 24
-#define WDT_WRITE_KEY 0x50D83AA1
-void int_wdt_init() {
+void esp_int_wdt_init() {
TIMERG1.wdt_wprotect=WDT_WRITE_KEY;
TIMERG1.wdt_config0.sys_reset_length=7; //3.2uS
TIMERG1.wdt_config0.cpu_reset_length=7; //3.2uS
}
+//Take care: the tick hook can also be called before esp_int_wdt_init() is called.
#if CONFIG_INT_WDT_CHECK_CPU1
//Not static; the ISR assembly checks this.
bool int_wdt_app_cpu_ticked=false;
#include "soc/dport_reg.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/timer_group_struct.h"
+#include "soc/timer_group_reg.h"
-#include "gdbstub.h"
-#include "panic.h"
-
-#define WDT_WRITE_KEY 0x50D83AA1
+#include "esp_gdbstub.h"
+#include "esp_panic.h"
/*
}
-//Disables all but one WDT, and allows enough time on that WDT to do what we need to do.
+/*
+If watchdogs are enabled, the panic handler runs the risk of getting aborted pre-emptively because
+an overzealous watchdog decides to reset it. On the other hand, if we disable all watchdogs, we run
+the risk of somehow halting in the panic handler and not resetting. That is why this routine kills
+all watchdogs except the timer group 0 watchdog, and it reconfigures that to reset the chip after
+one second.
+*/
static void reconfigureAllWdts() {
TIMERG0.wdt_wprotect=WDT_WRITE_KEY;
TIMERG0.wdt_feed=1;
TIMERG1.wdt_wprotect=0;
}
+/*
+This disables all the watchdogs for when we call the gdbstub.
+*/
static void disableAllWdts() {
TIMERG0.wdt_wprotect=WDT_WRITE_KEY;
TIMERG0.wdt_config0.en=0;
#if CONFIG_FREERTOS_PANIC_GDBSTUB
disableAllWdts();
panicPutStr("Entering gdb stub now.\r\n");
- gdbstubPanicHandler(frame);
+ esp_gdbstub_panic_handler(frame);
#elif CONFIG_FREERTOS_PANIC_PRINT_REBOOT || CONFIG_FREERTOS_PANIC_SILENT_REBOOT
panicPutStr("Rebooting...\r\n");
for (x=0; x<100; x++) ets_delay_us(1000);
}
-void setBreakpointIfJtag(void *fn) {
+void esp_set_breakpoint_if_jtag(void *fn) {
if (!inOCDMode()) return;
setFirstBreakpoint((uint32_t)fn);
}
// limitations under the License.
-/*
-This routine enables a more general-purpose task watchdog: tasks can individually
-feed the watchdog and the watchdog will bark if one or more tasks haven't fed the
-watchdog within the specified time. Optionally, the idle tasks can also configured
-to feed the watchdog in a similar fashion, to detect CPU starvation.
-
-This uses the TIMERG0 WDT.
-*/
#include <stdint.h>
#include <stdio.h>
#include "esp_intr.h"
#include "esp_attr.h"
#include "soc/timer_group_struct.h"
+#include "soc/timer_group_reg.h"
#include "esp_log.h"
#include "esp_task_wdt.h"
static wdt_task_t *wdt_task_list=NULL;
-//We use this interrupt number on whatever task calls task_wdt_init.
-#define WDT_INT_NUM 24
-
-#define WDT_WRITE_KEY 0x50D83AA1
-
static void IRAM_ATTR task_wdt_isr(void *arg) {
wdt_task_t *wdttask;
const char *cpu;
}
-void task_wdt_feed() {
+void esp_task_wdt_feed() {
wdt_task_t *wdttask=wdt_task_list;
bool found_task=false, do_feed_wdt=true;
TaskHandle_t handle=xTaskGetCurrentTaskHandle();
}
}
-void task_wdt_delete() {
+void esp_task_wdt_delete() {
TaskHandle_t handle=xTaskGetCurrentTaskHandle();
wdt_task_t *wdttask=wdt_task_list;
//Wdt task list can't be empty
}
}
-void task_wdt_init() {
+void esp_task_wdt_init() {
TIMERG0.wdt_wprotect=WDT_WRITE_KEY;
TIMERG0.wdt_config0.sys_reset_length=7; //3.2uS
TIMERG0.wdt_config0.cpu_reset_length=7; //3.2uS
#if !CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1
if (xPortGetCoreID()!=0) return;
#endif
- task_wdt_feed();
+ esp_task_wdt_feed();
}
#endif
If using the WiFi stack, this value must be at least 1.
-#This still needs to be implemented.
-choice FREERTOS_PANIC
- prompt "Panic handler behaviour"
- default FREERTOS_PANIC_PRINT_REBOOT
- help
- If FreeRTOS detects unexpected behaviour or an unhandled exception, the panic handler is
- invoked. Configure the panic handlers action here.
-
-config FREERTOS_PANIC_PRINT_HALT
- bool "Print registers and halt"
- help
- Outputs the relevant registers over the serial port and halt the
- processor. Needs a manual reset to restart.
-
-config FREERTOS_PANIC_PRINT_REBOOT
- bool "Print registers and reboot"
- help
- Outputs the relevant registers over the serial port and immediately
- reset the processor.
-
-config FREERTOS_PANIC_SILENT_REBOOT
- bool "Silent reboot"
- help
- Just resets the processor without outputting anything
-
-config FREERTOS_PANIC_GDBSTUB
- bool "Invoke GDBStub"
- help
- Invoke gdbstub on the serial port, allowing for gdb to attach to it to do a postmortem
- of the crash.
-endchoice
-
-config FREERTOS_DEBUG_OCDAWARE
- bool "Make exception and panic handlers JTAG/OCD aware"
- default y
- help
- The FreeRTOS panic and unhandled exception handers can detect a JTAG OCD debugger and
- instead of panicking, have the debugger stop on the offending instruction.
-
choice FREERTOS_ASSERT
prompt "FreeRTOS assertions"
default FREERTOS_ASSERT_FAIL_ABORT
#include "FreeRTOS.h"
#include "task.h"
-#include "panic.h"
+#include "esp_panic.h"
/* Defined in portasm.h */
extern void _frxt_tick_timer_init(void);
#if CONFIG_FREERTOS_BREAK_ON_SCHEDULER_START_JTAG
void vPortFirstTaskHook(TaskFunction_t function) {
- setBreakpointIfJtag(function);
+ esp_set_breakpoint_if_jtag(function);
}
#endif
*******************************************************************************/
#include "xtensa_rtos.h"
-#include "panic.h"
+#include "esp_panic.h"
#include "sdkconfig.h"
/*
Define for workaround: pin no-cpu-affinity tasks to a cpu when fpu is used.
*/
.section .iram1,"ax"
- .global panicHandler
+ .global panicHandler
.global _xt_panic
.type _xt_panic,@function
.align 4
- .literal_position
+ .literal_position
.align 4
_xt_panic:
movi a0, PS_INTLEVEL(7) | PS_UM | PS_WOE
wsr a0, PS
- //Call panic handler
- mov a6,sp
- call4 panicHandler
+ //Call panic handler
+ mov a6,sp
+ call4 panicHandler
1: j 1b /* loop infinitely */
- retw
+ retw
- .align 4
+ .align 4
//Call using call0. Prints the hex char in a2. Kills a3, a4, a5
panic_print_hex:
- movi a3,0x60000000
- movi a4,8
+ movi a3,0x60000000
+ movi a4,8
panic_print_hex_loop:
- l32i a5, a3, 0x1c
- extui a5, a5, 16, 8
- bgei a5,64,panic_print_hex_loop
-
- srli a5,a2,28
- bgei a5,10,panic_print_hex_a
- addi a5,a5,'0'
- j panic_print_hex_ok
+ l32i a5, a3, 0x1c
+ extui a5, a5, 16, 8
+ bgei a5,64,panic_print_hex_loop
+
+ srli a5,a2,28
+ bgei a5,10,panic_print_hex_a
+ addi a5,a5,'0'
+ j panic_print_hex_ok
panic_print_hex_a:
- addi a5,a5,'A'-10
+ addi a5,a5,'A'-10
panic_print_hex_ok:
- s32i a5,a3,0
- slli a2,a2,4
-
- addi a4,a4,-1
- bnei a4,0,panic_print_hex_loop
- movi a5,' '
- s32i a5,a3,0
+ s32i a5,a3,0
+ slli a2,a2,4
+
+ addi a4,a4,-1
+ bnei a4,0,panic_print_hex_loop
+ movi a5,' '
+ s32i a5,a3,0
- ret
+ ret
jx a3
#else
wsr a0, EXCSAVE+XCHAL_DEBUGLEVEL /* save original a0 somewhere */
- movi a0,PANIC_RSN_DEBUGEXCEPTION
- wsr a0,EXCCAUSE
+ movi a0,PANIC_RSN_DEBUGEXCEPTION
+ wsr a0,EXCCAUSE
call0 _xt_panic /* does not return */
rfi XCHAL_DEBUGLEVEL /* make a0 point here not later */
#endif
#if XCHAL_HAVE_DEBUG
break 1, 4 /* unhandled double exception */
#endif
- movi a0,PANIC_RSN_DOUBLEEXCEPTION
- wsr a0,EXCCAUSE
+ movi a0,PANIC_RSN_DOUBLEEXCEPTION
+ wsr a0,EXCCAUSE
call0 _xt_panic /* does not return */
rfde /* make a0 point here not later */
#if XCHAL_HAVE_DEBUG
break 1, 0 /* unhandled kernel exception */
#endif
- movi a0,PANIC_RSN_KERNELEXCEPTION
- wsr a0,EXCCAUSE
+ movi a0,PANIC_RSN_KERNELEXCEPTION
+ wsr a0,EXCCAUSE
call0 _xt_panic /* does not return */
rfe /* make a0 point here not there */
addi a2, a2, TASKTCB_XCOREID_OFFSET /* offset to xCoreID in tcb struct */
s32i a3, a2, 0 /* store current cpuid */
- /* Grab correct xt_coproc_owner_sa for this core */
- movi a2, XCHAL_CP_MAX << 2
- mull a2, a2, a3
+ /* Grab correct xt_coproc_owner_sa for this core */
+ movi a2, XCHAL_CP_MAX << 2
+ mull a2, a2, a3
movi a3, _xt_coproc_owner_sa /* a3 = base of owner array */
- add a3, a3, a2
+ add a3, a3, a2
extui a2, a0, 0, 16 /* coprocessor bitmask portion */
or a4, a4, a2 /* a4 = CPENABLE | (1 << n) */
#if XCHAL_HAVE_DEBUG
break 1, 1 /* unhandled user exception */
#endif
- movi a0,PANIC_RSN_COPROCEXCEPTION
- wsr a0,EXCCAUSE
+ movi a0,PANIC_RSN_COPROCEXCEPTION
+ wsr a0,EXCCAUSE
call0 _xt_panic /* not in a thread (invalid) */
/* never returns */
/* On the ESP32, this level is used for the INT_WDT handler. If that triggers, the program is stuck with interrupts
off and the CPU should panic. */
- rsr a0, EXCSAVE_4
- wsr a0, EXCSAVE_1 /* panic handler reads this register */
- /* Set EXCCAUSE to reflect cause of the wdt int trigger */
- movi a0,PANIC_RSN_INTWDT_CPU0
- wsr a0,EXCCAUSE
+ rsr a0, EXCSAVE_4
+ wsr a0, EXCSAVE_1 /* panic handler reads this register */
+ /* Set EXCCAUSE to reflect cause of the wdt int trigger */
+ movi a0,PANIC_RSN_INTWDT_CPU0
+ wsr a0,EXCCAUSE
#if CONFIG_INT_WDT_CHECK_CPU1
- /* Check if the cause is the app cpu failing to tick.*/
- movi a0, int_wdt_app_cpu_ticked
- l32i a0, a0, 0
- bnez a0, 1f
- /* It is. Modify cause. */
- movi a0,PANIC_RSN_INTWDT_CPU1
- wsr a0,EXCCAUSE
+ /* Check if the cause is the app cpu failing to tick.*/
+ movi a0, int_wdt_app_cpu_ticked
+ l32i a0, a0, 0
+ bnez a0, 1f
+ /* It is. Modify cause. */
+ movi a0,PANIC_RSN_INTWDT_CPU1
+ wsr a0,EXCCAUSE
1:
#endif
call0 _xt_panic