Firmware Tips and Tricks

“Spark flash” is fast, about 15-20 seconds as it’s all performed locally. “spark cloud flash” will take about the same time as the web IDE. Local compiles are only a few seconds, especially if it’s only the sketch that has changed

Times… After employing the great tutorial "How to video for compiling locally in Windows " I have been using the NetBeans IDE. This is very stable, and I NEVER want to go into command line modes.
In NetBeans, a full clean & build is about 20 seconds, and a small update build is 2 seconds. Loading is “automatic” from the IDE taking about 10 - 15 seconds; the dfu need information is embedded in the IDE setups.

Again I propose, why are we comfortable with using command line sequences when the integrated platforms make the tedious items so easy???

Great thanks… I’ll give Net Beans ago.

If I may ask. How did you configurate Netbeans to flash the core?:slight_smile:

This is a pretty neat step-by-step tutorial. Working nicely so far :slight_smile:

Thanks BDUB! Could it be that strlcpy function consumes a lot of Flash memory too? I’m having some problmes with it.

##Die, with the possibility of reincarnation##
Sometimes you want to create a “kill loop” which is just an infinite loop that terminates the execution of your program. However on the Spark Core this will cause your Core to not process the background tasks that allow it to talk to the Cloud, and also allow it to be reflashed OTA (Over The Air). To create a kill loop, that allows you to reprogram your core, you can just infinitely call the background tasks directly with code like this. Here we detect a failure connecting to our temperature sensor, and die… with the possibility of reincarnation :wink:

if (!bmp.begin()) {
  Serial.println("Could not find a valid BMP085 sensor, check wiring!");
  while(1) Spark.process(); // Die, with the possibility of reincarnation
}
3 Likes

If you do not want to wait for curl to time out after the Core goes to DFU mode, you can add -m 5to the curl command, which sets the timeout to (in this case) five seconds.

From the curl manual:

-m, --max-time {seconds}

Maximum time in seconds that you allow the whole operation to take. This is useful for preventing your batch jobs from hanging for hours due to slow networks or links going down. See also the --connect-timeout option.

If this option is used several times, the last one will be used.

1 Like

That’s a cool function. I added it to my commandline parser and can now flash the core without pressing the buttons. But what if I accindently start the DFU loader this way. Is there a way to reset to normal mode without really flashing? Some button tricks, timeouts or so.

I just managed to “brick” my core, it is now flashing blue. I have to look what that means. :slight_smile:

Flashing blue usually means the Core is in listening mode to accept WiFi credentials via USB serial.
I guess you always could do a factory reset.

This code will force the core to enter DFU mode but will not leave until a code is programmed via DFU-util.

Maybe I’ll check when I have time on how we can do it like a normal button pressed DFU mode that exits when the reset button is hit.

A little tip to speed up your TCP connections. the TCPclient print method is slow as it writes one character at a time to the cc3k and every now and then there is a big delay of a second or more… Changing to the write method prints an entire buffer at once. But how to change to the write you ask? easy with this little function

Create a function like this (assume you created the instance called client, using TCPClient client;)

void out(const char *s) {
client.write( (const uint8_t*)s, strlen(s) ); 
}

Now just change everywhere you used client.print("whatever"); to out("whatever");

Ahh but what about the client.println()? thats easy too just add \r\n like this out("whatever\r\n");

it also works well with variables too, i often have a buffer using sprintf, like this (also a handy thing to know when using an ip address)
sprintf(buf, "Host: %d.%d.%d.%d:%d\r\n", ip[0], ip[1], ip[2], ip[3], port); out(buf);

and if you want to print it on the serial port? just add the line serial.write( (const uint8_t*)s, strlen(s) ); to the out function.

3 Likes

@deancs I got the automatic dfu working, but I have to hit Ctrl-C to stop the curl command. This sounds reasonable, as the command doesn’t end up returning anything. Is this true for you as well? Do you have a method that automatically ends the process (I guess there are many where you can kill a process after x seconds)

Thanks!

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