Newsgroup: it.comp.lang.c
Titolo: Implementare un filesystem... microscopico

Riprovo a descrivere il mio problema in modo più generale.
Nel sistema embedded che utilizzo non ho né sistema operativo, né
filesystem, né hard-disk. Ho soltanto una EEPROM (8KByte) per
memorizzare in modo non volatile alcune impostazioni della macchina.
Diciamo un 300-400 variabile della dimensione media di 4-5 byte (ce ne
sono molte da 1 byte e alcune da 10-20 byte).
Vorrei modularizzare molto il codice e quindi creare una libreria di
accesso alla EEPROM che fornisca dei "servizi" di scrittura/lettura
delle variabili non volatili in EEPROM.
In pratica, un modulo dovrà poter comunicare con la libreria dicendo:
ho la necessità di memorizzare una variabile da 5 byte, un'altra da 3
byte, un'altra da 10 byte, ecc. E così gli altri moduli. L'effettiva
posizione in EEPROM dovrà essere compito della libreria e non del
modulo.
Siccome vorrei essere risparmioso in termini di codice e di memoria,
se ci pensate un attimo la disposizione (e quindi gli indirizzi di
allocazione) in EEPROM è qualcosa di statico che rimane costante
dall'inizio alla fine dell'esecuzione. Si potrebbe sfruttare ciò per
utilizzare delle costanti (memorizzate nella Flash del processore)
piuttosto che delle variabili in RAM.
Mi sembra di parlare di un piccolissimo filesystem statico dove ogni
file è rappresentato da una variabile. Statico perchè i file vengono
creati a design-time e non possono essere modificati né cancellati a
run-time (solo il contenuto dei file, cioè il valore della variabile
memorizzato in EEPROM può ovviamente cambiare a run-time).
Esiste già qualcosa del genere in giro? Qualcuno mi può aiutare con
l'implementazione di questo mostro? Oppure mi potete consigliare
qualche altro approccio?
PS: Ho abbandonato l'approccio della tabella (vedi il mio post
precedente) perchè non avrei modularità. Il modulo X che gestisce n
variabili da memorizzare in EEPROM non è self-contained, ma una sua
parte sarà presente appunto nella tabella.
PS2: Ci sarebbe anche un'altra questione, penso più difficile da
ottenere. Nella versione 1.0 ho una certa allocazione di variabili in
EEPROM, per esempio il contrasto del display è memorizzato
all'indirizzo 0x0100. Ovviamente nella versione 1.1 potrei aver
aggiunto o modificato le variabili in EEPROM perchè ho aggiunto altre
feature al software. Sarebbe però gradito poter mantenere lo stesso
indirizzo alle stesse variabili. Questo per evitare che
l'aggiornamento del software dalla versione 1.0 alla 1.1 faccia
perdere le impostazioni precedenti comuni alla versione precedente
(per esempio appunto il contrasto).


Metti i valori hardcoded. Sai che all'indirizzo 0x0100 c'è il
contrasto? metti una #define CONTRASTO 0x0100  :D
Ok, non è per nulla bello, ma se il problema è la "versione" della
eeprom (dalla 1.0 alla 1.1) scrivi sequenzialmente ciò che ti serve,
sversionando il file di defines in maniera programmatica. Questo direi
che è l'approccio classico. Se il problema è la modularità,
semplicemente metti il file di #define e le funzioni in una libreria
indipendente dal resto.
Se invece sei un maniaco della precisione e soprattutto se credi di
passare in futuro da una EEPROM a una flash (cosa che ritengo comunque
improbabile) usa un filesystem :-) In un giorno ti fai
l'implementazione di una FAT12. In ogni caso secondo me è fatica
sprecata e un extreme overkill per quello che devi fare.
Poi certo, è sempre possibile inventarsi un approccio intermedio, ma
io andrei per la prima.

 io andrei per la prima.
Se non c'è altra strada fattibile, penso allora che non abbandonerò il
vecchio sistema seppur
molto scomodo.

 In un giorno ti fai l'implementazione di una FAT12.
Però mi hai fatto venire un'idea... Se trovo dei tool su PC che
gestiscono immagini di FAT12,
potrei crearmi l'immagine del filesystem su PC e trasferirla così
com'è sulla EEPROM.
Implemento la FAT12 nel mio software embedded e il gioco è fatto.
Posso pure evitare di implementare
le routine di creazione/cancellazione file visto che la struttura è
statica durante l'esecuzione.
La coerenza con le versioni verrebbe mantenuta intrinsecamente perchè
ogni parametro viene
ricercato tramite nome e non tramite indirizzo, quindi anche se questi
cambia da una versione all'altra
non è un problema.
L'unico dubbio è sulla dimensione. Quanto può occupare una immagine di
un filesystem FAT12 con
300-400 file della dimensione media di 4-5 byte? Rientro negli 8KB
dellla mia EEPROM? Molto
probabilmente dipenderà anche dai nomi dei file che potrei mantenere
sempre di 3-4 caratteri.
Idea malsana?


<fat>
Nessuno dice che devi implementare tutte le caratteristiche della FAT.
Se non ti servono le cartelle, non scrivere il codice :-)
Per quanto riguarda i files, non è detto che tu debba avere un file
per parametro, anzi - a quel punto io li raggrupperei in vari files a
seconda di quel che fanno.
</fat>
<defines>
Per quanto riguarda i #defines, puoi scrivere "meno" anche facendo una
mega struct con tutti i parametri così come andrebbero sulla EEPROM, e
calcolarti l'offset facilmente.
</defines>


L'unico motivo che ho trovato per usare un filesystem del genere è
appunto la facilità di lettura/scrittura "fuori" dalla scheda (stacchi
la flash e la leggi/scrivi dal pc). Se non fosse per questo non
sarebbe una buona idea.
Senza contare che debuggare una cosa del genere è molto molto
fastidioso.
Ripeto - io andrei per i #define (o semmai la struct, a seconda di
cosa memorizzi)

 Gi� me lo vedo il file delle #define dei 300 indirizzi... :(
La butto li: un piccolo programma esterno per calcolare automaticamente 
gli indirizzi e generare il file con le varie define?
Magari le info sui parametri le metti fra i commenti (es: lunghezza in 
byte del parametro)
Alessandro

 del parametro)
Io farei la stessa cosa.
-- 
Mio figlio: 
http://it.youtube.com/davideippopotamo
La violenza non puï¿œ essere una esclusiva dei malfattori.
Ladri del mio appartamento, vi siete dimenticati un coltellaccio da 
cucina, tornate.

 Idea malsana?
abbastanza
io mi scriverei il preprocessore (yacc/flex o awk ) che dato 
tipo,nome,valore mi genera l'iimagine della eprom con i dati sequenziali

   
Il filesystem secondo me va preso in considerazione se hai un sistema 
operativo che ti d� un modo standard e pulito per accedere ai file: se 
gli fornisci un driver che permette di accedere all'eeprom in modo 
standard, il tuo programma diventa leggero ed elegante. Eleganza e 
pulizia che paghi con:
1) una maggior complessit� del codice nel suo complesso: un sistema 
operativo full fledged anzich� un main loop e qualche handler scritti ad 
hoc.
2) occupazione dell'eeprom da parte delle strutture necessarie al 
funzionamento del filesystem.
Comunque il problema che ti poni l'ho visto risolvere con la sfilza di 
#define
Giovanni

 dimensione fissa
Sicuramente un parametro per file non sarebbe possibile: considerando
300
parametri avrei 300 file che per 512 byte fanno più di 8KB.

 #define
E la soluzione con una struct da scrivere invece che calcolarsi a mano 
le posizioni?
Enrico

 parametri avrei 300 file che per 512 byte fanno pi� di 8KB.
ma a quel punto (tutti i parametri in sun solo file ) a cosa ti serve 
avere un file systme che gestisce piu' file ?
probabilmente la soluzione piu' semplice e' avere una gestione "lineare" 
  dei dati e la famosa sfilza di #define generata in maniera piu' o meno 
automatica, cosi' potrai vantarti di aver creato un tuo linguaggio di 
definizione dei dati :-)

Enrico Bassetti ha scritto:

S�, l'avevo proposto a chi ha aperto questo thread, nel thread "Array di 
struct con inizializzazione", per� il problema � che in eeprom sarebbe 
meglio avere qualcosa di impacchettato, cosa che il C standard non 
permette di specificare. Peccato che K & R non ci abbiano pensato, 
mentre ci ha pensato il Prof N.Wirth quando ha inventato il Pascal.
Se uno accetta di buttare via qualche byte e proprio non ne vol sapere 
di usare costrutti non standard, no problem, offsetof() e sizeof() le 
hanno inventate apposta.
Giovanni

 Giovanni
Se ti riferisci al padding delle struct basta sapere come lavora il
compilatore. Un compilatore potrebbe anche scegliere di non mettere
alcun padding, o viceversa di raddoppiare la dimensione in memoria di
ogni struct senza motivo.

 permette di specificare. Peccato che K & R non ci abbiano pensato, 
Non � standard, ma ogni compilatore C che ho usato ha la sua direttiva 
packed.
Per esempio, per il compilatore ARM Realview:
__packed struct {
	U16		pippo;
	U16		pluto [3];
	U8		 topolino;
} robi;
Col gcc, mi pare si usi __attribute__((packed));
Bye,
L