Wozu ein Firmware-Updater?
Um den Sinn und Zweck eines Firmware-Updaters zu erkennen, muss man zuerst verstanden haben, dass das "Programmieren" des "Applikationsprogramms" mittels ETS kein wirkliches Programmieren im herkömmlichen Sinne ist. Mittels ETS werden Konfigurationsdaten zu den KNX-Geräten gesendet, welche die Firmware (Software) sich entsprechend verhalten lassen.
Die Firmware auf dem KNX-Gerät lässt sich so nicht aktualisieren. Einige Hersteller haben ähnlich wie wir hier ein Updater-Programm, um über den KNX-Bus neue Firmware auf ihre Geräte zu übertragen. So macht es auch der Selfbus Firmware-Updater. Wenn eine neue Firmware mit neuen Funktionen, Bugfixes oder ähnlichem zur Verfügung steht, kann diese mithilfe des Firmware-Updaters auf das KNX-Gerät übertragen werden. Somit ist kein Ausbau der Controllerplatine, z.B. aus dem REG-Gehäuse oder kein Einsammeln der Rauchmelder, notwendig.
Funktionsweise
Der Firmware-Updater besteht aus 2 Teilen:
- Bootloader des KNX-Geräts auf dem Controller (ARM-Prozessor)
- Firmware-Updater auf Java-Basis (auf PC, Laptop, ...)
Der Bootloader bootet immer als erstes auf dem Controller und verwaltet dann die erste Funktionsweise. Ist noch keine Firmware auf dem Controller, verbleibt der Bootloader im (passiven) Bootloader-Modus. Sollte jedoch bereits vorher eine Firmware per Firmware-Updater übertragen worden sein, wird diese direkt gestartet.
Die folgende Grafik zeigt den Flash-Speicheraufbau eines LPC1115 mit Bootloader (Release-Version). Wenn eine gültige Firmware bei Adresse 0x3000 vorhanden ist, wird diese durch den Bootloader aufgerufen. Ist keine gültige Firmware vorhanden, bleibt der Bootloader "passiv" (LED blinkt) und kann durch Drücken des Programmier-Tasters in den aktiven Zustand versetzt werden (wartet auf Anweisungen des Firmware-Updaters).
Ab Bootloader Version v1.20 ist das zusätzliche Drücken des Programmier-Tasters nicht mehr notwendig. Der Bootloader befindet sich direkt im aktiven Zustand.
Der Firmware-Updater auf Java-Basis ist ein Konsolenprogramm, welches auf dem PC gestartet wird. Mit Version 1.20 des Firmware-Updaters gibt es nun auch eine grafische Benutzeroberfläche (GUI) (z.Zt. noch experimentell). Der Firmware-Updater prüft vor dem Senden der neuen Firmware, ob diese zur aktuell auf dem Gerät laufenden Firmware passt. Ein KNX-IP Interface oder Router mit Tunneling-Funktion sind die optimale Voraussetzung, um eine neue Firmware über den KNX Bus zu übertragen. Alternativ kann auch ein ft1.2 oder TPUART (allerdings mit niedrigerer Übertragungsgeschwindigkeit) verwendet werden.
Bedienung des Bootloaders auf dem Gerät / ARM
Der Bootloader hat 3 verschiedene Zustände, welche über die Programmier-LED angezeigt werden:
- blinkt langsam (1s an, 1s aus): Bootloader ist aktiv, hat aber aktuell keine Verbindung zum Firmware-Updater
- blinkt schnell (250ms an, 250ms aus): Bootloader hat Verbindung zum Firmware-Updater (Daten werden übertragen)
- blinkt langsam und wechselt zwischen hell und dunkel: Der Bootloader ist aktiv zusätzlich wurde der Programmiermodus über den PROG Taster gestartet
Den Bootloader kann man auf verschiedene Wege aktivieren:
- ohne Firmware ist der Bootloader immer nach dem Einschalten aktiv und signalisiert mit langsamem Blinken, dass er läuft.
Nur für Bootloader Versionen vor v1.20 gültig: Aber Achtung: um zum ersten Mal eine Firmware übertragen zu können, muss entweder der Programmier-Taster gedrückt oder die UID des ARM mit dem Kommandozeilenparameter --uid angegeben werden! - aus dem laufenden Programm kann der Bootloader durch den Firmware-Updater aktiviert werden (siehe "Bedienung des Firmware-Updaters")
- durch Abklemmen der Spannungsversorgung; beim Anklemmen muss der Programmier Taster ca. 1s gedrückt gehalten werden. Nach dem loslassen blinkt die Programmier-LED im 1s Takt
Bedienung des Firmware-Updaters
Der Firmware-Updater benötigt mindestens JAVA 17, welches u.a. hier heruntergeladen werden kann: https://jdk.java.net
- ein Powershell- oder ein Konsolenfenster öffnen (in Linux ein Terminal)
- eine Powershell lässt sich schnell durch die Eingabe von powershell in die Adresszeile des Dateiexplorers eingeben, dann entfällt das Navigieren in den richtigen Ordner
- die grafische Oberfläche (GUI) des Firmware-Updaters kann mit
java -jar SB_updater-1.20-all.jar
aufgerufen werden - mit dem Befehl
java -jar SB_updater-1.20-all.jar --help
lässt sich die Hilfe anzeigen, bzw. alle möglichen und notwendigen Parameter werden dargestellt:
INFO: Selfbus Firmware-Updater 1.20
usage: | SB_updater-1.20-all.jar <KNX Interface> [-f <filename>] [-m <tp1|rf> | -s <COM-port> | -t <COM-port>] [-d <x.x.x>] [-D <x.x.x>] [-o <x.x.x>] [--priority <SYSTEM|URGENT|NORMAL|LOW>] [-bs <256|512|1024>] [--user <id>] [--user-pwd <password>] [--device-pwd <password>] [-u <uid>] [-f1] [-H <localhost>] [-P <localport>] [-p <port>] [-t2] [-t1] [-n] [-r] [-h | -v] [--delay <ms>] [-l <TRACE|DEBUG|INFO>] [--ERASEFLASH] [--DUMPFLASH <start> <end>] [-f0] [--statistic] | |
Selfbus KNX-Firmware update tool options: | ||
-f | --fileName <filename> | Filename of hex file to program |
-m | --medium <tp1|rf> | KNX medium [tp1|rf] (default tp1) |
-s | --serial <COM-port> | use FT1.2 serial communication |
-t | --tpuart <COM-port> | use TPUART serial communication (experimental, needs serialcom or rxtx library in java.library.path |
-d | --device <x.x.x> | KNX device address in normal operating mode (default none) |
-D | --progDevice <x.x.x> | KNX device address in bootloader mode (default 15.15.192) |
-o | --own <x.x.x> | own physical KNX address (default 0.0.0) |
--priority <SYSTEM|URGENT|NORMAL|LOW> | KNX telegram priority (default LOW) | |
--user <id> | KNX IP Secure tunneling user identifier (1..127) (default 1) | |
--user-pwd <password> | KNX IP Secure tunneling user password (Commissioning password/Inbetriebnahmepasswort), quotation marks (") in password may not work | |
--device-pwd <password> | KNX IP Secure device authentication code (Authentication Code/Authentifizierungscode) quotation marks (") in password may not work | |
-u | --uid <uid> | send UID to unlock (default: request UID to unlock). Only the first 12 bytes of UID are used |
-f1 | --full | force full upload mode (disables differential mode) |
-H | --localhost <localhost> | local IP/host name |
-P | --localport <localport> | local UDP port (default system assigned) |
-p | --port <port> | UDP port on <KNX Interface> (default 3671) |
-n | --nat | enable Network Address Translation (NAT) |
-t2 | --tunnelingv2 | use KNXnet/IP tunneling v2 (TCP) (experimental) |
-t1 | --tunneling | use KNXnet/IP tunneling v1 (UDP) |
-r | --routing | use KNXnet/IP routing (not implemented) |
-bs | --blocksize <256|512|1024> | block size to program (default 1024 bytes) |
-h | --help | show this help message |
-v | --version | show tool/library version |
--delay <ms> | delay telegrams during data transmission to reduce bus load, valid 0-500ms, default 0 | |
-l | --logLevel <TRACE|DEBUG|INFO> | Logfile logging level [TRACE|DEBUG|INFO] (default DEBUG) |
--ERASEFLASH | USE WITH CAUTION! Erases the complete flash memory including the physical KNX address and all settings of the device. Only the bootloader is not deleted. | |
--DUMPFLASH <start> <end> | dump a flash range in intel(R) hex to the serial port of the MCU. Works only with DEBUG version of the bootloader. | |
-f0 | --NO_FLASH | for debugging use only, disable flashing firmware! |
--statistic | show more statistic data |
An dieser Ausgabe ist zu sehen, dass ohne GUI immer eine Host IP Adresse des IP Gateways oder COM-Port des ft1.2 bzw. TPUART benötigt wird. Sobald der Standard Port 3671 verwendet werden soll, braucht dieser nicht mit angegeben werden.
Die zu übertragende Datei wird mit dem Parameter --fileName angegeben.
Die Option --device wird nicht zwingend benötigt. Wenn das KNX-Gerät bereits ein Programm aktiv hat, kann durch die Angabe der physikalischen Adresse der Bootloader aktiviert und somit das Gerät neu programmiert werden.
Die UID des Controllers ist ein wichtiger Parameter. Diese UID ist die Identifikationsnummer des ARM Prozessors des Gerätes. Um zu verhindern, dass man das falsche Gerät aktualisiert, sollte man die --uid wenn möglich immer mit angeben. Die UID sollte man sich pro Gerät für ein eventuelles späteres Update der Firmware abspeichern (z.B. im Geräte-Kommentar der ETS beim entsprechendem Gerät) . Zum Auslesen der UID reicht die Angabe des Buszugangs (<KNX Interface>, --serial bzw. --tpuart). Ab Version 1.20 kann die UID auch über die grafische Oberfläche ausgelesen werden.
Nur relevant für Firmware-Updater vor Version 1.20: Ohne diese UID lässt sich ein Programm nicht ohne Eingriff am Gerät übertragen. Zum Auslesen der UID wird der Parameter --uid weggelassen. Dies bedingt aber einen aktiven Bootloader mit aktiviertem Programmiermodus. Zum auslesen der UID muss zusätzlich -f0 und ein vorhandenes .hex-File mittels --fileName angegeben werden.
Wie beim Schreiben der physikalischen Adresse per ETS ist es für den Firmware-Updater ebenso zwingend notwendig, dass nur ein Gerät am Bus sich im Bootloader Modus befindet bzw. in den Bootloader gestartet wird.
Der Firmware-Updater beherrscht ein differentielles Update (beta
), sodass nicht die gesamte Firmware wieder übertragen werden muss, wenn sich nur Teile dieser geändert haben. Das differentielle Update ist die Standardeinstellung. Wenn die gesamte Firmware übertragen werden soll, muss der Parameter --full mit angegeben werden.
Ein kompletter Aufruf für ein bereits mit Firmware im Normalmodus laufendes Gerät lautet z.B.:
java -jar SB_updater-1.20-all.jar 192.168.178.3 --fileName rauchmelder-bcu1_flashstart_0x3000_release_v3.00_libv2.10.hex --uid 31:30:00:0B:E9:14:BD:AE:9A:98:1B:77 --device 1.0.11 --full
Weitere Aufrufbespiele findet man in der README.md des Selfbus Firmware-Updaters.
Vorgehensweise bei neuem Gerät
Die Vorgehensweise bei Verwendung des Firmware-Updaters für den Aufbau eines neuen Gerätes unterscheidet sich ein wenig von der herkömmlichen Vorgehensweise:
- Den passenden Bootloader für die Übertragung mittels Flashmagic/UART (siehe ARM Entwicklung - Getting Started) herunterladen.
- Den Selfbus Firmware-Updater aus dem Git herunterladen.
- Java herunterladen und installieren.
- Die entsprechende Firmware für den ARM Prozessor herunter laden, oder mittels MCUXpresso selbst compilieren (Achtung: Flashstart build config verwenden oder Startadressen von Flash und RAM verschieben.)
- Den Selfbus Firmware-Updater in einer Konsole oder Powershell mit entsprechenden Parametern aufrufen
- Warten...
- Freuen ;-)
Problemlösungen
Ich hatte das Problem, dass auf Windows 10 keine farbigen Texte angezeigt wurden, sondern kryptische Zeichen (ansi escape codes der Farben).
Dieses Problem lässt sich folgendermaßen lösen:
- Aufrufen des Registry Editors: Windows Taste auf Tastatur drücken -> regedit eingeben
- in der linken Spalte "HKEY_CURRENT_USER" aufklappen
- "Console" auswählen
- im rechten Fenster den Eintrag "VirtualTerminalLevel" suchen und auf 1 setzen
- sollte der Eintrag "VirtualTerminalLevel" nicht vorhanden sein -> Rechtsklick -> Neu -> DWORD-Wert (32 Bit) -> Name: VirtualTerminalLevel -> Daten: 1
direkt im Anschluss an diese Einstellung sollten die Einträge im erneut geöffneten Powershell Fenster farbig erscheinen.
Erstellen von Programmen mit MCUXpresso für den Firmware-Updater
Wenn man versucht, ein "normal" übersetztes Programm per Firmware-Updater zu übertragen wird man recht schnell scheitern.
Der Firmware-Updater kontrolliert vor dem Übertragen, ob das Programm an der richtigen Speicheradresse beginnt.
Das kommt daher, dass der Bootloader im Speicherbereich 0x0000-0x3000 (bzw. 0x0000-0x7000 für die Debug Version des Bootloaders) installiert ist.
Man muss das Programm also so kompilieren und linken, dass es ab der Speicherstelle 0x3000 beginnt.
Dafür gibt es unser Linker-Script (memory.ldt), welches diese Änderungen automatisiert.
Für den "händischen" Weg müssen folgende Änderungen im MCUxpresso-Projekt vorgenommen werden:
Zuerst muss in die Einstellungen des entsprechenden Projektes gewechselt werden.
Dazu das Projekt im Projektexplorer anwählen und über Projekt -> Properties die Eigenschaften aufrufen
Für die post-build-steps gibt es ein von uns angepasstes post-build-steps.sh Script.
Alternativ müssen die post-build steps folgendermaßen angepasst werden:
Über den Button "Edit" kann man die Optionen verändern.
Sie müssen folgendermaßen lauten (oder zumindest beinhalten):
arm-none-eabi-size "${BuildArtifactFileName}"
arm-none-eabi-objcopy -O binary "${BuildArtifactFileName}" "${BuildArtifactFileBaseName}.bin"
arm-none-eabi-objcopy -O ihex "${BuildArtifactFileName}" "${BuildArtifactFileBaseName}.hex"
Anschließend müssen:
- die Startadresse des Flash zu 0x3000
- die Größe des Flash zu 0xc000
- die Startadresse des RAM zu 0x100000c0
- die Größe des RAM zu 0x1f40
geändert werden (siehe Abbildung).
Normalerweise steht bei Location 0x0000, da das Programm den ganzen Speicherplatz nutzen können soll.
Für den Bootloader müssen wir am Anfang 0x3000 Bytes Flash und 0xc0 Bytes RAM Platz lassen.
Bei der Size steht für den LPC1115 dort normalerweise 0x10000.
Um dem Linker klar zu machen, dass das Projekt in den verbleibenden Platz passen muss, sollte auch dieses angepasst werden.
Vom Gesamtplatz im LCP1115 von 0x10000 Bytes wird der Bootloaderplatz mit 0x3000 Bytes und der Platz für den Eeprom der BCU abgezogen (0x10000 - 0x3000 - 0x1000 = 0xC000)