Upgrading The Things Uno RN2903 firmware

It turns out that it wasn’t only the range that might have been causing my connection problems to The Things Network – Andrew Sargent from OpenSensing spotted that in my logs the LoRaWAN RN2903 chip was reporting a firmware version 0.9.5 whereas the version needed to connect is 1.0.3

I’m on macOS, so ideally wanted to use my mac to upgrade the firmware. Here are the steps that I followed:

  • Download the Microchip Development Suite software and install just the Application: https://www.microchip.com/DevelopmentTools/ProductDetails/DV164140-2
  • Install Java8 to run it via Homebrew: $ brew cask install java8
    • You may also need to tap versions first if you haven’t already: $ brew tap caskroom/versions
  • Find that java8 installation (I also have a new version of Java I didn’t want to disrupt): $ /usr/libexec/java_home -v 1.8
  • Download the new RN2903 SA1.0.3 firmware (Hex) from: https://github.com/TheThingsNetwork/arduino-device-lib/files/1899025/RN2903.SA1.0.3.Hex.zip
  • Upload the PassThrough sketch using the Arduino IDE to The Things Uno so that we can talk directly to the RN2903:
  • File > Examples > TheThingsNetwork > PassThrough
  • Back in Terminal, cd into the directory with LoRaDevUtility.jar
  • Run the Microchip utility: $ /Library/Java/JavaVirtualMachines/jdk1.8.0_192.jdk/Contents/Home/bin/java -jar LoRaDevUtility.jar
  • Click ‘RN Module 0’ from the left.
  • Click the DFU tab.
  • Upload the new firmware.

Unfortunately clicking the ‘Select File:’ button causes a Java exception on the mac:

Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
	at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1774)
...
Caused by: java.lang.IllegalArgumentException: Folder parameter must be a valid folder
	at com.sun.glass.ui.CommonDialogs.convertFolder(CommonDialogs.java:238)
	at com.sun.glass.ui.CommonDialogs.showFileChooser(CommonDialogs.java:190)
	at com.sun.javafx.tk.quantum.QuantumToolkit.showFileChooser(QuantumToolkit.java:1496)
	at javafx.stage.FileChooser.showDialog(FileChooser.java:416)
	at javafx.stage.FileChooser.showOpenDialog(FileChooser.java:350)
	at fed.FEDFXMLController.onFileBrowse(FEDFXMLController.java:7049)
	... 83 more

Decompiling the .jar, I found this in DFUFXMLController.java

@FXML
  void onFileBrowse()
  {
    try {
      fileOpenDialog.setInitialDirectory(new File(Preferences.userNodeForPackage(getClass()).get("FilePath", "C:\\")));
      fileOpenDialog.getExtensionFilters().add(new javafx.stage.FileChooser.ExtensionFilter(".hex", new String[] { "*.hex" }));
      File fileChosen = fileOpenDialog.showOpenDialog(application.getViewer().getScene().getWindow());
      
      if (fileChosen != null) {
        selectedFile.setText(fileChosen.getName());
        if (application.device.updateValueFlag) {
          application.device.dfuPojo.setHexFileName(fileChosen.getAbsolutePath());
        }
        Preferences.userNodeForPackage(getClass()).put("FilePath", fileChosen.getAbsolutePath().substring(0, fileChosen.getAbsolutePath().indexOf(fileChosen.getName())));
      }
    } catch (IllegalArgumentException ex) {
      if (ex.getMessage().contains("Folder parameter must be a valid folder")) {
        fileOpenDialog.setInitialDirectory(new File("C:\\"));
        fileOpenDialog.getExtensionFilters().add(new javafx.stage.FileChooser.ExtensionFilter(".hex", new String[] { "*.hex" }));
        File fileChosen = fileOpenDialog.showOpenDialog(application.getViewer().getScene().getWindow());
        
        if (fileChosen != null) {
          selectedFile.setText(fileChosen.getName());
          if (application.device.updateValueFlag) {
            application.device.dfuPojo.setHexFileName(fileChosen.getAbsolutePath());
          }
          Preferences.userNodeForPackage(getClass()).put("FilePath", fileChosen.getAbsolutePath().substring(0, fileChosen.getAbsolutePath().indexOf(fileChosen.getName())));
        }
      }
    }
  }

So it looks like C:\\ is hardcoded as the default location, which appears to be why it’s failing unless there’s a default path set (which there isn’t on first run).

This was reported to Microchip in 2016 so is unlikely to be fixed anytime soon.

Leo found a solution for Linux by adding a default FilePath entry, so I used that to add a default entry for macOS:

  • Open a finder window: $ open ~/Library/Preferences/
  • Search for com.apple.java.util.prefs in the finder window.
  • Right-click to open com.apple.java.util.prefs.plist in Xcode
  • Create a ‘Dictionary’ entry for fed/ and dfu/
  • Add a ‘String’ entry for FilePath with the value /Users/<your username>/ under fed/ and dfu/
  • Save and close.
Adding default FilePath values for Java on macOS

Now you should be able to run the Microchip utility and select the firmware to upload: $ /Library/Java/JavaVirtualMachines/jdk1.8.0_192.jdk/Contents/Home/bin/java -jar LoRaDevUtility.jar

Don’t do what I did and select the unzipped folder, instead copy the file RN2903_Parser.production.unified.hex to the Desktop and select it from there.

If you did try and flash the folder and it failed and won’t connect anymore, fear not – you can select Module > Boot Load Recover. And select the other hex file: RN2903_Parser.production.hex to recover. 😊

Join the Conversation

3 Comments

Leave a comment

Your email address will not be published. Required fields are marked *