Terminating main with one task running

Discussion about the ZBasic language including the System Library. If you're not sure where to post your message, do it here. However, do not make test posts here; that's the purpose of the Sandbox.
Post Reply
pjc30943
Posts: 220
Joined: 01 December 2005, 18:45 PM

Terminating main with one task running

Post by pjc30943 »

I'm measuring the execution time of a section of this task in two different ways. For now, ignore why I'm exiting a sub instead of letting it end naturally.

Method 1:

Code: Select all

sub main()
  ...
  calltask task, taskStack
  exit sub
  ...
end 
Method 2:

Code: Select all

sub main()
  ...
  task
  ...
end 
Method one will at first have multitasking, but then quickly will become the only code running. Method two will call the task as a subroutine, so there should be no task switching as it is all that runs.

With method one, that code section takes ~4ms (for unknown reasons, as it's just some lines of algebra).

With method two, that code section takes either 0.0 (i.e. <1.95ms) or 1.95ms, the task switching time.


Any thoughts on why different times are reported? Only task() is running both with both methods.

EDIT: I wrote "--thus it is also odd that execution time would be a multiple of task switch time", which is actually due to the Timer resolution; this statement is thus irrelevant.
mikep
Posts: 796
Joined: 24 September 2005, 15:54 PM

Re: Terminating main with one task running

Post by mikep »

pjc30943 wrote:I'm measuring the execution time of a section of this task in two different ways.
How are you measuring the time for a task? The timer() function as you surmised only has a resolution of 1.95ms. The normal way to measure performance with ZBasic is either to wrap the function in a loop of say 1000 iterations or to use a high resolution timer and setup the chip registers yourself. Some people also twiddle an I/O pin and use an oscilloscope or logic analyzer to measure the time.

I think you have to post more code. Only a little algebra taking 4 ms is suspicious. Perhaps we should start there with a simple loop and see how long the algebra routine really takes (after dividing by 1000).
Mike Perks
pjc30943
Posts: 220
Joined: 01 December 2005, 18:45 PM

Post by pjc30943 »

Yes, those results were from Timer().

There is also a scope observing the loop times:
With the task invoked, then main exited, the loop time is 95 Hz.
When the same routine is called in main, the loop time is 200 Hz.

In both cases the sub is the only thing running, yet there appears to still be some sort of task-switching going on, even though there's no multitasking.
I can see the waveform periodically pausing for 1.95ms as the scheduler takes command...
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Re: Terminating main with one task running

Post by dkinzer »

pjc30943 wrote:Method one will at first have multitasking, but then quickly will become the only code running.
Although this is a reasonble assumption, it is not actually true. The Main() task is special in several ways, not least because it is launched automatically. Another way in which it is special is that it never really terminates. Consider the code generated for an empty Main():

Code: Select all

0000 104001      LODSP          0x0140 &#40;320&#41;
0003 1b1100      PSHI_W         0x0011 &#40;17&#41;
0006 1b4001      PSHI_W         0x0140 &#40;320&#41;
0009 1b0000      PSHI_W         0x0000 &#40;0&#41;
000c fe4a        SCALL          TASK_START
000e 01fdff      BRA            000e

            Public Sub Main&#40;&#41;
            End Sub
0011 06          RET
Although both Main() and other ordinary task main routines end with a RET instruction, only the Main() task actually returns to the instruction immediately following the corresponding TASK_START instruction. When a non-Main() task returns, the fact that it is not the Main() task is detected and the task is removed from the task list.

If you want to free up most of the task time being "wasted" by Main(), modify your program thusly:

Code: Select all

Sub Main&#40;&#41;
  ...
  CallTask task, taskStack
  ...
  Do
    Call Sleep&#40;0&#41;
  Loop
End
- Don Kinzer
mikep
Posts: 796
Joined: 24 September 2005, 15:54 PM

Re: Terminating main with one task running

Post by mikep »

dkinzer wrote:
pjc30943 wrote:Method one will at first have multitasking, but then quickly will become the only code running.
Although this is a reasonable assumption, it is not actually true.
I had thought it worked this way too with the infinite loop being in the ZVM scheduler i.e. no runnable tasks so sleep until next timer tick or interrupt. Putting the code here would facilitate powering down the AVR when idle. Of course you would need a way to turn off the timer tick as well.
Mike Perks
pjc30943
Posts: 220
Joined: 01 December 2005, 18:45 PM

Post by pjc30943 »

It's still not completely clear to me what is going on inside the VM.

Consider the following example with one encoder, whose output pulses (pulse width varies with absolute position) are measured using waitForInterrupt.
This subroutine is an infinite loop of waitForInterrupt() used to watch for falling and rising edges. Sleep 0.0 is placed in each loop iteration.
On each edge transition, TMR5 values are stored, a pin is togged after the falling transition and again at the end of the loop, and some FP calculations are made.

The task is being called as a subroutine to ignore multitasking effects.

However even then there exists a delay of 2.03ms between the encoder's falling edge, and the first pin toggle placed immediately after the first WaitForInterrupt(falling) .

After that toggle--since the encoder pulse already went high due to the long delay when WFInt() triggered--the second rising WaitForInterrupt() immediately triggers, and so the loop completes in about 56us.
It is unclear why it takes 2ms to capture the falling edge, when there are no tasks running, and this loop is effectively in Main().
I would have thought the RTC doesn't play any role in this case; and the delay is not 1.95ms, but 2.03ms (though the difference could be overhead for executing the interrupt, and toggling the output pin).

Any thoughts?
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

pjc30943 wrote:It's still not completely clear to me what is going on inside the VM.
Any thoughts on how I might mock this up to observe the same phenomenon? It might work to use another ZX to produce a simulated encoder signal, triggering off of an output of the first ZX with a fixed or random delay.

If you could provide setup instructions and some minimal code that manifests the issue that would be quite helpful.
- Don Kinzer
pjc30943
Posts: 220
Joined: 01 December 2005, 18:45 PM

Post by pjc30943 »

dkinzer wrote:If you could provide setup instructions and some minimal code that manifests the issue that would be quite helpful.
I'll produce an example that is simple to set up, and that requires minimal code.
It's possible that while reducing the code I'll figure out what I've done wrong--but that's an equally desirable outcome of course...
Post Reply