Newsgroup: it.hobby.elettronica.digitale
Titolo: pic, C e goto()

Ciao a tutti
Se sono in una subroutine di main() e chiamo goto(pippo) dove:
main()
{
[codice di inizializzazione]
...
pippo:
while(1)
{
codice vario
funzione()
...
}}
void funzione(void)
{
...
if (ERROR) goto(pippo);
}
potrei avere problemi di stack? Cioe', con una goto() lo stack viene 
svuotato da eventuali riporti dovuti alla chiamata di funzione() ?
Se dovesse andare bene, e' questo l'unico modo di tornare ad un punto 
fisso da _qualsiasi_ punto del programma senza resettare il micro?
Infine, il goto() potrei attivarlo anche da interrupt senza problemi?
Grazie a tutti per l'aiuto
Saluti
ame

 Infine, il goto() potrei attivarlo anche da interrupt senza problemi?
non ti so rispondere in relazione ai quesiti che poni perchè non ho mai
incontrato questo tipo di problema. ti dico come ho risolto io nei miei
programmi (anche se su ATMEL, ma sempre di C si tratta).
semplicemente quando chiamo una funzione faccio sempre resituire un valore,
che sarà 0 se tutto OK altrimenti un valore che dipenderà dal tipo di errore
intercettato (se vuoi fare le cose fini, altrimenti basta un numero diverso
da zero). quindi, sei nella funzione, intercetti un errore, fai un return
codice_errore; per uscire immediatamente dalla chiamata e ritornare nel main
o nella funzione chiamante. dopo ogni chiamata a procedura inserisco una
verifica dell'errore: se 0 continua l'esecuzione, altrimenti gestisci
l'errore. quindi se sei ancora in una funzione diversa dal main (pensa a
chiamate nidificate) usi lo stesso trucchetto per risalire di livello.
quando arrivi al main farai il goto a pippo.
ciao,
Marco

 quando arrivi al main farai il goto a pippo.
il fatto e' che l'evento che farebbe tornare alla situazione di partenza 
(che io ho schematizzato genericamente come 'errore') e' di tipo 
asincrono (ad es., interrupt esterno).
Quindi ho l'informazione nella routine di interrupt e non posso sempre 
stare a controllare se l'evento e' verificato dal main! Il massimo per 
me sarebbe poter fare:
interrupt()
{
routines varie di interrupt...
...
if (condizione_di_reset_dello_stato)
goto (pippo);
}
volevo sapere, prima di provare alla cieca, se qualcuno ha gia 
affrontato una problematica del genere..
Grazie dell'aiuto cmq
ciao

Ciao,
in generale, il goto NON svuota lo stack, quindi
fare attenzione.
Hai pensato di usare un flag a mo' di semaforo nell' irq
handler, e fare i controlli su tale semaforo nel "while (1)"
del main?
non so, sono solo idee su quello che ho visto io
in passato -> da prendere con le pinze.
ciao,
Flavio

 del main?
si, ma prima di tutto sarebbe un macello dover fare una miriade di 
controlli nell'ambito di un programma abbastanza articolato..
..eppoi resterebbe un problema: se io non sono nel main() ma in una sua 
funzione, dovrei in qualche modo risalire prima del fatidico goto()...

, 
a.brunet...@libero.it
 says...

E' sbagliato. Già  è poco corretto utilizzare il goto interamnente 
all'interno di una funzione (ma qualche volta è comodo) figurati il goto 
da una funzione ad un'altra o addirittura sotto interrupt. Ti perdi 
sicuramente lo stack.
Sicuramente c'è una soluzione semplice e corretta al tuo problema, ma 
per fare ciò dovresti dirci più dettagliatamente le tue problematiche 
(che tipo di interrupt è, che cosè l'evento che si verifica, quali 
azioni devi intraprendere ecc.)
Ciao Domenico

 ha scritto nel messaggio
news:98l3c.23563$O31.1...@news4.tin.it...

Se hai un sistema suscettibile di condizioni non previste dal sw (tali da
generare un errore così critico),
e se vuoi essere sicuro al 100% di controllare a posteriori la situazione,
perchè non resetti effettivamente il micro ?
Alla ripartenza controlli se vieni da un warm reset o da watchdog, ecc , e
inizializzi di conseguenza.
Ciao, Roberto.

 azioni devi intraprendere ecc.)
grazie per l'attenzione.
l'evento che si verifica e' la pressione manuale di una determinata 
sequenza di tasti, che attualmente viene riconosciuta (come tutti gli 
altri tasti) all'interno della routine di interrupt.
Nel frattempo il programma principale sta facendo le sue cose (fra cui 
andare all'interno di alcune subroutines).
Questo programma realizza una macchina a stati; da uno stato si passa 
all'altro ma non si torna indietro se non a ciclo concluso.
Il tutto e' all'interno di un while(1) all'interno del main().
La combinazione di tasti di cui sopra dovrebbe dare la possibilita' di 
tornare allo stato iniziale e conosciuto, che e' quello specificato dal 
codice subito dopo il while(1).

Ciao,
come gia' suggeriva anche Domenico,
cerca di riorganizzare il codice in modo da uscire dalla funzione interna
in modo "pulito", cioe' potresti, as es., dal main controllare un opportuno
flag di "condizione verificata" che viene settato solo dall'interno
dell'interrupt;
dall'ISR, al verificarsi della condizione, puoi uscire immediatamente con
un goto con label prima dell'ultimo } dell'ISR, ma va bene anche return
credo:
main()
{
[codice di inizializzazione]
flag = 0;
while(1)
{
codice vario
funzione();
if (flag == 1)
     {
     flag = 0; // se vuoi resettare l'evento subito
     [...]
     goto dovevuoi;
     }
}
}
void funzione(void)
{
[...]
if (ERROR) flag = 1;
if (flag == 1) return;  // se devi proprio scappare!
[...]
}
Non so se posssa aiutarti. Speriamo!
ciao


 
Non è ancora molto molto chiaro ma già è qualcosa.
Comunque prima di procedere vediamo di stabilire dei punti chiave.
Il while che hai al main deve sempre girare,cioè nessuna funzione 
chiamata dal main deve bloccare l'esecuzione del codice main. Questo 
significa che ogni funzione chiamata dal main una volta svolto il suo 
compito deve ritornare al main, evitare quindi delay, stati di attesa di 
altri eventi ecc.
Fatto questo (se hai dei problemi di questo tipo, posta pure)il tutto 
diventa molto semplice.
Dal main all'interno del loop chiami una funzione che prevede a 
verificare l'ordine di pressione di ogni singolo tasto, e ritorna true 
se l'ordine è andato a buon fine.
Ti posto un esempio:
// Prototipo
BOOL CheckKeybCode (void);
void main (void)
{
	BOOL Exit = FALSE;
	while (!Exit)
	{
		// Chiama tutte le funzioni che vuoi senza che esse 	
		// prendano il controllo del micro.
 
		if ( CheckKeybCode() )
		{
			// Ordine corretto della pressione dei tasti
		}
	}
}
BOOL CheckKeybCode (void)
{
	// Qui devi sviluppare la routine che premette il riconoscimento 
dell'ordine di pressione dei tasti 	
	senza attendere inutilmente.
 
	if Ordine corretto dei tasti?
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}
Se anche qui hai dei problemi si può approfondire.
La cosa importante da ricordare qundo si sviluppa un programma è quello 
di ridare SEMPRE il controllo al 
main.
Ciao Domenico


Di solito si resetta un micro soltanto quando si verifica un errore non
previsto talmente grave da compromettere la funzionalità del programma
stesso.
In questo caso è corretto impementare ciò che hai descritto. In tutti gli
altri casi c'è sempre una soluzione non dico migliore, ma certamente più
corretta.
Ciao Domenico