2010-10-26 11 views
5

Je vais avoir problème pour comprendre un morceau de code dans le pilote MTDaide à comprendre macro

#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; 

Alors voici mes questoins: 1) pourquoi est-il nécessaire d'arrondir la taille de la partition? 2) pourriez-vous aider à comprendre comment les arrondis fonctionnent? 3) le pilote flash dans le chargeur de démarrage sur la même plate-forme n'effectue pas l'arrondi pour cette partition spécifique, donc la disposition flash a des décalages différents dans le noyau et dans le bootloader. Quelle est la raison pour ça?

Merci d'avance pour tous les commentaires utiles!

Répondre

6

(1) La mémoire flash est fournie en multiples de sa taille d'effacement. (Apparemment, au moins, c'est ce que le code cité me dit.) Cela signifie qu'il y a un écart entre la fin de la NVRAM et ce qui vient ensuite. Cet écart est inférieur à la taille d'une taille d'effacement. En Flash, il est commode de ne pas placer deux objets avec des horaires de réécriture différents dans un seul bloc d'effacement - le changement de l'objet nécessite que le contrôleur de stockage flash copie le bloc dans un magasin temporaire, applique une mise à jour partielle, efface le bloc slow-ish), et écrire le bloc mis à jour dans le magasin principal. (Il peut réutiliser un autre bloc effacé précédemment et le fil en arrière à la place du bloc d'origine, mais cela est considéré comme une optimisation de haute technologie..)

(2) Comment analyser les macros:

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

Étape 1, supprimez les parens autour des arguments qui s'assurent que les expressions compliquées passées en arguments ne se reconnectent pas soudainement de manière inattendue en raison de la priorité de l'opérateur.

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

Étape 2, supprimez les parens paranoïa pour les opérations qui ont clairement la priorité indiquée.

(x+y-1)/y*y

Étape 3, utilisez vos règles d'analyse C, pas vos règles d'algèbre. Si x et y sont des types entiers (pas assez d'informations dans votre code pour en être certain), alors la division est une division entière, donc traduisez de C en math.

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

Étape 4, lire. Si x est un multiple de y, alors y-1 est trop petit pour être un multiple de y, l'opération ne fait que renvoyer x. Si x est 1 plus qu'un multiple de y, alors + y-1 pousse le numérateur sur le multiple suivant de y et le résultat est le plus petit multiple de y qui est plus grand que x. En fait, si x est entre 1 plus et y-1 plus qu'un multiple de y, le "+ y-1" heurte le numérateur sur le multiple suivant de y et le résultat de l'arrondi est le plus petit multiple de y que x. Nous constatons donc que ROUNDUP (x, y) arrondit x au plus petit multiple de y qui soit supérieur ou égal à x. De plus, cette macro évalue son deuxième argument plus d'une fois: ne placez pas d'expressions avec des effets secondaires dans le second emplacement à moins que vous ne souhaitiez que ces effets secondaires se produisent trois fois par appel. (Considérez int i = 3; ROUNDUP (6, i ++) et demandez quelles sous-expressions sont évaluées avant et lesquelles après chacun des trois incréments de i.)

(3) Aucune idée. Personne n'a dit au rédacteur de bootloader que les NVRAM ne viennent qu'en multiples d'effacement?