forked from espressif/esp-idf
Merge branch 'feature/openocd-freertos-support_try2' into 'master'
Add symbol needed for OpenOCD to detect FreeRTOS, add feature to break execution, try 2 Add symbol needed for OpenOCD to detect FreeRTOS, add optional feature to break execution when the scheduler is initially started. The workflow is now so that if you start an esp-idf program, you can reset the CPU and end up in a gdb prompt just before all threads start up. In gdb you can then inspect all threads and watch breakpoints. Has the nice side effect that OpenOCD will restore any break/watchpoints that were there before you reset the chip. This is try 2 because seemingly, someone or something replaced the bit of my brain that is responsible for handling Git with a squeaky toy. See merge request !24
This commit is contained in:
23
components/freertos/FreeRTOS-openocd.c
Normal file
23
components/freertos/FreeRTOS-openocd.c
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Since at least FreeRTOS V7.5.3 uxTopUsedPriority is no longer
|
||||
* present in the kernel, so it has to be supplied by other means for
|
||||
* OpenOCD's threads awareness.
|
||||
*
|
||||
* Add this file to your project, and, if you're using --gc-sections,
|
||||
* ``--undefined=uxTopUsedPriority'' (or
|
||||
* ``-Wl,--undefined=uxTopUsedPriority'' when using gcc for final
|
||||
* linking) to your LDFLAGS; same with all the other symbols you need.
|
||||
*/
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define USED __attribute__((used))
|
||||
#else
|
||||
#define USED
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FREERTOS_DEBUG_OCDAWARE
|
||||
const int USED uxTopUsedPriority = configMAX_PRIORITIES - 1;
|
||||
#endif
|
@@ -121,5 +121,12 @@ config FREERTOS_DEBUG_OCDAWARE
|
||||
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 FREERTOS_BREAK_ON_SCHEDULER_START_JTAG
|
||||
bool "Stop program on scheduler start when JTAG/OCD is detected"
|
||||
depends on FREERTOS_DEBUG_OCDAWARE
|
||||
default y
|
||||
help
|
||||
If JTAG/OCD is connected, stop execution when the scheduler is started and the first
|
||||
task is executed.
|
||||
|
||||
endmenu
|
||||
|
@@ -2,6 +2,7 @@
|
||||
# Component Makefile
|
||||
#
|
||||
|
||||
COMPONENT_ADD_LDFLAGS = -l$(COMPONENT_NAME) -Wl,--undefined=uxTopUsedPriority
|
||||
COMPONENT_ADD_INCLUDEDIRS := include
|
||||
COMPONENT_PRIV_INCLUDEDIRS := include/freertos
|
||||
|
||||
|
7
components/freertos/include/freertos/panic.h
Normal file
7
components/freertos/include/freertos/panic.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef PANIC_H
|
||||
#define PANIC_H
|
||||
|
||||
void setBreakpointIfJtag(void *fn);
|
||||
|
||||
|
||||
#endif
|
@@ -118,8 +118,11 @@ typedef unsigned portBASE_TYPE UBaseType_t;
|
||||
// portbenchmark
|
||||
#include "portbenchmark.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#define portMUX_DEBUG
|
||||
#define portFIRST_TASK_HOOK CONFIG_FREERTOS_BREAK_ON_SCHEDULER_START_JTAG
|
||||
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t mux;
|
||||
|
@@ -142,6 +142,17 @@ void panicHandler(XtExcFrame *frame) {
|
||||
commonErrorHandler(frame);
|
||||
}
|
||||
|
||||
static void setFirstBreakpoint(uint32_t pc) {
|
||||
asm(
|
||||
"wsr.ibreaka0 %0\n" \
|
||||
"rsr.ibreakenable a3\n" \
|
||||
"movi a4,1\n" \
|
||||
"or a4, a4, a3\n" \
|
||||
"wsr.ibreakenable a4\n" \
|
||||
::"r"(pc):"a3","a4");
|
||||
return;
|
||||
}
|
||||
|
||||
void xt_unhandled_exception(XtExcFrame *frame) {
|
||||
int *regs=(int*)frame;
|
||||
int x;
|
||||
@@ -158,14 +169,7 @@ void xt_unhandled_exception(XtExcFrame *frame) {
|
||||
panicPutStr(". Setting bp and returning..\r\n");
|
||||
//Stick a hardware breakpoint on the address the handler returns to. This way, the OCD debugger
|
||||
//will kick in exactly at the context the error happened.
|
||||
asm(
|
||||
"wsr.ibreaka0 %0\n" \
|
||||
"rsr.ibreakenable a3\n" \
|
||||
"movi a4,1\n" \
|
||||
"or a4, a4, a3\n" \
|
||||
"wsr.ibreakenable a4\n" \
|
||||
::"r"(regs[1]):"a3","a4");
|
||||
return;
|
||||
setFirstBreakpoint(regs[1]);
|
||||
}
|
||||
panicPutStr(". Exception was unhandled.\r\n");
|
||||
commonErrorHandler(frame);
|
||||
@@ -209,3 +213,9 @@ void commonErrorHandler(XtExcFrame *frame) {
|
||||
while(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void setBreakpointIfJtag(void *fn) {
|
||||
if (!inOCDMode()) return;
|
||||
setFirstBreakpoint((uint32_t)fn);
|
||||
}
|
||||
|
@@ -101,6 +101,8 @@
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#include "panic.h"
|
||||
|
||||
/* Defined in portasm.h */
|
||||
extern void _frxt_tick_timer_init(void);
|
||||
|
||||
@@ -385,6 +387,10 @@ portBASE_TYPE vPortCPUReleaseMutex(portMUX_TYPE *mux) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#if CONFIG_FREERTOS_BREAK_ON_SCHEDULER_START_JTAG
|
||||
void vPortFirstTaskHook(TaskFunction_t function) {
|
||||
setBreakpointIfJtag(function);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
@@ -445,6 +445,11 @@ to its original value when it is released. */
|
||||
extern void vApplicationTickHook( void );
|
||||
#endif
|
||||
|
||||
#if portFIRST_TASK_HOOK
|
||||
extern void vPortFirstTaskHook(TaskFunction_t taskfn);
|
||||
#endif
|
||||
|
||||
|
||||
/* File private functions. --------------------------------*/
|
||||
|
||||
/*
|
||||
@@ -707,6 +712,12 @@ BaseType_t i;
|
||||
/* Schedule if nothing is scheduled yet, or overwrite a task of lower prio. */
|
||||
if ( pxCurrentTCB[i] == NULL || pxCurrentTCB[i]->uxPriority <= uxPriority )
|
||||
{
|
||||
#if portFIRST_TASK_HOOK
|
||||
if ( i == 0) {
|
||||
vPortFirstTaskHook(pxTaskCode);
|
||||
}
|
||||
#endif /* configFIRST_TASK_HOOK */
|
||||
|
||||
pxCurrentTCB[i] = pxNewTCB;
|
||||
break;
|
||||
}
|
||||
|
Reference in New Issue
Block a user