Particle.connect() blocking main loop

Hi,
I’m using https://docs.particle.io/reference/firmware/photon/#manual-mode

SYSTEM_MODE(MANUAL);

but as soon as I call Particle.connect(), the main loop halts. The very same happens if the connection drops for some reason. The only way around this I’ve found for now is to turn off network before doing anything remotely time-critical. As far as I’ve understood - the purpose of manual-mode is to let the user control this. There must be a better way?

You won't be able to get absolutely no impact of the connection process, but with SYSTEM_THREAD(ENABLED) you should be able to reduce the impact.

Depending on what you mean by that

There are multiple avenues for different kinds of time criticality.
e.g. very short time critical tasks can be handled via interrupts. Another route would be using dedicated threads or Software Timers, ...

In my case - time critical means making sure the valve that lets Propane into the system isn’t held wide open and burning for 2 minutes while the P1 reconnects… In other words - this needs to have 100% attention at all times. I don’t mind if the network drops out, but if it halts other tasks while trying to reconnect, that could become severe…

Isn’t there a flag that says “don’t reconnect”?

If +/- 5 sec won’t make a lot of difference you might get that sorted with SYSTEM_THREAD(ENABLED) alone.

Otherwise - as already mentioned - you can always go for Software Timers and for even more critical tasks with timed interrupts via SparkIntervalTimer library.

Can you explain this further? Why, with SYSTEM_THREAD(ENABLED), would the application thread be possibly blocked for up to 5 seconds? I was under the impression that the two threads took alternating 1 ms time slices.

Critical blocks (especially bare metal tasks like the network stack) can be “marked as do not interrupt” and hence FreeRTOS shouldn’t pull the controller off the task to do something else.

You can easily test that behaviour with a rapid D7 blink in loop() and then fiddling with your AP.

+/-5 seconds is quite a lot when it comes to PID control, so I think I’ll just disable the Network on startup and buffer to the P1 SPI Flash for later upload.

Does anyone other than I think that a “Don’t automatically reconnect if connection is lost”-flag would be a good idea? It’s basically the automatic reconnection that possibly screws this up. In 99.9% of cases, the connection will probably be just fine. in the last 0.1% I just want to make sure I don’t start a fire…

The +/-5 sec was just a rough time frame - if you do some tests you might see the actual impact.

@jenschr, with careful coding (using integer math vs floating point), you could run your PID via a SparkIntervalTimer ISR, avoiding any problems with the system firmware vs user app blocking. I’ve never tried the scenario you are describing but it would be interesting to put a test app together to test Software Timers, loop() and SparkIntervalTimer for running critical code during wifi reconnection in manual, semi-automatic and automatic modes.

@peekay123 @ScruffR I’ll do an implementation based on “SparkIntervalTimer” and update this thread with the result. Technically - can I use I2C while inside in an ISR on STM32?

@jenschr, I wouldn’t do I2C in an ISR if possible. What are you doing via I2C?

Despite using a P1, I’m running out of pins so I had to put some inductive switches on an I2C-based I/O expander. If any of these are triggered, I should shut down the machine safely.

@jenschr, that is not ideal as the shutdown logic should be independent (of the P1) if safety is an issue. The biggest issue with using I2C in the ISR is if you are also using it in your loop() code. There is only a single I2C resource so the timer ISR could interrupt and I2C code in loop() causing havoc. Ideally, assuming you are using an MCP230xx I/O expander, you would have hooked up the the interrupt output of the MCP230xx to a pin on the P1. That would have allowed you to setup an interrupt on the pins you wanted to monitor.

1 Like

Curious why you say that SparkIntervalTImer are preferred over Software Timers for critical tasks. Any information would be helpful. Thanks!

All up to 10 Software Timers run on one FreeRTOS thread. So if one timer would behave selfish and hog the thread other timers might not get their time slice. Due to this the timing might also be off by several milliseconds.

SparkIntervalTimers are real interrupts and hence don’t need to rely on the well-behavedness of any other code. Also since the actuall timing is based on hardware timers, timing is much more precise and can also be controlled a lot finer than the aprox. 1ms time slice granularity of FreeRTOS.

2 Likes

Thanks, very clear. Appreciate it!

1 Like