Aiuto per compilazione STK500boot.c

Altrimenti, visto che il bootloader è comunque di diversi kB, si può impostare il timer 2 per incrementare un contatore una volta ogni ms, un po' come faccio io sulla swRTC. In questo modo si ha un contamillisecondi com poche righe di C, basta agire direttamente sui registri.

Uh state andando un po sul difficile per me..
Nel frattempo sto provando con qualche contatore,qualche delay e qualche forzatura di bootstate, ma ho trovato solo un gran numero di modi di evitare che lo sketch parta :wink:

Caspita che parto..

già bisogna entrare più in merito.. quando uppi il codice, poi non parte linearmente, ma mi pare ci sia un reset a fine upload.se così fosse bisogna fare in modo che invece parta lo skecth senza quel reset.
sinceramente è solo un'idea, prima di esprimermi seriamente voglio osservare bene tutto il codice, altrimenti son solo supposizioni

Il seguente codice crea un contamillisecondi agganciato al timer 2.
Basta mettere una chiamata a setTimer2 per attivare il timer, che aggancia un interrupt alla ISR TIMER2_OVF_vect, la quale aggiorna ms. Inserisci il codice da qualche parte nel bootloader.

volatile unsigned int ms=0;

//set timer 2 to use it in combination with the Real-Time Counter module
void setTimer2() {
    TIMSK2 &= ~(1<<TOIE2); 
    TIMSK2 &= ~((1<<OCIE2A) | (1<<OCIE2B));
    ASSR &= ~(1<<AS2);
    TCCR2A &= ~((1<<WGM21) | (1<<WGM20)); 
    TCCR2B &= ~(1<<WGM22);
    TCCR2B |= (1<<CS22);
    TCCR2B &= ~((1<<CS21) | (1<<CS20));
    TCNT2=6;
    TIMSK2 |= (1<<TOIE2); 
    SREG|=1<<SREG_I;
}


//Interrupt Routine: this manipulates the software RTC
ISR(TIMER2_OVF_vect) {
    ms++;
}

Questo codice mi pare occupi solo 46 byte, compilato su un Mega2560.

non riesco.. dovunque la metto mi rifila una sfilza di 22 errori.

La dichiarazione della variabile va in testa, fra quelle globali. Le altre 2 funzioni in un punto qualunque del codice. Ma che errori ti da?

Eccoli qui.
Tra un po butto fuori tutto dalla finestra.
(Ringrazio davvero tutti per la gentilezza e pazienza però...)

Build started 25.5.2012 at 16:42:55
../stk500boot.c: In function 'setTimer2':
../stk500boot.c:512:1: error: stray '\240' in program
../stk500boot.c:512:1: error: stray '\240' in program
../stk500boot.c:513:1: error: stray '\240' in program
../stk500boot.c:513:1: error: stray '\240' in program
../stk500boot.c:514:1: error: stray '\240' in program
../stk500boot.c:514:1: error: stray '\240' in program
../stk500boot.c:515:1: error: stray '\240' in program
../stk500boot.c:515:1: error: stray '\240' in program
../stk500boot.c:516:1: error: stray '\240' in program
../stk500boot.c:516:1: error: stray '\240' in program
../stk500boot.c:517:1: error: stray '\240' in program
../stk500boot.c:517:1: error: stray '\240' in program
../stk500boot.c:518:1: error: stray '\240' in program
../stk500boot.c:518:1: error: stray '\240' in program
../stk500boot.c:519:1: error: stray '\240' in program
../stk500boot.c:519:1: error: stray '\240' in program
../stk500boot.c:520:1: error: stray '\240' in program
../stk500boot.c:520:1: error: stray '\240' in program
../stk500boot.c:521:1: error: stray '\240' in program
../stk500boot.c:521:1: error: stray '\240' in program
../stk500boot.c: In function 'main':
../stk500boot.c:526:1: error: static declaration of '__vector_15' follows non-static declaration
../stk500boot.c:526:1: note: previous declaration of '__vector_15' was here
../stk500boot.c: In function '__vector_15':
../stk500boot.c:527:1: error: stray '\240' in program
../stk500boot.c:527:1: error: stray '\240' in program
../stk500boot.c: In function 'PrintFromPROGMEM':
../stk500boot.c:1169:13: warning: cast from pointer to integer of different size
../stk500boot.c: In function 'DumpHex':
../stk500boot.c:1419:34: warning: cast to pointer from integer of different size
../stk500boot.c: In function 'EEPROMtest':
../stk500boot.c:1462:21: warning: cast from pointer to integer of different size
../stk500boot.c:1483:21: warning: cast from pointer to integer of different size
In file included from ../stk500boot.c:1514:0:
../avrinterruptnames.h: At top level:
../avrinterruptnames.h:312:0: warning: ignoring #pragma mark __AVR_ATmega169__
../avrinterruptnames.h:351:0: warning: ignoring #pragma mark __AVR_ATmega640__
../stk500boot.c: In function 'VectorDisplay':
../stk500boot.c:1623:19: warning: cast from pointer to integer of different size
../stk500boot.c:1624:20: warning: cast to pointer from integer of different size
make: *** [stk500boot.o] Error 1
Build failed with 23 errors and 8 warnings...

Siccome adesso non sono a casa ed ho fatto un copia & incolla di un codice preso da un mio file generato su Linux ed elaborato su Windows, non vorrei che fosse passato qualche carattere unicode. Togli tutti gli spazi prima delle righe di codice, forse sono tabulazioni e non spazi.

Poi pare che ci sia già una dichiarazione di utilizzo dello stesso vettore ISR...

Scusate ma qual'è l'obbiettivo?

Rendere sordo il bootloader per tot tempo?
Con sordo intendo che anche se gli arrivano dati esso non li prende in considerazione per x secondi.

Questo è il codice originale che ho io.
ps. non so se è lo stesso che avete voi.

// siamo nel main
// Non ho idea se BLINK_LED_WHILE_WAITING è definito sulla riga di comando di GCC, 
// ma supponiamo che boot_timeout è 20000
#ifdef BLINK_LED_WHILE_WAITING
	boot_timeout	=	 20000;		//*	should be about 1 second
//	boot_timeout	=	170000;
#else
	boot_timeout	=	3500000; // 7 seconds , approx 2us per step when optimize "s"
#endif	

        // boot_state deve essere 0 per rimanere intrappolato qui
        while (boot_state==0)        
	{
		while ((!(Serial_Available())) && (boot_state == 0))  cicla fintanto che boot_state è zero && non cè niente nel serial buffer 
		{
			_delay_ms(0.001);      // per eseguire questa istruzione ci vuole 1us
			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
		}
		_delay_ms(1000);  // non originale: aspetta 1 secondo prima di incrementare boot_state
                boot_state++; // ( if boot_state=1 bootloader received byte from UART, enter bootloader mode)
	}


	if (boot_state==1)
	{
		//*	main loop

Si esce dal ciclo sulla seriale solo se arriva un dato, allora aspetta 1 secondo circa e incrementa boot_state che comporta l'uscita
dal primo while. Purtroppo si deve aumentare anche il boot_timeout che deve essere maggiore di un secondo o comunque superiore a valore impostato qui _delay_ms(1000); // non originale: aspetta 1 secondo prima di incrementare boot_state.

mmm... non funge neanche così perchè rimangono dati nel buffer e alla fine il risultato è che parte il bootloader ma con ritardo, ma parte comunque.

Ciao.

L'obiettivo è far si che lo sketch parta lo stesso se ci sono dati sulla seriale, pur permettendo l'upload di un nuovo sketch dalla usb

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.

L'unica sensata a livello software è quella di Astro, ma se si riesce a svuotare il buffer della seriale per tot secondi dall'avvio, (dipende quanto serve) si rende insensibile il bootloader ai dati su seriale per tot secondi, ma è quello che vuoi?

Ciao.

Altra possibile soluzione, più semplice da implementare a livello di bootloader, usare una cella della EEPROM come flag di attivazione, in pratica il bootloader come prima cose legge questa cella se contiene un certo valore procede con la normale procedura, in caso contrario cede immediatamente il controllo al programma utente.
Ovviamente tocca prevedere a livello software sul 2560 un modo per settare questa cella della EEPROM tramite un qualche comando inviato sulla seriale tramite USB e serial monitor così diventa possibile fare tutto direttamente dall'IDE di Arduino.

Io butto li qualche idea:

La mia esigenza primaria è che arduino faccia partire lo sketch anche se ci sono dati sulla seriale rs485.
Se questo avviene istantaneamente oppure dopo 10 secondi non è grave.L'importante è che se si resetta oppure manca tensione questo riparta.Sempre. Adesso questo non avviene.

L'esigenza secondaria è poter fare l'upgrade del software tramite IDE di Arduino,operazione da fare manualmente,staccando la RS485 manualmente.

Ho 8 pulsanti sul frontale e 8 dipswitch. Eventualmente potrei anche adibire un dipswitch alla funzione di upload dello sketch tramite usb.

Oppure si potrebbe semplicemente dire una cosa tipo "se non ti arriva uno sketch entro 10 secondi fa partire lo sketch prevaricato ignorando eventuali dati sulla seriale.."
che è poi quello che ho provato a fare tutto il giorno,ottenendo le più svariate cose.. :slight_smile:

E adesso, vi prego, svagatevi con le vostre famiglie, ne riparliamo lunedì, se no abuso troppo dell'altrui disponibilità :slight_smile:
Un caloroso augurio di buon weekend a tutti.E ancora grazie.
Ciao

La soluzione della cella EEPROM è stata usata anche nel bootloader della 2009 XD
Ho visto che usavano il tempo di scrittura come delay per qualche attesa interna.

Tornando alla questione, ti chiedo: ma tu programmi il chip tramite porta USB oppure tramite connettore ICSP con l'MKII?
Se c'è il connettore ICSP non hai bisogno di altro, sei a posto. Ti costruisci un cavetto ICSP, carichi lo sketch ArduinoISP su un Arduino e poi programma il micro tramite IDE.

Giorgio:
Oppure si potrebbe semplicemente dire una cosa tipo "se non ti arriva uno sketch entro 10 secondi fa partire lo sketch prevaricato ignorando eventuali dati sulla seriale.."

Questo non puoi farlo senza modificare pesantemente la parte di avvio del bootloader.
Visto che hai a disposizione dei pulsanti la soluzione diventa semplicissima, basta che il bootloader come prima cosa verifica se un pulsante è premuto, in caso positivo fai procedere il tutto nel modo normale, in caso contrario lo consideri come un timeout e attivi il programma.
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.

in risposta a leo:

non ci sarebbe nemmeno bisogni di un altro arduino, compri un usbasp a 5 euro e lo usi in modo diretto dall'ide 1.x, ma il problema non e' questo, ha gia' detto che vorrebbe tenere in piedi il discorso usb per non modificare meccanicamente la scatola.
Io cmq andrei verso questa soluzione, cioe' prendi tutte queste scatole e modificale meccanicamente al fine di portare fuori il connettore ICSP, oltre a non avere problemi con il bootloader non ti perdi nessuna funzionalita' dell'ide, e non devi nemmeno staccare il bus manualmente per la programmazione

Ma lui ha detto che quando deve fare l'aggiornamento prende la scatola "in mano", quindi aprirla non è un problema. Forse non può modificare però a livello HW ciò che ha fatto.
Inoltre il suo interesse è quello di fare tutto dall'IDE, se non ho capito male.

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

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.