mbed-memory-status Supports SWO Now

A quick note: I finally got around to updating mbed-memory-status to support outputting data using the Serial Wire Output port on a Nordic nRF52 Development Kit.

The trick to getting it work was, as usual with Nordic stuff, a compiler #define (-DENABLE_SWO to be exact). Took a bit of digging to figure this one out and get it working.

This actually lead to some further investigation and the interesting discovery that SWO could possibly offer an extra output-only serial port on most Cortex-M3-and-up chips. But, there are still some blockers on getting that thought working and I haven’t had the time to clear them.

esptool-ck, esp8266, and FTDI Bug Hunting

Ever feel like you’re riding the Struggle Bus when using the esp8266?

tl;dr

Try a different USB serial adapter.

The Debug

This is the first part of a series on the insanely stupid amount of debugging I had to endure, in order to get started with this magnificent chip.

A lot of people seem to have problems programming it, myself included. There are a lot of documented cases of weird errors showing up, such as a flash failing at 7 or 8%, every time [1] [2] :

While I was getting up to speed on the esp8266, I built at least three programming circuits, and each one failed to upload a program correctly to the chip.

This was extremely irritating and I wasted a ridiculous amount of time trying to figure out what’s going on, whether I was at fault, or the circuit was at fault, or the uploader program was at fault.

I tried adding decoupling capacitors to the 3.3v → ground lines, I tried tying up the RESET and GPIO2 lines.

I tried the NodeMCU flasher, esptool.py, and esptool-ck, and none of them worked.

I tried on a Windows machine, on a Mac, and on a Linux machine, again nothing worked.

I tried attaching jumper cables directly between the programming pins and an FTDI serial adapter, and it still froze on upload.

I tried adding a separate 2A regulated power supply, this didn’t help either.

I even tried buying an EEPROM programming clip and seeing if I could write the EEPROM that way, no luck.

The esp8266 has become my white whale, as they say. And I will see it at the gates of Hell, waiting for me with a espcomm_send_command(FLASH_DOWNLOAD_DATA) failed message.

Or with obtuse responses like:

$ ./esptool.py --baud 115200 --port /dev/cu.usbserial-A50285BI write_flash 0x00000 nodemcu_integer_0.9.6-dev_20150704.bin 
Connecting...
Erasing flash...
Took 2.21s to erase flash block
Writing at 0x00008000... (7 %) 
A fatal error occurred: Invalid head of packet
$ ./esptool.py --baud 115200 --port /dev/cu.usbserial-A50285BI write_flash 0x00000 nodemcu_integer_0.9.6-dev_20150704.bin 
Connecting...
Erasing flash...
Took 2.32s to erase flash block
Writing at 0x00005000... (4 %) 
A fatal error occurred: Invalid head of packet
$ ./esptool.py --baud 115200 --port /dev/cu.usbserial-A50285BI write_flash 0x00000 nodemcu_integer_0.9.6-dev_20150704.bin 
Connecting...
Erasing flash...
Took 2.28s to erase flash block
Writing at 0x00003c00... (3 %) 
A fatal error occurred: Invalid head of packet
$ ./esptool.py --baud 57600 --port /dev/cu.usbserial-A50285BI write_flash 0x00000 nodemcu_integer_0.9.6-dev_20150704.bin 
Connecting...
Erasing flash...
Took 2.28s to erase flash block
Writing at 0x00000000... (0 %) 
A fatal error occurred: Invalid head of packet
$ ./esptool.py --baud 57600 --port /dev/tty.usbserial-A50285BI write_flash 0x00000 nodemcu_integer_0.9.6-dev_20150704.bin 
Connecting...
Erasing flash...
Took 2.17s to erase flash block
Writing at 0x00000000... (0 %) 
A fatal error occurred: Invalid head of packet
$ ./esptool.py --baud 230400 --port /dev/tty.usbserial-A50285BI write_flash 0x00000 nodemcu_integer_0.9.6-dev_20150704.bin 
Connecting...
Erasing flash...
Took 2.24s to erase flash block
Writing at 0x00008000... (7 %) 
A fatal error occurred: Invalid head of packet
$ ./esptool.py --baud 460800 --port /dev/tty.usbserial-A50285BI write_flash 0x00000 nodemcu_integer_0.9.6-dev_20150704.bin 
Connecting...
Erasing flash...
Took 2.25s to erase flash block
Writing at 0x00008000... (7 %) 
A fatal error occurred: Invalid head of packet
$

It was high time for me to start debugging esptool-ck, to find out why it was failing, and to see if there were problems I could solve.

I’d tried everything everything, and I was beginning to suspect my crappy, Chinese-knockoff FTDI converter is to blame. It was the one common denominator I thought could not possibly be the problem.

This gave me a good opportunity to mess around with JetBrains’ CLion, since importing esptool-ck into Xcode turned into a complete and utter clusterfuck. (Way to go, Apple. Why is Xcode such a pain in the ass to import existing files into and set dependencies? Seriously, way too hard.)

After a bit of debugging, I caught esptool-ck blocking on the tcdrain() call multiple times when running in multiple CLion lldb debugging sessions. This is interesting, and seems to be a good place to start.

1-tcdrain

2-tcdrain-12k-bound

3-close-fail-tcdrain-again

I suspected that OS X might have some issues, so as a start, I modified espcomm.c to remove calls to tcdrain() under OS X. The fact that esptool-ck was unable to exit, when it got stuck in the tcdrain() pointed to a potential hardware issue with the counterfeit circuit. A genuine device should simply not exhibit problems here.

Another particularly gruesome issue with the crappy knock-off FTDI boards, was that they refused to execute the close() properly and would actually hang. So the only way to fix the situation was to unplug the counterfeit FTDI board and power cycle the esp8266.

In the end, the problem was with the counterfeit FTDI hardware. Don’t buy this adapter for esp8266 programming, you will totally regret it:

Counterfeit FTDI Adapter (front)

Counterfeit FTDI Adapter (rear)

After testing out an adapter using a genuine FTDI chip, all of the programming methods worked just fine.

Sure, It Only Cost 5 EUR

Starting to muck around with the ExpressIf ESP8266 chip, which has been the darling of the IoT scene the past year. Unfortunately, I didn’t realize the carrier boards used 2mm pitch instead of your standard 2.54mm pitch. So I spent probably a good forty-five minutes building a breakout board. Fun times. Now to electrically split the copper strip down the middle and to actually program the thing.

esp-board-01

esp-board-02

esp-board-03

esp-board-04

esp-board-05