Vai al contenuto
PLC Forum


Scrivere Nella Flash Dati Di Un Micro


valeria.dea

Messaggi consigliati

Ciao a tutti,

spero che qualcuno mi possa aiutare. worthy.gif

Sto sviluppando il firmware per un sensore che monta un microcontrollore della renesas, in particolare parlo del R8C/27.

E' la seconda volta che smanetto con i micro, ma prima non avevo avuto occasione di dover salvare dei dati nella data flash per poterli riavere disponibili ad ogni power-on.

Ho cercato i vari AN sul sito della renesas e ce ne sono anche di ben argomentati con tutte le istruzioni e i comandi per accedere ai blocchi della memoria dati.

Nonostante ciò non riesco ancora a capire di preciso come funzioni: in particolare non ho ben capito, ma la memoria viene scritta e cancellata in blocchetti da 64 byte? sempre?

E quando ho da memorizzare per esempio un array di char di dati diversi, come me li dispone?

Non sono ancora entrata nella logica della mappatura.

Attenzione, parlo della memoria dati e non della memoria programma.

unsure.gif

QUalche luminare all'ascolto che mi "illumini" rolleyes.gif

Grazie a tutti

Link al commento
Condividi su altri siti


Non conosco quel tipo di microcontrollore.

Sei sicura che si tratti di una flash e non di una EEPROM?

Solitamente la flash la si usa per il programma e per i dati statici si usa una EEPROM.

Link al commento
Condividi su altri siti

In pochi avevano sentito parlare di questo micro purtroppo,

infatti sto imparando tutto da sola, è difficile che qualcuno sappia darmi una dritta.

comunque chiedendo al grande popolo di internet sento di avere una speranza.

Dicevo,

sono sicura che sia una flash.

Praticamente è divisa in 2 blocchi separati.

Dall'indirizzo 0x2400 a 0x2BFF è memoria dati, mentre da 0x8000 a 0xFFFF è memoria programma. Il tool per programmare la flash è impostato automaticamente per iniziare a scrivere dall'indirizzo 0x8000, quindi io ci ho memorizzato un programmino che esegue i comandi di scrittura specifici per il blocco di memoria superiore (data flash). Lo faccio partire, quello dovrebbe memorizzarmi i dati che gli ho dato, e poi lo riprogrammo con un prog di lettura per verificare.

Mi restituisce solo 0x00.

Prima provavo a leggere direttamente dall'indirizzo di memoria e mi ridava 0xFF, ora ho riprovato col comando specifico di lettura per la memoria dati (preso dal suo application note) e mi ridà 0x00.

Non so che pesci pigliare

Grazie per l'attenzione

Link al commento
Condividi su altri siti

Se è una flash allora è possibile che si debba scrivere un blocco di lunghezza specifica.

Io proverei, come prima cosa, a verificare se è possiible modificare l'indirizzo di partenza del tool per la programamzione in flash.

Proverei anche a capire come lavora questo tool

Link al commento
Condividi su altri siti

Allora,

L'indirizzo di partenza si può modificare, ci avevo anche pensato a fare una cosa del genere, impostare l'area di memoria da scrivere ai soli blocchi della memoria dati.

In questo caso dovrei semplicemente allocare la memoria con degli array di dati costanti? e in che modo me li memorizza? perchè poi io ho bisogno di andare a recuperarli in fase di run-time ed eventualmente modificare i dati di default.

Quindi in qualsiasi caso io devo riuscire a far funzionare i comandi di scrittura sulla flash dati, anche perchè questa particolare modalità richiede esplicitamente che le aree di memoria che vado a sovrascrivere non devono essere quelle in cui è contenuto il programma che esegue i comandi.

Per quanto riguarda il funzionamento del tool, non so come muovermi, nel senso che non so bene cosa andare a guardare per capire come funziona effettivamente, come gestisce la mappa della memoria, o cose simili.

comunque intanto scrivo i nomi del kit di sviluppo che utilizzo così magari qualcuno li ha usati e sa qualcosa in più.

Il compilatore è High-Performance Embedded Workshop e il programmatore è M16C Flash Start.

Link al commento
Condividi su altri siti

Nelle flash "standard" la cancellazione e la scrittura si eseguono a blocchi e attraverso opportuni comandi scritti in una certa sequenza.

Devi trovare il datasheet specifico e utilizzare i comandi di sequenza, forse dovrei avere un prg fatto tempo addietro in delphi, lo cercherò....

Comunque non è semplice... wallbash.gif

Link al commento
Condividi su altri siti

Meno male che c'è qualcuno che mi rincuora, non sono io allora che vedo tutto così complicato!?!?!

Comunque il datasheet con tutti i comandi (che poi sono solo 5) e la sequenza richiesta per mandarli, ce l'ho e ho già provato.

Ci sono anche degli esempi in C, che ho adattato al mio caso (spero in modo corretto).

Su gli AN si parla di trattare la memoria a blocchi da 64 byte l'uno.

Ora, quello che non capisco è, in questi 64 byte cosa ci metto se io devo memorizzare solo qualche char?

Cioè, se io creo un array di char con le costanti da memorizzare ma di grandezza inferiore a 64 byte, e poi lo affido ad un loop che me lo passa all'indirizzo del primo blocco libero, cosa succede praticamente? Fin dove scrive?

Appena trovi il codice che hai scritto (anche se il delphi non lo conosco) me lo passeresti?

Grazie

Link al commento
Condividi su altri siti

Purtroppo le flash si scrivono a blocchi.

Io userei questa tecnica. Leggo il blocco; vado al primo byte libero ed inizio a scrivere i miei dati; scrivo tutti ff nei bytes che rimangono liberi.

Puoi riservare uno o più bytes dove scriverai l'indirizzo dell'ultimo byte memorizzato nel blocco, per esempio il 64.o bytes o il primo.

Link al commento
Condividi su altri siti

Livio Orsini+25/09/2009, 18:37--> (Livio Orsini @ 25/09/2009, 18:37)

Che io ricordi non è possibile "scrivere" FFh nei bytes, nelle flash la cancellazione di un blocco porta tutti i bytes a FFh, poi la scrittura mette a zero i bit ove necessario, ma non si può una volta azzerato il bit riportarlo a 1 senza la cancellazione.

Comunque ho trovato l'esempio di codice, lo aggiusto un po' e poi lo posto.

Link al commento
Condividi su altri siti

Innanzi tutto vorrei scusarmi se questo post sarà un po' lungo, spero di non annoiare nessuno!

Premessa:

- il codice Delphi in questione, scritto da me e da un collega di Ancona, era specifico per le flash 29LV160D e 29LV800B

- la 29LV160D esiste in due formati diversi, B e T che si differenziano dalla dimensione diverse di alcuni blocchi e dalla loro posizione (Bottom e Top), per migliorare l'eventuale comprensione potete trovare il datasheet della flash su Google.

- la scrittura avveniva mediante la porta EJTAG di un microprocessore MIPS, quindi in seriale.

Interrogazione del microprocessore MIPS per sapere di che flash si tratta:

     FlashId:=FlashIdentify($1fc00001);
     case FlashId of
        $90: Edit4.Text:='AMD';
        $04: Edit4.Text:='Fujitsu';
        $20: Edit4.Text:='ST';
     else
        Edit4.Text:=' Unknow!';
     end;
     FlashId:=FlashIdentify($1fc00002);
     case FlashId of
        $22DA: Edit3.Text:='29LV800BT';
        $22C4: Edit3.Text:='29LV160DT';
        $2249: Edit3.Text:='29LV160DB';
     else
        Edit3.Text:=' Unknow!';
     end;
Cancellazione di un settore (blocco):
     // Reset Flash
     writedata := $F0;
     writedata := (writedata and $FFFF) or ((writedata shl $10) and $FFFF0000);
     Write16(adr,writedata);

     // Sector Erase command
     padr := (adr and $FFF00000) or $AAA;
     writedata := $AA;
     writedata :=( writedata and $FFFF) or ((writedata shl $10) and $FFFF0000);
     Write16(padr,writedata);

     padr := (adr and $FFF00000)  or $554;
     writedata := $55;
     writedata := (writedata and $FFFF) or ((writedata shl $10) and $FFFF0000);
     Write16(padr,writedata);

     padr := (adr and $FFF00000) or $AAA;
     writedata := $80;
     writedata := (writedata and $FFFF) or ((writedata shl $10) and $FFFF0000);
     Write16(padr,writedata);

     padr := (adr and $FFF00000) or $AAA;
     writedata := $AA;
     writedata := (writedata and $FFFF) or ((writedata shl $10) and $FFFF0000);
     Write16(padr,writedata);

     padr := (adr and $FFF00000) or $554;
     writedata := $55;
     writedata := (writedata and $FFFF) or ((writedata shl $10) and $FFFF0000);
     Write16(padr,writedata);

     padr := (adr and $FFFFF000);
     writedata := $30;
     writedata := (writedata and $FFFF) or ((writedata shl $10) and $FFFF0000);
     Write16(padr,writedata);
Scrittura della flash:
procedure TForm1.ProgramFlash(adr,size,offset : dword);
var  data      : dword;
     writedata : dword;
     padr      : dword;
     startadr  : dword;
     dump      : dword;
     Count     : dword;
     error     : byte;
begin

     // Reset Flash  
     writedata := $F0;
     writedata := (writedata and $FFFF) or ((writedata shl $10) and $FFFF0000);
     Write16(adr,writedata);

  
     // Unlock Bypass command
     padr      := (adr and $FFF00000) or $AAA;
     writedata := $AA;
     writedata := (writedata and $FFFF) or ((writedata shl $10) and $FFFF0000);
     Write16(padr,writedata);

     padr      := (adr and $FFF00000) or $554;
     writedata := $55;
     writedata := (writedata and $FFFF) or ((writedata shl $10) and $FFFF0000);
     Write16(padr,writedata);

     padr      := (adr and $FFF00000) or $AAA;
     writedata := $20;
     writedata := (writedata and $FFFF) or ((writedata shl $10) and $FFFF0000);
     Write16(padr,writedata);

     error     := 0;
     startadr  := adr;
     writedata := 0;
     Count     := 0;

     while ( (Count < Size) and (error < 5) ) do
           begin
  writedata :=              (Buffer[Count+$00 + Offset] shl $18);
  writedata := writedata or (Buffer[Count+$01 + Offset] shl $10);
  writedata := writedata or (Buffer[Count+$02 + Offset] shl $08);
  writedata := writedata or (Buffer[Count+$03 + Offset]);
  Inc(Count,$04);

  writedata := bigtolittle(writedata);
  dump      := writedata;

  if (writedata <> $FFFF) then
     begin

                        // Unlock Program
          data := $A0;
          data := (data and $FFFF) or ((data shl $10) and $FFFF0000);
          Write16(adr,data);

          writedata := (writedata and $FFFF);
          writedata := ((writedata and $FF) shl $08) or ((writedata and $FF00) shr $08);
          writedata := writedata or (writedata shl $10);
          Write16(adr,writedata);

          writedata := (dump shr $10) and $FFFF;
                 inc(adr,$02);

          data := $A0;
          data := (data and $FFFF) or ((data shl $10) and $FFFF0000);
          Write16(adr,data);

          writedata := (writedata and $FFFF);
          writedata := ((writedata and $FF) shl $08) or ((writedata and $FF00) shr $08);
          writedata := writedata or (writedata shl $10);
          Write16(adr,writedata);


                 inc(adr,$02);
     end;
    end;

     // Unlock Reset command
     writedata := $90;
     writedata := (writedata and $FFFF) or ((writedata shl $10) and $FFFF0000);
     Write16(startadr,writedata);
     writedata := $F0;
     writedata := (writedata and $FFFF) or ((writedata shl $10) and $FFFF0000);
     Write16(startadr,writedata);
     Write16($33330000,$100E8);
     Write16($3333,$100EA);
end;

Molte flash utilizzano comandi standard, ma è sempre meglio verificare il datasheet per sicurezza.

Modificato: da Jtag
Link al commento
Condividi su altri siti

Ciao Valeria

Visto che sei alle prime armi con i micro ti consiglio vivamente di abbandonare in fretta i renesas. IO ho appena ultimato un lavoro con renesas e giuro mai più !

Ti accorgerai presto di quanto flessibili meglio documentati semplici sono altri micro ma questo non risolve il tuo problema....

Se ho capito bene tu vuoi utilizzare il blocco flash della memoria dati interno al micro.

Riassumo i suggerimenti che ti hanno dato qui sopra:

innanzitutto nella flash non scrivi quello che vuoi puoi solo azzerare i bit come dei birlilli li metti tutti in piedi (a 1) e poi li butti giù (a zero).

Leggendo la doc del tuo micro vedo che si può scrivere un byte alla volta ma scrivere in flash significa portare dei bit da 1 a zero non puoi mai portare dei bit da 0 a 1 Quindi se tu hai fatto più tentativi di scrittura dello stesso byte con valori diversi probabilmente hai messo a zero tutti bit del byte e per questo leggi il valore zero.

Prima operazione da fare per una scrittura in flash è assicurarsi di aver rimesso tutti i bit a 1. Per far questo devi cancellare il byte da riscrivere. Sembra facile ma in realtà c'è l'inghippo perchè la cancellazione funziona a blocchi. Non cancelli un solo byte ma un blocco di bytes. Quindi devi cancellare il blocco in modo che tutti byte della flash siano a 0FFh poi scrivi un byte alla volta e di fatto metti a 0 alcuni di questi bit.

Attenzione la scrittura in flash non è la stessa della ram devi fare una sequenza Leggendo velocemente la doc renesas devi scrivere 040h all'indirizzo flash che vuoi aggiornare poi scrivi il byte e, importante (!!!), aspetti che FRMO0 sia a 1 vedi il diagramma a pag 368 della doc hw. La scrittura in flash è lenta perciò per scrivere il byte successivo devi attendere la fine della scrittura byte precedente.

Quindi io imposterei le cose così ti crei una variabile in RAM con dimensioni pari a un blocco flash (dove blocco indica il numero di byte che devi cancellare tutti insieme prima di riscrivere la flash) e fai questa procedura

1.- Copia da flash a ram del blocco dati da aggiornare

2.- aggiornamento in ram dei dati che devo modificare

3.- cancellazione blocco flash

4.- scrittura di tutto il blocco flash

Modificato: da accacca
Link al commento
Condividi su altri siti

Ecco quello che mi ci voleva,

uno che ci ha già lavorato, perchè chi non ha mai avuto a che fare con i renesas non si rende conto dell' "antipatia" di questi micro.

Purtroppo non posso abbandonarlo perchè è un lavoro.

Ti ringrazio tantissimo,

almeno ora ho capito la logica di funzionamento.

Lunedì appena torno al lavoro applico tutti i tuoi suggerimenti e speriamo che sia la volta buona.

Grazie grazie grazie

Link al commento
Condividi su altri siti

Ora ho capito dov'era il problema, e in effetti ancora infierisce, ed è il seguente.

La memoria del micro, avevo già accennato, è una flash suddivisa in 2 blocchi, uno per la memoria dati e l'altro per la memoria programma.

La mia idea era quella di scrivere la memoria dati preinserendo un programmino (nella memoria programma) che memorizzasse i valori di default tramite gli appositi comandi software.

Dopo di che, l'intenzione era di riprogrammare solo la memoria programma col firmware che poi avrebbe utilizzato quei dati caricati nella memoria dati ed eventualmente modificati all'occorrenza.

Ora però mi sono accorta che il motivo per cui leggevo 0xFF nella memoria dati nonostante l'avessi scritta nel primo passaggio, è che per inserire il secondo programma è necessario cancellare la memoria con il comando di Erase del tool di programmazione.

Io pensavo che cancellasse solo a partire dall'indirizzo della memoria programma, dato che anche sul manuale c'è scritto che con questo tool non è possibile cancellare/scrivere/leggere la memoria dati; e invece facendo una ricerca degli indirizzi vuoti tramite il comando Blank proprio di questo tool, mi sono accorta che era vuoto anche il blocco della memoria dati.

Ho pensato di caricare i valori di default con un unico programma che poi sarà quello definitivo, ma l'inconveniente sta nel fatto che ad ogni accensione mi riscrive i dati di default e invece io voglio che in caso di modifica, restino tali ad una successiva accensione, e che vengano ripristinati solo in caso di un mio comando specifico.

Come si può aggirare il problema secondo voi?

Link al commento
Condividi su altri siti

checksum!

leggi i dati fai qualche operazione su tutti i byte e il risultato lo memorizzi alal fine della tabella

La prima volta leggi fai i calcoli e la checksum è sbagliata perciò scrivi i valori di default.

La seconda volta leggi fai i calcoli e la checksum è corretta non scrivi niente

Svantaggio ad ogni modifica dei parametri devi ricalcolare e riscrivere la checksum

Per il calcolo della checkusm un'idea semplice semplice potrebbe essere lo xor di tutti i byte coinvolti partendo da un valore predefinito ad es. 0x55

Link al commento
Condividi su altri siti

Non esageriamo ne ho già quattro sulla gobba....

mi ero dimenticato una cosa prima

sarebbe cosa buona e giusta fare un cotnrollo di congruenza dei dati della tabella prima di dire tutto ok

fai il test chksum se ok controlli che i dati abbiano valori coerenti con quello che prevede il programma cioè il valore sia tra min e max così non parti con dati sballati che potrebbero creare problemi

Link al commento
Condividi su altri siti

Alla fine sto facendo un controllo iniziale,

con la condizione che se il blocco è tutto vuoto (0xFF) allora vuol dire che è la prima accensione e devo scrivere la memoria dati, alla seconda accensione il blocco ha dei dati diversi da 0xff e quiindi posso iniziare con le operazioni di routine.

Così sta andando bene fino ad ora,

e man mano sto impostando i controlli affinchè i dati siano veritieri.

Grazie ancora

Link al commento
Condividi su altri siti

Crea un account o accedi per commentare

Devi essere un utente per poter lasciare un commento

Crea un account

Registrati per un nuovo account nella nostra comunità. è facile!

Registra un nuovo account

Accedi

Hai già un account? Accedi qui.

Accedi ora
×
×
  • Crea nuovo/a...