Firmware Tips and Tricks

Getting out of DFU mode without manual resetting of overwriting the current firmware

NOTE: Tested with a Photon.

As specified in an old post titled [Getting out of DFU mode], and in the Photon documentation, the only ways to get out of the DFU mode are by manually reseting the Photon of by writing a firmware with the :leave option.

The trick here is to use the dfu-util writing a 0 byte firmware with the :leave option to force the reboot that gets out the Photon from the DFU mode, preserving the current firmware and keys configuration.

For the Photon:

$ dfu-util -d 2b04:d006 -a 0 -s 0x080A0000:leave -D /dev/null

For the Core:

$ dfu-util -d 1d50:607f -a 0 -s 0x08005000:leave -D /dev/null

The addresses specified are the respective userFirmware addresses of the Photon and Core, which firmwares are actually not overwritten.


On the other side we can add a function to our firmware to enter in DFU mode by code (without pressing any Reset+Setup button combination). The advantage is that we won’t need to leave access to the physical buttons to enter in DFU mode (remotely), then write custom data by USB to the internal or external memory using several calls to dfu-util without the :leave parameter, and finally force a reboot to get out of the DFU mode (using this trick).

// Force enter in DFU mode
int enterDFU(String param) {
    System.dfu();
    return 0;
}

or forcing a persistent DFU mode that will remain after a power-cycle, and only would get out by using the :leave option:

// Force enter in persistent DFU mode
int enterPersistentDFU(String param) {
    System.dfu(true);
    return 0;
}

This option could also be added in future releases of particle-cli, if you consider it of enough interest.

2 Likes

On OSX/Linux, If you have 0.4.2 firmware you can also enter DFU mode automatically using the makefile target program-dfu after setting SPARK_SERIAL_DEV to the serial device of the Photon. Details here.

This functionality will eventually be part of Particle Dev so firmware can be flashed locally to the device without touching it.

1 Like

I already red about that automatically way to enter in DFU mode, but that parameter looks like operating system dependent to me, isn’t it?

If I understand well the documentation, to make it work propertly in a GNU/Linux you should probably set
PARTICLE_SERIAL_DEV=/dev/ttyACM0

while in OSX you should set:
PARTICLE_SERIAL_DEV=/dev/tty.usbmodem12345

Is this correct?

Is there a generic way to set this variable to make it auto enter in DFU mode in any OS and not host-dependent?

There’s no generic way since the system needs to know the USB device to change the line rate of. If all OSs handled this in the same way then it would be generic.

But not being generic shouldn’t be a hindrance - the setting is a one-off setting that you add once to your environment and then forget out.

1 Like

@mdma Works great!! when using with the make and program-dfu option… but, by default the PARTICLE_SERIAL_DEV auto-DFU option will not work with the particle-cli utility :disappointed:

For me it would be great if the particle keys server (and in general the particle-cli) will auto enter in DFU mode, in this case to set the local Cloud public key and its IP address… and finally reboot (with :leave option).

First, I started trying the particle-cli, and it doesn’t support the auto-DFU mode using the PARTICLE_SERIAL_DEV variable:

$ particle keys server default_key.pub.pem 192.168.1.1
running dfu-util -l
Apparently I didnt find a DFU device? util said  dfu-util 0.7
 
Copyright 2005-2008 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2012 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to dfu-util@lists.gnumonks.org
 
 
Make sure your device is in DFU mode (blinking yellow), and is connected to your computer
Error - no dfu device found.

But then, I saw in the module.mk file of the 0.4.3 firmware that setting the Photon dev file with stty does the trick of entering in DFU mode, before calling to dfu-util:

...
program-dfu: $(TARGET_BASE).dfu
ifdef START_DFU_FLASHER_SERIAL_SPEED
# PARTICLE_SERIAL_DEV should be set something like /dev/tty.usbxxxx and exported
#ifndef PARTICLE_SERIAL_DEV
ifeq ("$(wildcard $(PARTICLE_SERIAL_DEV))","")
	@echo Serial device PARTICLE_SERIAL_DEV : $(PARTICLE_SERIAL_DEV) not available
else
	@echo Entering dfu bootloader mode:
	stty -f $(PARTICLE_SERIAL_DEV) $(START_DFU_FLASHER_SERIAL_SPEED)
	sleep 1
endif
endif
	@echo Flashing using dfu:
	$(DFU) -d $(USBD_VID_SPARK):$(USBD_PID_DFU) -a 0 -s $(PLATFORM_DFU)$(if $(PLATFORM_DFU_LEAVE),:leave) -D $<
...

So, finally the following 3 commands solved my problem of: Entering DFU -> use particle-cli DFU operation -> Exit DFU:

$ stty -f $PARTICLE_SERIAL_DEV 14400
$ particle keys server default_key.pub.pem 192.168.1.1
$ dfu-util -d 2b04:d006 -a 0 -s 0x080A0000:leave -D /dev/null

As shown, these 3 commands auto-updates the cloud public key and IP address without physically interacting with any Reset or Setup buttons but only using the USB port.

The same trick can be used to update/load/save, etc. any key, firmware or parameter that needs to be done in DFU mode using the particle-cli, without using any buttons.

EDIT: This was tested using a Photon on Mac OS X. In GNU/Linux stty -F /dev/ttyACM0 14400 doesn’t work, so I don’t really know how to force the auto-DFU mode in GNU/Linux or in Windows.

1 Like

Hi again @mdma

Do you know any way to make the stty -F command to put the Photon in DFU mode in GNU/Linux?

I could only make it work in Mac OSX with stty -f, but not way in GNU/Linux :disappointed_relieved:

It’s the line rate for the serial device - setting that to 14400 causes the system firmware to reset and enter DFU mode.

I don’t know off the top of my head how to do that using GNU linux. This Stack Exchange question seems to have it solved.

1 Like

@mdma Finally I have discovered where the problem was!! :facepunch:

This behaviour seems to be particular to some versions of Ubuntu. I’m testing it with the 14.04.2 LTS version, and it also seems to be present in the 12.04 version.

It’s not due to a permission problem writing the ttyACM0 device, nor due to a userserial module problem (that one guy commented in the StackOverflow post you have linked, using modprobe -r usbserial and then modprobe usbserial).

The problem is that in some Ubuntu versions, the 14400 baudrate is NOT supported as an standard port speed. The stty command fails at that speed, but not in many others like 9600, 19200, 38400, 115200, etc.

Let’s see. The port is by default configured at 115200, nothing special here:

$ stty -F /dev/ttyACM0
speed 115200 baud; line = 0;
kill = ^H; eof = ^A; min = 1; time = 0;
-icrnl -imaxbel
-opost -onlcr
-isig -icanon -iexten -echo -echoe -echok -echoctl -echoke

Setting it to 14400 fails!!, as it would fail when setting at any non standard baudrate:

$ stty -F /dev/ttyACM0 14400
stty: invalid argument ‘14400’
Try 'stty --help' for more information.

$ stty -F /dev/ttyACM0 56000
stty: invalid argument ‘56000’
Try 'stty --help' for more information.

But setting it to other rates doesn’t fail:

$ stty -F /dev/ttyACM0 9600
$ stty -F /dev/ttyACM0 
speed 9600 baud; line = 0;
kill = ^H; eof = ^A; min = 1; time = 0;
-icrnl -imaxbel
-opost -onlcr
-isig -icanon -iexten -echo -echoe -echok -echoctl -echoke

$ stty -F /dev/ttyACM0 19200
$ stty -F /dev/ttyACM0 
speed 19200 baud; line = 0;
kill = ^H; eof = ^A; min = 1; time = 0;
-icrnl -imaxbel
-opost -onlcr
-isig -icanon -iexten -echo -echoe -echok -echoctl -echoke

$ stty -F /dev/ttyACM0 38400
$ stty -F /dev/ttyACM0 
speed 38400 baud; line = 0;
kill = ^H; eof = ^A; min = 1; time = 0;
-icrnl -imaxbel
-opost -onlcr
-isig -icanon -iexten -echo -echoe -echok -echoctl -echoke

After this, I found out that you have a constant variable START_DFU_FLASHER_SERIAL_SPEED=14400 defined in build/module.mk file, related exactly to this behavious of auto DFU. And after changing it to 19200 (for example) the problem is solved!!!.

Now, when calling stty from both GNU/Linux and Mac OSX with 19200 baudrate, it puts the Photon in DFU mode automatically!!.

Summarising, to auto enter and exit DFU mode with the Photon without touching any button:

Mac OSX:

$ stty -f /dev/tty.usbmodemXXXXX 19200
$ dfu-util -d 2b04:d006 -a 0 -s 0x080A0000:leave -D /dev/null

GNU/Linux:

$ stty -F /dev/ttyACM0 19200
$ dfu-util -d 2b04:d006 -a 0 -s 0x080A0000:leave -D /dev/null

NOTE: The 28800 baud rate to enter in Ymodem mode is also not supported in Ubuntu, but yes in OSX, so the same should be made in the build/module.mk file with the START_YMODEM_FLASHER_SERIAL_SPEED=28800 in order to make it work in Ubuntu using stty.

$ stty -F /dev/ttyACM0 28800
stty: invalid argument ‘28800’
Try 'stty --help' for more information.

@mdma I don’t really know the possible side effects of changing the START_DFU_FLASHER_SERIAL_SPEED to 19200, or the START_YMODEM_FLASHER_SERIAL_SPEED to any other rate. Could you clarify if this has any side effect or if this values are just chosen to detect the baudrate changing from 115200 to these fixed values to force entering in the corresponding mode?

As always, thank you very much for your support!! :+1::+1::+1:

2 Likes

Wow, that’s some great research there! Congratulations on chasing down that bug! :smiley:

We chose 14400 and 28800 as the baudrate specifically because they were uncommon, and so unlikely to conflict with the baudrate that the application might wish to use.

There’s no consequence from changing the value other than a possible collision with the application baudrate. As we’re discussing this, I’m thinking that the system should allow the value to be configurable, rather than it being hard-coded. I’ll add that to our backlog!

2 Likes

@mdma @jrodas Found a way to automatically complete the port number for the stty command, and added these aliases to my ~/.bash_profile in Mac OSX as:

alias dfu='x="stty -f ";y=`compgen -f -- "/dev/tty.usbmodem"`;z=" 14400";eval $($x$y$z)'
alias dfuq="dfu-util -d 2b04:d006 -a 0 -s 0x080A0000:leave -D /dev/null"
2 Likes

Really great idea @BDub

This can even be improved by detecting if the USB device is connected or not:

OSX:

$ alias dfu='x=`compgen -f -- "/dev/tty.usbmodem"`;if [ -z "$x" ]; then echo "No USB device found"; else eval $(stty -f $x 14400); fi'
$ alias dfuq="dfu-util -d 2b04:d006 -a 0 -s 0x080A0000:leave -D /dev/null"

GNU/Linux:

$ alias dfu='x=`compgen -f -- "/dev/ttyACM"`;if [ -z "$x" ]; then echo "No USB device found"; else eval $(stty -F $x 14400); fi'
$ alias dfuq="dfu-util -d 2b04:d006 -a 0 -s 0x080A0000:leave -D /dev/null"

NOTE: Remember that the 14400 baud rate fails in some Ubuntu GNU/Linux distributions as I explained here. The module.mk file has to be modified accordingly and the firmware rebuilt to make it work in Ubuntu, and the baud rate changed in the previous dfu alias definition.

2 Likes

Nice @jrodas! Thanks for the simplification as well :wink: I was having some trouble with that putting the literal parts in quotes… didn’t think to try it without quotes!

2 posts were split to a new topic: How to Auto DFU on Windows

Hey I’m trying to get the PARTICLE_SERIAL_DEV setting working, so I can put the Photon in DFU mode without touching it. I’m on Ubuntu 14.04 LTS and it seems stty -F /dev/ttyACM0 14400 does not work for me either. I was originally getting these errors when running sudo make all PARTICLE_SERIAL_DEV=/dev/ttyACM0 PLATFORM=photon program-dfu:

Entering dfu bootloader mode:
stty -F /dev/ttyACM0 14400
stty: invalid argument ‘14400’
Try 'stty --help' for more information.

make[1]: *** [program-dfu] Error 1
make[1]: Leaving directory `/home/brian/Documents/photon-firmware/modules/photon/user-part'
make: *** [modules/photon/user-part] Error 2

I tried doing the things @jrodas outlined here:

  • Changed START_DFU_FLASHER_SERIAL_SPEED to 19200 in build/module-defaults.mk

  • Changed stty -f $(PARTICLE_SERIAL_DEV) $(START_DFU_FLASHER_SERIAL_SPEED) to stty -F $(PARTICLE_SERIAL_DEV) $(START_DFU_FLASHER_SERIAL_SPEED) in build/module.mk

This seems to have helped, but I still cannot upload new firmware without manually putting the Photon into DFU mode. The new output is:

Entering dfu bootloader mode:
stty -F /dev/ttyACM0 19200
sleep 1
Flashing using dfu:
dfu-util -d 0x2B04:0xD006 -a 0 -s 0x80A0000:leave -D ../../../build/target/user-part/platform-6-m/user-part.dfu
dfu-util 0.9

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2016 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

dfu-util: No DFU capable USB device available
make[1]: *** [program-dfu] Error 74
make[1]: Leaving directory `/home/brian/Documents/photon-firmware/modules/photon/user-part'
make: *** [modules/photon/user-part] Error 2

What’s the recommended way of getting this to work?

I feel embarrassed that I can't figure this out, but is there a library other than "application.h" that I need to include.
Compiling throws errors that 'FLASH_OTA_Update_SysFlag', 'BKP_DR10', and 'BKP_WriteBackupRegister' were not declared in this scope.

First:

  • How are you building?
  • What platform are you targeting?
  • What system version are you targeting?
  • How does the rest of your code look?

And then Spark.function() is deprecated. You should now use Particle.function().

Hey @ScruffR;
I actually got it figured out. Totally missed the “System.dfu();” function that has since been added to the firmware.
All good now.