Scheduler ufficiale

vbextreme:
f1 time 240
f2 time 250

primo sequenze()
...
f1 contatore 239
f2 contatore 239
...
f1 240 lancio funzione
f1 run, isr->f2 contatore++
...
f1 run, isr->f2 240 + 20 tick persi = contatore = 5

eccoci, mi sono spiegato?
come hai fatto notare però un tempo elevato di tick risolve parzialmente il problema perché comunque rimane li in attesa di fregarti.
usando però tick elevati si hanno enormi latenze, il chip rimarrebbe spesso inutilizzato, esempio
f1 tempo 1
f2 tempo 2
si ha una latenza di tempo(f1) - tempo(tick), se la tua funzione dura 5 ms per il restanti 11ms eseguì loop vuoti.Per non parlare del ritorno da 1 !
Più che uno scheduler sembra un timer!
sembra che richiami le varie funzioni ogni x secondi come farebbe un comunissimo timer, lo scheduler invece si impegna a utilizzare sempre tutta la CPU e cerca di garantire una sorta di parallelismo.

Gli AVR, ovviamente, sono estremamente limitati, ma con una MCU un pò più evoluta (un dsPIC o un PIC32) la granularità del clock (leggi velocità) è tale che è possibile impiegare anche un doppio scheduler usando due timer separati.

Uno scheduler legato ad timer (e relativo Interrupt) per le funzioni ad alta priorità, ed uno scheduler legato ad un secondo timer per le funzioni, diciamo di servizio, per il quali la latenza (cmq sempre limitata) non è un problema. Inoltre si possono utilizzare due risoluzioni diverse per i Tick, con buon pace delle latenze: poco importanti per i servizi, importantissime per i Task principali.

Inoltre i PIC32 (per esempio) gestiscono nativamente le code per le priorità degli interrupt, ed hanno una gestione degli stessi talmente flessibile e ben congegnata che, a meno di non aver scritto le routine con i piedi, i problemi che poni sono facilmente ovviabili.

E ancora: dispongono di un "Shadow register set" ovvero di un set di registri ulteriori, per cui il Context Switch è ulteriormente ridotto, anzi, swappando questi registri con i principali, non serve nemmeno più fare un Context Switch.
Quindi, l'ipotesi dello sforamento temporale, sebbene possibile, non è così facile che accada.

Certo che poi va ingegnerizzato per bene il software, è necessario fare i conti della serva fino al conteggio dei cicli di clock delle singole istruzioni e/o funzioni e cautelarsi stando abbondanti con il Tick, ma è ordinaria amministrazione per chi sviluppa questo genere di firmware. Siamo anni luce dalla programmazione "spannometrica" di Arduino, fatta per lo più con i piedi.