Particle-CLI OTA Electron flashing timed out

Hi,

I have a problem with OTA updates with Particle-CLI. I’m using Windows, the last CLI release 1.28.2 (it happened with 1.27.1 too). I installed it from the CLI setup.

This is the log when I try to update the device.

>> particle flash XXXXXXXXXXXXXXXXX "Code.bin"
Including:
    Code.bin

! Flashing firmware Over The Air (OTA) uses cellular data, which may cause you to incur usage charges.
! This flash is estimated to use at least 0.046 MB, but may use more depending on network conditions.

! Please type 0.046 below to confirm you wish to proceed with the OTA flash.
! Any other input will cancel.
? Confirm the amount of data usage in MB: 0.046
attempting to flash firmware to your device XXXXXXXXXXXXXXXXX 
Flash device failed.
Timed out.
Send firmware to your device
Usage: particle flash [options] [device|binary] [files...]

Global Options:
  -v, --verbose  Increases how much logging to display                                                                                                                                                                                [count]
  -q, --quiet    Decreases how much logging to display                                                                                                                                                                                [count]

Options:
  --cloud    Flash over the air to the device. Default if no other flag provided                                                                                                                                                    [boolean]
  --usb      Flash over USB using the DFU utility                                                                                                                                                                                   [boolean]
  --serial   Flash over a virtual serial port                                                                                                                                                                                       [boolean]
  --factory  Flash user application to the factory reset location. Only available for DFU                                                                                                                                           [boolean]
  --force    Flash even when binary does not pass pre-flash checks                                                                                                                                                                  [boolean]

Examples:
  particle flash red                          Compile the source code in the current directory in the cloud and flash to     device red
  particle flash green tinker                 Flash the default Tinker app to device green
  particle flash blue app.ino --target 0.6.3  Compile app.ino in the cloud using the 0.6.3 firmware and flash to device blue
  particle flash cyan firmware.bin            Flash the pre-compiled binary to device cyan
  particle flash --usb firmware.bin           Flash the binary over USB. The device needs to be in DFU mode
  particle flash --serial firmware.bin        Flash the binary over virtual serial port. The device needs to be in     listening mode

Sometimes, few seconds after the reply, I see the update with the console logs (spark/flash/status: started, etc), and sometimes it’s never shown.

Why is this happening? How can solve it?
Thank you

Your code currently running on the device may be interfering with the OTA update (can happeny especially when using SYSTEM_THREAD(ENABLED))

1 Like

It’s exactly the case.

I’m using SYSTEM_THREAD(ENABLED) but the code doesn’t represent a big % of CPU use. It only process events once a minute. How can I minimize this effects? Any tip about it?

Thank you

To answer that we’d need to see your code.

I’m sorry but I can’t share the project with the community (work-related) :frowning_face:.

If it helps, I can say that the system is event-oriented. I mean:

void loop()
{
	if (eventX())
	{
		processEventX();
	}
	
	if (eventY())
	{
		processEventY();
	}
}

The events are triggered at most once in a minute. That’s why I haven’t thought that could be a conflict with it.

Assuming that eventX() and eventY() are realy fast returning (< 1ms - if not the risk increases) but processEventX() and processEventY() are rather long running you may still run into the problem outlined above.

One workaround would be

void loop()
{
	uint32_t ms = millis();
	while(System.updatesPending() && millis() - ms < 120000) Particle.process();
   
	if (eventX())
	{
		processEventX();
	}
	
	if (eventY())
	{
		processEventY();
	}
}

This might still fail when the OTA update starts during processEventX() or processEventY() but should help in the other cases to keep your code from interfering while an update is being downloaded and applied (max. 2 minutes).

To have an option that also works in the edge cases, you could subscribe to the system event that indicates and OTA update and trap the code there.

Thank you @ScruffR. I always though that the updates had priority over the current code execution, so once the critical part started, the application-code stopped.

I’ll did a quick search of updatesPending and found some problems with it (https://github.com/particle-iot/firmware/issues/1285). Are they still active? (I’m working with electron 0.6.2/0.6.4).

About the system events, I found System.on(firmware_update_pending, function). I’m thinking to use it like this:

void setup()
{
	updatePending = false;
	System.disableUpdates();
	
	System.on(firmware_update_pending, updatePendingHandler)

    Particle.connect();
}

void loop()
{
	if (updatePending == true)
	{
		System.enableUpdates();
		
		uint32_t ms = millis();
            //Timeout needed?
		while(System.updatesPending() && millis() - ms < 120000){ Particle.process();}
		
		// Is this code ever reached? Force reset in case of error?
		System.disableUpdates();
		updatePending = false;
	}
	
	if (eventX())
	{
		processEventX();
	}
}

void updatePendingHandler()
{
	updatePending = true;
}

This way, I don’t really interfere with the application processes (and no changes need to be made), and also avoid the collision with the OTA process. What do you think?

Thank you very much!

Regarding the open issue, I don't think anything has been done since.

Yes but I doubt that's when your problem occures. Once the critical part has started application code will be stopped, but I think what you are seeing is that your code is still running prior the critical part (non-critical binary download and flash to intermediate memory) and hence impedes these parts from finishing successfully.

I also doubt that your event will fire while System.disableUpdates() is active, just the same way as System.updatesPending() doesn't report a pending update when updates are disabled.
AFAIK the latter depends on the former and hence what is true for one is also true for the other.

BTW, since your event handler relies on out-of-order execution it might be required to mark your updatePending flag as volatile.

All right. Then my approach is not valid. I'll try if your solution is enough to solve the problem (or at least in the majority of cases).

That makes sense. It might be what's happening. It's hard to get a whole picture of what is happening in the system.

Thank you for the tip :wink: