ESP-12E pinout differences

A while ago, I found an e-book about the 8266.  It’s called “Kolban’s book on ESP8266” by Neil Kolban.  He compiled a lot of information on the ESP8266.  I decided to look at this book to see if it has any useful information concerning the HSPI.  It has very little to say about HSPI.  The book lists the API calls without any detail.  What is important is it lists a GitHub repository that has very easy to read example code.  The author of the example code also has a blog with a very good description of how to use the SPI registers.

Since I have the HSPI working with one byte, I decided to try to get the Overlap mode working before trying to add functionality.  I retested with the code from last week and got the same results. Let’s hear it for consistency!  Then I put the call to hspi_overlap_init() in my code just before the sending of data.  Without changing which pins the logic analyzer is attached to, I expect to see chip select to go low and but not see any clock or data, they should move to the other pins.  The data didn’t change pins.  I connected to the SPI bus to see if the data is being sent on both buses.  I checked what should be the clk line and got what looks like data. Next I checked what should be the MOSI line and it looks like the CLK line should look. I created the table below while doing the testing.  I did find that data was on both sets of pins.

Pin#(expected) — Most likely signal
PIN10(MISO) — ?
PIN11(IO2) — ?
PIN12(CLK) — ?
PIN13(IO3) — MOSI
PIN14(MOSI) — CLK

I grabbed the first build of the board to see if it acted the same. I soldered component leads to each of the SPI signals I was interested in and then attached the logic analyzer to those pins as I needed.  With the old board it looks like MOSI is on Pin13 and CLK is on Pin12.  There are definitely different pinouts of the ESP12E from (I assume) different manufacturers.  This could be a problem if I go to any kind of mass production.  There is a newer version of the chip ESP-12F that seems to match the pinout of the chip I currently have.  I don’t see any evidence on the web of different pinouts of the 12F yet.  This needs more research.

I will have to change the layout again but I can test the HSPI with RAM by cutting the traces and putting jumpers in to correctly wire the chip.  I went back and modified the schematics to reflect these changes.  Since the pinout for the 12F matches the lines I am pretty sure of, I used it to update the schematic.  I changed the labels on the Pins of the chip then changed the connections to the SPI RAM.

SPI Pinout FixESP-12F

Have you had to work with manufactures changing specs on you? Or obsoleting a chip? How did you deal with it?

Troubleshooting

I started out this week by hooking the SPI RAM to the logic analyzer. Then I hooked up the USB cable and it was stuck in a reboot cycle. I set the flash speed back to 20. Still stuck in reboot cycle. I disconnected the logic analyzer still in reboot loop.  I commented out the initSpiRam function in the startup code still stuck in reboot loop. This leads me to believe I have a power supply problem.

If it’s a power problem, adding large (100 μF) and small (0.01 μF) capacitors around the ESP-12E would solve the problem.  The 100 μF capacitor will act as an energy reservoir. The small capacitor will act as a noise filter. I piggy backed both a 100 μF and  a 0.01 μF capacitor on top of C4 the decoupling capacitor for the ESP-12E module. This didn’t solve the problem.  Next I suspected the SPI RAM was the problem.

I probed CS0 along with the SPI RAM CS line and they were in perfect phase.  This means that Q6 is not inverting the signal. This results with U2 on the SPI bus while the flash is being accessed.  That would definitely get it stuck in a reboot loop.  After feeling stumped for a while, I replaced Q6. It booted normally again. I uncommented the initSpiRam function and it started rebooting again. I tried with and without initSpiRam being called and it would consistently reboot when initSpiRam was called.

With initSpiRam uncommented, I went into the function and started commenting out lines to see what was causing the reboot.  It appears that ENABLE_SPI_DEV_CS() is causing the reboots. I moved it to after spi_master_init to see if that would work. spi_master_init(HSPI) by itself works. Next I tried adding overlap mode. It appears that overlap has to be after master init.  The SPI driver files and headers don’t have any way to read back data while in SPI master mode.

I decided to do a very simple test. I would do a SPI Master Write without overlap mode turned on. One write of one byte immediately after boot so it would be easy to catch on the logic analyzer.  The HSPI pins are:

GPIO14: CLK  Pin 5
GPIO12: MISO Pin 6
GPIO13: MOSI Pin 7
GPIO15: !CS  Pin 16

Chip select is the same pin I am already using, the rest are unconnected. I put a jumper across Q6 to always disable U2 by pulling CS (pin 1) high. I also soldered test points to each pin so I could easily attach the logic analyzer. With the jumper across Q6 I couldn’t even program the board!  This doesn’t make sense, I’ll have to come back to that.  I think I have some mis-wiring. I removed U2 from the board, and this allowed me to reprogram the PCB.

It now boots but doesn’t give me a menu. It appears to hang on the spi_mast_byte_write() call.

This is not a big deal, I haven’t set the SPI port.

All that time spent fighting this problem, and it turned out to be a solder bridge between R27 and a PCB trace from FLASH CS0.  I cleaned up this bridge and it started working reliably.

Finally I tested the basic HSPI write function. It didn’t work. but code is running without freezing or rebooting.  So I added a call to spi_master_init() still not working, no data on lines.  Looking in spi.c, I saw that spi_master_init() doesn’t assign pins to the HSPI port.  I added the lines below to user_init(). HSPI_PIN is defined as 2.

PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U,HSPI_PIN); // GPIO14
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U,HSPI_PIN); // GPIO12
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U,HSPI_PIN);// GPIO13
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U,HSPI_PIN);// GPIO15

And I saw a byte on the logic analyzer. Yeah! progress.

SPI Byte outThe data speed is at 20MHz. I tried two writes in a row and got a chip select active for each write, and inactive in between. I need to figure out how to change this behavior, the SPI RAM commands always follow the falling(going active) edge of chip select. To write data to the RAM, I have to send more than one byte while chip select is active.

How do you do troubleshooting? Have you gotten HSPI Working on the ESP-12E? Does anyone know if there are different pinouts for the ESP-12E? Something I saw suggested to me that I still have the SPI RAM connected wrong again.

New PCBs

The PCBs arrived this week.  I really like the way my Logo came out.  20160415BarePCB

I do want to make an adjustment, make the arrows larger, they didn’t even show up on the silkscreen.

PCBLogo

To start testing, I put a jumper in bypassing the lithium cell charger. I then installed the ESP-12E, the SPI RAM, The Crystal, the USB Serial Bridge, the voltage regulator, and the USB connector. Just enough to power up, load a program and test the basics.

20160415assembledPCB

First test was to  connect to PC and run ESPlorer– it worked.

I got a message:


AT-based firmware detected.
AT+GMR
AT version:0.40.0.0(Aug 8 2015 14:45:58)
SDK version:1.3.0
Ai-Thinker Technology Co.,Ltd.
Build:1.3.0.2 Sep 11 2015 11:48:04

I then tried to install my test version of the software and it wouldn’t install.  I went back to ESPlorer and started playing with the DTR and RTS to see what would happen. It turns out I got DTR and RTS backwards. So I cut the traces and added a couple of jumpers. This is the kind of mistake I was hoping to catch in the design review.

It programmed great with the wires swapped. My code crashed, back to a “Hello World” version.

Turns out the internal memory chip installed on the ESP-12E does not run at the settings I had specified with esptool.py.  I found this out by setting it to 20MHz DIO mode which started working. I then switched it to QIO mode to see what happened. QIO worked, next I tried running at 40 MHz. That worked.

../esptool/esptool.py --port /dev/ttyUSB0 --baud 230400 write_flash -ff 40m -fm qio -fs 32m 0x00000 ../bin/eagle.flash.bin 0x40000 ../bin/eagle.irom0text.bin

I enabled HSPI Overlap mode by adding spiRamInit() to the end user_init(). Ran without crashing. When I started building for use, I discovered no SPI Master Read available.  I saw something that looked correct for slave read, so I borrowed a line from it and did a write followed by that line– it built. I uploaded the code, and it ran, still no testing of the SPI Ram.

I added the function calls to write “Hello World” to the SPI RAM. and read back and put out to the console. and I got garbage back to the console.  Not a surprise. Debugging with a logic analyzer next week.

Have you written code for the ESP8266. Have you worked with SPI before? I would love to Hear from you.

 

Hardware SPI test software (Firmware V00G)

The PCBs haven’t arrived yet.  So, I worked on the test code for the SPI ram.

Using the datasheet, I started setting up for SPI overlap mode.  On the ESP8266 there are two hardware SPI modules.  In overlap mode, they share the same pins.  This means that if you use the second SPI module you can directly work with the flash memory by using CS0 for the chip select.  I don’t see a lot of use for that other than for performance.  If you choose a different chip select, like I am using GPIO15. You are just sharing the pins with the processor. You have to make sure your code will run in RAM while using the second SPI.  ESP8266 documentation calls the second SPI HSPI.

From Microchips 23LC1024 datasheet, the sequence to write to the SPI RAM in sequential mode is:

Set CS low, write out the value 2 MSB First followed by the 24bit address to start writing at(in 3 bytes), followed by the data to be written(as many bytes as wanted up to the size of the RAM) followed by setting CS high.

A Sequential read has the following steps:

Set CS low, Write out the value 3 MSB first followed by the 24 bit address, then read in as many bytes as wanted. Then set CS high.

Side Note: MSB means Most Significant Bit.  Some protocols transfer in the opposite order or LSB first.  It is important to know this when setting up any serial communication. Data is clocked out on the falling edge of SCK and latched on the rising edge of SCK.  The inactive state of SCK is low.

To help out Espressif provides a guide called:

ESP8266 SPI Overlap & Display Application Guid

This guide describes the SPI Overlap mode API as well as gives a reference implementation using an LCD.  Unfortunately this document is missing a lot of useful information.  There is a post on Espressif’s forum describing it and showing an example.

To get started I have created two new files SPIRam.c and SPIRam.h.  This will make the code easier to locate and modify. To begin with I just want to write some data, and read it back and send it out on the serial connection. Basically a Hello World on the SPI RAM

I created 3 functions:

initSpiRam(); // Set up SPI and Overlap Mode
disableSpiRam(); // Shut down Overlap Mode
writeRam(char data[], int length);
readRam(char data[], int length);

I got it to build but I am unable to test it.

I still have to add a couple of commands over the serial port to tell it to write and tell it to read. I pushed a copy up to Github

I’d like to hear about the projects you are working on.  Please leave a comment below.

SPI RAM

I am anticipating the new PCBs coming in soon, (I have a tracking number but it doesn’t show up with Hong Kong Post or USPS). In light of this, I decided to do a little research on the SPI RAM so that when it gets here, I can quickly write code to test the functionality of the design.  The SPI RAM I have chosen is a 23LC1024.  A common manufacturer of this chip is MicroChip, I downloaded their datasheet for this chip and started looking at the process to write to and read from the RAM.

Notes for writing to SPI RAM:

Maximum 20 Mhz Clock for all data transfers (might cause me to slow down the FLASH)

Write speed only limited by clock speed.

Write command(0x02) followed by 24bit address followed by data

Page Mode 32bytes before sending a new address

Sequential mode can fill the whole RAM

Write is terminated by CS going inactive(HIGH)

Notes for reading from RAM

Same maximum clock speed.

read only limited by clock speed.

Read command(0x03) followed by 24bit address start receiving/clocking data from RAM

Three modes of operation, Byte, Page, and Sequential.

Byte mode only allows reading/writing one byte before having to resend an address.

Page mode all data is accessed in pages of thirty two bytes. Not very useful for this project.

Sequential mode allows access to all of RAM as one big block that I can start accessing from any point. I need to set the mode register bits 7 and 6 to 01.

I am going to start in standard SPI mode, Make sure it is working then adjust the code to start taking advantage of the SQI interface.