Newsgroup: it.hobby.elettronica.digitale
Titolo: interrupt che fa uscire subito da while

     Salve
microcontrollore
sono in una funzione che fa varie cose,addirittura alcune bloccanti,
 
quando scatta un interrupt voglio uscire da quel while qualsiasi cosa stia
facendo
 
O addirittura,se in quell'while ci sono delle chiamate a una certa
funzione e sono in quella funzione,
voglio uscirne immediatamente,e uscire dal while..è possibile?
 
es
 
#define STAY 	  1
 
void main(void)
{
     Inizializza();
     var=STAY;
 
     while(var==STAY)
     {
       Controlla_alcuni_ingressi();//richiede 1 ms
       PrintValoreIngressi(); 	 //richiede 2 ms
       Del_ms(4);				  //richiede 4 ms
       if(var !=STAY)break;				
     }
 
}
 
grazie
 
---
Questa email è stata esaminata alla ricerca di virus da AVG.
http://www.avg.com
 
 

 }
In un microcontrollore uscire dal ciclo in main significa sostanzialmente resettarlo o bloccarlo (dipende da come e' implementato 
main , tu lo vuoi resettare ?
 
Se le funzioni in cui sei dentro sono in una libreria fuori dal tuo controllo l'unico modo che vedo per forzare l'uscita e' 
manipolare lo stack all internno dell ISR , ma rischi di scassare tutto visto che e' un sistema cooperativo e non preemptive.
 
Forse dovresti esporre meglio il problema e non la soluzione.
 
Giulia
 
 


ti ringrazio,ma io non ho postato nessuna soluzione.
Forse ho esposto male la domanda:se sono in una qualsisi di queste  
funzioni,mie tra l'altro..
posso in qualch modo fare saltare il programma nel 2ndo while?


 qualch modo fare saltare il programma nel 2ndo while?
 
E' ovvio che tu ci abbia pensato prima di me, ma la
soluzione più pulita sembrerebbe essere un "goto" ovunque
serva con l'etichetta target alla fine della funzione, e
così via a cascata fino al chiamante che ti interessa (BTW
in fondo è un'implementazione manuale di un gestore di
eccezioni). Ora mi chiedo, perché non può andare nel tuo
caso dato che dovrebbe avere un costo computazionale quasi
zero? Lo chiedo perché un domani potrei incontrare un
problema simile al tuo e così saprò perché la soluzione
più ovvia potrebbe non funzionare. Chiaro, se le funzioni
non sono tue e sono pure bloccanti non vedo alcuna
possibilità "pulita".
 
 
 
-- 
- Tesoro, un pene piccolo non può certo mettere
   in crisi la nostra relazione!
- Lo so cara, ma preferirei che tu non lo avessi
   proprio.
 

 soluzione più pulita sembrerebbe essere un "goto" ovunque
 
goto è la soluzione più sporca che potevi proporre :)
 
Una soluzione possibile, per uscire da tutti cicli while o funzioni, è 
quella del controllo su una variabile (che ha già fatto nel suo while) 
in più posizioni possibili (dove ritiene giusto uscire).
La variabile (dichiarata volatile per usarla all'interno 
dell'interruzione) va gestita globalmente in modo che ogni funzione 
possa uscire quando viene variato il suo valore.

 valore.
 
Non credo sia così sporca, ha il vantaggio di essere
locale invece di gestire variabili globali. Penso che
entrambe le soluzioni si equivalgano e sia questione di
stile. Io personalmente preferisco scrivere in modo da
poter riutilizzare il più possibile e il goto resta
all'interno della funzione. Non solo, ma col tempo è
possibile raffinare la scrittura dove possibile
sostituendo il goto con il più formale "if"/"else".
Chiaro, presto la funzione si riempie o si potrebbe
riempire di blocchi annidati ma ho visto che le due
soluzioni sono tranquillamente mescolabili, e non
dimentichiamo il "break" che può sempre tornare comodo.
 
Però come di prammatica nella programmazione spesso c'è
più di una possibile soluzione; capisco che il goto sia
brutto come la morte, però in casi come questo me ne sono
servito senza problemi, chiaramente senza abusarne.


 servito senza problemi, chiaramente senza abusarne.
 
Che goto sia una soluzione sporca non lo dico io ma i testi di 
programamzione. Sicuramente ci sono programmatori che, pur sapendo 
questo, lo usano (forse meglio dire usavano) ugualmente. Un esempio è 
python, che in origine (da qualche anno lo seguo poco e non so dirti) 
era pieno di goto :).
 
Sicuramente nella programmazione di questi microcontrollori, con tutti i 
loro limiti, qualche porcheria te la puoi permettere, però meglio 
evitarle se possibile:)

 se possibile:)
 
Certo, vediamo se escono soluzioni migliori a parte quelle
in stile "puro terrore" suggerita da Giulia (è un
complimento, io non saprei nemmeno come cominciare per
manipolare direttamente lo stack senza passare per
l'assembler).


 l'assembler).
 
il goto non ti permette di uscire pulito da una funzione perchè non 
decrementi lo stack, e ti porterà ad errori sicuri.
Appunto, come diceva Giulia, devi andare a toccare lo stack, se proprio 
vuoi fare quella porcheria.
 

 posso in qualch modo fare saltare il programma nel 2ndo while?
 
Allora:
salvarti in una variabile globale(SP) il puntatore allo stack poco prima di entrare nel primo while
e il PC sempre prima del primo while.
 
Nella ISR devi acchiappare tutti i dati che salva nello stack  SOLO  per eseguire la ISR e spostarli sotto l'area di memoria 
puntata da SP  che hai salvato, modificando l'indirizzo di ritorno sostituendolo con il PC salvato prima.
 
Sempre nella ISR modifica il puntatore allo stack partendo da SP sottraendo la dimensione dei dati della ISR e imposta la 
variabile (globale) var a LEAVE .
Ritorna dalla ISR.
 
 
 
Buona fortuna!!!
 
 
Giulia
 
 

 porcheria.
 
Perché mai? L'uso che io pensavo del "goto" è quasi
sinomimo di "return", solo che tutti i goto rimandano a
una sola label a fine funzione, eventualmente può essere
un solo ";" prima dell'ultima parentesi graffa. In questo
modo lo stack dovrebbe essere correttamente manipolato
però non so. Io faccio così (le rare volte che mi serve)
perché sono su desktop e a fine funzione libero la memoria
dinamica prima di uscire, ma suppongo che su un micro si
possa direttamente usare "return". Tutto sta a vedere che
codice genera, magari son troppe istruzioni.


 
 
verifica se il compilatore suppporta la coppia setjmp longjmp per i 
salti non locali, e' lo "standard" per ritornare da qualsiasi posto in 
un livello piu' esterno ( esempio tipico piu' funzioni annidate )
 
non penso che funzioni in una routine di interrupt ma combinando un flag 
volatile ( settato dall'interrupt ) e un po' i test nelle zone bloccanti 
dovrebbe essere sufficiente per fare un lavoro pulito.


In data  febbraio 2019 alle ore 13:12:15, Giulia  

ringrazio per l'interessamento e per le soluzioni proposte
Sarei anch'io per quella proposta da Giulia,SP e PC riferiti a un punto  
del programma noto,
non sono sicuro di riuscirci senza errori,
faccio sapere,
saluti a tutto il newsgroup ,solo apparentemente dormiente


 non penso che funzioni in una routine di interrupt
 
Non dovrebbe funzionare perché nessuno eseguirà mai l'istruzione ReturnFromInterrupt mettendo a posto i flag , per questo 
preferivo ingannare RFI facendogli trovare i dati nello stack e lasciandogli settare tutti i flag extra che deve ripristinare.
 
Pero la cosa e' totalmente dipendente dall' architettura........da sperimentare.
 
 

 sinomimo di "return", solo che tutti i goto rimandano a
 
non è sinonimo di return, di conseguenza incasini lo stack.
 
Non ho provato da anni, ma il compilatore non ti segnala nulla?
 

 segnala nulla?
 
Non sapevo proprio... Da GCC 6 in poi e con -Wall non mi
dice niente. E' anche vero che è un tipo di approccio che
uso di rado ma penso che al compilatore non importi molto.
 
Però mi chiedo cosa accada sotto il cofano. Le variabili 
globali non sono toccate, l'heap si disalloca prima 
dell'uscita, resta lo stack il cui spazio necessario viene 
riservato al momento della chiamata. Ora, se io arrivo a 
fine funzione arrivandoci da un goto, lo stack resta 
quello; solo in corrispondenza dell'ultima parentesi 
graffa il compilatore dovrebbe comunque generare le 
istruzioni per liberare lo stack, per lui come può fare 
differenza il modo in cui è arrivato alla fine?


 ha  
scritto:

cose da fare con attenzione per quel che mi riguarda,mai fatte.
intanto il processore che sto usando è un STM32L010,un Cortex M0 da meno  
di 0,5 euro per volumi appena consistenti
Non ho mai utilizzato lo stack di questi micro in modo cosi diretto,al  
massimo mi era capitato di forzare la sua  dimensione o locazione nel  
linker file
Al momento ho visto che non riesco nemmeno a leggere il contenuto dello  
stack tramite un puntatore generico.Immagino che ci sia qualche  
protezione,visto che mi manda in hard fault quando ci provo
Non succede se il puntatore accede a tutta l'area stack..e nemmeno a  
quella inclusa tra l'inizio dello stack e la stack pointer



mi viene un dubbio: tu sai che la coppia setjmp e longjmp sono 
"standard" C vero ?
non fanno niente di troppo anomalo, tranne il fatto che il compilatore 
SA come manipolare lo stack ;-)
 
usate dentro una unica "linea" (*) di esecuzione sono perfettamente 
lecite, diverso e' il fatto se si tentano di usare su "linee" differenti
 
http://www.onarm.com/forum/60652/
 ( qui dicono che non funziona )
 
(*) inteso come: "longjmp va chiamata da funzioni chiamate dalla 
funzione che ha chiamato la setjmp"


>  ---
no,non ne sapevo nulla,ora leggo


 l'heap si disalloca prima dell'uscita
 
Negativo, l'heap in C non viene gestito dal compilatore ma dal
programmatore. Solo in C++ l'heap viene liberato se un oggetto lo
utilizza e il distruttore dell'oggetto lo libera correttamente.
 
 
Per quanto riguarda il problema di intercettare l'interrupt per uscire
da una funzione propria, la soluzione più pulita mi sembra quella di
settare una variabile volatile tramite interrupt e testare
periodicamente tale variabile all'interno della funzione. Questo ha
anche un altro vantaggio: se la funzione è implementata come macchina a
stati allora (successivamente) è possibile rientrare nella funzione e
riprendere l'elaborazione dal punto in cui essa era stata interrotta (se
serve ovviamente).
 
Saluti
Flavio
 
 
-- 
Indirizzo email non valido, no risposte private grazie.

Potresti aggiungere una condizione nel while:
while(... ... ... && stop==0)
 
 
-- 
 
 
----Android NewsGroup Reader----
http://usenet.sinaapp.com/
 

 stata interrotta (se serve ovviamente).
 
Terrò a mente, dato che sei una delle persone più
competenti nel campo :) Anche se non ho la minima idea di
come si faccia ma tanto la mia esperienza sui micro è zero
e credo che tale resterà.
 
 
 
-- 
"La teoria è sapere come funzionano le cose e
non sapere come farle funzionare; la pratica è
sapere come far funzionare la cose senza sapere come
funzionano; il nostro scopo è unire la pratica
alla teoria per riuscire a non far funzionare
le cose senza capire come abbiamo fatto"
 

 e credo che tale resterà.
 
Dai, non ti sottovalutare, basta che fai mente locale al codice
sviluppato per divesystem, se ti ricordi molte funzioni erano
implementate mediante macchine a stati.


 stati.
 
Sì ma se non mi avessi spiegato tu cos'è, per me "macchina
a stati" sarebbe stata un'automobile in scatola di
montaggio con una "d" di differenza :D (OK, mi sento più
contorto del solito).


 contorto del solito).
 
:-)



 
 
forse sto capendo male,ma questa condizione che suggerisci mi verrebbe  
valutata solo a fine del ciclo while,io invece voglio uscirne anche se  
sono in un punto qualsiasi,o addirittura in una funzione chiamata dal  
ciclo.
 
Per non fare misteri questo mi serve perchè la condizione sarebbe un  
avviso di
mancanz di alimentazione,e allora devo saltare subitissimo a una funzione
che metta il uC in un modo ultra lowpower,nella speranza che sopravviva  
alcuni minuti
grazie a un condensatore da 1000 uF,cosa possibilissimo visto che in  
STOP_MODE ho misurato
390 nA ,grazie a una scheda ST specifica per misure di corrente e energia  
su queste scale.
 
per adesso,non padroneggiando il necessario per mettere in pratica i  
suggerimenti precedenti,sto semplicemente facendo così,per aggirare e fare  
quello che mi serve:
 
avviente l'evento "urgente" ,chiama un interrupt,nell'interrupt chiamo un
software reset,il programma riparte,verifico che il reset sia un software  
reset
e in questo caso vado in sleep.
Gira,non ho ancora verificato i tempi di reazione,ma per adesso è quello  
che sono riuscito a fare


 
 
 
aspe', se si tratta solo di mettere a dormire il micro, dovresti poterlo 
fare direttamente dall'interrupt senza terminarlo, al risveglio ti 
ritroveresti ancora dentro l'interrupt che a quel punto basterebbe 
semplicemente completare


... e siamo arrivati a 27 risposte prima di sapere che cosa doveva
 fare!!! :(


 
 
Potremmo tirare in lungo il thread e forse a 2.332.432
risposte ci confesserà il suo conto numerato alle isole
Cayman che provvederemo a svuotare ^_^


 
E' stata la mia prima domanda se noti, purtroppo quando arrivano le richieste sui ng
il 99% sono le loro soluzioni mascherate da problemi.
 
Giulia
 

 soluzioni mascherate da problemi.
 
Un giorno posterai la tua autobiografia? Sono curioso da
morire.


   fare!!! :(
 
Perlomeno Blisca l'ha detto.... Gia' qualcosa.
Io ho letto tutto in timoroso silenzio dato che in materia sono 
decisamente arrugginito.
Ritiro fuori i miei tomi di C++
:-(
 
 
-- 
 
Ciao, Renato
 
 
---
Questa e-mail è stata controllata per individuare virus con Avast antivirus.
https://www.avast.com/antivirus
 
 


si ,ma in quel caso mi farebbe ripartire magari dalla funzione chiamata  
dalla funzione
che era in corso al momento dell'interrupt e non è quello che mi serve
 
 
-- 
Creato con il client email di Opera: 
http://www.opera.com/mail/
 



aspetta,io non chiedevo  solo per risolvere il mio caso specifico
faccio la domanda generica ,per cultura generale ,e la risposta mi verrà  
buona in futuro
poi parlo della mia situazione specifica,che è probabilmente meno  
interessante



finalmente qualcuno che ci arriva
 
uno può avere il problema che ha lasciato le chiavi dell'auto a casa,
e prendendo spunto da quello può chiedere come si aprono le serrature con  
un fil di ferro
che mi sembra più interessante di "come non dimenticare le chiavi a casa"
 
 
 
 
-- 
Creato con il client email di Opera: 
http://www.opera.com/mail/
 
 


 morire.
 
 
 
Ci provo:
la mia prima auto fu una Ritmo grigia completamente inaffidabile,
aveva i coprisedili tigrati da rockstar anni 80,ma lo sterzo a volte ecc  
ecc
