Topic permanente di programmazione newbie

Sui lock bits spero di fare qualche prova diretta, non avendo risposte certe, sono andato al lab e ho recuperato il Programmatore; solo che avevo "blindato" l'input in modo da non poter fornire valori diversi dai "3" e quindi mi tocca rimetterci mano, ci sta :sweat_smile:, se dovesse andar bene sarebbe sempre una funzione in più; con tutto il lavoraccio che ho fatto sulle routine di lettura e scrittura.....

Sul WD il link che mi hai dato pare proprio fatto per i tardi come me, grazie :D; ora me lo studio; se mai arrivasse un giorno che un nanetto si blocchi o si scarichi la batteria (ma ho calcolato 5 anni :sweat_smile:) o, più facilmente, si dovesse rompere una corda, approfitto per aggiornare il firmware ;) un si sa mai :)

[quote author=Michele Menniti link=topic=95050.msg787589#msg787589 date=1336496817] Sul WD il link che mi hai dato pare proprio fatto per i tardi come me, grazie :D; ora me lo studio; se mai arrivasse un giorno che un nanetto si blocchi o si scarichi la batteria (ma ho calcolato 5 anni :sweat_smile:) o, più facilmente, si dovesse rompere una corda, approfitto per aggiornare il firmware ;) un si sa mai :) [/quote] Se vuoi evitare problemi di basse tensioni, usa il brown-out al posto del watchdog: è fatto apposta. Ma che te lo dico a fare :P

Se vuoi esser sicuro di non ritrovarti con il codice infilato in un loop infinito o piantato perché le piogge radioattive ti hanno mandato a meretrici il micro, allora pensa al watchdog con i tempi massimi consentiti (mi pare sia 2s il max impostabile sui Tiny).

Letto e [forse] capito: (scusa Leo, ti leggo mentre posto) uso la libreria wdt.h in setup setto il tempo di WD (lì però non consiglia di NON scendere sotto i due secondi come diceva lesto....ma a me risulta che abbia ragione lesto, quindi?) in un punto strategico del loop, ma non necessariamente ad ogni ciclo..., resetto il WD. Il punto strategico lo fisso in un punto al quale il software arriva solo se è andato tutto bene fino a quel momento. E a quel punto il siftware deve arrivare sempre prima del tempo impostato per il WD, altrimenti il micro si resetta perennemente. Quindi se imposto il timer del WD a 4 secondi, io devo scegliere il punto di reset in modo che normalmente esso azzeri il timer PRIMA che passino i 4 secondi; se succede qualcosa il timer non viene resettato e quindi WD interviene (allo scadere dei 4 secondi) e resetta il micro. Ho capito bene :fearful:? Il brown-out l'ho disattivato Leo, per un circuito a batteria lo vedo invece "pericoloso", comunque lo sto proprio descrivendo ora nell'articolo :D

http://www.nongnu.org/avr-libc/user-manual/group__avr__watchdog.html

Sì, è vero. Anche i Tiny consentono tempi di 4 e 8s. Andavo a memoria.

Per il resto è come hai interpretato. Fissi un punto di azzeramento del contatore del watchdog, che valuti in base a come hai strutturato il codice. Se non passa da quel punto, il tuo codice significa che si è piantato ed il watchdog farà il suo dovere.

Dando ragione a lesto mi riferivo al fatto di NON impostare tempi sotto i due secondi per non rischiare l'impallo sotto forma di reset perenne, in quando al riavvio il bootloader ci metterebbe più tempo di quello del reste WD per diventare operativo. Come stanno le cose? Se c'è questo rischio come mai prevedono tempi inferiori a quelli di riattivazione del BL (probabilmente perché i tempi del WD li stabilisce ATMEL mentre il BL è specifico di Arduino?)

A logica non si corre questo pericolo perché se andiamo ad analizzare la sequenza di avvio del micro, abbiamo:

  • accensione
  • controllo passato al bootloader: questo esegue il controllo sulla seriale per vedere se arriva uno sketch
  • se non arrivano sketch da flashare, passa il controllo al programma dell'utente
  • parte il programma dell'utente che, solo a questo punto, imposta e gestisce il watchdog

Per dirla tutta, c'è un watchdog anche internamente al bootloader, per resettarlo nel caso si pianti in ascolto. Ma che si può evitare di considerare. Se il tuo sketch imposta 2 secondi, i 2 secondi sono conteggiati al suo interno. Essi sono impostati nel setup, quindi il tempo del bootloader non entra nel conteggio.

/* CAGNACCIO
sketch di esempio per imparare ad usare il watchdog (by Leo72)
*/

#include  //libreria necessaria per gestire il watchdog
const byte LED=13; //led sul pin 13
byte statoLed=1; //stato del led

void setup() {
    pinMode(LED, OUTPUT); //led come ouput
    flashStart(); //salutiamo
    //Watch out! Watchdog! (Pericolo! Cane mordace!)
    cli(); //stop agli interrupt
    wdt_reset(); //resettiamo il cagnaccio
    wdt_enable(WDTO_4S); //4 secondi di attesa prima del reset
    sei(); //riattivo gli interrupt
    
}

void loop() {
    delay(1000); //1 secondo d'attesa
    statoLed^=1; //cambio di stato del led
    digitalWrite(LED, statoLed); //lampeggio del led
    
    //**********
    //delay(3500); //commenta/decommenta questa riga per vedere il cagnaccio in azione
    //**********
    wdt_reset(); //resettiamo il contatore
}
    

//semplice routine per verificare il reset della scheda
//esegue 5 flash veloci del led integrato
void flashStart() {
    for (byte i=0; i<5; i++) {
        digitalWrite(LED, statoLed);
        delay(50);
        statoLed^=1;
        digitalWrite(LED, statoLed);
        delay(50);
    }
}

Piccolo sketch di esempio. Caricatelo sull'Arduino. 5 flash del led e poi lampeggi regolari ogni secondo. Se decommentate la riga delay(3500) avrete la soprersa. Vedrete in azione il watchdog: 5 lampeggi veloci, led acceso fisso per 3,5 secondi e poi altri 5 lampeggi veloci ecc.. Questo perché il tempo complessivo supera i 4 secondi impostati per il watchdog ed il circuito resetta l'Atmega.

Ragazzi, primo programma con Arduino e subito sono in crisi. Cavolo non capisco proprio perchè non funzioni..

  int x = 9;
  int y = 3;
  int z;

void setup(){

  z = x/y;
  Serial.begin(2400);
  
}

void loop(){
  
  Serial.println(z);
  
}

Apro serial monitor e guardate cosa trovo:

(una sfilza infinita...)

Non dovrei avere una sfilza di "3"?..Mi sto perdendo in un bicchiere d'acqua, nonostante ciò non trovo l'errore..Cosa sono questa serie di X accompagnate da un simbolo strano?

1) non si vede bene 2) hai messo la stessa velocità sul monitor seriale? 3) i numeri stampali con Serial.println(z, DEC)

Mi stavo per incavolare per l'"intrusione" di legolas93, poi mi sono ricordato che il titolo al Topic l'ho dato proprio io..... :sweat_smile: Ho copiato il tuo code, lo proverò; hai ragione su quello che dici, solo non ricordo più perché tempo fa più di qualcuno bloccò Arduino usando male il WD, tu ne hai memoria?

[quote author=Michele Menniti link=topic=95050.msg787844#msg787844 date=1336508122] Mi stavo per incavolare per l'"intrusione" di legolas93, poi mi sono ricordato che il titolo al Topic l'ho dato proprio io..... :sweat_smile: [/quote] Esatto ;)

Ho copiato il tuo code, lo proverò; hai ragione su quello che dici, solo non ricordo più perché tempo fa più di qualcuno bloccò Arduino usando male il WD, tu ne hai memoria?

No, se ne è sempre parlato ma sempre di terzi, io non mi ricordo di qualcuno che abbia scritto "io ho briccato il micro".

Michee..ehh :P io mi sono rifatto al titolo!

Grazie Leo72..era la velocità impostata diversa :~ La cosa bella è che è una cosa che so e che avevo anche controllato.. :zipper_mouth_face: Questi sono proprio errori da newbie.

Vediamo se ora della Maturità riesco a tirare fuori qualche progetto carino da portare alla commissione 8)

legolas93: Grazie Leo72..era la velocità impostata diversa :~ La cosa bella è che è una cosa che so e che avevo anche controllato.. :zipper_mouth_face: Questi sono proprio errori da newbie.

E per questo sei degnamente finito su questo Topic :grin:

[quote author=Michele Menniti link=topic=95050.msg787290#msg787290 date=1336480902] Introduco un altro argomento, o meglio lo riprendo, quello dei Lock bits: ora è chiaro che i boot lock bits ed i lock bits sono 6 bits dello stesso byte; nelle prove non mi è mai balenata l'idea che potesse essere così e non ho provato valori diversi da FF, FE, FC (i tre che agiscono sui lb); ma nelle note di programmazione del reference non vedo traccia della programmazione dei BLB, in quanto parla sempre e solo di lb. Non ho l'HV se non mi rispondevo da solo :grin: Secondo Voi per programmare anche i BLB mi basterebbe semplicemente inserire un valore, tra quelli permessi, contemplando anche lo status 0/1 che voglio dare ai blb? P.es. con CF potrei programmare i due blb più alti lasciando il resto a 1? [/quote] Fatte le prove "LI CONTI TORNANO" (ultimo dialogo tra la Morte e Brancaleone): effettivamente, rimossi i blocchi che avevo messo, al LOCK BITS BYTE nel suo insieme riesco a dare qualsiasi valore, quindi posso programmare sia i BLB e i LB. Il vero problema che mi si pone ora è capire tutto il casino che ruota attorno a questi 6 bit (due non sono usati); attenzione, non mi riferisco alla questione protegge/non protegge, già abbondantemente chiarita, ma proprio come si dovrebbe usarli. E per quanto sono riuscito a comprendere io spiegherei questo in prima battuta: Il LBB è così organizzato: 7-6 : non usati 5-4 : Protezione della Sezione Bootloader della memoria Flash 3-2 : Protezione della Sezione Application della memoria Flash 1-0 : Protezione della memoria Flash e EEPROM

Cioè a me pare di capire che mentre i bit 5-4 e 3-2 agiscono solo sulla specifica sezione di memoria flash (la Application va da 0x0000 all’inizio della Bootloader, che è fissato dai fuse: 512-1024-2048-4096 byte), i bit 1-0 agiscono sull’intera memoria flash e anche sulla EEPROM (sempre che non sia protetta dall’attivazione dell’apposito Fuse.

Tutto ciò lo ricavo dal Rev. 8271D–AVR–05/11 del 328P (salvo eccezioni sul 48P) pag. 283 par. 27.5 e pag. 297 par. 28.1 e la cosa mi sembra confermata dalla nota “Program the Fuse bits and Boot Lock bits before programming the LB1 and LB2” che ora finalmente capisco; infatti se è come ho intuito è ovvio che i LB siano più “potenti” dei BLB, che verrebbero ignorati; e infatti riesco a programmare nella direzione FF->FE->FC ma non nella direzione opposta.

Ma il mio inglese… :~ vi chiedo conferma, ho capito bene secondo voi?

Concordo con te. Ma la parte più significativa secondo me è la coppia di tabelle a pagina 284, dove spiega "chi" e "dove" può accedere. Vedi infatti le distinzioni fra area dell'applicazione ed area del booloader nonché i permessi della programmazione seriale e parallela.

Ah, piccola precisazione. Questo non è corretto:

la Application va da 0x0000 all’inizio della Bootloader, che è fissato dai fuse: 512-1024-2048-4096 byte

In realtà quei valori indicano la dimensione, non l'indirizzo di partenza. Il bootloader occupa sempre la parte più alta della memoria. Ma penso che tu abbia solo scritto male.

Comunque per chiarezza facciamo un esempio. Se abbiamo un Atmega168, la sua memoria va da 0000 a 16383 ($0000-$3FFF). Se impostiamo un bootloader di 512 byte, la memoria dell'applicazione va da $0000 a $3DFF, poi da $3E00 a $3FFF c'è il bootloader. In un 328, lo stesso bootloader occupa da $7E00 a $7FFF.

Menniti se non ricordo male (due settimane fa ho letto circa i 6 bit nel datasheet del 328) il tuo inglese questa volta è stato sufficiente. Possiamo dire che LB è Global Lockbit, e BLB e BLB1 sono Specific Lockbit.

Come usarli non lo so, io in avrdudequi li ho implementati come si vedono nel datasheet, con la stessa descrizione "pessima" perchè non ho saputo trovare niente di meglio e in mancanza ho preferito lasciare le note di Atmel.

Ciao.

Anticipato da leo:

Comunque per chiarezza facciamo un esempio. Se abbiamo un Atmega168, la sua memoria va da 0000 a 16383 ($0000-$3FFF). Se impostiamo un bootloader di 512 byte, la memoria dell'applicazione va da $0000 a $3DFF, poi da $3E00 a $3FFF c'è il bootloader. In un 328, lo stesso bootloader occupa da $7E00 a $7FFF.

Vero anche io penso che abbia scritto sbagliato ma sa come stanno le cose.

Grazie ragazzi, mi conforta questa cosa :) Allora chiarisco che mi sono spiegato male ma che ho ben presente la questione dell'area di bootloader: l'ho approfondita studiando i fuse bits in questi giorni; so che l'area Bootloader è nella parte alta della memoria e che l'indirizzo di partenza dipende da quanta memoria viene riservata ad essa, essendo tale valore variabile in base al settaggio dei fuse bits. Ora mi pare di aver capito anche ciò che dice lo specifico, pes. i due bit della sezione Application: 1 1 No restrictions for SPM or LPM accessing the Application section. (sezione non protetta) 1 0 SPM is not allowed to write to the Application section. (protetta da scrittura) 0 0 SPM is not allowed to write to the Application section, and LPM executing from the Boot Loader section is not allowed to read from the Application section. If Interrupt Vectors are placed in the Boot Loader section, interrupts are disabled while executing from the Application section. (protetta da scrittura e anche dalla lettura da parte del bootloader, eventuali vettori di interrupt collocati nel BL vengono disabilitati durante l'esecuzione dalla sezione Application) 0 1 LPM executing from the Boot Loader section is not allowed to read from the Application section. If Interrupt Vectors are placed in the Boot Loader section, interrupts are disabled while executing from the Application section. (come sopra ma solo per ciò che riguarda la protezione dalla lettura) :sweat_smile: che dite?

che l'area Bootloader è nella parte alta della memoria e che l'indirizzo di partenza dipende da quanta memoria viene riservata ad essa, essendo tale valore variabile in base al settaggio dei fuse bits.

Non mi pare così, direi che l'indirizzo di partenza in cui risiede il bootloader è sempre 00, poi dopo tot byte (in base ai fuse) termina l'area del bootloader e comincia quella così detta application area.

Ora mi pare di aver capito anche ciò che dice lo specifico, pes. i due bit della sezione Application: 1 1 No restrictions for SPM or LPM accessing the Application section. (sezione non protetta) 1 0 SPM is not allowed to write to the Application section. (protetta da scrittura) 0 0 SPM is not allowed to write to the Application section, and LPM executing from the Boot Loader section is not allowed to read from the Application section. If Interrupt Vectors are placed in the Boot Loader section, interrupts are disabled while executing from the Application section. (protetta da scrittura e anche dalla lettura da parte del bootloader, eventuali vettori di interrupt collocati nel BL vengono disabilitati durante l'esecuzione dalla sezione Application) 0 1 LPM executing from the Boot Loader section is not allowed to read from the Application section. If Interrupt Vectors are placed in the Boot Loader section, interrupts are disabled while executing from the Application section. (come sopra ma solo per ciò che riguarda la protezione dalla lettura) smiley-sweat che dite?

Si in effetti ora è anche più chiaro, scrivilo tutto in italiano che ha più senso. Appunto se ho un bootloader installato e voglio evitare che l'utente lo usi per leggere l'application area devo selezionare l'ultima sequenza di bit 0 1. Ma il bootloader può scrivere però magari non offre questa capacità all'utente di suo. Insomma io non ho un buon motivo per usarle forse per questo non mi figuro un caso di uso.

Ciao.

menny sono daccordo con la tua interpretazione/traduzion, mentre sul posizionamento fisico del bootloader anche io sapevo che era all'inizio della flash, mi sembra anche abbastanza logico, cioe' l'mcu inizia a lavorare sempre da 0000 e poi vediamo, se' ce' un bootloader il suo codice che mi indirizzera' all'applicativo, che e' piu' avanti fisicamente parlando

No, mi spiace contraddirvi. Il bootloader è nell'ultima sezione della Flash. La tabella a pag. 18 fa vedere chiaramente come il bootloader sia posizionato proprio in alto (basta vedere gli indirzzi).