Flash issue with SYSTEM_THREAD(ENABLED)

Hi all,

I have some issues with flashing a Xenon with SYSTEM_THREAD(ENABLED).
It is not possible to flash when using SYSTEM_THREAD(ENABLED).
Only after entering safe mode I am able to flash the Xenon correctly.
Is there any trick I can do to flash my Xenon without entering safe-mode?
EDIT: not only Xenon. on Photon the same issue.

@aart, which DeviceOS version is on the Xenon? The flashing issue is more than likely caused by user code than threading.

I am running the latest os 0.9.0.
When I am running without SYSTEM_THREAD(ENABLED) flashing is working correctly.

My code:

#include "somelibrary"

SYSTEM_MODE(SEMI_AUTOMATIC);
SYSTEM_THREAD(ENABLED);

void threadFunction(void);

void setup() {
  // some setup stuff

  Thread thread("testThread", threadFunction);
  Particle.connect();
}

void loop() {
  // loop code here
}

void threadFunction(void) {
  while(true) {
    //some thread code here
    os_thread_yield();
  }
}

You could try looking for the system events and then allow for a reset. Does the software get flashed (LED flash magenta?).

Is it possible that your theadFunction() is not allowing the application thread to confirm the reset?

The following is what I use to disable OTA in the middle of running the application- you could modify this approach to check where the control is?

void handle_restart_events(system_event_t event, int data)
{
    if (event == reset)
    {
        isResetPending = false; 
    }
    else if (event == reset_pending)
    {
        System.enableReset();
    }
    else if (event == firmware_update && data == firmware_update_complete)
    {
        isResetPending = true;
    }
    else if (event == firmware_update && data == firmware_update_begin)
    {
        isOKtoSleep = false;
        statusMessage("Software Update In Progress");
    }
}

Hum, on a Photon I’ve got the same behavior.
After some testing, I found the problem.
It makes sense where you start the thread function.
In my first example, I started the tread at the end of the main setup.
In that case, everything works ok, but only flashing did not work.

Now I start the tread direct after the declaration and not in the setup. That makes sense!
Now I can flash the device normally.

My new code:

#include "somelibrary"

SYSTEM_MODE(SEMI_AUTOMATIC);
SYSTEM_THREAD(ENABLED);

void threadFunction(void);
Thread thread("testThread", threadFunction);  // <- HERE

void setup() {
  // some setup stuff
 // <- NOT HERE
  Particle.connect();
}

void loop() {
  // loop code here
}

void threadFunction(void) {
  while(true) {
    //some thread code here
    os_thread_yield();
  }
}

Maybe the issue was bigger than only flashing. I didn’t test any cloud function, but I wasn’t able to catch any system event with the System.on(all_events, handle_all_the_events); function.
In my opinion, this is kind of weird.
Maybe someone can explain this?

Your first example declared your Thread() as a local variable of the setup function. That means all storage for the Thread() instance was on the stack and corrupted as soon as you returned out of setup and did anything else. I’m honestly surprised you didn’t run into even more severe problems. Not worth much effort sorting out why OTA in particular failed. Maybe the system tries to check status on all threads when preparing for an OTA which references the corrupted memory and causes a fault?

Either way…

Starting your thread in global scope isn’t a great idea either. Global constructors happen in a non-deterministic order and before rest of the system initialization which can also cause all sorts of problems. Suggest either declaring a Thread pointer global and using new from setup (if you need a reference to your thread) or simply declaring it like before inside of setup() but adding the static keyword.

1 Like