Lock / UnlockTask()

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

Lock / UnlockTask()

Post by pjc30943 »

The following is an example whos behavior is not clear. A task is locked while acquiring a pulse via waitForInterrupt(); this locking is for debugging purposes only, as obviously the point is to allow the task to run briefly only on pulse edges.

PulseIn() (i.e. blocking code) works fine, but WaitForInt() gives variable results, even with the locks around the interrupts; I would have thought LockTask() gives the task all runtime until unlocked, yielding precise pulses.
Anyone have thoughts on why a variable count may arise?


Main() just calls two tasks.; the first is in question.

Code: Select all

main()
...
calltask Task1(), stackTask1
calltask Task2(false, true), stackTask2
do
  waitforSem(printsem)
  debug.print "ThTarget="; cstr(thighTargetAngle); ",THangle=";   cstr(thighAngle); ",standVPos="; cstr(standVPos); ",standAng="; cstr(standAngle)
  resetSem(printsem)
  sleep 0.2
loop

Task1 is as follows:

Code: Select all

public sub Task1()
...
  do
    locktask
    waitforinterrupt zxPinFallingEdge, WaitInt3
    timerStart = register.TCNT5
    waitforinterrupt zxPinRisingEdge, WaitInt3
    timerEnd = register.TCNT5 - timerstart
    unlocktask

    'pulsin is accurate:
    pulsein thighEncoder, 1-activestate(thighEncoder), thighEncoderPulse

    waitforSem(printsem)
    debug.print "ThighAngle/ticks in enc="; cstr(ThighAngle);"/";cstr(timerEnd);",pulse="; cstr(thighEncoderPulse)
    resetSem(printsem)
  loop
end sub
Some output, where timer counts vary, especially after printing (though they should be independent operations due to locktask() ). Note that there is some angle quadrant correction, so by chance an apparently relatively correct 48.56 deg results from erroneously large TMR5 counts.

ThTarget=6.582081, THangle=46.77373, standVPos=44.96813, standAng=39.82911
ThighAngle/ticks in enc=-54.38251/6552, pulse=7.302516E-04
ThighAngle/ticks in enc=50.79094/1287, pulse=7.248263E-04
ThighAngle/ticks in enc=52.53334/1323, pulse=7.183159E-04
ThighAngle/ticks in enc=50.88774/1289, pulse=7.118054E-04
ThighAngle/ticks in enc=52.48494/1322, pulse=7.074651E-04
ThTarget=14.83113, THangle=52.48494, standVPos=44.96813, standAng=37.29125
ThighAngle/ticks in enc=241.0034/12655, pulse=6.987846E-04
ThighAngle/ticks in enc=53.40454/1341, pulse=6.90104E-04
ThighAngle/ticks in enc=47.79013/1225, pulse=6.846787E-04
ThighAngle/ticks in enc=49.04853/1251, pulse=6.781683E-04
ThighAngle/ticks in enc=48.56455/8679, pulse=6.684027E-04
ThTarget=14.17367, THangle=48.56455, standVPos=44.96813, standAng=33.66576
ThighAngle/ticks in enc=561.7993/19283, pulse=6.510415E-04
ThighAngle/ticks in enc=45.51533/1178, pulse=6.347655E-04
ThighAngle/ticks in enc=43.24052/1131, pulse=6.217447E-04
ThighAngle/ticks in enc=43.38572/1134, pulse=6.10894E-04
ThighAngle/ticks in enc=40.82052/1081, pulse=5.95703E-04
Paul
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Re: Lock / UnlockTask()

Post by dkinzer »

pjc30943 wrote:I would have thought LockTask() gives the task all runtime until unlocked, yielding precise pulses.
Although not specifically cited in the documentation, invoking WaitForInterrupt() unlocks the calling task. Consequently, the code as written is ineffective. I believe that the following code will have the effect that you're seeking:

Code: Select all

waitforinterrupt zxPinFallingEdge, WaitInt3 
locktask 
timerStart = register.TCNT5 
waitforinterrupt zxPinRisingEdge, WaitInt3 
locktask 
timerEnd = register.TCNT5 - timerstart 
unlocktask 
The idea is that the first instruction following WaitForInterrupt() is guaranteed to be executed (referring to VM instructions, of course, not ZBasic instructions). It is important to note that a task lock is not a guarantee that the task won't be suspended. If another task is awaiting an interrupt or an interval expiration, that task may get control, in spite of the lock, if the awaited event occurs.

Native mode devices can utilize an Atomic Block or DisableInt() to prevent all interruptions. This capability may be available in a future VM release.
- Don Kinzer
pjc30943
Posts: 220
Joined: 01 December 2005, 18:45 PM

Post by pjc30943 »

Ah--thanks Don. That makes sense, then, with what is being observed.

Actually, in hindsight I recall a thread that describes WFI() unlocking a task, but did not notice it in the forum search results before posting.

Unfortunately the code output does not actually change from before, with the code changed as proposed; the same phenomena occurs.
The other task running does not have any interrupts or expirations, but is a loop with several sleep 0.0 scattered about, to allow the encoder sub to take control when required.
Post Reply