Ich würde gerne meine Honeywell Heizkörperregler HR-20 Rondostat zeitgesteuert nicht nur passiv auslesen (das geht auch schon mit der nativen Firmware), sondern auch über einen ESP8266 steuern. Das wurde schon von schlauen Leuten vorgedacht, und daher gibt es mit OpenHR20 auch eine neue Firmware, welche man mittels JTAG-Interface auf das HR20 flashen kann.
Ich habe nur kein JTAG-Programmierer zur Hand, aber dafür einen Arduino Uno. Ich habe den Ansatz eines JTAGduino gefunden. Die notwendigen Lötarbeiten waren schnell erledigt, ich habe die nachfolgende Steckerbelegung (Quelle) berücksichtigt, um den JTAGduino zu versorgen. Um eine durchgehende Stiftleiste am Arduino Uno verwenden zu können, habe ich die gesamte Kommunikation auf die Analogen Ports A0 bis A4 gelegt.
Die ersten Tests mit den von JTAGduino mitgelieferten Skripten verliefen erfolgreich, wenn ich das JTAG-Interface vom Arduino an den HR20 angeschlossen habe und mein Arduino an meinen Linux-Rechner per USB verbunden ist, kommt folgende Ausgabe:
user@host:~/work/JTAGduino$ ./host_test.py if_ver_major = 0; if_ver_minor = 1 fw_ver_major = 0; fw_ver_minor = 1 set_serial_speed(115200) = 0 clear pin TDI rsp = 1 set pin TDI rsp = 0 get pin TDO rsp = 0; val = 0 jtag_clock(1,1): rsp = 1; tdo = 0 jtag_clock(1,0): rsp = 0; tdo = 1 jtag_sequence([1,1,1,1], [1, 1, 0, 1]), rsp = 0; tdo_seq = [1, 0, 0, 0] jtag_sequence([1] * 255, [1] * 255), rsp = 0; tdo_seq = [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] device.set_jtag_speed(1) = 255 jtag_sequence([1] * 255, [1] * 255), rsp = 127; tdo_seq = [] user@host:~/work/JTAGduino$ ./readid.py Traceback (most recent call last): File "./readid.py", line 81, in if rsp != 0: raise Exception('error: set_jtag_speed returned %d' % rsp) Exception: error: set_jtag_speed returned 191 user@host:~/work/JTAGduino$ ./readid.py #Taps = 1 Device identifier registers (beginning from closest to TDO): 0x6940503F
Die Fehlermeldung habe ich absichtlich drin gelassen, damit man auch andere den Grund für den Fehler finden können. Man muss vor JEDEM Ansprechen des JTAGduino diesen manuell auf durch einen Druck auf den Reset-Button am Arduino zurücksetzen.
Die ID 0x6940503F
ist bereits die vom HR20, wir können also grundsätzlich per JTAG bereits mit ihm kommunizieren.
Als nächstes muss ich noch herausfinden, wie avrdude mit dem so gebauten „Programmer“ sprechen kann, bisher habe ich nur ermitteln können, dass es eine mögliche Liste von Programmern in avrdude vordefiniert gibt: (Der Pfad zur Arduino-Installation muss natürlich angepasst werden)
user@host:~/work/JTAGduino$ PATH=$PATH:/arduino-1.8.1/hardware/tools/avr/bin avrdude -c dslfkj -C /arduino-1.8.1/hardware/tools/avr/etc/avrdude.conf 2<&1 | grep -i jtag atmelice = Atmel-ICE (ARM/AVR) in JTAG mode (avrdude: jtag3_open_common(): JTAGICE3/EDBG port names must start with "usb") dragon_jtag = Atmel AVR Dragon in JTAG mode jtag1 = Atmel JTAG ICE (mkI) jtag1slow = Atmel JTAG ICE (mkI) jtag2 = Atmel JTAG ICE mkII jtag2avr32 = Atmel JTAG ICE mkII im AVR32 mode jtag2dw = Atmel JTAG ICE mkII in debugWire mode jtag2fast = Atmel JTAG ICE mkII jtag2isp = Atmel JTAG ICE mkII in ISP mode jtag2pdi = Atmel JTAG ICE mkII PDI mode jtag2slow = Atmel JTAG ICE mkII jtag3 = Atmel AVR JTAGICE3 in JTAG mode jtag3dw = Atmel AVR JTAGICE3 in debugWIRE mode jtag3isp = Atmel AVR JTAGICE3 in ISP mode jtag3pdi = Atmel AVR JTAGICE3 in PDI mode jtagkey = Amontec JTAGKey, JTAGKey-Tiny and JTAGKey2 jtagmkI = Atmel JTAG ICE (mkI) jtagmkII = Atmel JTAG ICE mkII jtagmkII_avr32 = Atmel JTAG ICE mkII im AVR32 mode o-link = O-Link, OpenJTAG from www.100ask.net (avrdude: Error: no libftdi or libusb support. Install libftdi1/libusb-1.0 or libftdi/libusb and run configure/make again.) xil = Xilinx JTAG cable (tested - avrdude: can't claim device "/dev/ttyACM0": Inappropriate ioctl for device) xplainedpro = Atmel AVR XplainedPro in JTAG mode
Den nachfolgenden Befehl nutze ich zum Test, ob der jeweilige Programmer-Typ funktioniert, er sollte bei erfolgreicher Kommunikation nur Backups von fuses anlegen, also führt noch keine schreibenden Operationen aus:
user@host:~/work/JTAGduino$ PATH=$PATH:/arduino-1.8.1/hardware/tools/avr/bin avrdude -p m169 -c xil -P /dev/ttyACM0 -C /arduino-1.8.1/hardware/tools/avr/etc/avrdude.conf -U lfuse:r:backup/unknown/`date "+%F_%T"`/lfuse.hex:h -U hfuse:r:backup/unknown/`date "+%F_%T"`/hfuse.hex:h -U efuse:r:backup/unknown/`date "+%F_%T"`/efuse.hex:h
So wie es aussieht, ist die Library nicht komplett, und für meinen Anwendungszweck vielleicht gar nicht geeignet. Ich bin dadurch über eine JTAG-Library gestoßen, welche man direkt über die Arduino-IDE nachinstallieren kann: https://github.com/mrjimenez/JTAG
Nach dem Upload des JTAGTest-Programms (wird als Beispiel in der ArduinoIDE bereitgestellt, wenn man die Bibliothek installiert hat) auf dem Arduino kann man das python-Programm „xsvf“ nutzen, um erste Tests durchzuführen:
user@host:~/work/JTAG/extras/python$ ./xsvf ../xsvf/all/idcode_simpler.xsvf File: /work/JTAG/extras/xsvf/all/idcode_simpler.xsvf Ready to send 18 bytes. Sent: 18 bytes, 0 remaining IMPORTANT: ******** IMPORTANT: Success! IMPORTANT: ******** IMPORTANT: Last TDO: FF FF FF FF/32 bits IMPORTANT: Processed 5 instructions. IMPORTANT: Checksum: 0xC2/18. IMPORTANT: Sum: 0x0000003E/18. Quit: No error (0). Expected checksum: 0xC2/18. Expected sum: 0x0000003E/18. Elapsed time: 0.02 seconds.
Mit der neuen JTAG-Library alle möglichen Programmiermodi des avrdude durchgegangen:
atmelice = Atmel-ICE (ARM/AVR) in JTAG mode (avrdude: jtag3_open_common(): JTAGICE3/EDBG port names must start with "usb") dragon_jtag = Atmel AVR Dragon in JTAG mode (no response) jtag1 = Atmel JTAG ICE (mkI) (avrdude: jtagmkI_open(): failed to synchronize to ICE) jtag1slow = Atmel JTAG ICE (mkI) (avrdude: jtagmkI_open(): failed to synchronize to ICE) jtag2 = Atmel JTAG ICE mkII (no response) jtag2avr32 = Atmel JTAG ICE mkII im AVR32 mode (avrdude: jtagmkII_recv_frame(): timeout avrdude: jtagmkII_getsync(): sign-on command: status -1) jtag2dw = Atmel JTAG ICE mkII in debugWire mode jtag2fast = Atmel JTAG ICE mkII jtag2isp = Atmel JTAG ICE mkII in ISP mode jtag2pdi = Atmel JTAG ICE mkII PDI mode jtag2slow = Atmel JTAG ICE mkII jtag3 = Atmel AVR JTAGICE3 in JTAG mode jtag3dw = Atmel AVR JTAGICE3 in debugWIRE mode jtag3isp = Atmel AVR JTAGICE3 in ISP mode jtag3pdi = Atmel AVR JTAGICE3 in PDI mode jtagkey = Amontec JTAGKey, JTAGKey-Tiny and JTAGKey2 jtagmkI = Atmel JTAG ICE (mkI) jtagmkII = Atmel JTAG ICE mkII jtagmkII_avr32 = Atmel JTAG ICE mkII im AVR32 mode o-link = O-Link, OpenJTAG from www.100ask.net (avrdude: Error: no libftdi or libusb support. Install libftdi1/libusb-1.0 or libftdi/libusb and run configure/make again.) xil = Xilinx JTAG cable (avrdude: can't claim device "/dev/ttyACM0": Inappropriate ioctl for device) xplainedpro = Atmel AVR XplainedPro in JTAG mode (avrdude: jtag3_open_common(): JTAGICE3/EDBG port names must start with "usb")