2010-10-26 14 views
5

Ich habe Probleme einige Stück Code in MTD TreiberHilfe zu verstehen, Makro

#define ROUNDUP(x, y)  ((((x)+((y)-1))/(y))*(y)) 
... 
static struct mtd_partition my_parts[] = 
{ 
    { 
     .name = "boot", 
     .size = 0, 
     .offset = 0, 
     .mask_flags = MTD_WRITEABLE 
    }, 
    { 
     .name = "linux", 
     .size = 0, 
     .offset = 0 
    }, 
    { 
     .name = "rootfs", 
     .size = 0, 
     .offset = 0, 
     .mask_flags = MTD_WRITEABLE 
    }, 
    { 
     .name = "nvram", 
     .size = 0, 
     .offset = 0 
    }, 
    { 
     .name = 0, 
     .size = 0, 
     .offset = 0 
    } 
} 
... 

i = (sizeof(bcm947xx_parts)/sizeof(struct mtd_partition)) - 2; 

bcm947xx_parts[i].size = ROUNDUP(NVRAM_SPACE, mtd->erasesize); 
bcm947xx_parts[i].offset = size - bcm947xx_parts[i].size; 

So, hier sind meine questoins zu verstehen: 1) Warum ist es notwendig, die Größe der Partition abzurunden? 2) Könnten Sie helfen zu verstehen, wie die Rundung funktioniert? 3) Flash-Treiber im Bootloader auf der gleichen Plattform runden diese spezielle Partition nicht ab, daher hat das Flash-Layout verschiedene Offsets in der Kernel-Seite und im Bootloader. Was ist der Grund dafür?

Vielen Dank im Voraus für alle wertvollen Kommentare!

Antwort

6

(1) Der Flash-Speicher wird in Vielfachen seiner Löschgröße geliefert. (Anscheinend. Das sagt mir zumindest der zitierte Code.) Das bedeutet, dass zwischen dem Ende des NVRAM und dem, was als nächstes kommt, eine Lücke ist. Diese Lücke ist kleiner als die Größe einer Löschgröße. Im Flash ist es praktisch, zwei Objekte mit unterschiedlichen Zeitplänen für das Umschreiben nicht in einen einzelnen Löschblock zu setzen - das Ändern eines der Objekte erfordert, dass der Flash-Speichercontroller den Block in einen temporären Speicher kopiert, eine partielle Aktualisierung auf den Speicher anwendet, den Block löscht (langsam-ish) und schreibe den aktualisierten Block in den Hauptspeicher. (Es kann einen anderen zuvor gelöschten Block wiederverwenden und fädeln Sie es an der Stelle des ursprünglichen Blockes zurück aber das ist eine High-Tech-Optimierung berücksichtigt..)

(2) Wie Makros analysieren:

((((x)+((y)-1))/(y))*(y))

Schritt 1: Entfernen Sie die Parens um die Argumente herum, die sicherstellen, dass komplizierte Ausdrücke übergeben werden, da Argumente aufgrund der Vorrangstellung des Operators nicht plötzlich unerwartet neu verknüpft werden.

Schritt 2, entfernen paranoide Parens für Operationen, die eindeutig die angegebene Priorität haben.

Schritt 3, verwenden Sie Ihre C-Parsing-Regeln, nicht Ihre Algebra-Regeln. Wenn x und y ganzzahlige Typen sind (nicht genug Informationen in Ihrem Code, um sicher zu sein, dass dies der Fall ist), dann ist die Division eine Integer-Division, also übersetzen Sie von C nach math.

 floor((x+y-1)/y)*y

Schritt 4, lesen. Wenn x ein Vielfaches von y ist, dann, da y-1 zu klein ist, um ein Vielfaches von y zu sein, gibt die Operation nur x zurück. Wenn x 1 mehr als ein Vielfaches von y ist, dann schiebt das + y-1 den Zähler über das nächste Vielfache von y und das Ergebnis ist das kleinste Vielfache von y, das zufälligerweise größer als x ist. In der Tat, wenn x zwischen 1 mehr und y-1 mehr als ein Vielfaches von y ist, stößt das "+ y-1" den Zähler über das nächste Vielfache von y und das Ergebnis der Aufrundung ist das kleinste Vielfache von y größer als x.

Wir finden daher, dass ROUNDUP (x, y) x bis zum kleinsten Vielfachen von y rundet, das größer oder gleich x ist. Darüber hinaus wertet dieses Makro sein zweites Argument mehr als einmal aus: Fügen Sie keine Ausdrücke mit Nebenwirkungen in den zweiten Slot ein, es sei denn, Sie möchten, dass diese Nebenwirkungen dreimal pro Aufruf auftreten. (Betrachte int i = 3; ROUNDUP (6, i ++) und frage mich, welche Teilausdrücke vor und welche nach jedem der drei Inkremente von i.)

(3) Keine Ahnung. Niemand hat dem Bootloader-Writer gesagt, dass NVRAMs nur in Vielfachen von Erasesize kommen.

Verwandte Themen