Skip to content

Commit bff3a6d

Browse files
earlephilhowerdevyte
authored andcommitted
GDB support w/new toolchain and UART driver (#5559)
* Add full gdb support with uart/Serial integration * Fix GDB merge errors * Update to unpatched GDB protocol specification It appears that Espressif patched the open source xtensa GDB port in order to build their old GDB executable and their old gdbstub (basically removing any register in a generic xtensa and only leaving those present in the chip they synthesized). Their GDBStub also assumed this behavior. Unpatched upstream GNU GDB now expects all the registers in xtensa-config.c to be sent/read on a 'g' command. Change the GDB stub to send "xxxxxxxx"s (legal per the spec) for unimplemented registers. This makes the 'g' response much longer, but it's results are cached and in an interactive debugger it isn't noticeable. * Fix .iram.literal to come before .iram.text for GDB * Move functions to flash, call using wrappers All functions which are not interrupt or exception called are now in flash. A small IRAM wrapper enables flash when processing main GDB ops by calling Cache_Read_Enable_New() and then jumping to the main flash code. This seems to work for catching exceptions, data and code breaks, and Ctrl-C. The UART ISR handler and exception handler register-saving bits of code in ASM are still in IRAM. GDB IRAM usage is now about 670 bytes. * Remove LWIP2 builder commit * Add documentation and gdbstub_init header Add some simple GDB documentation to the main tree showing a worked example. Adds the definition of `void gdbstub_init()` to <GDBStub.h> * Clean up GDB include and library dir Replace GDBstub.h with the version in the internal/ directory, and adjust stub code accordingly. This way, only one copy of a file called "GDBstub.h" will exist. Update the gdbcommands and replace the obsolete ESPRESSIF readme with @kylefleming's version since we're mainly doing serial, not TCP, connected debugging. Bump the library rev. number since this is a pretty big functionality change. Minor documentation tweak. * Undo much of UART refactoring, set fifo IRQ to 16 Remove the refactoring of pin control and other little things not directly related to GDB processing. Should greatly reduce the diff size in uart.c. Should also remove any register value changes (intended or otherwise) introduced in the original PR from @kylefleming. Set the FIFO interrupt to 16 chars when in GDB mode, matching the latest UART configuration for highest speed. * Add architecture comments, cleanup uart.c code Comments added to UART.c trying to explain (as best as I understand it) the changes done to support GDB and how they interact with standard operation. Fix the uart_uninit to stop the ISR and then free appropriately. Fix uart_isr_handle_data (GDB's shim for sending chars to the 8266 app) to do the exact same thing as the standard UART handler including set the overflow properly and either discard or overwrite in that case. Fix serial reception when GDB enabled by enabling the user recv ISR. Remove commented attributes from gdbstub, leftover from the move to flash. General logic cleanup per comments in the PR. * Also set the UART flags for HW error in GDB Ensure we also check the UART flags and set the uart status appropriately when in GDB mode.
1 parent 4657666 commit bff3a6d

16 files changed

+1399
-679
lines changed

cores/esp8266/gdb_hooks.c

+10-4
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,18 @@
2525
value is in register, it doesn't hurt to return a bool, so that the
2626
same stub can be used for gdb_present. */
2727

28-
bool ICACHE_RAM_ATTR __gdb_no_op()
28+
static bool ICACHE_RAM_ATTR __gdb_no_op()
2929
{
3030
return false;
3131
}
3232

33-
extern void gdb_init(void) __attribute__ ((weak, alias("__gdb_no_op")));
34-
extern void gdb_do_break(void) __attribute__ ((weak, alias("__gdb_no_op")));
35-
extern bool gdb_present(void) __attribute__ ((weak, alias("__gdb_no_op")));
33+
void gdb_init(void) __attribute__ ((weak, alias("__gdb_no_op")));
34+
void gdb_do_break(void) __attribute__ ((weak, alias("__gdb_no_op")));
35+
bool gdb_present(void) __attribute__ ((weak, alias("__gdb_no_op")));
36+
bool gdbstub_has_putc1_control(void) __attribute__ ((weak, alias("__gdb_no_op")));
37+
void gdbstub_set_putc1_callback(void (*func)(char)) __attribute__ ((weak, alias("__gdb_no_op")));
38+
bool gdbstub_has_uart_isr_control(void) __attribute__ ((weak, alias("__gdb_no_op")));
39+
void gdbstub_set_uart_isr_callback(void (*func)(void*, uint8_t), void* arg) __attribute__ ((weak, alias("__gdb_no_op")));
40+
void gdbstub_write_char(char c) __attribute__ ((weak, alias("__gdb_no_op")));
41+
void gdbstub_write(const char* buf, size_t size) __attribute__ ((weak, alias("__gdb_no_op")));
3642

cores/esp8266/gdb_hooks.h

+65
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,71 @@ void gdb_do_break(void);
5252
*/
5353
bool gdb_present(void);
5454

55+
// If gdbstub has these set true, then we will disable our own
56+
// usage of them, but use gdbstub's callbacks for them instead
57+
/**
58+
* @brief Check if GDB is installing a putc1 callback.
59+
*
60+
* By default, this function returns false. When GDBStub library is linked,
61+
* this function is overriden and returns true.
62+
*
63+
* @return true if GDB is installing a putc1 callback
64+
*/
65+
bool gdbstub_has_putc1_control(void);
66+
67+
/**
68+
* @brief Register a putc1 callback with GDB.
69+
* @param func function GDB will proxy putc1 data to
70+
*
71+
* By default, this function is a no-op. When GDBStub library is linked,
72+
* this function is overriden and sets GDB stub's secondary putc1 callback to
73+
* func. When GDB stub is linked, but a GDB session is not current attached,
74+
* then GDB stub will pass putc1 chars directly to this function.
75+
*/
76+
void gdbstub_set_putc1_callback(void (*func)(char));
77+
78+
/**
79+
* @brief Check if GDB is installing a uart0 isr callback.
80+
*
81+
* By default, this function returns false. When GDBStub library is linked,
82+
* this function is overriden and returns true.
83+
*
84+
* @return true if GDB is installing a uart0 isr callback
85+
*/
86+
bool gdbstub_has_uart_isr_control(void);
87+
88+
/**
89+
* @brief Register a uart0 isr callback with GDB.
90+
* @param func function GDB will proxy uart0 isr data to
91+
*
92+
* By default, this function is a no-op. When GDBStub library is linked,
93+
* this function is overriden and sets GDB stub's secondary uart0 isr callback
94+
* to func. When GDB stub is linked, but a GDB session is not current attached,
95+
* then GDB stub will pass uart0 isr data back to this function.
96+
*/
97+
void gdbstub_set_uart_isr_callback(void (*func)(void*, uint8_t), void* arg);
98+
99+
/**
100+
* @brief Write a character for output to a GDB session on uart0.
101+
* @param c character to write
102+
*
103+
* By default, this function is a no-op. When GDBStub library is linked,
104+
* this function is overriden and writes a char to either the GDB session on
105+
* uart0 or directly to uart0 if not GDB session is attached.
106+
*/
107+
void gdbstub_write_char(char c);
108+
109+
/**
110+
* @brief Write a char buffer for output to a GDB session on uart0.
111+
* @param buf buffer of data to write
112+
* @param size length of buffer
113+
*
114+
* By default, this function is a no-op. When GDBStub library is linked,
115+
* this function is overriden and writes a buffer to either the GDB session on
116+
* uart0 or directly to uart0 if not GDB session is attached.
117+
*/
118+
void gdbstub_write(const char* buf, size_t size);
119+
55120
#ifdef __cplusplus
56121
}
57122
#endif

0 commit comments

Comments
 (0)