gdbstub.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. /******************************************************************************
  14. * Description: A stub to make the ESP32 debuggable by GDB over the serial
  15. * port, at least enough to do a backtrace on panic. This gdbstub is read-only:
  16. * it allows inspecting the ESP32 state
  17. *******************************************************************************/
  18. #include <string.h>
  19. #include "rom/ets_sys.h"
  20. #include "soc/uart_reg.h"
  21. #include "soc/io_mux_reg.h"
  22. #include "esp_gdbstub.h"
  23. #include "esp_panic.h"
  24. #include "driver/gpio.h"
  25. #include "freertos/FreeRTOS.h"
  26. #include "freertos/task.h"
  27. #include "sdkconfig.h"
  28. //Length of buffer used to reserve GDB commands. Has to be at least able to fit the G command, which
  29. //implies a minimum size of about 320 bytes.
  30. #define PBUFLEN 512
  31. static unsigned char cmd[PBUFLEN]; //GDB command input buffer
  32. static char chsum; //Running checksum of the output packet
  33. #define ATTR_GDBFN
  34. //Receive a char from the uart. Uses polling and feeds the watchdog.
  35. static int ATTR_GDBFN gdbRecvChar() {
  36. int i;
  37. while (((READ_PERI_REG(UART_STATUS_REG(0))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT)==0) ;
  38. i=READ_PERI_REG(UART_FIFO_REG(0));
  39. return i;
  40. }
  41. //Send a char to the uart.
  42. static void ATTR_GDBFN gdbSendChar(char c) {
  43. while (((READ_PERI_REG(UART_STATUS_REG(0))>>UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT)>=126) ;
  44. WRITE_PERI_REG(UART_FIFO_REG(0), c);
  45. }
  46. //Send the start of a packet; reset checksum calculation.
  47. static void ATTR_GDBFN gdbPacketStart() {
  48. chsum=0;
  49. gdbSendChar('$');
  50. }
  51. //Send a char as part of a packet
  52. static void ATTR_GDBFN gdbPacketChar(char c) {
  53. if (c=='#' || c=='$' || c=='}' || c=='*') {
  54. gdbSendChar('}');
  55. gdbSendChar(c^0x20);
  56. chsum+=(c^0x20)+'}';
  57. } else {
  58. gdbSendChar(c);
  59. chsum+=c;
  60. }
  61. }
  62. //Send a string as part of a packet
  63. static void ATTR_GDBFN gdbPacketStr(const char *c) {
  64. while (*c!=0) {
  65. gdbPacketChar(*c);
  66. c++;
  67. }
  68. }
  69. //Send a hex val as part of a packet. 'bits'/4 dictates the number of hex chars sent.
  70. static void ATTR_GDBFN gdbPacketHex(int val, int bits) {
  71. char hexChars[]="0123456789abcdef";
  72. int i;
  73. for (i=bits; i>0; i-=4) {
  74. gdbPacketChar(hexChars[(val>>(i-4))&0xf]);
  75. }
  76. }
  77. //Finish sending a packet.
  78. static void ATTR_GDBFN gdbPacketEnd() {
  79. gdbSendChar('#');
  80. gdbPacketHex(chsum, 8);
  81. }
  82. //Error states used by the routines that grab stuff from the incoming gdb packet
  83. #define ST_ENDPACKET -1
  84. #define ST_ERR -2
  85. #define ST_OK -3
  86. #define ST_CONT -4
  87. //Grab a hex value from the gdb packet. Ptr will get positioned on the end
  88. //of the hex string, as far as the routine has read into it. Bits/4 indicates
  89. //the max amount of hex chars it gobbles up. Bits can be -1 to eat up as much
  90. //hex chars as possible.
  91. static long ATTR_GDBFN gdbGetHexVal(unsigned char **ptr, int bits) {
  92. int i;
  93. int no;
  94. unsigned int v=0;
  95. char c;
  96. no=bits/4;
  97. if (bits==-1) no=64;
  98. for (i=0; i<no; i++) {
  99. c=**ptr;
  100. (*ptr)++;
  101. if (c>='0' && c<='9') {
  102. v<<=4;
  103. v|=(c-'0');
  104. } else if (c>='A' && c<='F') {
  105. v<<=4;
  106. v|=(c-'A')+10;
  107. } else if (c>='a' && c<='f') {
  108. v<<=4;
  109. v|=(c-'a')+10;
  110. } else if (c=='#') {
  111. if (bits==-1) {
  112. (*ptr)--;
  113. return v;
  114. }
  115. return ST_ENDPACKET;
  116. } else {
  117. if (bits==-1) {
  118. (*ptr)--;
  119. return v;
  120. }
  121. return ST_ERR;
  122. }
  123. }
  124. return v;
  125. }
  126. //Swap an int into the form gdb wants it
  127. static int ATTR_GDBFN iswap(int i) {
  128. int r;
  129. r=((i>>24)&0xff);
  130. r|=((i>>16)&0xff)<<8;
  131. r|=((i>>8)&0xff)<<16;
  132. r|=((i>>0)&0xff)<<24;
  133. return r;
  134. }
  135. //Read a byte from ESP32 memory.
  136. static unsigned char ATTR_GDBFN readbyte(unsigned int p) {
  137. int *i=(int*)(p&(~3));
  138. if (p<0x20000000 || p>=0x80000000) return -1;
  139. return *i>>((p&3)*8);
  140. }
  141. //Register file in the format exp108 gdb port expects it.
  142. //Inspired by gdb/regformats/reg-xtensa.dat
  143. typedef struct {
  144. uint32_t pc;
  145. uint32_t a[64];
  146. uint32_t lbeg;
  147. uint32_t lend;
  148. uint32_t lcount;
  149. uint32_t sar;
  150. uint32_t windowbase;
  151. uint32_t windowstart;
  152. uint32_t configid0;
  153. uint32_t configid1;
  154. uint32_t ps;
  155. uint32_t threadptr;
  156. uint32_t br;
  157. uint32_t scompare1;
  158. uint32_t acclo;
  159. uint32_t acchi;
  160. uint32_t m0;
  161. uint32_t m1;
  162. uint32_t m2;
  163. uint32_t m3;
  164. uint32_t expstate; //I'm going to assume this is exccause...
  165. uint32_t f64r_lo;
  166. uint32_t f64r_hi;
  167. uint32_t f64s;
  168. uint32_t f[16];
  169. uint32_t fcr;
  170. uint32_t fsr;
  171. } GdbRegFile;
  172. GdbRegFile gdbRegFile;
  173. /*
  174. //Register format as the Xtensa HAL has it:
  175. STRUCT_FIELD (long, 4, XT_STK_EXIT, exit)
  176. STRUCT_FIELD (long, 4, XT_STK_PC, pc)
  177. STRUCT_FIELD (long, 4, XT_STK_PS, ps)
  178. STRUCT_FIELD (long, 4, XT_STK_A0, a0)
  179. [..]
  180. STRUCT_FIELD (long, 4, XT_STK_A15, a15)
  181. STRUCT_FIELD (long, 4, XT_STK_SAR, sar)
  182. STRUCT_FIELD (long, 4, XT_STK_EXCCAUSE, exccause)
  183. STRUCT_FIELD (long, 4, XT_STK_EXCVADDR, excvaddr)
  184. STRUCT_FIELD (long, 4, XT_STK_LBEG, lbeg)
  185. STRUCT_FIELD (long, 4, XT_STK_LEND, lend)
  186. STRUCT_FIELD (long, 4, XT_STK_LCOUNT, lcount)
  187. // Temporary space for saving stuff during window spill
  188. STRUCT_FIELD (long, 4, XT_STK_TMP0, tmp0)
  189. STRUCT_FIELD (long, 4, XT_STK_TMP1, tmp1)
  190. STRUCT_FIELD (long, 4, XT_STK_TMP2, tmp2)
  191. STRUCT_FIELD (long, 4, XT_STK_VPRI, vpri)
  192. STRUCT_FIELD (long, 4, XT_STK_OVLY, ovly)
  193. #endif
  194. STRUCT_END(XtExcFrame)
  195. */
  196. static void commonRegfile() {
  197. if (gdbRegFile.a[0] & 0x8000000U) gdbRegFile.a[0] = (gdbRegFile.a[0] & 0x3fffffffU) | 0x40000000U;
  198. if (!esp_stack_ptr_is_sane(gdbRegFile.a[1])) gdbRegFile.a[1] = 0xDEADBEEF;
  199. gdbRegFile.windowbase=0; //0
  200. gdbRegFile.windowstart=0x1; //1
  201. gdbRegFile.configid0=0xdeadbeef; //ToDo
  202. gdbRegFile.configid1=0xdeadbeef; //ToDo
  203. gdbRegFile.threadptr=0xdeadbeef; //ToDo
  204. gdbRegFile.br=0xdeadbeef; //ToDo
  205. gdbRegFile.scompare1=0xdeadbeef; //ToDo
  206. gdbRegFile.acclo=0xdeadbeef; //ToDo
  207. gdbRegFile.acchi=0xdeadbeef; //ToDo
  208. gdbRegFile.m0=0xdeadbeef; //ToDo
  209. gdbRegFile.m1=0xdeadbeef; //ToDo
  210. gdbRegFile.m2=0xdeadbeef; //ToDo
  211. gdbRegFile.m3=0xdeadbeef; //ToDo
  212. }
  213. static void dumpHwToRegfile(XtExcFrame *frame) {
  214. int i;
  215. long *frameAregs=&frame->a0;
  216. gdbRegFile.pc=(frame->pc & 0x3fffffffU)|0x40000000U;
  217. for (i=0; i<16; i++) gdbRegFile.a[i]=frameAregs[i];
  218. for (i=16; i<64; i++) gdbRegFile.a[i]=0xDEADBEEF;
  219. gdbRegFile.lbeg=frame->lbeg;
  220. gdbRegFile.lend=frame->lend;
  221. gdbRegFile.lcount=frame->lcount;
  222. gdbRegFile.ps=(frame->ps & PS_UM) ? (frame->ps & ~PS_EXCM) : frame->ps;
  223. //All windows have been spilled to the stack by the ISR routines. The following values should indicate that.
  224. gdbRegFile.sar=frame->sar;
  225. commonRegfile();
  226. gdbRegFile.expstate=frame->exccause; //ToDo
  227. }
  228. //Send the reason execution is stopped to GDB.
  229. static void sendReason() {
  230. //exception-to-signal mapping
  231. char exceptionSignal[]={4,31,11,11,2,6,8,0,6,7,0,0,7,7,7,7};
  232. int i=0;
  233. gdbPacketStart();
  234. gdbPacketChar('T');
  235. i=gdbRegFile.expstate&0x7f;
  236. if (i<sizeof(exceptionSignal)) {
  237. gdbPacketHex(exceptionSignal[i], 8);
  238. } else {
  239. gdbPacketHex(11, 8);
  240. }
  241. gdbPacketEnd();
  242. }
  243. static int sendPacket(const char * text) {
  244. gdbPacketStart();
  245. if (text != NULL) gdbPacketStr(text);
  246. gdbPacketEnd();
  247. return ST_OK;
  248. }
  249. #if CONFIG_GDBSTUB_SUPPORT_TASKS
  250. #define STUB_TASKS_NUM CONFIG_GDBSTUB_MAX_TASKS
  251. //Remember the exception frame that caused panic since it's not saved in TCB
  252. static XtExcFrame paniced_frame;
  253. //Allows GDBStub to disable task support after a crash
  254. //(e.g. if GDBStub crashes while trying to get task list, e.g. due to corrupted list structures)
  255. static enum {
  256. HANDLER_NOT_STARTED,
  257. HANDLER_STARTED,
  258. HANDLER_TASK_SUPPORT_DISABLED
  259. } handlerState;
  260. static void dumpTaskToRegfile(XtSolFrame *frame) {
  261. int i;
  262. long *frameAregs=&frame->a0;
  263. gdbRegFile.pc=(frame->pc & 0x3fffffffU)|0x40000000U;
  264. for (i=0; i<4; i++) gdbRegFile.a[i]=frameAregs[i];
  265. for (i=4; i<64; i++) gdbRegFile.a[i]=0xDEADBEEF;
  266. gdbRegFile.lbeg=0;
  267. gdbRegFile.lend=0;
  268. gdbRegFile.lcount=0;
  269. gdbRegFile.ps=(frame->ps & PS_UM) ? (frame->ps & ~PS_EXCM) : frame->ps;
  270. //All windows have been spilled to the stack by the ISR routines. The following values should indicate that.
  271. gdbRegFile.sar=0;
  272. commonRegfile();
  273. gdbRegFile.expstate=0; //ToDo
  274. }
  275. // Fetch the task status. Returns the total number of tasks.
  276. static unsigned getTaskInfo(unsigned index, unsigned * handle, const char ** name, unsigned * coreId) {
  277. static unsigned taskCount = 0;
  278. static TaskSnapshot_t tasks[STUB_TASKS_NUM];
  279. if (!taskCount) {
  280. unsigned tcbSize = 0;
  281. taskCount = uxTaskGetSnapshotAll(tasks, STUB_TASKS_NUM, &tcbSize);
  282. }
  283. if (index < taskCount) {
  284. TaskHandle_t h = (TaskHandle_t)tasks[index].pxTCB;
  285. if (handle) *handle = (unsigned)h;
  286. if (name) *name = pcTaskGetTaskName(h);
  287. if (coreId) *coreId = xTaskGetAffinity(h);
  288. }
  289. return taskCount;
  290. }
  291. typedef struct
  292. {
  293. uint8_t * topOfStack;
  294. } DumpTCB;
  295. static void dumpTCBToRegFile(unsigned handle) {
  296. // A task handle is a pointer to a TCB in FreeRTOS
  297. DumpTCB * tcb = (DumpTCB*)handle;
  298. uint8_t * pxTopOfStack = tcb->topOfStack;
  299. //Deduced from coredump code
  300. XtExcFrame * frame = (XtExcFrame*)pxTopOfStack;
  301. if (frame->exit) {
  302. // It's an exception frame
  303. dumpHwToRegfile(frame);
  304. } else {
  305. XtSolFrame * taskFrame = (XtSolFrame*)pxTopOfStack;
  306. dumpTaskToRegfile(taskFrame);
  307. }
  308. }
  309. #define CUR_TASK_INDEX_NOT_SET -2
  310. #define CUR_TASK_INDEX_UNKNOWN -1
  311. // Get the index of the task currently running on the current CPU, and cache the result
  312. static int findCurrentTaskIndex() {
  313. static int curTaskIndex = CUR_TASK_INDEX_NOT_SET;
  314. if (curTaskIndex == CUR_TASK_INDEX_NOT_SET) {
  315. unsigned curHandle = (unsigned)xTaskGetCurrentTaskHandleForCPU(xPortGetCoreID());
  316. unsigned handle;
  317. unsigned count = getTaskInfo(0, 0, 0, 0);
  318. for(int k=0; k<(int)count; k++) {
  319. if (getTaskInfo(k, &handle, 0, 0) && curHandle == handle) {
  320. curTaskIndex = k;
  321. return curTaskIndex;
  322. }
  323. }
  324. curTaskIndex = CUR_TASK_INDEX_UNKNOWN;
  325. }
  326. return curTaskIndex;
  327. }
  328. #endif // CONFIG_GDBSTUB_SUPPORT_TASKS
  329. //Handle a command as received from GDB.
  330. static int gdbHandleCommand(unsigned char *cmd, int len) {
  331. //Handle a command
  332. int i, j, k;
  333. unsigned char *data=cmd+1;
  334. if (cmd[0]=='g') { //send all registers to gdb
  335. int *p=(int*)&gdbRegFile;
  336. gdbPacketStart();
  337. for (i=0; i<sizeof(GdbRegFile)/4; i++) gdbPacketHex(iswap(*p++), 32);
  338. gdbPacketEnd();
  339. } else if (cmd[0]=='G') { //receive content for all registers from gdb
  340. int *p=(int*)&gdbRegFile;
  341. for (i=0; i<sizeof(GdbRegFile)/4; i++) *p++=iswap(gdbGetHexVal(&data, 32));
  342. sendPacket("OK");
  343. } else if (cmd[0]=='m') { //read memory to gdb
  344. i=gdbGetHexVal(&data, -1);
  345. data++;
  346. j=gdbGetHexVal(&data, -1);
  347. gdbPacketStart();
  348. for (k=0; k<j; k++) {
  349. gdbPacketHex(readbyte(i++), 8);
  350. }
  351. gdbPacketEnd();
  352. } else if (cmd[0]=='?') { //Reply with stop reason
  353. sendReason();
  354. #if CONFIG_GDBSTUB_SUPPORT_TASKS
  355. } else if (handlerState != HANDLER_TASK_SUPPORT_DISABLED) {
  356. if (cmd[0]=='H') { //Continue with task
  357. if (cmd[1]=='g' || cmd[1]=='c') {
  358. const char * ret = "OK";
  359. data++;
  360. i=gdbGetHexVal(&data, -1);
  361. handlerState = HANDLER_STARTED; //Hg0 is the first packet received after connect
  362. j = findCurrentTaskIndex();
  363. if (i == j || (j == CUR_TASK_INDEX_UNKNOWN && i == 0)) {
  364. //GDB has asked us for the current task on this CPU.
  365. //This task either was executing when we have entered the panic handler,
  366. //or was already switched out and we have paniced during the context switch.
  367. //Either way we are interested in the stack frame where panic has happened,
  368. //so obtain the state from the exception frame rather than the TCB.
  369. dumpHwToRegfile(&paniced_frame);
  370. } else {
  371. unsigned handle, count;
  372. //Get the handle for that task
  373. count = getTaskInfo(i, &handle, 0, 0);
  374. //Then extract TCB and gdbRegFile from it
  375. if (i < count) dumpTCBToRegFile(handle);
  376. else ret = "E00";
  377. }
  378. return sendPacket(ret);
  379. }
  380. return sendPacket(NULL);
  381. } else if (cmd[0]=='T') { //Task alive check
  382. unsigned count;
  383. data++;
  384. i=gdbGetHexVal(&data, -1);
  385. count = getTaskInfo(i, 0, 0, 0);
  386. return sendPacket(i < count ? "OK": "E00");
  387. } else if (cmd[0]=='q') { //Extended query
  388. // React to qThreadExtraInfo or qfThreadInfo or qsThreadInfo or qC, without using strcmp
  389. if (len > 16 && cmd[1] == 'T' && cmd[2] == 'h' && cmd[3] == 'r' && cmd[7] == 'E' && cmd[12] == 'I' && cmd[16] == ',') {
  390. data=&cmd[17];
  391. i=gdbGetHexVal(&data, -1);
  392. unsigned handle = 0, coreId = 3;
  393. const char * name = 0;
  394. // Extract the task name and CPU from freeRTOS
  395. unsigned tCount = getTaskInfo(i, &handle, &name, &coreId);
  396. if (i < tCount) {
  397. gdbPacketStart();
  398. for(k=0; name[k]; k++) gdbPacketHex(name[k], 8);
  399. gdbPacketStr("20435055"); // CPU
  400. gdbPacketStr(coreId == 0 ? "30": coreId == 1 ? "31" : "78"); // 0 or 1 or x
  401. gdbPacketEnd();
  402. return ST_OK;
  403. }
  404. } else if (len >= 12 && (cmd[1] == 'f' || cmd[1] == 's') && (cmd[2] == 'T' && cmd[3] == 'h' && cmd[4] == 'r' && cmd[5] == 'e' && cmd[6] == 'a' && cmd[7] == 'd' && cmd[8] == 'I')) {
  405. // Only react to qfThreadInfo and qsThreadInfo, not using strcmp here since it can be in ROM
  406. // Extract the number of task from freeRTOS
  407. static int taskIndex = 0;
  408. unsigned tCount = 0;
  409. if (cmd[1] == 'f') {
  410. taskIndex = 0;
  411. handlerState = HANDLER_STARTED; //It seems it's the first request GDB is sending
  412. }
  413. tCount = getTaskInfo(0, 0, 0, 0);
  414. if (taskIndex < tCount) {
  415. gdbPacketStart();
  416. gdbPacketStr("m");
  417. gdbPacketHex(taskIndex, 32);
  418. gdbPacketEnd();
  419. taskIndex++;
  420. } else return sendPacket("l");
  421. } else if (len >= 2 && cmd[1] == 'C') {
  422. // Get current task id
  423. gdbPacketStart();
  424. k = findCurrentTaskIndex();
  425. if (k != CUR_TASK_INDEX_UNKNOWN) {
  426. gdbPacketStr("QC");
  427. gdbPacketHex(k, 32);
  428. } else gdbPacketStr("bad");
  429. gdbPacketEnd();
  430. return ST_OK;
  431. }
  432. return sendPacket(NULL);
  433. }
  434. #endif // CONFIG_GDBSTUB_SUPPORT_TASKS
  435. } else {
  436. //We don't recognize or support whatever GDB just sent us.
  437. return sendPacket(NULL);
  438. }
  439. return ST_OK;
  440. }
  441. //Lower layer: grab a command packet and check the checksum
  442. //Calls gdbHandleCommand on the packet if the checksum is OK
  443. //Returns ST_OK on success, ST_ERR when checksum fails, a
  444. //character if it is received instead of the GDB packet
  445. //start char.
  446. static int gdbReadCommand() {
  447. unsigned char c;
  448. unsigned char chsum=0, rchsum;
  449. unsigned char sentchs[2];
  450. int p=0;
  451. unsigned char *ptr;
  452. c=gdbRecvChar();
  453. if (c!='$') return c;
  454. while(1) {
  455. c=gdbRecvChar();
  456. if (c=='#') { //end of packet, checksum follows
  457. cmd[p]=0;
  458. break;
  459. }
  460. chsum+=c;
  461. if (c=='$') {
  462. //Wut, restart packet?
  463. chsum=0;
  464. p=0;
  465. continue;
  466. }
  467. if (c=='}') { //escape the next char
  468. c=gdbRecvChar();
  469. chsum+=c;
  470. c^=0x20;
  471. }
  472. cmd[p++]=c;
  473. if (p>=PBUFLEN) return ST_ERR;
  474. }
  475. //A # has been received. Get and check the received chsum.
  476. sentchs[0]=gdbRecvChar();
  477. sentchs[1]=gdbRecvChar();
  478. ptr=&sentchs[0];
  479. rchsum=gdbGetHexVal(&ptr, 8);
  480. if (rchsum!=chsum) {
  481. gdbSendChar('-');
  482. return ST_ERR;
  483. } else {
  484. gdbSendChar('+');
  485. return gdbHandleCommand(cmd, p);
  486. }
  487. }
  488. void esp_gdbstub_panic_handler(XtExcFrame *frame) {
  489. #if CONFIG_GDBSTUB_SUPPORT_TASKS
  490. if (handlerState == HANDLER_STARTED) {
  491. //We have re-entered GDB Stub. Try disabling task support.
  492. handlerState = HANDLER_TASK_SUPPORT_DISABLED;
  493. gdbPacketEnd(); // Ends up any pending GDB packet (this creates a garbage value)
  494. } else if (handlerState == HANDLER_NOT_STARTED) {
  495. //Need to remember the frame that panic'd since gdb will ask for all threads before ours
  496. memcpy(&paniced_frame, frame, sizeof(paniced_frame));
  497. dumpHwToRegfile(&paniced_frame);
  498. }
  499. #else // CONFIG_GDBSTUB_SUPPORT_TASKS
  500. dumpHwToRegfile(frame);
  501. #endif // CONFIG_GDBSTUB_SUPPORT_TASKS
  502. //Make sure txd/rxd are enabled
  503. gpio_pullup_dis(1);
  504. PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_U0RXD);
  505. PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_U0TXD);
  506. sendReason();
  507. while(gdbReadCommand()!=ST_CONT);
  508. while(1);
  509. }