Table of Contents
Looking at the guts
(click on a picture for fullscreen view)
The next step was to disassemble the thermostat itself and see what is actually powering it. Maybe there is way to read the flash chip without powering the device? So after disassembling the device, I immediately noticed a PIC microcontroller. In this case the PIC18F4550. Also I noticed a lot of testing points on the main board which is always nice to see. This makes my life a lot easier. What particularly raised my interest, were 5 test points/holes adjacent to the PIC microcontroller. Pulling up the datasheet and probing around the board with a multimeter, I noticed these were probe points for In Circuit Serial Programming i.e. ICSP. As the name implies, this is used to program the chip without lifting it off the board. So even after manufacturing, it is possible to upload new firmware to the chip, debug it and so on.
The PIC microcontroller has built-in flash memory where the program is stored so no (easy) way to read the flash without powering the controller. Keeping my hopes up, I built a high voltage ICSP using an Arduino and an external 12V power supply. I also soldered headers to the board to easily connect and disconnect wires. Using an existing Arduino ICSP sketch by Kirill Kulakov and verifying the workings of these sketches with the programming specification provided by Microchip (the manufacturer of PIC microcontrollers), I was able to succesfully put the chip in ‘programming mode’ and play around with some commands.
I verified everything was working by reading the configuration registers of the chip and got some valid responses. So far so good. In my mind I was almost close to dumping the firmware. I tried reading some addresses from the chip in the region where the program must be stored. The response was nothing but zeros. Could be just valid data right? Not every section of the chip has to contain data. So I wrote some quick code in the Arduino sketch to dump the whole flash memory over the serial console, and ran the code. And the response was… all zeros again. That was a bummer. Was my code wrong? No it wasn’t, because using the same code I was able to read the registers and get valid responses. Was the flash memory actually empty? No it wasn’t, because the device still worked fine and there were no other flash chips on the board so the program must be stored there. What was going wrong?