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)
  • Updater-Tool 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 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 PROG-Tasters in den aktiven Zustand versetzt werden (wartet auf Anweisungen des Updaters).

Skizze Speicheraufbau

Der Updater auf Java-Basis ist ein Konsolenprogramm, welches auf dem PC gestartet wird. Der 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 keine Verbindung zum Updater
  • blinkt schnell (250ms an, 250ms aus): Bootloader hat Verbindung zum 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. Aber Achtung: um zum ersten Mal eine Firmware übertragen zu können, muss entweder der PROG-Taster gedrückt oder die UID des ARM mit dem Kommandozeilenparameter --uid angegeben werden!
  • aus dem laufenden Programm kann der Bootloader durch den Updater aktiviert werden (siehe "Bedienung des Updaters")
  • durch Abklemmen der Spannungsversorgung; beim Anklemmen muss der PROG Taster gedrückt sein (bis die PROG LED blinkt)

Bedienung des Updaters

Der Updater benötigt mindestens JAVA 17. JAVA kann u.a. hier heruntergeladen werden: 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
  • mit dem Befehl java -jar SB_updater-1.11-all.jar --help lässt sich die Hilfe anzeigen, bzw. alle möglichen und notwendigen Parameter werden dargestellt:

 

INFO: SelfFirmware-Updater 1.11

usage:  SB_updater-1.11-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|NORMAL|URGENT|LOW>] [--user <id>] [--user-pwd <password>] [--device-pwd <password>] [-u <uid>] [-f1] [-H <localhost>] [-P <localport>] [-p <port>] [-n] [-r] [-a <address>] [-h | -v]  [--delay <ms>] [--timeout] [-l <TRACE|DEBUG|INFO>] [--ERASEFLASH] [--DUMPFLASH <start> <end>] [-f0]
     
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|NORMAL|URGENT|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)
-r --routing use KNXnet/IP routing (not implemented)
-a --appVersionPtr <address> pointer address to APP_VERSION string in new firmware file
-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
  --timeout Enable transport layer 4 connection-oriented 6s timeout. Can be helpful with connection problems.
-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 immer eine Host IP Adresse des IP Gateways benötigt wird. Sobald der Standard Port 3671 verwendet werden soll, braucht dieser nicht mit angegeben werden.

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 eines ARM Prozessors. 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. Wie beim Schreiben der physikalischen Adresse per ETS ist es hier auch zwingend notwendig, dass nur ein Gerät am Bus sich in diesem Modus befindet. Die UID sollte man sich pro Gerät abspeichern für ein eventuelles Update der Firmware.

Der 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 er Parameter --full mit angegeben werden.

Die zu übertragende Datei wird mit dem Parameter --fileName angegeben.
Soll nur die UID des ARM herausgefunden werden, kann auch der Parameter -f0 angegeben werden, dann wird keine Firmware übertragen.

Ein kompletter Aufruf für ein bereits mit Firmware im Normalmodus laufendes Gerät lautet z.B.:

java -jar SB_updater-1.11-all.jar 192.168.178.3 --fileName Rauchmelder-bcu1_Release_0x3000.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 Updaters.

Erstellen von Programmen mit MCUXpresso für den Firmware-Updater

Wenn man versucht, ein "normal" übersetztes Programm per Firmware-Updater zu übertragen wird recht schnell scheitern.
Das PC Tool 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.

Dazu muss der Linker die entsprechende Einstellung haben:

Zuerst muss in die Einstellungen des entsprechenden Projektes gewechselt werden.
Dazu das Projekt im Projektexplorer anwählen und über Projekt -> Properties die Eigenschaften aufrufen

project properties

Anschließend die post-build steps suchen

post build steps

Ü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).

MCU start addresses

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 (LPC1114: 0x8000).
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) (Size beim LPC1114: 0x8000 - 0x3000 - 0x1000 = 0x4000)

Vorgehensweise

Die Vorgehensweise bei Verwendung des Firmware-Updaters für den Aufbau eines neuen Gerätes unterscheidet sich ein wenig von der herkömmlichen Vorgehensweise.
Daher möchte ich hier einmal die einzelnen Schritte aufführen

  1. Den Bootloader aus dem Selfbus-Releases Repository herunterladen. Dabei ist die benötigte Dateiendung davon abhängig, wie der Bootloader auf den ARM Prozessor übertragen werden soll:
    - Für die Übetragung mittels UART (siehe ARM Entwicklung - Getting Started) wird die .hex Version benötigt.

    - Falls ein JTAG-Programmer (LPC-Link o.ä.) zur Verfügung steht und MCUXpresso installiert ist, kann die .axf Datei mit dem GUI Flash Tool aus MCUXpresso heraus verwendet werden.
  2. Den Selfbus Updater aus dem Git herunterladen.
  3. Java herunterladen und installieren.
  4. Die entsprechende Software für den ARM Prozessor herunter laden oder mittels MCUXpresso compilieren (Achtung: Startadresse Flash und RAM verschieben!)
  5. Den Selfbus Firmware-Updater in einer Konsole oder Powershell mit entsprechenden Parametern aufrufen
  6. Warten...
  7. Freuen ;-)
       

Problemlösungen

Ich hatte das Problem, dass ich auf meiner Windows 10 Powershell keine farbigen Texte angezeigt bekam, sondern kryptische Zeichen.
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 in der Powershell farbig erscheinen