Module 10Módulo 10

Cooperative MultitaskingMultitarea cooperativa

Many tasks, one CPU, no operating system. Each task does a little and steps aside. Muchas tareas, una CPU, sin sistema operativo. Cada tarea hace un poco y cede el paso.

Santi Scagliusi, PhD

The superloopEl superbucle

No OS. Just one loop in main that calls each task in turn, forever.Sin SO. Un solo bucle en main que llama a cada tarea por turno, para siempre.

taskA
taskB
taskC
foreverpara siempre
The contract: every task returns quickly. El contrato: cada tarea retorna rápido.
In exchange: the next task runs almost immediately. A cambio: la siguiente tarea corre casi de inmediato.

The whole module is about honoring that one contract. Todo el módulo trata de honrar ese único contrato.

A delay loop starves everyoneUn bucle de retardo deja sin CPU a todos

One task spins in a wait loop. The CPU is busy, so no other task runs.Una tarea gira en un bucle de espera. La CPU está ocupada, así que ninguna otra tarea corre.

taskA
delay mov.w #50000, r5
wait dec.w r5
jnz wait
ret
; ~50000 iterations of doing nothing; ~50000 vueltas sin hacer nada
taskA spins in delaytaskA gira en delay
B
C

B and C wait the whole delay before they get a turn. B y C esperan todo el retardo antes de tener turno.

A task is a finite state machineUna tarea es una máquina de estados finitos

Instead of waiting inside the task, the task remembers a state and returns.En vez de esperar dentro de la tarea, la tarea recuerda un estado y retorna.

ON LED onLED encendido
period elapsedpasó el periodo
period elapsedpasó el periodo
OFF LED offLED apagado

Each call checks the trigger, maybe changes state, then returns. No spinning. Cada llamada comprueba el disparo, quizás cambia de estado, y retorna. Sin girar.

The two-state blinker, in assemblyEl parpadeo de dos estados, en ensamblador

The state lives in a variable. A jump table picks the code for the current state.El estado vive en una variable. Una tabla de saltos elige el código del estado actual.

blink
blink mov.b &state, r14
br tabEst(r14)
sOn bic.b #BIT0, &P1OUT
mov.b #OFF, &state
ret
sOff bis.b #BIT0, &P1OUT
mov.b #ON, &state
ret
state codes and tablecódigos de estado y tabla
ON .equ 0*2
OFF .equ 1*2
tabEst .word sOn
.word sOff
State × 2 indexes a word table of handler addresses.Estado × 2 indexa una tabla de palabras con direcciones de manejadores.
br tabEst(r14) jumps to the code for that state.br tabEst(r14) salta al código de ese estado.

Wait without spinningEsperar sin girar

Do not burn cycles counting down. Compare the clock against a deadline.No quemes ciclos contando hacia atrás. Compara el reloj contra un plazo.

BlockingBloqueante dec.w r5 / jnz wait
taskA spins until the wait endstaskA gira hasta que acaba la espera
B
C

CPU held the whole wait. B and C never get a turn.CPU retenida toda la espera. B y C no tienen turno.

Non-blockingNo bloqueante cmp.w &deadline,r12 / jlo done
A?
B
C
A?
B
C
A!

A checks the clock and returns. B and C run every pass; A acts only when the deadline arrives.A mira el reloj y retorna. B y C corren en cada vuelta; A actúa solo cuando llega el plazo.

A wait becomes a question asked each pass, not a loop that holds the CPU. Una espera pasa a ser una pregunta en cada vuelta, no un bucle que retiene la CPU.

TA

Timer_A is the heartbeatTimer_A es el latido

A periodic CCR0 interrupt increments one shared 32-bit time counter.Una interrupción periódica de CCR0 incrementa un contador de tiempo de 32 bits compartido.

each pulse = one CCR0 interrupt → SystemTimer + 1cada pulso = una interrupción CCR0 → SystemTimer + 1
TA2 CCR0 interrupt (the tick)interrupción CCR0 de TA2 (el tick)
stA2ISR inc.w &SystemTimer
adc.w &SystemTimer+2
add.w &stPeriod, &TA2CCR0
bic.w #LPM4, 0(sp)
reti
One job: count the tick and wake the CPU.Una tarea: contar el tick y despertar la CPU.

TA0 CCR0 sits at vector 0xFFE8. This example uses TA2 (0xFFD8).CCR0 de TA0 está en 0xFFE8. Este ejemplo usa TA2 (0xFFD8).

ISRs set flags, main consumes themLas ISR activan flags, main los consume

Keep the interrupt short. The real work happens in the cooperative loop.Mantén la interrupción breve. El trabajo real ocurre en el bucle cooperativo.

Producer · ISRProductor · ISR
inc.w &SystemTimer
set, return fastactiva, retorna rápido
FlagFlag
SystemTimer
the handoffel relevo
Consumer · mainConsumidor · main
call #stTime
read, take its timelee, sin prisa

The ISR never waits for main, and main never blocks the ISR. La ISR nunca espera a main, y main nunca bloquea a la ISR.

The cooperative schedulerEl planificador cooperativo

Round-robin: call each task once, in order, every pass of the loop.Round-robin: llama a cada tarea una vez, en orden, en cada vuelta del bucle.

semaforo
blink
pintura
main
superloop
call #semaforo
call #blink
call #pintura
bis.w #LPM3+GIE, sr
jmp superloop

No priorities, no preemption. Order in the list is the whole policy. Sin prioridades, sin expropiación. El orden en la lista es toda la política.

Sleep when no task is readyDormir cuando ninguna tarea está lista

After one pass, the loop sleeps in LPM3. The tick interrupt wakes it.Tras una vuelta, el bucle duerme en LPM3. La interrupción del tick lo despierta.

Loop: run every task, then bis.w #LPM3+GIE, sr.Bucle: ejecuta cada tarea, luego bis.w #LPM3+GIE, sr.
ISR: clears the LPM bits in the stacked SR with bic.w #LPM4, 0(sp).ISR: borra los bits LPM en el SR apilado con bic.w #LPM4, 0(sp).
RETI: returns to an awake CPU, one pass per tick.RETI: retorna a una CPU despierta, una vuelta por tick.
awake: one passdespierta: una vuelta asleep: LPM3dormida: LPM3
run
LPM3
run
LPM3

The amber line is the tick. Between ticks the CPU draws almost nothing.La línea ámbar es el tick. Entre ticks la CPU consume casi nada.

Everything together: one task, one tickTodo junto: una tarea, un tick

blinkLed toggles the LED every ledPeriod ticks, scheduled by the SystemTimer.blinkLed conmuta el LED cada ledPeriod ticks, planificado por el SystemTimer.

the loopel bucle
superloop
call #blinkLed
bis.w #LPM3+GIE, sr
jmp superloop
the task: non-blocking deadline checkla tarea: comprobación de plazo no bloqueante
blinkLed call #stTime
mov.w &ledDue, r14
mov.w &ledDue+2, r15
call #cmp32
jlo blinkDone ; not yet
add.w #ledPeriod, &ledDue
adc.w &ledDue+2
xor.b #BIT0, &P1OUT
blinkDone ret

Cooperation is only as good as the worst taskLa cooperación vale lo que la peor tarea

One task that refuses to return on time blocks every other task.Una tarea que se niega a retornar a tiempo bloquea a todas las demás.

The deal holdsEl trato se cumple every task returns in µscada tarea retorna en µs
A
B
C
A
B
C
A
B

Short slices. Each task waits one quick lap for its turn.Rebanadas cortas. Cada tarea espera una vuelta rápida su turno.

The deal breaksEl trato se rompe one task loops 10 msuna tarea gira 10 ms
A
B hogs the CPU for 10 msB acapara la CPU 10 ms
C

For those 10 ms nothing else runs, no matter how urgent.Durante esos 10 ms nada más corre, por urgente que sea.

There is no kernel to step in. Timing is a shared responsibility of every task. No hay un kernel que intervenga. El tiempo es una responsabilidad compartida de cada tarea.

Cooperative vs preemptiveCooperativo vs expropiativo

When tasks cannot be trusted to yield, a kernel takes the CPU by force.Cuando no se confía en que las tareas cedan, un kernel toma la CPU por la fuerza.

Cooperative · this moduleCooperativo · este módulo switch only when a task returnscambia solo cuando una tarea retorna
A
B
C
B

Switches land at task boundaries. No kernel, tiny RAM, but one bad task freezes the rest.Los cambios caen en los bordes de tarea. Sin kernel, poca RAM, pero una mala tarea congela al resto.

Preemptive RTOS · the outlookRTOS expropiativo · lo que viene a timer can cut any taskun timer puede cortar cualquier tarea
A
B
A
B
A

Amber lines are the timer tick: it cuts a task mid-run. A scheduler and a stack per task cost RAM, but a runaway task cannot starve the others.Las líneas ámbar son el tick del timer: corta una tarea a mitad. Un planificador y una pila por tarea cuestan RAM, pero una tarea descontrolada no deja sin CPU a las demás.

Three ideas to take with youTres ideas para llevarte

Structuring firmware without an operating system.Estructurar firmware sin sistema operativo.

Return fastRetorna rápido

Never block in a task.Nunca bloquees en una tarea.

Model each task as an FSM. Check, maybe change state, return.Modela cada tarea como una FSM. Comprueba, quizás cambia de estado, retorna.

One tickUn tick

Timer_A is the clock.Timer_A es el reloj.

Compare against a deadline. ISRs set flags, the loop consumes them.Compara contra un plazo. Las ISR activan flags, el bucle los consume.

Then sleepY duerme

Sleep until the next tick.Duerme hasta el próximo tick.

LPM3 between passes. Cooperation only works if every task yields.LPM3 entre vueltas. La cooperación solo funciona si toda tarea cede.