Equivalence of Delay and Delay_Microsecond

Hi,
I would like to understand whether the Delay and Delay_Microsecond functions are functionally equivalent, with the exception of course that the first specifies a millisecond delay, while the latter specifies a microsecond delay.

I can see that the former works off the SysTick_Handler interrupt and the latter works off the watchdog timer. So does this make a difference?
Obviously there is the maximum delay time difference, but using a 32-bit counter for a 1us tick means a maximum delay of approximately 59.65 s. So I wonder why there is even a Delay function (unless one wants to delay for up to approximately 16.5 hours(!) for the 1 ms delay function).

Background to my question is: I would like to use the SysTick_Handler for my own code, specifically moving the Timing_Decrement function to a different timer.

Thanks in advance.

Hey @bit_cyber!

I’ve been thinking about allowing user code to hook the systick interrupt, see https://github.com/spark/firmware/issues/399. If this is useful to you, please let us know and please outline your use case so we can help you implement it. With a hook, you don’t need to move the Timing_Decrement to a new handler - chaining the existing handler will work just fine!

Also, just a heads up that neither of those functions (Delay, Delay_Milliseconds) are part of the public API and they won’t be available to user code in the next release. There will be equivalent functions provided by our HAL layer.

1 Like

@mdma, chaining the systick handler to a user is begging for trouble IMO, especially in a FreeRTOS environment. I believe this kind of requirement could be handled at the local compilation level with some compiler directives. :smiley:

1 Like

I do agree, and it will need to be managed well. I’ve not implemented it since it’s also possible for the user to set up a timer to achieve the same. But always looking for use cases that might change our course!

2 Likes

@mdma,
Thanks for the reply.

So the background to my request is that I’d like to use the Quantam-Leaps QP state machine framework (www.state-machine.com) for my project. I’ve used it very successfully for my Arduino based projects.

On the ARM M3 Cortex platform, the framework uses the systick interrupt for scheduling purposes, at its own N ticks per second. Therefore I was thinking - and the reason for my question - to move all the existing spark core ā€œsystem codeā€ off this interrupt, just to make sure everything is separated. (There indeed may be no need for this separation because I think the QP framework could co-exist, but I wanted to make things simple, i.e., make sure I knew what was driving what…)

I realise there are various parts of the code using the Delay function - specifically some of the WLAN / CC3300 code. It wasn’t clear to me whether this Delay function was part of an underlying ā€œRTOSā€ type system or could be driven from the watchdog timer.

So your thoughts?

A further comment…

If there was a hook from the systick interrupt service routine, it might work.i.e., it would call the ā€œtickā€ function for the QP framework - QP::QF::TICK(). Of course this would be a 1 ms tick. However, the QP framework is the pseudo RTOS in this case.

And thus back to my thinking about the Delay vs. Delay_Milliseconds functions: I would move everything off the systick interrupt, i.e., to the watchdog timer; so the WLAN functionality, etc. Then I would drive everything which is in the Timing_Decrement() function from the RTOS state machine (LED display and button debounce). If that all make sense…

I don’t have my spark core with me right now - I’m travelling for work - but when I return, I can easily test out the possibility: I’ll put a call to QP::QF::TICK() into the SysTick_Handler() function to test things out.

@bit_cyber, this issue is really about the Core’s management of systick. The photon will give you a much better platform for QP as it could use a 1ms software timer (with callback) to drive the QP timebase. One thing I want to discuss with the Spark Team is the possibility of opening up a second user thread. One thread for setup()/loop() and another for a ā€œparallelā€ task.

Eventually the user code will run on a separate thread and the system on another thread. It’s certainly possible, but by no means simple. There’s lots of small but critical details that need working out, such as which thread does Spark.function() execute on? How are shared resources like the LED managed? Do variables need to be thread-safe since they can be set from both the user thread and read by the system thread? etc etc…

It’s interesting to note that i’d decided on active objects as the principle design to achieve threading separation of system and user code. And with a pre-emptive scheduler, they don’t need to be co-oprative so we can ensure responsiveness even with long blocking delays in one thread.

2 Likes

@mdma, having RTOS will both create challenges but also huge opportunities. I’m so glad you are on the Spark Team with other top Engineers! :stuck_out_tongue_winking_eye:

1 Like

@peekay123, Point taken in regard to the management of systick, but in my mind if QP is going to be the RTOS, then it should be driven off a hardware derived timer.
Also the QP framework does offer both vanilla (cooperative) and qk (preemptive) kernels. Certainly the latter would be best to run off a hardware timer.

@mdma, Have you considered the QP framework? It does enforce state-machine thinking, so a change in perspective, but I believe that on an embedded platform this is a definite benefit. (In a previous life I was a professional developer and now can see it would have been beneficial for some tasks to have used such a framework.)
Anyway, maybe something even that could be supported, rather than the absolutely must have to use.
If things go well with my experimentation, I’d be willing to contribute.

But - getting back to the my original question: do you think it will work to move tasks using the Delay() function, and therefore the systick interrupt, to the watchdog timer?

1 Like

@bit_cyber, I would say you won’t really know till you try it! As for using the preemptive QK kernel, it’s a possibility but WICED is designed around FreeRTOS and ThreadX. Running QP (cooperative) as a separate thread may be possible.

With the Core firmware totally open and with HAL you can try anything! :grinning:

You know, I’d not heard of it until you mentioned it! Although the principles and advantages of active objects are well documented (hence that being my chosen strategy to bring parallelism to the photon without all the pitfalls of traditional multithreading.)

We’ve also been looking at go-like channels as another high-level take on multithreading (which are hugely similar to active objects in some respects.) If you have any thoughts on the benefits of leveraging QP I’d love to hear them!

2 Likes

OK - so, I’ve done some further work… (Interspersed by work (the day job) and some holidays.) The system seems to be working pretty well, here are the details and some comments:

Things performed
The Delay function was replaced with the Delay_Microsecond function. Achieved via calling the Delay_Microsecond function within the Delay function, of course multiplying the delay time by 1000.
(The TimingDelay variable was also removed as part of this, as it’s no longer necessary to track the delay, as ā€˜clocked’ via the systick interrupt handler.)

A port of the QP framework - specifically QP/C++ Version 4.5.04, and that provided in one of the examples for the ARM CORTEX M3 (dpp-stm3210c-eval) - was used. STM3210C specific code was removed as it’s irrelevant, particularly given that the STM3210C is an evaluation board with an LCD, etc., etc.

A basic ā€œsupervisorā€ type active object was implemented to manage everything. The systick timing wasn’t changed, so it’s still every 1 ms. This means that the QP framework is tick’ed every 1 ms. Then there is a 1 ms user (QP) timer which checks on the network status.

The wlan specific code was moved from the main routine into the supervisor active object such that network connection is handled and then maintained.

I’m yet to move the button press handling from the Timing_Decrement routine. Based on what I’m thinking handling these this is best located in the supervisor active object.

Comments

  1. The spark core (or rather: particle core) performs the network connection fine and connects to the cloud.
  2. Currently I can’t put the particle core into listening mode - I’m sure there’s some minor issue here which I’ve missed. Although I can easily write new firmware (DFU mode) and then it connects to the wlan / cloud fine.

How to leverage the QP framework? (read: why QP?)
So a good question… Here’s my thinking:

  1. Relating to state machines, but maybe not the prime focus: A lot of programming problems exist because of lack of knowledge of what will happen in the future (the classic example is: ā€œHow many bytes to allocate in a buffer?ā€). A state machine clearly indicates what to do when.
    (And the particle core is powerful enough to require some form of realistic OS, nothing too complicated, but something that makes everything easy and possible.)

  2. The QP framework makes developing embedded code easy(!). (I’ve developed a GPS Disciplined Oscialltor on an Arduino, with an LCD and button UI, not to mention the GPS message handlers. Everything just works.)

  3. Active objects are a mechanism to provide for all of this. A good design pattern.

  4. The framework offers both co-operative and pre-emptive scheduling options built-in.

  5. The QP framework is freely available (GPL v2 licencing).

Of course preference for programming style is just that. But I’m a believer of state machines for embedded development, with the QP framework being readily available, quite well documented and it makes things easy.

Anyway, I’ll keep you posted of my adventures…

2 Likes