più o meno è come hai descritto tu.
Visti i tempi biblici per un micro io farei così
interrupt che incrementa variabile fino a 50.
micro che normalmente "gira in tondo" senza fare nulla esegue solo due if
if variabile%10 == 0 (fa il modulo)
if variabile == 0 (ha raggiunto 50 e nell'interrupt è stata azzerata per ripartire con il conteggio)
all'interno del primo if leggi il sensore
all'interno del secondo gestisci il led.
Siccome hai interrupt ogni 10ms tutto funziona se la lettura del sensore richiede un tempo molto inferiore ai 10ms in modo che il micro abbia il tempo di eseguire entrambi gli if tra due interrupt successivi.
C'è una potenziale disgrazia se usi micro 8bit definisci la variabile char per schivarla
Schedulatore
Moderatore:
Paolino
24 messaggi
• Pagina 2 di 3 • 1, 2, 3
0
voti
[11] Re: Schedulatore
-

luxinterior
4.311 3 4 9 - Master EY

- Messaggi: 2690
- Iscritto il: 6 gen 2016, 17:48
0
voti
[12] Re: Schedulatore
Però se ho una funzione che deve essere eseguita ogni 100ms perché devo stare sotto i 10ms?
Func1
{
leggi sensore 1
leggi sensore 2
---
---
}
la lettura di x sensori deve essere inferiore a 100ms non 10ms o sbaglio?
Forse devo fare un interrupt direttamente ogni 100ms al posto di 10ms per eseguire la lettura dei sensori?
Func1
{
leggi sensore 1
leggi sensore 2
---
---
}
la lettura di x sensori deve essere inferiore a 100ms non 10ms o sbaglio?
Forse devo fare un interrupt direttamente ogni 100ms al posto di 10ms per eseguire la lettura dei sensori?
0
voti
[13] Re: Schedulatore
Sì va bene come dici tu 100ms
Pensandoci la cosa pultia sarebbe fare così
isr_flag lo metti a 1 ogni 100ms dentro l'interrupt.
In questo modo il micro esce dal loop while (isr_flag) ogni 100m sper faare quello che deve
Pensandoci la cosa pultia sarebbe fare così
- Codice: Seleziona tutto
while (1)
{
while (isr_flag == 0) ;
isr_flag = 0 ;
if (variabile%10 == 0)
if (variabile == 0)
}
isr_flag lo metti a 1 ogni 100ms dentro l'interrupt.
In questo modo il micro esce dal loop while (isr_flag) ogni 100m sper faare quello che deve
-

luxinterior
4.311 3 4 9 - Master EY

- Messaggi: 2690
- Iscritto il: 6 gen 2016, 17:48
1
voti
[14] Re: Schedulatore
Quella variabile "isr_flag" deve essere globale e deve essere dichiarata "volatile" o in un altro modo, dipende dalle linee guide di programmazione del micro-controllare in uso, altrimenti il compilatore può decidere di ottimizzarla in un registro con esiti disastrosi.
L'uso dell'operatore "%" con 10 implica una divisione, molti micro controllori non hanno in hardware la divisione. Consiglio di incrementare e poi azzerare o sfruttare le potenze di 2, ad esempio per ogni otto basta un AND con 0x07 o ogni 16 un AND con 0x0F.
Comunque se le operazione sono molto semplici per me il micro nel loop principale deve stare in stato di sleep con risveglio solo in caso di interrupt e nel codice degli interrupt gestire più velocemente possibile i compiti assegnati.
L'uso dell'operatore "%" con 10 implica una divisione, molti micro controllori non hanno in hardware la divisione. Consiglio di incrementare e poi azzerare o sfruttare le potenze di 2, ad esempio per ogni otto basta un AND con 0x07 o ogni 16 un AND con 0x0F.
Comunque se le operazione sono molto semplici per me il micro nel loop principale deve stare in stato di sleep con risveglio solo in caso di interrupt e nel codice degli interrupt gestire più velocemente possibile i compiti assegnati.
0
voti
[15] Re: Schedulatore
Vi aggiorno sul firmware. Allora il timer 4 fa scattare un interrupt ogni 2ms
Nel main ho messo questa funzione:
Mentre nel file di interrupt:
Mentre il segnale all'oscilloscopio dei primi due task da 10ms e 100ms:
Task 10ms
Task 100ms
A me sembra tutto corretto. Esiste un modo migliore per scrivere questo codice?
Nel main ho messo questa funzione:
- Codice: Seleziona tutto
bool flag_10ms;
bool flag_100ms;
bool flag_1000ms;
void main(void)
{
while (1)
{
if (flag_10ms == 1) //Task da 10ms
{
GPIO_WriteReverse(LED1);
flag_10ms = 0;
}
if (flag_100ms == 1) //Task da 100ms
{
GPIO_WriteReverse(LED2);
flag_100ms = 0;
}
if (flag_1000ms == 1) //Task da 1000ms
{
GPIO_WriteReverse(LED3);
flag_1000ms = 0;
}
}
}
Mentre nel file di interrupt:
- Codice: Seleziona tutto
int tmr_10ms;
int tmr_100ms;
int tmr_1000ms;
extern bool flag_10ms;
extern bool flag_100ms;
extern bool flag_1000ms;
void TIM4_UPD_IRQHandler(void)
{
tmr_10ms++;
tmr_100ms++;
tmr_1000ms++;
if(tmr_10ms == 5)
{
flag_10ms = 1;
}
if(tmr_10ms > 5)
{
flag_10ms = tmr_10ms = 0;
}
if(tmr_100ms == 50)
{
flag_100ms = 1;
}
if(tmr_100ms > 50)
{
flag_100ms = tmr_100ms = 0;
}
if(tmr_1000ms == 500)
{
flag_1000ms = 1;
}
if(tmr_1000ms > 500)
{
flag_1000ms = tmr_1000ms = 0;
}
TIM4_ClearFlag(TIM4_FLAG_UPDATE);
}
Mentre il segnale all'oscilloscopio dei primi due task da 10ms e 100ms:
Task 10ms
Task 100ms
A me sembra tutto corretto. Esiste un modo migliore per scrivere questo codice?
0
voti
[16] Re: Schedulatore
Le variabili booleane utilizzate devono essere dichiarate almeno "volatile", sono condivise.
Fai un test e poi un assegnamento, di solito questa operazione deve essere atomica, vedi se hai una libreria o delle macro per operazioni atomiche.
Fai 2 test sui timer, uno per scatenare e uno per azzerarlo, prova a vedere se riesci a farne uno solo.
Fai un test e poi un assegnamento, di solito questa operazione deve essere atomica, vedi se hai una libreria o delle macro per operazioni atomiche.
Fai 2 test sui timer, uno per scatenare e uno per azzerarlo, prova a vedere se riesci a farne uno solo.
0
voti
[17] Re: Schedulatore
Ciao, per operazioni atomiche non basta ad esempio mettere all'interno di tutti i task la funzione per disabilitare tutti gli interrupt e poi riabilitarli quando ha finito tutte le operazioni?
Oppure intendi una cosa del genere:
- Codice: Seleziona tutto
if (flag_10ms == 1) //Task da 10ms
{
--> DISSATTIVO TUTTI GLI INTERRUPT
GPIO_WriteReverse(LED1);
flag_10ms = 0;
--> RIATTIVO TUTTI GLI INTERRUPT
}
Oppure intendi una cosa del genere:
- Codice: Seleziona tutto
if (flag_10ms == 1 && flag_100ms == 0 && flag_1000ms == 0 )
{
...
}
if (flag_100ms == 1 && flag_10ms == 0 && flag_1000ms == 0 )
{
...
}
if (flag_1000ms == 1 && flag_10ms == 0 && flag_100ms == 0 )
{
...
}
0
voti
[18] Re: Schedulatore
Dipende dal micro controllore. Con i micro-controllori a 8 bit si salva lo stato, si disattivano gli interrupt, si eseguono le operazioni critiche, si ripristina lo stato. Con i micro controllori a 32 bit le cose sono più complesse, ad esempio gli ARM Cortex hanno delle opportune librerie e macro per operazioni atomiche.
Per leggere un booleano se è true e subito dopo impostarlo a falso si usa un'altra tecnica. Si esegue una swap in assembler tra un registro col valore falso e la memoria che contiene il booleano, questa operazione è in generale atomica. Se il registro contiene falso il booleano non ha cambiato stato, se è true il booleano ha cambiato stato e contemporaneamente è stato impostato a false. Questa operazione è di solito presente in qualche libreria con una funzione inline o una macro.
Quei test con le AND non sono operazione atomiche.
Per leggere un booleano se è true e subito dopo impostarlo a falso si usa un'altra tecnica. Si esegue una swap in assembler tra un registro col valore falso e la memoria che contiene il booleano, questa operazione è in generale atomica. Se il registro contiene falso il booleano non ha cambiato stato, se è true il booleano ha cambiato stato e contemporaneamente è stato impostato a false. Questa operazione è di solito presente in qualche libreria con una funzione inline o una macro.
Quei test con le AND non sono operazione atomiche.
0
voti
[19] Re: Schedulatore
Grazie delle risposte. Ma ho un'ultima domanda. Secondo te perché non ottengo
10ms ma 12.3ms
100ms ma 105ms
A cosa può essere dovuto? Utilizzo l'oscillatore interno e la frequenza è 2MHz
Facendo due conti e considerando la tolleranza dell'oscillatore dovrei ottenere
Tick TIM x5 (10ms) --> [ms] 10,343 10,240 10,139
Tick TIM x50 (100ms) --> [ms] 103,434 102,400 101,386
10ms ma 12.3ms
100ms ma 105ms
A cosa può essere dovuto? Utilizzo l'oscillatore interno e la frequenza è 2MHz
Facendo due conti e considerando la tolleranza dell'oscillatore dovrei ottenere
Tick TIM x5 (10ms) --> [ms] 10,343 10,240 10,139
Tick TIM x50 (100ms) --> [ms] 103,434 102,400 101,386
0
voti
[20] Re: Schedulatore
Se i pin di I/O vengono cambiati all'interno del codice dell'interrupt con un conteggio esatto del contatore, senza nessuna biforcazione o ritardi variabili il tempo misurato è preciso con la stessa tolleranza del clock principale.
Se invece dal interrupt si cambia il valore di una variabile condivisa, letta dal ciclo principale per pilotare i pin di I/O allora qui si ha una tolleranza maggiore, dovuto a quando viene scatenato interrupt (tra due istruzioni) e dal tempo di esecuzioni dei vari compiti gestisti nel ciclo principale.
Se invece dal interrupt si cambia il valore di una variabile condivisa, letta dal ciclo principale per pilotare i pin di I/O allora qui si ha una tolleranza maggiore, dovuto a quando viene scatenato interrupt (tra due istruzioni) e dal tempo di esecuzioni dei vari compiti gestisti nel ciclo principale.
24 messaggi
• Pagina 2 di 3 • 1, 2, 3
Torna a Firmware e programmazione
Chi c’è in linea
Visitano il forum: Nessuno e 14 ospiti

Elettrotecnica e non solo (admin)
Un gatto tra gli elettroni (IsidoroKZ)
Esperienza e simulazioni (g.schgor)
Moleskine di un idraulico (RenzoDF)
Il Blog di ElectroYou (webmaster)
Idee microcontrollate (TardoFreak)
PICcoli grandi PICMicro (Paolino)
Il blog elettrico di carloc (carloc)
DirtEYblooog (dirtydeeds)
Di tutto... un po' (jordan20)
AK47 (lillo)
Esperienze elettroniche (marco438)
Telecomunicazioni musicali (clavicordo)
Automazione ed Elettronica (gustavo)
Direttive per la sicurezza (ErnestoCappelletti)
EYnfo dall'Alaska (mir)
Apriamo il quadro! (attilio)
H7-25 (asdf)
Passione Elettrica (massimob)
Elettroni a spasso (guidob)
Bloguerra (guerra)


