Discuss here different C compiler set ups, and compiling executables for the ESP8266

User avatar
By projectgus
#11157 I've been working on adding esp8266 support to the openocd open source debugger program. Mostly this means adding Xtensa architecture support, or at least enough that esp8266 can work.

Progress is up on github: https://github.com/projectgus/openocd

Still very early days, not quite usable as a JTAG debugger yet but I think we will get there.

Current status:
  • Can connect, halt, resume and single step instructions.
  • Can read and write memory and registers.
  • gdb kind of works - using the gdb built from the esp8266 crosstool-ng fork can attach, halt, step, view register state and assembly dump, etc. [s]>There's currently a bug that causes it to lose sync randomly after a short time and requires a reset. :(.[/s] EDIT: This bug is fixed, gdb seems stable now

Todos:

Problems with no (yet) known solution:

Help wanted! Anyone who can help debug problems or finish things off is very welcome!! :)
(Note: at this stage un-detailed bug reports like "it doesn't work" aren't helpful, sorry, it doesn't work particularly well for anyone right now... :? )

JTAG Connections

I've only used an ESP-12 module as it has an exposed RESET line. I think it may be possible to use modules without exposed RESET, provided you don't configure those pins as GPIOs in your program(?)

  • JTAG Signal -> ESP8266 GPIO Pin -> JTAG Pin (standard 20 pin connector)
  • TMS -> 14 -> 7
  • TDI -> 12 -> 5
  • TCK -> 13 -> 9
  • TDO -> 15 -> 13
  • RST -> RST -> 15
[/list]

openocd command line
Something like:
Code: Select allopenocd -f interface/ftdi/olimex-arm-usb-tiny-h.cfg -f target/esp8266.cfg

Replace the first -f argument with the config file for your JTAG interface.

If you don't want to 'make install', you can run in-place like this:
Code: Select all./src/openocd -f ./tcl/interface/ftdi/olimex-arm-usb-tiny-h.cfg -f ./tcl/target/esp8266.cfg


Hope this is eventually useful for some people. :). In particular I'm hoping this will be a tool to further understand the inner secret workings of the esp8266 hardware.
Last edited by projectgus on Wed Mar 04, 2015 8:22 am, edited 2 times in total.
User avatar
By uzevla
#11223 Hi, for setting the breakpoints, hopefully this code might help you.
CACHE_Ax(), WRITE_Ax, READ_Ax and EXEC_INSN() are dummy macros - shouldn't be a problem to replace them with your functionality, you already use all over the code.
Code is not compiled so consider it like a pseudo code. What it does is reading from the memory using L32i only as that's required for possible IRAM access. So, it might need 2 accesses in the case breakpoint address is not 4-byte aligned. Read data is stored in your BP table location i (here given as a simple pointer named saved_data). Then, the read out data is updated with the breakpoint and is written back to the memory - two S32i if needed.

Code: Select all#define LITTLE_BREAKPOINT { 0x00, 0x40, 0x00 }
#define DENSITY_LITTLE_BREAKPOINT { 0x2d, 0xf0 }

void set_bp(UINT32 addr, INT size, UCHAR* saved_data)
{
  // saved_data points to the location in your BP array. Here, it's assumed
  // to be 8+3 bytes so it stores 2-words read out + breakpoint. Of course,

  UINT32 wrbuf[2]; // temp var used to read and write memory
  UCHAR* breakpoint = (size == 2) ? DENSITY_LITTLE_BREAKPOINT: LITTLE_BREAKPOINT;

  UCHAR skip    = addr & 0x3;
  UCHAR sz      = ((skip + size) > 4) ? 8 : 4;
  addr &= ~0x3;

  CACHE(A2);  //cache registers
  CACHE(A3);

  /* Write BP address (aligned to 4-bytes because IRAM is accessible wi) */
  WRITE_A2(addr);

  /* Read first word and save to wrbuf[0] */
  EXEC_INSN(0x002232);   // l32i a3,a2,0
  wrbuf[0] = READ_A3();

  if(sz > 4) {
    EXEC_INSN(0x012232); // l32i a3,a2,4
    wrbuf[1] = READ_A3();
  }

  /* Save memory to provided location, save BP as well for comparison when unplanting
  memcpy(saved_data, (char*)wrbuf, 8);
  memcpy(saved_data+8, breakpoint, size);

  /* Put BP into wrbuf */
  memcpy((wrbuf + skip), breakpoint, size);

  /* Write out first memory word */
  WRITE_A3(wrbuf[0]);
  EXEC_INSN(0x006232); // s32i a3,a2,0

  if(sz > 4) {
    WRITE_A3(wrbuf[0]);
    EXEC_INSN(0x016232); // s32i a3,a2,0
  }
}
Last edited by uzevla on Wed Mar 04, 2015 10:48 pm, edited 1 time in total.
User avatar
By projectgus
#11236
uzevla wrote:Hi, for setting the breakpoints, hopefully this code might help you.


Thanks for this, definitely helpful! The 24-bit instructions with 32-bit word access really make for some gotchas.

Do you have any clues how software breakpoints like these interact with the IRAM caching? Does anyone know how the cache is mapped to flash, is it as simple as "the first 32kb of SPI flash is cached" or are there cache lines?

If there are cache lines, is there a chance breakpoints will vanish randomly as they get invalidated from the IRAM cache? In which case they'll need to be written to flash as well as IRAM. :/

(Even if software breakpoints have problems, the overlay indicates that lx106 has one hardware breakpoint address register and one watchpoint address register, so that's better than nothing.)

uzevla wrote:About the 'reset halt':
If you enable OCD and issue Debug Interrupt while SRST is asserted, the core will enter halt mode as soon as you release SRST. For this to work, JTRST should not be touched.


Excellent news! I'm a little confused though, do you mind explaining more?

My guess was that the reset pin on the esp8266 (EXT_RSTB in the datasheet, pin 32) is an SRST, that possibly also pulls TRST internally. I haven't had any luck getting JTAG to respond at all with this reset pin pulled low.

Someone on twitter (jcmvbkbc, also posts here) mentioned holding TDO high on reset to connect though, which seemed odd. Maybe this is required to connect under reset?