Refactoring Electronics (Hardware V00K)

Side Project:

I still haven’t gotten the OLED display working.  I am beginning to question Pinouts and even if the driver IC listed by the seller(s) is correct.  At this point I can’t even tell if the device is seeing my commands. I checked the board for shorts/solder bridges and even replaced the OLED display. I still can’t get anything to show up on the display.

I think a reasonable test would be to measure current to the display and send it a power on command.  If I am sending commands correctly, I should see a change in current draw.  After that, I will try working through the commands available in the datasheet for a SSD1332 chip looking for a change in the display or the current draw.

Refactoring:

Just like refactoring the code, It’s time to refactor the electronics design.  I checked on my feature request on the Espressif forum. Nothing new has happened.  So I am considering adding an external ADC to measure voltages.

Planning and Research:

Continue reading

Layout check … continued

With the new check plots I made last week, I checked the layout net by net like I did back in Sept 5, 2015. I am still uncertain about the pinout of the ESP-12F modules. To test it, I removed the ESP-12E installed on the board I am currently using, and replaced it with a new ESP-12F.  I had to be careful that the jumper wires all got back to where they were before removing the module.

The new module programmed first try but didn’t boot correctly.  I had forgot to upload default values, the flash comes programmed for a different memory layout.  Once I installed the default settings, it booted up correctly.  I had removed the test for HSPI/SPI RAM, so I went back into the code and re-enabled the Hello World ram test.

I went into serialInit() and changed the line DISPLAY_MENU(); to DISPLAY_MENU_W_SPI(); Re-compiled and tested.  Unfortunately the result was not “Hello World”. When I cleaned up the code, I made the write to SPI RAM easier, but I need to initialize the hspi.  I started connecting my mixed signal oscope to analyze what was happening on the SPI bus.  And… I found a loose jumper wire.  The one that connects the chip select between the ESP-12F and the SPI RAM. Once this was connected, the extra stuff I had put into the software became unnecessary.  I deleted the extra code and it works just fine.  The firmware is back to where it was before I started testing. There are no changes to upload.

This means that the circuit is tested and the current layout is ready to send to fabrication.  I zipped up the gerber files. Then checked pricing with PCBway, DFRobot, and Seeed Studio.  With shipping PCBway came in a little less at US $19.  With PCBway, I have to wait for a design review before they will give me a final price and allow me to pay for it. Usually this is pretty quick but depends on the day it is submitted.

Have you bought boards from Chinese manufacturers? How quickly did you get them?

New Release of Espressif’s SDK (Firmware Version 00I)

Espressif released a new version of their NonOs SDK.  The new Version is 2.0.0 released on July 19, 2016.  The change from 1. something to 2. suggests it might break the code.  I downloaded the new version.

Last week I crippled the software for debugging purposes. I found the bug. This week I want to update to the new version of the SDK.  Since it might break my code, I want to get all the functionality back in the code before I move to the new SDK.

First, I uncommented the HSPI overlap test code. I made a small change to the code that reads out from the SPI RAM to guarantee there is a null terminator in the 13th position of the buffer that is filled from the SPI  RAM. Then I compiled and tested it. It immediately crashed.  I am really glad I haven’t upgraded the SDK yet.

I put hspi_overlap_deinit(); directly after the call to the writeRam(); function. It didn’t crash, but I didn’t get the Hello World from the SPI RAM.  I need to init and deinit hspi overlap mode in the writeRam() and readRam() functions. I modified these two functions and tried again.  Now I get the Hello World after the menu after a reset.

Next, I enabled the WiFi modem.  I set the wifi opmode to  STATION_MODE and commented out the other lines that disabled the modem. It booted, I set the SSID and Password, requested a connect and no apparent result.  I remembered the WiFi Callback is still disabled, I uncommented that and tried again. This time, it remembered the settings from the previous try and connected immediately.

Next, I re-enabled the Sigma Delta circuit and tried changing values.  It is working without crashing.  The code is where it should have been before the buffer overrun bug.  I am ready to upgrade the build environment.

I am going to use this code as my base going forward because the web server code was unstable, and I don’t want to work with the web protocols as much as that would require.

I did some of these tests while the file was downloading from Espressif’s website.  I ran make with the clean option. This removes all the intermediary files used in compiling. Next, I copied the folder I was working with to UProgrammer-SDK1.5.4  This gives me something to go back to if the upgrade fails.  Next I opened up the zip archive of the new SDK.  I copied all the files and folders in the ESP8266_NONOS_SDK into the UProgrammer folder.  This copies over all the SDK files but leaves all my files in place.  It does mean the linker file I modified will get overwritten as well.  I checked this file and they have changed it in the new version of the SDK.  It doesn’t match my linker file, but it might have enough room for my code.  I decided to try compiling without modifying the linker file.

There are linker errors but they are not based on code size.  They describe undefined references to user_rf_cal_sector_set in function flash_data_check.  This looks like a makefile error.  I compared the makefile in the app directory with the one in my project directory.  There was no makefile in the app directory like there has been in previous versions of the SDK.  I went into the examples folder and used the makefile from the IOT_Demo Example for my comparison.  I did some clean up and made some changes to make the files closer to each other.

The changes I made weren’t enough, So I copied the whole file over to see if it fixed it. It didn’t, It looks like a file library file isn’t being linked in. I went into the lib directory looking for the library I needed to link. user_rf_cal_sector_set sounds like a memory function to me. So I looked for a library that dealt with calibration memory.  In the include directory, used the following command line:

grep -r user_rf_cal_sector *

and I got no results back, so for a sanity check, I tried the following command:

grep -r smartconfig *

and I got a list of lines with smartconfig  listed.

On a hunch, I decided to remove the link to main. In the makefile under LINKFLAGS, I removed the line -lmain \.

That also didn’t work.  I did the following command in the UProgrammer foler:

grep -r user_rf_cal_sector *

The result looks like every example implements this function. So I copied that function into user_main.c from the IOT_Demo user_main.c and it turns out they required this new function because they changed the layout of the flash calibration data. Now it builds.  Now the code no longer works.

I tried changing the ld file back to having a length of 0xC0000 and I noticed that the build said I should upload the code to 0x10000.  My shell scripts upload the code to 0x40000.  So, I restored my makefile from the copy of the folder and tried again. It still builds to load at address 0x10000. I modified my script file to load to that location.

And finally, success.  I set the SSID and the password and requested a connect. it seemed to stall.  I reset the board and it connected immediately. I am going to have to take a look at that.

I tested the Sigma Delta and that worked as expected. I measured 22 volts on the output with a duty of 102 and Prescaler of 4.

I re-uploaded the default settings and tried again. I set the SSID, Password, and requested a connect. it seemed to stall again.  I waited ten minutes to see if something would change.  I looked at the connect request code while I was waiting.  Somewhere along the development I deleted the actual call to connect.  I didn’t make it to the full ten minutes. Put the connect request in the code, compiled it, reset the flash to defaults, and uploaded the new version.

This time it connected in about 5 seconds. Success. I have uploaded the new version of the code to GitHub, click the Firmware on GitHub link at the top of the right column to go get it or just take a look.

Please comment below about your experiences upgrading to a new version of API/APK.  Maybe you have had similar experiences switching between devices in a processor family?  I would love to hear from you.

Sigma Delta Testing V00A

I have been fighting using the Sigma Delta(ΣΔ) for a few weeks now and all of my research so far has not been fruitful.  So, My intention this week is to implement a very basic ΣΔ operation that will change the prescaler for the whole range of possibilities 0 – 255.

The hardware watchdog timer triggers after about 6 seconds without a WDT reset. I have decided I want the sigma delta prescaler to step from 0 to 255 every 5 seconds.  I will put each step of the prescaler out to the serial port using system calls.

I will put all the code in the user_main.c file so that I, and anyone else that looks at my code can see all that is going on.  I extracted a new set of SDK files into a new folder called SigmaDelta.  I then created a new Eclipse project file in this new folder.    I struggled with creating the project in Eclipse.  I finally got it set up the way I wanted.  In the past setting up a project in Eclipse has always been easier, but this time it just didn’t work well for me.

I copied my shell scripts(that is batch files for windows users) that I use to automate building and testing from the UProgrammer folder. Next, I removed the references to AT_CUSTOM_UPGRADE in user_main.c and user_config.h.  I then performed a sanity check by putting one line of code to send “Hello World” out the serial connection and tried to build.  It failed because I forgot a semicolon.  I fixed that and got a new message saying code will not fit in irom0_0_seg.  I need to update the linker  file.  I copied the one from the UProgrammer folder.  Built again and it compiled. Next I uploaded it to see if it still works.  It doesn’t seem to work.  The baud rate is set to 115200, but I am getting a little bit of garbled text after boot completes.  I decided to try putting a small delay(5 ms) in before printing the “hello World”. This also didn’t work.

I need to implement a timer and looked at the sntp example in the API guide.  I set the timer to repeat every 5 seconds. Unfortunately it seems to just hang. I had a similar problem when I moved to this version of the API, I removed the uart_init line and I started getting regular data coming across the serial line. Still garbled, but happening every 5 seconds.  So I looked at uart_init from the uart.c. I found and copied the call that actually sets the baud rate.  I used this to modify the baud rate for UART0 and I started getting Hello World every 5 seconds.  Next step, turn on the Sigma Delta and start incrementing the prescaler.

I created the variables prescaler and duty and set them to 0. Then I went back to my old code and grabbed a copy of the set prescaler code.  I put the code in to set the prescaler, increment it, and print out the value every the timer event is called. I compiled, uploaded it and I saw numbers increasing across the serial terminal.  Then I waited for it to get to 100.  It continued to count.  I let it continue all the way up to 255 and then changed the wifi mode to STATION_MODE like the UProgrammer firmware. Next, I modified the code to turn on the output(GPIO4) and change the duty cycle.

Still working. Connected to wifi and tested again. Still working.  I explicitly set GPIO4 as an output set to 1 and tried again. Still working I turned on HSPI overlap mode and tried again. It started crashing and rebooting.  It looks like somehow the HSPI is conflicting with the SigmaDelta generator.

I commented out the code to set up GPIO4, and the code to connect to the wifi access point and it crashes. I changed the duty back to 0 and it doesn’t crash anymore. Next I checked the Pin assignment worksheet to see what else is connected to GPIO4 and I didn’t find anything interesting.

It looks like I have to do an HSPI overlap deinit immediately after getting data out of the RAM.  This could be a problem because I want to be generating Vpp while transferring data into the processor.  This could limit my options.  If my code is small, I can generate Vpp. If it’s large, I may have to program in blocks.

I do have the capabilities to assemble and test the voltage booster now.  I will go back into the UProgrammer Firmware code and deinit the HSPI overlap and see what happens.

I have put this week’s test code on GitHub here. How do you find problem code?

Switching to SPI from HSPI Firmware V00I

I decided to try to use the SPI module instead of overlap mode this week.  I went into the code that writes and reads from the SPI and changed the working registers to SPI in place of HSPI. I had to store and restore 6 variables in the writeRam() and readRam() functions.  It worked but sent more data than expected. I noticed that I left the overlap init code in place, I removed it and tried again. I still got more data than I expected. I searched for HSPI and found one place that I had forgot to change it to SPI. I fixed that and now it is working. The code is also working without crashing.

SPI Write Hello World

Next I added the read function back into the main code to see what would happen. I saw only 4 bytes on the SPI bus. I had missed a value change I needed to make the SPI read 12 bytes.    It seems that either the DMA or an Interrupt routine is taking control of the SPI Hardware before i can finish a read. I disabled interrupts and it’s still only sending the command (3) and the address (0) plus 6 more clock cycles.

Incomplete SPI Read

Since SPI is used for loading code into internal RAM as well as running it directly from flash, it might be difficult to figure out when I can use it for the SPI  RAM.  I had the HSPI appearing to work in overlap mode.  Since I can switch between overlap and normal mode on the fly, maybe the HSPI in overlap mode is the best choice. In the writeRam() and readRam() functions, I changed the all references to SPI Registers to HSPI Registers and I commented out the code to save and restore the SPI Registers.  I used find and replace to simplify the changes.  I searched on (SPI) and filled in the replace with (HSPI) and then I selectively hit REPLACE/FIND for each instance.

Then I built and tested the code, hopefully back to where I was last week.  I got all zeros but I hadn’t done a write since I started working on it this time. So I put the writeRam() just before the readRam() in user_init() and tried again. On the logic analyzer, the write looks exactly like I would expect. The read is still not getting anything but zeros for the data section.  Next step is to look at the HOLD and WP lines on the SPI RAM. I had to look at the datasheet to see what state they needed to be in to work correctly.  Looking at the datasheet, there is no WP line, but there is a HOLD line.  If HOLD is low, the serial interface of the chip doesn’t work.  I clipped one more logic analyzer line on to Pin 7 of the SPI RAM.  The signal looks identical to MOSI.  I should have cut the trace when I was re-wiring this board but I missed it. I proceeded to cut it and add a jumper from the HOLD line to the ESP12E Pin 11. this is my best guess for the pins to use SQI. With Re-testing I got a successful read from the chip.

SPI Successful read

Next week, I need to verify the SPI working registers have the expected values from the ram.  I put the current version of the code up on GitHub.

How do you handle cutting in circuit changes?  Do you have any stories about a design change only to find it best to go back to the original plan?

Understanding HSPI Firmware V00H

What I wasn’t understanding last week is the definition of HSPI_CS.  It is the same as CS0 in the HSPI module.  So when I turn on overlap mode, of course, it maps to SPI_CS0.  That leaves me with setting the HSPI to use CS1(GPIO1/U0TXD) or CS2(GPIO0).  Since I use U0TXD for reprogramming the module, CS1 is unavailable.

I cut the trace going to U2 CS0 and added a jumper wire to GPIO0.  I then changed the code to use CS2 to enable the RAM.  This included setting the HSPI to use CS2 and setting GPIO0 MUX to be SPICS2.  And I got what looks like a successful write to the SPI RAM.

Successful SPI Write

The byte command (2) followed by 24bit address (0) followed by the data.  The first four bytes of data are “lleH”.  This is backwards to what I was planning, I can change it by setting a bit or changing the bytes I put into the registers. As long as I read them back the same way, it really doesn’t matter as long as I read and write aligned to 4 byte words.  The data is one byte short, I had a typo sending only 11 bytes of data.

Note: When data is aligned to 4 bytes, it means you need to read or write only on increments of 4 bytes.  So you would only Write or Read to/from addresses that in hexadecimal end in 0, 4, 8, or C. Since this chip is a 32 bit processor, this is required often.

I then decided to implement the hard coded read command.  I copied the write code, changed the command from 2 to to 3, set the HSPI to read back  and zeroed out the working registers so that I can see if they have been filled with the data I stored in the RAM. Then I commented out the writeRam() call in user_init and added readRam() in it’s place. Doing this without powering down, I should get the data back without having to write it again. I forgot to switch the length to the receive length register; I fixed this then I got back all zeros for the data.

Unsuccessful SPI read

I see the command (3) followed by the address (0) followed by 12 Bytes of data(0). So I have more debugging to do.  My first guess is the WP or HOLD lines of the chip are not doing what I need them to do.

I have gotten a better understanding of the SPI hardware on the ESP8266.  It looks to me that I can get the same control by just using the main SPI channel to control my RAM chip.  This needs testing.  I will need to save any registers I change and restore them when I am done accessing the RAM.  This will also have to be done from code that runs from internal RAM.

I have put the current state of the code on GitHub.  Use the link under the search box on the right side of this page.

Have you used chips with similar SPI configuration?  I like that I can have any bit length of data on the SPI bus, this will be useful for JTAG data. Have you worked directly with JTAG data?

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.