The esp8266 portion of the project
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

926 lines
27 KiB

  1. /******************************************************************************
  2. * Copyright 2015 Espressif Systems
  3. *
  4. * Description: A stub to make the ESP8266 debuggable by GDB over the serial
  5. * port.
  6. *
  7. * License: ESPRESSIF MIT License
  8. *******************************************************************************/
  9. #include <GDBStub.h>
  10. #include <stddef.h>
  11. #include <Arduino.h>
  12. #include "ets_sys.h"
  13. #include "eagle_soc.h"
  14. #include "c_types.h"
  15. #include "gpio.h"
  16. #include "xtensa/corebits.h"
  17. #include "uart_register.h"
  18. #include "gdbstub-entry.h"
  19. #include "gdbstub-cfg.h"
  20. //From xtruntime-frames.h
  21. struct XTensa_exception_frame_s {
  22. uint32_t pc;
  23. uint32_t ps;
  24. uint32_t sar;
  25. uint32_t vpri;
  26. uint32_t a[16]; //a0..a15
  27. //These are added manually by the exception code; the HAL doesn't set these on an exception.
  28. uint32_t litbase;
  29. uint32_t sr176;
  30. uint32_t sr208;
  31. //'reason' is abused for both the debug and the exception vector: if bit 7 is set,
  32. //this contains an exception reason, otherwise it contains a debug vector bitmap.
  33. uint32_t reason;
  34. };
  35. #if GDBSTUB_FREERTOS
  36. struct XTensa_rtos_int_frame_s {
  37. uint32_t exitPtr;
  38. uint32_t pc;
  39. uint32_t ps;
  40. uint32_t a[16];
  41. uint32_t sar;
  42. };
  43. /*
  44. Definitions for FreeRTOS. This redefines some os_* functions to use their non-os* counterparts. It
  45. also sets up some function pointers for ROM functions that aren't in the FreeRTOS ld files.
  46. */
  47. #include <string.h>
  48. #include <stdio.h>
  49. void os_isr_attach(int inum, void *fn);
  50. void os_install_putc1(void (*p)(char c));
  51. #define os_printf(...) printf(__VA_ARGS__)
  52. #define os_strncmp(...) strncmp(__VA_ARGS__)
  53. typedef void wdtfntype();
  54. static wdtfntype *ets_wdt_disable = (wdtfntype *)0x400030f0;
  55. static wdtfntype *ets_wdt_enable = (wdtfntype *)0x40002fa0;
  56. #else
  57. /*
  58. OS-less SDK defines. Defines some headers for things that aren't in the include files, plus
  59. the xthal stack frame struct.
  60. */
  61. #include "osapi.h"
  62. #include "user_interface.h"
  63. void _xtos_set_exception_handler(int cause, void (exhandler)(struct XTensa_exception_frame_s *frame));
  64. #endif
  65. #define EXCEPTION_GDB_SP_OFFSET 0x100
  66. //Length of buffer used to reserve GDB commands. Has to be at least able to fit the G command, which
  67. //implies a minimum size of about 190 bytes.
  68. #define PBUFLEN 256
  69. //The asm stub saves the Xtensa registers here when a debugging exception happens.
  70. struct XTensa_exception_frame_s gdbstub_savedRegs;
  71. #if GDBSTUB_USE_OWN_STACK
  72. //This is the debugging exception stack.
  73. int exceptionStack[256];
  74. #endif
  75. static bool gdb_attached = false;
  76. static unsigned char cmd[PBUFLEN]; //GDB command input buffer
  77. static char chsum; //Running checksum of the output packet
  78. #if GDBSTUB_CTRLC_BREAK
  79. static void (*uart_isr_callback)(void*, uint8_t) = NULL;
  80. static void* uart_isr_arg = NULL;
  81. #endif
  82. #if GDBSTUB_REDIRECT_CONSOLE_OUTPUT
  83. static void (*uart_putc1_callback)(char) = NULL;
  84. #endif
  85. //Stores ps when single-stepping instruction. -1 when not in use.
  86. static int32_t singleStepPs = -1;
  87. //Uart libs can reference these to see if gdb is attaching to them
  88. bool gdbstub_has_putc1_control() {
  89. #if GDBSTUB_REDIRECT_CONSOLE_OUTPUT
  90. return true;
  91. #else
  92. return false;
  93. #endif
  94. }
  95. bool gdbstub_has_uart_isr_control() {
  96. #if GDBSTUB_CTRLC_BREAK
  97. return true;
  98. #else
  99. return false;
  100. #endif
  101. }
  102. //Small function to feed the hardware watchdog. Needed to stop the ESP from resetting
  103. //due to a watchdog timeout while reading a command.
  104. static void ATTR_GDBFN keepWDTalive() {
  105. uint64_t *wdtval = (uint64_t*)0x3ff21048;
  106. uint64_t *wdtovf = (uint64_t*)0x3ff210cc;
  107. int *wdtctl = (int*)0x3ff210c8;
  108. *wdtovf = *wdtval + 1600000;
  109. *wdtctl |= 1 << 31;
  110. }
  111. //Error states used by the routines that grab stuff from the incoming gdb packet
  112. #define ST_ENDPACKET -1
  113. #define ST_ERR -2
  114. #define ST_OK -3
  115. #define ST_CONT -4
  116. #define ST_DETACH -5
  117. //Grab a hex value from the gdb packet. Ptr will get positioned on the end
  118. //of the hex string, as far as the routine has read into it. Bits/4 indicates
  119. //the max amount of hex chars it gobbles up. Bits can be -1 to eat up as much
  120. //hex chars as possible.
  121. static long gdbGetHexVal(unsigned char **ptr, int bits) {
  122. int i;
  123. int no;
  124. unsigned int v = 0;
  125. char c;
  126. no = bits / 4;
  127. if (bits == -1)
  128. no = 64;
  129. for (i = 0; i < no; i++) {
  130. c = **ptr;
  131. (*ptr)++;
  132. if (c >= '0' && c <= '9') {
  133. v <<= 4;
  134. v |= (c-'0');
  135. } else if (c >= 'A' && c <= 'F') {
  136. v <<= 4;
  137. v |= (c-'A') + 10;
  138. } else if (c >= 'a' && c <= 'f') {
  139. v <<= 4;
  140. v |= (c-'a') + 10;
  141. } else if (c == '#') {
  142. if (bits == -1) {
  143. (*ptr)--;
  144. return v;
  145. }
  146. return ST_ENDPACKET;
  147. } else {
  148. if (bits == -1) {
  149. (*ptr)--;
  150. return v;
  151. }
  152. return ST_ERR;
  153. }
  154. }
  155. return v;
  156. }
  157. //Swap an int into the form gdb wants it
  158. static int iswap(int i) {
  159. return ((i >> 24) & 0xff)
  160. | (((i >> 16) & 0xff) << 8)
  161. | (((i >> 8) & 0xff) << 16)
  162. | (((i >> 0) & 0xff) << 24);
  163. }
  164. //Read a byte from the ESP8266 memory.
  165. static unsigned char readbyte(unsigned int p) {
  166. if (p < 0x20000000 || p >= 0x60000000) return -1;
  167. int *i = (int*)(p & ~3);
  168. return *i >> ((p & 3) * 8);
  169. }
  170. //Write a byte to the ESP8266 memory.
  171. static void writeByte(unsigned int p, unsigned char d) {
  172. if (p < 0x20000000 || p >= 0x60000000) return;
  173. int *i = (int*)(p & ~3);
  174. if ((p & 3) == 0) *i = (*i & 0xffffff00) | (d << 0);
  175. else if ((p & 3) == 1) *i = (*i & 0xffff00ff) | (d << 8);
  176. else if ((p & 3) == 2) *i = (*i & 0xff00ffff) | (d << 16);
  177. else if ((p & 3) == 3) *i = (*i & 0x00ffffff) | (d << 24);
  178. }
  179. //Returns 1 if it makes sense to write to addr p
  180. static int validWrAddr(int p) {
  181. return (p >= 0x3ff00000 && p < 0x40000000)
  182. || (p >= 0x40100000 && p < 0x40140000)
  183. || (p >= 0x60000000 && p < 0x60002000);
  184. }
  185. static inline bool ATTR_GDBFN gdbRxFifoIsEmpty() {
  186. return ((READ_PERI_REG(UART_STATUS(0)) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT) == 0;
  187. }
  188. static inline bool ATTR_GDBFN gdbTxFifoIsFull() {
  189. return ((READ_PERI_REG(UART_STATUS(0)) >> UART_TXFIFO_CNT_S) & UART_TXFIFO_CNT) >= 126;
  190. }
  191. //Receive a char from the uart. Uses polling and feeds the watchdog.
  192. static inline int gdbRecvChar() {
  193. while (gdbRxFifoIsEmpty()) {
  194. keepWDTalive();
  195. }
  196. return READ_PERI_REG(UART_FIFO(0));
  197. }
  198. //Send a char to the uart.
  199. static void gdbSendChar(char c) {
  200. while (gdbTxFifoIsFull())
  201. ;
  202. WRITE_PERI_REG(UART_FIFO(0), c);
  203. }
  204. //Send the start of a packet; reset checksum calculation.
  205. static void gdbPacketStart() {
  206. chsum = 0;
  207. gdbSendChar('$');
  208. }
  209. //Send a char as part of a packet
  210. static void gdbPacketChar(char c) {
  211. if (c == '#' || c == '$' || c == '}' || c == '*') {
  212. gdbSendChar('}');
  213. chsum += '}';
  214. c ^= 0x20;
  215. }
  216. gdbSendChar(c);
  217. chsum += c;
  218. }
  219. //Send a hex val as part of a packet. 'bits'/4 dictates the number of hex chars sent.
  220. static void gdbPacketHex(int val, int bits) {
  221. static const char hexChars[] = "0123456789abcdef";
  222. int i;
  223. for (i = bits; i > 0; i -= 4) {
  224. gdbPacketChar(hexChars[(val >> (i - 4)) & 0xf]);
  225. }
  226. }
  227. //Send a hex val as part of a packet. 'bits'/4 dictates the number of hex chars sent.
  228. static void gdbPacketSwappedHexInt(int val) {
  229. gdbPacketHex(iswap(val), 32);
  230. }
  231. static void gdbPacketXXXXInt() {
  232. for (int i=0; i<8; i++) gdbPacketChar('x');
  233. }
  234. //Finish sending a packet.
  235. static void gdbPacketEnd() {
  236. gdbSendChar('#');
  237. //Ok to use packet version here since hex char can never be an
  238. //excape-requiring character
  239. gdbPacketHex(chsum, 8);
  240. }
  241. // Send a complete packet containing str
  242. static void gdbSendPacketStr(const char *c) {
  243. gdbPacketStart();
  244. while (*c != 0) {
  245. gdbPacketChar(*c);
  246. c++;
  247. }
  248. gdbPacketEnd();
  249. }
  250. // Send a complete packet containing str as an output message
  251. static inline void ATTR_GDBEXTERNFN gdbSendOutputPacketStr(const unsigned char* buf, size_t size) {
  252. size_t i;
  253. gdbPacketStart();
  254. gdbPacketChar('O');
  255. for (i = 0; i < size; i++)
  256. gdbPacketHex(buf[i], 8);
  257. gdbPacketEnd();
  258. }
  259. // Send a complete packet containing c as an output message
  260. static inline void ATTR_GDBEXTERNFN gdbSendOutputPacketChar(unsigned char c) {
  261. gdbPacketStart();
  262. gdbPacketChar('O');
  263. gdbPacketHex(c, 8);
  264. gdbPacketEnd();
  265. }
  266. static long gdbGetSwappedHexInt(unsigned char **ptr) {
  267. return iswap(gdbGetHexVal(ptr, 32));
  268. }
  269. //Send the reason execution is stopped to GDB.
  270. static void sendReason() {
  271. static const char exceptionSignal[] = {4,31,11,11,2,6,8,0,6,7,0,0,7,7,7,7};
  272. #if 0
  273. char *reason=""; //default
  274. #endif
  275. //exception-to-signal mapping
  276. size_t i;
  277. gdbPacketStart();
  278. gdbPacketChar('T');
  279. if (gdbstub_savedRegs.reason == 0xff) {
  280. gdbPacketHex(2, 8); //sigint
  281. } else if (gdbstub_savedRegs.reason & 0x80) {
  282. //We stopped because of an exception. Convert exception code to a signal number and send it.
  283. i = gdbstub_savedRegs.reason & 0x7f;
  284. if (i < sizeof(exceptionSignal))
  285. gdbPacketHex(exceptionSignal[i], 8);
  286. else
  287. gdbPacketHex(11, 8);
  288. } else {
  289. //We stopped because of a debugging exception.
  290. gdbPacketHex(5, 8); //sigtrap
  291. //Current Xtensa GDB versions don't seem to request this, so let's leave it off.
  292. #if 0
  293. if (gdbstub_savedRegs.reason&(1<<0)) reason="break";
  294. if (gdbstub_savedRegs.reason&(1<<1)) reason="hwbreak";
  295. if (gdbstub_savedRegs.reason&(1<<2)) reason="watch";
  296. if (gdbstub_savedRegs.reason&(1<<3)) reason="swbreak";
  297. if (gdbstub_savedRegs.reason&(1<<4)) reason="swbreak";
  298. gdbPacketStr(reason);
  299. gdbPacketChar(':');
  300. //ToDo: watch: send address
  301. #endif
  302. }
  303. gdbPacketEnd();
  304. }
  305. static inline void ATTR_GDBFN gdbSendPacketOK() {
  306. gdbSendPacketStr("OK");
  307. }
  308. static inline void ATTR_GDBFN gdbSendPacketE01() {
  309. gdbSendPacketStr("E01");
  310. }
  311. static inline void ATTR_GDBFN gdbSendEmptyPacket() {
  312. gdbPacketStart();
  313. gdbPacketEnd();
  314. }
  315. void ATTR_GDBEXTERNFN gdbstub_write_char(char c) {
  316. if (gdb_attached) {
  317. ETS_UART_INTR_DISABLE();
  318. gdbSendOutputPacketChar(c);
  319. ETS_UART_INTR_ENABLE();
  320. } else {
  321. gdbSendChar(c);
  322. }
  323. }
  324. void ATTR_GDBEXTERNFN gdbstub_write(const char* buf, size_t size) {
  325. size_t i;
  326. if (gdb_attached) {
  327. ETS_UART_INTR_DISABLE();
  328. gdbSendOutputPacketStr((const unsigned char *)buf, size);
  329. ETS_UART_INTR_ENABLE();
  330. } else {
  331. for (i = 0; i < size; i++) {
  332. gdbSendChar(buf[i]);
  333. }
  334. }
  335. }
  336. /*
  337. Register file in the format lx106 gdb port expects it.
  338. Inspired by gdb/regformats/reg-xtensa.dat from
  339. https://github.com/jcmvbkbc/crosstool-NG/blob/lx106-g%2B%2B/overlays/xtensa_lx106.tar
  340. As decoded by Cesanta.
  341. struct regfile {
  342. uint32_t a[16];
  343. uint32_t pc;
  344. uint32_t sar;
  345. uint32_t litbase;
  346. uint32_t sr176;
  347. uint32_t sr208;
  348. uint32_t ps;
  349. };
  350. */
  351. //Handle a command as received from GDB.
  352. static inline int gdbHandleCommand() {
  353. //Handle a command
  354. int i, j, k;
  355. unsigned char *data = cmd + 1;
  356. if (cmd[0]=='g') { //send all registers to gdb
  357. gdbPacketStart();
  358. gdbPacketSwappedHexInt(gdbstub_savedRegs.pc);
  359. for (int i=1; i<=35; i++) gdbPacketXXXXInt();
  360. gdbPacketSwappedHexInt(gdbstub_savedRegs.sar);
  361. gdbPacketSwappedHexInt(gdbstub_savedRegs.litbase);
  362. for (int i=38; i<=39; i++) gdbPacketXXXXInt();
  363. gdbPacketSwappedHexInt(gdbstub_savedRegs.sr176);
  364. for (int i=41; i<=41; i++) gdbPacketXXXXInt();
  365. gdbPacketSwappedHexInt(gdbstub_savedRegs.ps);
  366. for (int i=43; i<=96; i++) gdbPacketXXXXInt();
  367. for (i=0; i<16; i++) gdbPacketSwappedHexInt(gdbstub_savedRegs.a[i]);
  368. gdbPacketEnd();
  369. } else if (cmd[0]=='G') { //receive content for all registers from gdb
  370. gdbstub_savedRegs.pc=gdbGetSwappedHexInt(&data);
  371. for (int i=1; i<=35; i++) gdbGetHexVal(&data, 32);
  372. gdbstub_savedRegs.sar=gdbGetSwappedHexInt(&data);
  373. gdbstub_savedRegs.litbase=gdbGetSwappedHexInt(&data);
  374. for (int i=38; i<=39; i++) gdbGetHexVal(&data, 32);
  375. gdbstub_savedRegs.sr176=gdbGetSwappedHexInt(&data);
  376. for (int i=41; i<=41; i++) gdbGetHexVal(&data, 32);
  377. gdbstub_savedRegs.ps=gdbGetSwappedHexInt(&data);
  378. for (int i=43; i<=96; i++) gdbGetHexVal(&data, 32);
  379. for (i=0; i<16; i++) gdbstub_savedRegs.a[i]=gdbGetSwappedHexInt(&data);
  380. gdbSendPacketOK();
  381. } else if ((cmd[0] | 0x20) == 'm') { //read/write memory to gdb
  382. i = gdbGetHexVal(&data, -1); //addr
  383. data++;
  384. j = gdbGetHexVal(&data, -1); //length
  385. if (cmd[0] == 'm') { //read memory to gdb
  386. gdbPacketStart();
  387. for (k = 0; k < j; k++) {
  388. gdbPacketHex(readbyte(i++), 8);
  389. }
  390. gdbPacketEnd();
  391. } else { //write memory from gdb
  392. if (validWrAddr(i) && validWrAddr(i + j)) {
  393. data++; //skip :
  394. for (k = 0; k < j; k++, i++) {
  395. writeByte(i, gdbGetHexVal(&data, 8));
  396. }
  397. //Make sure caches are up-to-date. Procedure according to Xtensa ISA document, ISYNC inst desc.
  398. asm volatile("ISYNC\nISYNC\n");
  399. gdbSendPacketOK();
  400. } else {
  401. //Trying to do a software breakpoint on a flash proc, perhaps?
  402. gdbSendPacketE01();
  403. }
  404. }
  405. } else if (cmd[0] == '?') { //Reply with stop reason
  406. sendReason();
  407. } else if (cmd[0] == 'c') { //continue execution
  408. return ST_CONT;
  409. } else if (cmd[0] == 's') { //single-step instruction
  410. //Single-stepping can go wrong if an interrupt is pending, especially when it is e.g. a task switch:
  411. //the ICOUNT register will overflow in the task switch code. That is why we disable interupts when
  412. //doing single-instruction stepping.
  413. singleStepPs=gdbstub_savedRegs.ps;
  414. gdbstub_savedRegs.ps=(gdbstub_savedRegs.ps & ~0xf) | (XCHAL_DEBUGLEVEL - 1);
  415. gdbstub_icount_ena_single_step();
  416. return ST_CONT;
  417. } else if (cmd[0] == 'D') { //detach
  418. gdbSendPacketOK();
  419. return ST_DETACH;
  420. } else if (cmd[0] == 'k') { //kill
  421. system_restart_core();
  422. } else if (cmd[0] == 'q') { //Extended query
  423. if (os_strncmp((char*)&cmd[1], "Supported", 9) == 0) { //Capabilities query
  424. gdbSendPacketStr("swbreak+;hwbreak+;PacketSize=FF"); //PacketSize is in hex
  425. } else if (os_strncmp((char*)&cmd[1], "Attached", 8) == 0) {
  426. //Let gdb know that it is attaching to a running program
  427. //In general that just means it detaches instead of killing when it exits
  428. gdbSendPacketStr("1");
  429. } else {
  430. //We don't support other queries.
  431. gdbSendEmptyPacket();
  432. }
  433. // case insensitive compare matches 'Z' or 'z'
  434. } else if ((cmd[0] | 0x20) == 'z' && cmd[1] >= '1' && cmd[2] <= '4') { //hardware break/watchpoint
  435. int result;
  436. data += 2; //skip 'x,'
  437. i = gdbGetHexVal(&data, -1);
  438. data++; //skip ','
  439. j = gdbGetHexVal(&data, -1);
  440. if (cmd[0] == 'Z') { //Set hardware break/watchpoint
  441. if (cmd[1] == '1') { //Set breakpoint
  442. result = gdbstub_set_hw_breakpoint(i, j);
  443. } else { //Set watchpoint
  444. int access;
  445. unsigned int mask = 0;
  446. if (cmd[1] == '2') access = 2; //write
  447. if (cmd[1] == '3') access = 1; //read
  448. if (cmd[1] == '4') access = 3; //access
  449. if (j == 1) mask = 0x3F;
  450. if (j == 2) mask = 0x3E;
  451. if (j == 4) mask = 0x3C;
  452. if (j == 8) mask = 0x38;
  453. if (j == 16) mask = 0x30;
  454. if (j == 32) mask = 0x20;
  455. result = mask != 0 && gdbstub_set_hw_watchpoint(i, mask, access);
  456. }
  457. } else { //Clear hardware break/watchpoint
  458. if (cmd[1] == '1') { //hardware breakpoint
  459. result = gdbstub_del_hw_breakpoint(i);
  460. } else { //hardware watchpoint
  461. result = gdbstub_del_hw_watchpoint(i);
  462. }
  463. }
  464. if (result) {
  465. gdbSendPacketOK();
  466. } else {
  467. gdbSendPacketE01();
  468. }
  469. } else {
  470. //We don't recognize or support whatever GDB just sent us.
  471. gdbSendEmptyPacket();
  472. }
  473. return ST_OK;
  474. }
  475. //Lower layer: grab a command packet and check the checksum
  476. //Calls gdbHandleCommand on the packet if the checksum is OK
  477. //Returns only if execution of the user program should continue
  478. //Otherwise keeps reading uart data and executing commands
  479. //Flags that gdb has been attached whenever a gdb formatted
  480. // packet is received
  481. //While gdb is attached, checks for ctl-c (\x03) if it's not
  482. // already paused
  483. //Keeps reading commands if it is paused, until either a
  484. // continue, detach, or kill command is received
  485. //It is not necessary for gdb to be attached for it to be paused
  486. //For example, during an exception break, the program is
  487. // paused but gdb might not be attached yet
  488. static int gdbReadCommand() {
  489. unsigned char chsum;
  490. unsigned char sentchs[2];
  491. size_t p;
  492. unsigned char c;
  493. unsigned char *ptr;
  494. int result;
  495. ETS_UART_INTR_DISABLE();
  496. ets_wdt_disable();
  497. sendReason();
  498. while (true) {
  499. gdbReadCommand_start:
  500. while (gdbRecvChar() != '$')
  501. ;
  502. gdbReadCommand_packetBegin:
  503. chsum = 0;
  504. p = 0;
  505. while ((c = gdbRecvChar()) != '#') { //end of packet, checksum follows
  506. if (c == '$') {
  507. //Wut, restart packet?
  508. goto gdbReadCommand_packetBegin;
  509. }
  510. if (c == '}') { //escape the next char
  511. c = gdbRecvChar() ^ 0x20;
  512. }
  513. chsum += c;
  514. cmd[p++] = c;
  515. if (p >= PBUFLEN) {
  516. //Received more than the size of the command buffer
  517. goto gdbReadCommand_start;
  518. }
  519. }
  520. cmd[p] = 0;
  521. sentchs[0] = gdbRecvChar();
  522. sentchs[1] = gdbRecvChar();
  523. ptr = &sentchs[0];
  524. if (gdbGetHexVal(&ptr, 8) == chsum) {
  525. gdb_attached = true;
  526. gdbSendChar('+');
  527. result = gdbHandleCommand();
  528. if (result != ST_OK) {
  529. break;
  530. }
  531. } else {
  532. gdbSendChar('-');
  533. }
  534. }
  535. if (result == ST_DETACH) {
  536. gdb_attached = false;
  537. }
  538. ets_wdt_enable();
  539. ETS_UART_INTR_ENABLE();
  540. return result;
  541. }
  542. //Get the value of one of the A registers
  543. static unsigned int ATTR_GDBFN getaregval(int reg) {
  544. return gdbstub_savedRegs.a[reg];
  545. }
  546. //Set the value of one of the A registers
  547. static inline void ATTR_GDBFN setaregval(int reg, unsigned int val) {
  548. // os_printf("%x -> %x\n", val, reg);
  549. gdbstub_savedRegs.a[reg] = val;
  550. }
  551. //Emulate the l32i/s32i instruction we're stopped at.
  552. static inline void emulLdSt() {
  553. unsigned char i0 = readbyte(gdbstub_savedRegs.pc);
  554. unsigned char i1 = readbyte(gdbstub_savedRegs.pc + 1);
  555. unsigned char i2;
  556. int *p;
  557. if ((i0 & 0xf) == 2 && (i1 & 0xb0) == 0x20) {
  558. //l32i or s32i
  559. i2 = readbyte(gdbstub_savedRegs.pc + 2);
  560. p = (int*)getaregval(i1 & 0xf) + (i2 * 4);
  561. i0 >>= 4;
  562. if ((i1 & 0xf0) == 0x20) { //l32i
  563. setaregval(i0, *p);
  564. } else { //s32i
  565. *p = getaregval(i0);
  566. }
  567. gdbstub_savedRegs.pc += 3;
  568. } else if ((i0 & 0xe) == 0x8) {
  569. //l32i.n or s32i.n
  570. p = (int*)getaregval(i1 & 0xf) + ((i1 >> 4) * 4);
  571. if ((i0 & 0xf) == 0x8) { //l32i.n
  572. setaregval(i0 >> 4, *p);
  573. } else {
  574. *p = getaregval(i0 >> 4);
  575. }
  576. gdbstub_savedRegs.pc += 2;
  577. // } else {
  578. // os_printf("GDBSTUB: No l32i/s32i instruction: %x %x. Huh?", i1, i0);
  579. }
  580. }
  581. //We just caught a debug exception and need to handle it. This is called from an assembly
  582. //routine in gdbstub-entry.S
  583. static void gdbstub_handle_debug_exception_flash();
  584. void ATTR_GDBFN gdbstub_handle_debug_exception() {
  585. Cache_Read_Enable_New();
  586. gdbstub_handle_debug_exception_flash();
  587. }
  588. static void __attribute__((noinline)) gdbstub_handle_debug_exception_flash() {
  589. if (singleStepPs != -1) {
  590. //We come here after single-stepping an instruction. Interrupts are disabled
  591. //for the single step. Re-enable them here.
  592. gdbstub_savedRegs.ps = (gdbstub_savedRegs.ps & ~0xf) | (singleStepPs & 0xf);
  593. singleStepPs =- 1;
  594. }
  595. gdbReadCommand();
  596. if ((gdbstub_savedRegs.reason & 0x80) == 0) { //Watchpoint/BREAK/BREAK.N
  597. if ((gdbstub_savedRegs.reason & 0x4) != 0) {
  598. //We stopped due to a watchpoint. We can't re-execute the current instruction
  599. //because it will happily re-trigger the same watchpoint, so we emulate it
  600. //while we're still in debugger space.
  601. emulLdSt();
  602. } else if ((((gdbstub_savedRegs.reason & 0x8) != 0)
  603. //We stopped due to a BREAK instruction. Skip over it.
  604. //Check the instruction first; gdb may have replaced it with the original instruction
  605. //if it's one of the breakpoints it set.
  606. && readbyte(gdbstub_savedRegs.pc + 2) == 0
  607. && (readbyte(gdbstub_savedRegs.pc + 1) & 0xf0) == 0x40
  608. && (readbyte(gdbstub_savedRegs.pc) & 0x0f) == 0x00)
  609. || (((gdbstub_savedRegs.reason & 0x10) != 0)
  610. //We stopped due to a BREAK.N instruction. Skip over it, after making sure the instruction
  611. //actually is a BREAK.N
  612. && (readbyte(gdbstub_savedRegs.pc + 1) & 0xf0) == 0xf0
  613. && readbyte(gdbstub_savedRegs.pc) == 0x2d)) {
  614. gdbstub_savedRegs.pc += 3;
  615. }
  616. }
  617. }
  618. #if GDBSTUB_BREAK_ON_EXCEPTION || GDBSTUB_CTRLC_BREAK
  619. #if !GDBSTUB_FREERTOS
  620. static inline int gdbReadCommandWithFrame(void* frame) {
  621. //Copy registers the Xtensa HAL did save to gdbstub_savedRegs
  622. os_memcpy(&gdbstub_savedRegs, frame, 5 * 4);
  623. os_memcpy(&gdbstub_savedRegs.a[2], ((uint32_t*)frame) + 5, 14 * 4);
  624. //Credits go to Cesanta for this trick. A1 seems to be destroyed, but because it
  625. //has a fixed offset from the address of the passed frame, we can recover it.
  626. gdbstub_savedRegs.a[1] = (uint32_t)frame + EXCEPTION_GDB_SP_OFFSET;
  627. int result = gdbReadCommand();
  628. //Copy any changed registers back to the frame the Xtensa HAL uses.
  629. os_memcpy(frame, &gdbstub_savedRegs, 5 * 4);
  630. os_memcpy(((uint32_t*)frame) + 5, &gdbstub_savedRegs.a[2], 14 * 4);
  631. return result;
  632. }
  633. #endif
  634. #endif
  635. #if GDBSTUB_BREAK_ON_EXCEPTION
  636. #if GDBSTUB_FREERTOS
  637. //Freertos exception. This routine is called by an assembly routine in gdbstub-entry.S
  638. void ATTR_GDBFN gdbstub_handle_user_exception() {
  639. gdbstub_savedRegs.reason |= 0x80; //mark as an exception reason
  640. while (gdbReadCommand() != ST_CONT)
  641. ;
  642. }
  643. //FreeRTOS doesn't use the Xtensa HAL for exceptions, but uses its own fatal exception handler.
  644. //We use a small hack to replace that with a jump to our own handler, which then has the task of
  645. //decyphering and re-instating the registers the FreeRTOS code left.
  646. extern void user_fatal_exception_handler();
  647. extern void gdbstub_user_exception_entry();
  648. static void ATTR_GDBINIT install_exceptions() {
  649. //Replace the user_fatal_exception_handler by a jump to our own code
  650. int *ufe = (int*)user_fatal_exception_handler;
  651. //This mess encodes as a relative jump instruction to user_fatal_exception_handler
  652. *ufe = ((((int)gdbstub_user_exception_entry - (int)user_fatal_exception_handler) - 4) << 6) | 6;
  653. }
  654. #else
  655. //Non-OS exception handler. Gets called by the Xtensa HAL.
  656. static void gdbstub_exception_handler_flash(struct XTensa_exception_frame_s *frame);
  657. static void ATTR_GDBFN gdbstub_exception_handler(struct XTensa_exception_frame_s *frame) {
  658. //Save the extra registers the Xtensa HAL doesn't save
  659. gdbstub_save_extra_sfrs_for_exception();
  660. Cache_Read_Enable_New();
  661. gdbstub_exception_handler_flash(frame);
  662. }
  663. static void __attribute__((noinline)) gdbstub_exception_handler_flash(struct XTensa_exception_frame_s *frame) {
  664. gdbstub_savedRegs.reason |= 0x80; //mark as an exception reason
  665. while (gdbReadCommandWithFrame((void*)frame) != ST_CONT)
  666. ;
  667. }
  668. //The OS-less SDK uses the Xtensa HAL to handle exceptions. We can use those functions to catch any
  669. //fatal exceptions and invoke the debugger when this happens.
  670. static void ATTR_GDBINIT install_exceptions() {
  671. static int exno[] = {EXCCAUSE_ILLEGAL, EXCCAUSE_SYSCALL, EXCCAUSE_INSTR_ERROR, EXCCAUSE_LOAD_STORE_ERROR,
  672. EXCCAUSE_DIVIDE_BY_ZERO, EXCCAUSE_UNALIGNED, EXCCAUSE_INSTR_DATA_ERROR, EXCCAUSE_LOAD_STORE_DATA_ERROR,
  673. EXCCAUSE_INSTR_ADDR_ERROR, EXCCAUSE_LOAD_STORE_ADDR_ERROR, EXCCAUSE_INSTR_PROHIBITED,
  674. EXCCAUSE_LOAD_PROHIBITED, EXCCAUSE_STORE_PROHIBITED};
  675. unsigned int i;
  676. for (i = 0; i < (sizeof(exno) / sizeof(exno[0])); i++) {
  677. _xtos_set_exception_handler(exno[i], gdbstub_exception_handler);
  678. }
  679. }
  680. #endif
  681. #endif
  682. #if GDBSTUB_REDIRECT_CONSOLE_OUTPUT
  683. //Replacement putchar1 routine. Instead of spitting out the character directly, it will buffer up to
  684. //OBUFLEN characters (or up to a \n, whichever comes earlier) and send it out as a gdb stdout packet.
  685. static void ATTR_GDBEXTERNFN gdbstub_semihost_putchar1(char c) {
  686. if (!gdb_attached && uart_putc1_callback != NULL) {
  687. uart_putc1_callback(c);
  688. } else {
  689. gdbstub_write_char(c);
  690. }
  691. }
  692. void ATTR_GDBINIT gdbstub_set_putc1_callback(void (*func)(char)) {
  693. uart_putc1_callback = func;
  694. }
  695. #endif
  696. #if GDBSTUB_FREERTOS
  697. static void ATTR_GDBINIT configure_uart() {}
  698. #else
  699. static void ATTR_GDBINIT configure_uart() {
  700. #ifdef ARDUINO
  701. // Set the UART input/output pins to TX=1, RX=3
  702. pinMode(3, SPECIAL);
  703. pinMode(1, FUNCTION_0);
  704. #endif
  705. WRITE_PERI_REG(UART_CONF0(0), 0b00011100); //8N1
  706. SET_PERI_REG_MASK(UART_CONF0(0), UART_RXFIFO_RST | UART_TXFIFO_RST); //RESET FIFO
  707. CLEAR_PERI_REG_MASK(UART_CONF0(0), UART_RXFIFO_RST | UART_TXFIFO_RST);
  708. }
  709. #endif
  710. #if GDBSTUB_CTRLC_BREAK
  711. #if GDBSTUB_FREERTOS
  712. void ATTR_GDBFN gdbstub_handle_uart_int(struct XTensa_rtos_int_frame_s *frame) {
  713. int doDebug = 0, fifolen, x;
  714. fifolen = (READ_PERI_REG(UART_STATUS(0)) >> UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT;
  715. while (fifolen != 0) {
  716. //Check if any of the chars is control-C. Throw away rest.
  717. if ((READ_PERI_REG(UART_FIFO(0)) & 0xFF) == 0x3)
  718. doDebug = 1;
  719. fifolen--;
  720. }
  721. WRITE_PERI_REG(UART_INT_CLR(0), UART_RXFIFO_FULL_INT_CLR | UART_RXFIFO_TOUT_INT_CLR);
  722. if (doDebug) {
  723. //Copy registers the Xtensa HAL did save to gdbstub_savedRegs
  724. gdbstub_savedRegs.pc = frame->pc;
  725. gdbstub_savedRegs.ps = frame->ps;
  726. gdbstub_savedRegs.sar = frame->sar;
  727. for (x = 0; x < 16; x++)
  728. gdbstub_savedRegs.a[x] = frame->a[x];
  729. // gdbstub_savedRegs.a1=(uint32_t)frame+EXCEPTION_GDB_SP_OFFSET;
  730. gdbstub_savedRegs.reason = 0xff; //mark as user break reason
  731. gdbReadCommand();
  732. //Copy any changed registers back to the frame the Xtensa HAL uses.
  733. frame->pc = gdbstub_savedRegs.pc;
  734. frame->ps = gdbstub_savedRegs.ps;
  735. frame->sar = gdbstub_savedRegs.sar;
  736. for (x = 0; x < 16; x++)
  737. frame->a[x] = gdbstub_savedRegs.a[x];
  738. }
  739. }
  740. static void ATTR_GDBINIT install_uart_hdlr() {
  741. os_isr_attach(ETS_UART_INUM, gdbstub_uart_entry);
  742. SET_PERI_REG_MASK(UART_INT_ENA(0), UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA);
  743. ETS_UART_INTR_ENABLE();
  744. }
  745. #else
  746. static void ATTR_GDBFN gdbstub_uart_hdlr(void* arg, void* frame) {
  747. (void) arg;
  748. unsigned char c;
  749. //Save the extra registers the Xtensa HAL doesn't save
  750. gdbstub_save_extra_sfrs_for_exception();
  751. ETS_UART_INTR_DISABLE();
  752. WRITE_PERI_REG(UART_INT_CLR(0), UART_RXFIFO_FULL_INT_CLR | UART_RXFIFO_TOUT_INT_CLR);
  753. int fifolen = (READ_PERI_REG(UART_STATUS(0)) >> UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT;
  754. while (true) {
  755. if (fifolen == 0) {
  756. ETS_UART_INTR_ENABLE();
  757. return;
  758. }
  759. c = READ_PERI_REG(UART_FIFO(0)) & 0xFF;
  760. //Check if any of the chars is control-C
  761. if (c == 0x3) {
  762. break;
  763. }
  764. #if GDBSTUB_CTRLC_BREAK
  765. if (!gdb_attached && uart_isr_callback != NULL) {
  766. uart_isr_callback(uart_isr_arg, c);
  767. }
  768. #endif
  769. fifolen--;
  770. }
  771. gdbstub_savedRegs.reason = 0xff; //mark as user break reason
  772. gdbReadCommandWithFrame(frame);
  773. }
  774. static void ATTR_GDBINIT install_uart_hdlr() {
  775. ETS_UART_INTR_DISABLE();
  776. ETS_UART_INTR_ATTACH(gdbstub_uart_hdlr, NULL);
  777. configure_uart();
  778. WRITE_PERI_REG(UART_CONF1(0),
  779. ((16 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) |
  780. ((0x02 & UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S) |
  781. UART_RX_TOUT_EN);
  782. WRITE_PERI_REG(UART_INT_CLR(0), 0xffff);
  783. SET_PERI_REG_MASK(UART_INT_ENA(0), UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA);
  784. ETS_UART_INTR_ENABLE();
  785. }
  786. void ATTR_GDBINIT gdbstub_set_uart_isr_callback(void (*func)(void*, uint8_t), void* arg) {
  787. ETS_UART_INTR_DISABLE();
  788. uart_isr_callback = func;
  789. uart_isr_arg = arg;
  790. ETS_UART_INTR_ENABLE();
  791. }
  792. #endif
  793. #endif
  794. //gdbstub initialization routine.
  795. void gdbstub_init() {
  796. #if GDBSTUB_REDIRECT_CONSOLE_OUTPUT
  797. os_install_putc1(gdbstub_semihost_putchar1);
  798. #endif
  799. #if GDBSTUB_CTRLC_BREAK
  800. install_uart_hdlr();
  801. #else
  802. configure_uart();
  803. #endif
  804. #if GDBSTUB_BREAK_ON_EXCEPTION
  805. install_exceptions();
  806. #endif
  807. gdbstub_init_debug_entry();
  808. #if GDBSTUB_BREAK_ON_INIT
  809. gdbstub_do_break();
  810. #endif
  811. }
  812. bool ATTR_GDBEXTERNFN gdb_present() {
  813. return true;
  814. }
  815. void ATTR_GDBFN gdb_do_break() { gdbstub_do_break(); }
  816. void gdb_init() __attribute__((alias("gdbstub_init")));