Now that we have sorted the rpm capture code, I decided to move the capture and math to a separate task and just populate a global variable for use by the main task as and when required. However it did not work as I expected so I need to clarify some thinking on this:-
I've been looking through the documentation to find backup to things i think i read elsehwere.
1) does any task have to specifically yield the cpu back to other tasks or in the normal course of events is this not required programmatically ? i seem to recall sleep (0) has this affect or is this not the case and should yield be used if required instead.
2) does inputcapture affect the multi-tasking in any unexpected way
3) is this block valid to read a global variable whilst ensuring its not being written to (I saw this code elsewhere but can't the relevant docmentation)?
Atomic
in_RPM=RPM
End Atomic
as ever, thanks for your time
Multi-tasking - yielding to other tasks
Re: Multi-tasking - yielding to other tasks
No. The ZBasic "operating system" implements a preemptive strategy. This means that the CPU time gets shared "fairly" among the set of existing tasks in that the next ready-to-run task is activated on each RTC tick. That said, a task can override this behavior in two ways. Firstly, a task can lock itself thereby preventing an RTC tick from switching tasks. Secondly, if a task has nothing useful to do it can relinquish the rest of its time slice to the next task by calling Yield() or Sleep(0). In this case, if no other task is ready to run the current task continues.FFMan wrote:does any task have to specifically yield the cpu back to other tasks
That would depend upon what one expects. The documented behavior is that the calling task is suspended until 1) the specified number of input segments is seen, 2) the specified timeout value is reached, or 3) another task invokes ResumeTask() to cause the waiting task to resume.FFMan wrote:does inputcapture affect the multi-tasking in any unexpected way
Yes. It is unnecessary to take such precautions, however, unless the variable might be read (if this task writes) or written (if this task reads) by another task or an ISR. Even then, it is not necessary to do so for single-byte variables (Byte, Boolean) unless you are performing a read-modify-write operation. See Executing Blocks of Code Atomically.FFMan wrote:is this block valid to read a global variable whilst ensuring its not being written to
Additional special precautions must be taken for native mode applications for any variable that is read by one task and written by another task or ISR. The issue is that the back end compiler can't know that the variable might be modified outside the scope of the function it is optimizing. Lacking any direction to the contrary, the compiler assumes that it is sufficient to read a variable from memory only once and thereafter keep the value in registers unless that variable is also modified in that same function. This can lead to code that loops waiting on a variable to change but it never sees the change made by another task or ISR.
The solution to this problem is to add the Volatile attribute to such a variable. This puts the compiler on notice that the variable might be modified by code outside of the current function. Consequently, the compiler will generate code to read the variable from memory every time it needs its value. This is discussed in [url=http://www.zbasic.net/doc/ZBasicRef.php?page=127][Attributes for Procedures and Variables[/i].
- Don Kinzer
See also the following application note: AN210 - Sharing Data Between Tasks which describes the basic techniques for sharing data. It does not include the Atomic option described by Don which tends to be more advanced. From your description a simple semaphore will do the job.
Mike Perks