Aiuto per compilazione STK500boot.c

La modifica al bootloader è semplicissima in questo caso, basta aggiungere poche righe nel main loop per attivare l'input che vuoi verificare, l'eventuale pullup interna se necessaria, una if per controllare se il tasto è premuto e avvia la "while (boot_state==0)" oppure la salta completamente facendo partire il programma utente.

Si questa è la soluzione semplice visto che ha dei pulsanti collegati alla board.

Ok buon fine settimana a tutti.

Ciao.

C'è comunque un problema.
Con l'USBasp, così come l'USBtinyISP, hai il difetto che non programmi oltre i 64 kB di flash. Serve un firmware aggiornato, avevo controllato tempo fa sul sito del creatore dell'SUBasp. Per l'USBtiny invece non ci sono aggiornamenti ufficiali che fanno ciò.

Testato:
ma con usbasp (o altri) e ide 1.x fai appunto tutto dall'IDE :slight_smile: oppure devo modificare la mia guida

La deve programmare dalla porta USB, la scheda, e non è una MEGA2560, è dentro una scatola e non ha accesso al connettore ISP, ha anche postato le foto del tutto.

astrobeed:
Per me state usando un approccio sbagliato, potete mettere tutti i delay che volete però non serve a nulla per il semplice motivo che il bootloader si aspetta di vedere dei dati sulla seriale per attivarsi, solo se per un certo tempo non arriva nulla cede il controllo al programma principale.
Dato che in questo caso specifico la seriale è connessa ad un bus dati con un certo traffico alla fine il bootloader vedrà sempre arrivare dei byte con la conseguente attivazione e blocco della scheda.
La soluzione è una sola, il bootloader si deve attivare solo se riceve una ben precisa sequenza di caratteri entro un certo timeout, p.e. la stringa "@***#", va da se che poi tocca usare uno script per inviare questa stringa e subito dopo far partire AvrDude per la programmazione, il timeout del bootloader dovrebbe essere di almeno 1 secondo per dare modo ad AvrDude di partire.

non sono d'accordo. anzi, ho osservato il codice ed è più facile del previsto.

lasciamo intatto il codice che abbiamo visto fin'ora. riceveremo il carattere che fa entrare il boot-loader in stato di programmzione (boot_state==1).

osserviamo questa parte di codice;

  1. notiamo che il ciclo è condizionato da isLeave
  2. ciclo che legge un byte fino a formare un comando
  3. switch che contrlla il comando.
    notamo nello switch 2 cose interessanti:
    a. il comando
case CMD_LEAVE_PROGMODE_ISP:
					isLeave	=	1;
					//*	fall thru

b. il caso default:

default:
msgLength		=	2;
msgBuffer[1]	=	STATUS_CMD_FAILED;
break;

iniziamo a dire di uscire dal while se trova un comando che non è valido:

default:
msgLength		=	2;
msgBuffer[1]	=	STATUS_CMD_FAILED;
isLeave	=	1;  //<<<<<<< modified by lesto, start sketch if command not found
break;

ora passiamo al ciclo acquisiszione comando. (che nel ciclo è precedente, riga 571)
come si può notare il ciclo è condizionasto da while ( msgParseState != ST_PROCESS )
e nello switch, in caso che il comando rilevato sia erroneo, viene azzerato tutto il processo di lettura messaggio attarverso l'istruzione
msgParseState = ST_START;
ma noi non vogliamo che lui ricominci la lettura, quindi nei vari casi dello switch sostituiamo il reset del comando con invece il termine comando:
msgParseState = ST_PROCESS;
i casi da modificare sono ST_GET_SEQ_NUM, ST_GET_TOKEN, ST_GET_CHECK

ed ecco che il nostro boot-loader sarà molto schizzinoso sui comandi che gli arrivano: mentre prima un comando che arrivava con sequenza o sintassi errata veniva scartato e ci si metteva in attesa del prossimo comando, ora si esce dai vari cicli e si procede ad eseguire il codice utente.

Buongiorno a tutti.

@lesto

Ho provato minuziosamente quanto suggerisci,
aggiungendo cioè l'istruzione isLeave=1; e l'ST_PROCESS nei 3 casi switch. Il bootloader si comporta normalmente, nessun problema a caricare gli sketch.

Tuttavia, se una volta caricato e messo in esecuzione il mio sketch provo a spegnere o resettare il modulo con la seriale collegata e all'avvia si blocca ancora con il led fisso acceso :frowning:

Spero che potremmo adottare la tua soluzione perché è quella che di gran lunga mi piace di più.
Allego il file qualora tu volessi controllare, le modifiche le ho commentate con //mod by giorgio

grazie ancora

stk500boot.c (49.3 KB)

siamo a cavallo. se lìupload va bene, allora attiva la DEBUG_SERIAL e controlla dove si blocca durante il reset...

E come faccio a controllarlo?
se ho la seriale collegata a sparare dati come posso debuggare?

Giorgio:
E come faccio a controllarlo?
se ho la seriale collegata a sparare dati come posso debuggare?

Ma perché ti devi complicare la vita per nulla ?
Fai come ti ho detto io, usa uno dei pulsanti che hai sul box, se è premuto dopo reset avvia il bootloader altrimenti salta tutta la parte del timeout in modo da far avviare subito il tuo programma.
Devi solo inserire una if nel codice e attivare in lettura, più eventuale pull up, il pin dove è connesso il pulsante.

astrobeed:
Ma perché ti devi complicare la vita per nulla ?
Fai come ti ho detto io, usa uno dei pulsanti che hai sul box, se è premuto dopo reset avvia il bootloader altrimenti salta tutta la parte del timeout in modo da far avviare subito il tuo programma.
Devi solo inserire una if nel codice e attivare in lettura, più eventuale pull up, il pin dove è connesso il pulsante.

Effettivamente... avendo i pulsanti disponibili...

Giusto per capirci, l'unica modifica che devi fare, oltre ad attivare il pin per leggere il tasto, è questa:

if (tastopremuto) // modifica
{
	while (boot_state==0)
	{
		while ((!(Serial_Available())) && (boot_state == 0))		// wait for data
		{
			_delay_ms(0.001);
			boot_timer++;
			if (boot_timer > boot_timeout)
			{
				boot_state	=	1; // (after ++ -> boot_state=2 bootloader timeout, jump to main 0x00000 )
			}
		#ifdef BLINK_LED_WHILE_WAITING
			if ((boot_timer % 7000) == 0)
			{
				//*	toggle the LED
				PROGLED_PORT	^=	(1<<PROGLED_PIN);	// turn LED ON
			}
		#endif
		}
		boot_state++; // ( if boot_state=1 bootloader received byte from UART, enter bootloader mode)
	}
}
else  boot_state=0; // garantisce l'esecuzione immediata del programma utente

@astrobeed
Non voglio complicarmi la vita,diciamo che questa sarebbe la soluzione meno complicata per evitare di dover premere un pulsante e resettare il modulo per caricare lo sketch..nell'altro caso basterebbe scollegare la linea seriale e uploadare lo sketch.Diciamo che se si riuscisse questa sarebbe proprio la soluzione a 5 stelle :wink: vista la comodità che si avrebbe lavorando all'interno del quadro elettrico dove vanno alloggiati i moduli.

Non ultimo non conosco la sintassi per leggere lo stato di un bottone all'interno del bootloader :frowning:
Ho chiaro quale parte saltare, ma come leggo lo stato?
Il mio bottone è il PIN22 che dovrebbe corrispondere a PA0 (AD0) sull'atmel.

grazie

Giorgio:
Non voglio complicarmi la vita,diciamo che questa sarebbe la soluzione meno complicata per evitare di dover premere un pulsante e resettare il modulo per caricare lo sketch..

Non devi resettare nulla, ci pensa l'IDE ad attivare l'autoreset quando trasferisci lo sketch, in pratica non devi fare altro che collegare l'usb, premere il pulsante e fare l'upload dello sketch dall'IDE.
Non appena parte l'upload puoi rilasciare il pulsante.

Non ultimo non conosco la sintassi per leggere lo stato di un bottone all'interno del bootloader :frowning:
Ho chiaro quale parte saltare, ma come leggo lo stato?
Il mio bottone è il PIN22 che dovrebbe corrispondere a PA0 (AD0) sull'atmel.

Se non hai fretta nel tardo pomeriggio ti posto il bootloader già modificato per partire tenendo premuto un pulsante su PA0, mi devi solo dire se il pulsante chiude a GND, in questo caso devi avere una R di pull down sulla scheda, o VDD, in questo caso se è già presente una pull up sulla scheda oppure devo attivare quella del GPIO utilizzato.

@astrobeed
grazie, non ho grande fretta..ma niente pappa pronta, spiegami magari solo qual'e' la sintassi corretta che ci provo io... va bene aiutare ma non esageriamo :wink:

I pulsanti chiudono a VDD e ho già previsto sul pcb la resistenza di pull-up.

Puoi manipolare le porte di I/O con i registri:

Con DDRA imposti il pin/bit 0 in lettura, poi su PINA leggi lo stato del pin/bit 0.

uh che casino:

non basta fare una cosa tipo:
#define BOTTONE PINA0

e poi usare gli
IF (BOTTONE &= ~(1<<BOTTONE)) // condizione bottone low
IF (BOTTONE |= (1<<BOTTONE)) // condizione bottone high

è sbagliato?

Giorgio:
è sbagliato?

Mettiamola così: !corretto

:stuck_out_tongue_closed_eyes: :stuck_out_tongue_closed_eyes: :stuck_out_tongue_closed_eyes:

Questo è essere diplomatici :smiley:

prima di tutto devi settare il pin come input

poi leggi se il pin è 0 o 1

poi fai quello che devi fare.

cerca "port manipulation" sul playground!

Ecco la modifica pronta all'uso (testata).
Non mi è chiaro come usi il pulsante perché dici che hai le pullup e che chiude verso Vdd, in questo caso ci deve essere una pull down.
Comunque non è un problema basta che nella if metti il confronto verso 0 logico oppure 1 logico a seconda di come chiude il pulsante.
Io ho impostato che per attivare il bootloader il pin PA0 deve essere a stato logico 1 come dovrebbe essere per la configurazione che hai descritto.
Attenzione che dopo aver caricato il nuovo bootloader non vedrai nessun led lampeggiare perché non trovando il pulsante premuto viene ceduto subito il controllo al programma utente che non c'è, quindi apparentemente il processore sembra non fare nulla.

// codice da inserire subito prima della while (boot_state)
// Setto PA0 come input
DDRA = 0b00000000;
// Attivo pullup interna up su PA0 (usato per il test)
// PORTA = 0b00000001;  

  if ((PINA & 0b00000001) == 1)	// inserire la condizione logica desiderata (1 o 0)
   {
	while (boot_state==0)
	{
		while ((!(Serial_Available())) && (boot_state == 0))		// wait for data
		{
			_delay_ms(0.001);
			boot_timer++;
			if (boot_timer > boot_timeout)
			{
				boot_state	=	1; // (after ++ -> boot_state=2 bootloader timeout, jump to main 0x00000 )
			}
		#ifdef BLINK_LED_WHILE_WAITING
			if ((boot_timer % 7000) == 0)
			{
				//*	toggle the LED
				PROGLED_PORT	^=	(1<<PROGLED_PIN);	// turn LED ON
			}
		#endif
		}
		boot_state++; // ( if boot_state=1 bootloader received byte from UART, enter bootloader mode)
	}
   }
  else boot_state = 0;