Best practise, every task should have 1 call to wait1Msec in it’s while loop. I usually use times of between 10mS and 25mS. Tasks that are controlling motors on ports 2 through 9 do not need to run any faster than 25mS, tasks controlling motors on port1 and port10 may benefit from the faster loop time.
Any blocking functions should also call wait1Msec. I’m always seeing this code (in some Robomatter examples
)
void waitForRelease()
{
while(nLCDButtons != 0){}
wait1Msec(5);
}
That’s a blocking function that is (IMHO) written incorrectly. It should be like this so it yields to other tasks.
void waitForRelease()
{
while(nLCDButtons != 0)
{
wait1Msec(5);
}
}
How long is a time slice?
Just about everyone runs their tasks at the default priority of 7. This means that, without calls to wait1Msec, a task will have exclusive use of the cpu until its time slice runs out. There is a little known system variable in ROBOTC called nOpcodesPerTimeslice, this tells us how many ROBOTC instuctions (an opcode is an instruction) will execute per time slice. When multiple equal priority tasks are running, each one gets an equal share of this amount of time. For example, if three tasks are running then each gets 333 opcodes worth of time. This does not necessarily mean each gets the same amount of absolute time (as in mS) as not all opcodes take the same amount of time to execute, for example, a complex math opcode (pow, exp etc.) will take a lot longer than a simple addition. An example,
#pragma config(Sensor, dgtl1, , sensorLEDtoVCC)
#pragma config(Sensor, dgtl2, , sensorLEDtoVCC)
#pragma config(Sensor, dgtl3, , sensorLEDtoVCC)
//*!!Code automatically generated by 'ROBOTC' configuration wizard !!*//
task otherTask2()
{
while(1) {
SensorValue dgtl3 ] = !SensorValue dgtl3 ];
}
}
task otherTask()
{
while(1) {
SensorValue dgtl2 ] = !SensorValue dgtl2 ];
}
}
task main()
{
startTask( otherTask );
startTask( otherTask2 );
while(1) {
SensorValue dgtl1 ] = !SensorValue dgtl1 ];
}
}
There tasks, all the same priority, all just toggling an LED. If we look at the assembly language for one of these tasks it would be like this.
task otherTask2()
{
while(1) {
0000: 4E012B00000AS00(slong) = (long) GetProperty(propertySensor, dgtl3:10)
0006: 4E012B04000AS04(slong) = (long) GetProperty(propertySensor, dgtl3:10)
000C: 24025500002B04000800TestAndBranchSLong(0(0x00000000) != S04(slong), L001C)
0016: CB000100S00(slong) = 1 // long/float
001A: 7905BranchNear(L0020)
001C: CB000000S00(slong) = 0 // long/float
0020: 57012B00000ASetProperty(propertySensor, dgtl3:10, S00(slong))
SensorValue dgtl3 ] = !SensorValue dgtl3 ];
0026: 79D9BranchNear(L0000) // Jump to end Expression
}
}
A bit complicated, but the point is that there are about 6 opcodes for each loop iteration. This means that the loop will run for approximately (333 / 6) 50 times before this task is swapped out and another run.
This is a very basic overview, it is in reality a bit more complicated, but you get the idea.