2010-10-26 19 views
5

estoy teniendo problema para entender alguna pieza de código en el controlador MTDayuda a entender 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; 

Así que aquí están mis questoins: 1) ¿por qué es necesario redondear el tamaño de la partición? 2) ¿podría ayudarme a entender cómo funciona el redondeo? 3) el controlador flash en el cargador de arranque en la misma plataforma no hace el redondeo para esta partición específica, por lo que el diseño del flash tiene diferentes compensaciones en el lado del kernel y en el gestor de arranque. ¿Cuál es la razón para esto?

¡Gracias de antemano por sus valiosos comentarios!

Respuesta

6

(1) La memoria flash viene en múltiplos de su tamaño de borrado. (Al parecer, al menos, esto es lo que el código citado me dice). Esto significa que hay un espacio entre el final de la NVRAM y lo que viene después. Esta brecha es menor que el tamaño de un tamaño de borrado. En flash, es conveniente no colocar dos objetos con diferentes programaciones de reescritura en un solo bloque de borrado: cambiar cualquiera de los objetos requiere que el controlador de almacenamiento flash copie el bloque en una tienda temporal, aplique una actualización parcial a la tienda, borre el bloque (slow-ish), y escribe el bloque actualizado en la tienda principal. (Se puede volver a utilizar alguno de los bloques borrados diferente y el hilo de nuevo en el lugar del bloque original, pero esto se considera una optimización de alta tecnología..)

(2) Cómo analizar las macros:

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

Paso 1, elimine los parens en torno a los argumentos que aseguran que las expresiones complicadas pasadas como argumentos no vuelvan a vincularse repentinamente de forma inesperada debido a la precedencia del operador.

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

Paso 2, elimine pares paranoicos para las operaciones que claramente tienen la precedencia indicada.

(x+y-1)/y*y

Paso 3, use sus reglas de análisis C, no sus reglas de álgebra. Si xey son tipos integrales (no hay suficiente información en su código para estar seguro de esto), entonces la división es una división entera, entonces traduzca de C a matemática.

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

Paso 4, leer. Si x es un múltiplo de y, dado que y-1 es demasiado pequeño para ser un múltiplo de y, la operación simplemente devuelve x. Si x es 1 más que un múltiplo de y, entonces + y-1 empuja el numerador sobre el siguiente múltiplo de y y el resultado es el múltiplo más pequeño de y que resulta ser mayor que x. De hecho, si x está entre 1 más y y-1 más que un múltiplo de y, "+ y-1" subirá el numerador en el siguiente múltiplo de y y el resultado del redondeo será el múltiplo más pequeño de y más grande que x.

Lo que encontramos, por lo tanto, es que ROUNDUP (x, y) redondea x hasta el múltiplo más pequeño de y que resulta ser mayor o igual a x. Además, esta macro evalúa su segundo argumento más de una vez: no coloque expresiones con efectos secundarios en la segunda ranura a menos que desee que esos efectos secundarios sucedan tres veces por llamada. (Considere int i = 3; ROUNDUP (6, i ++) y pregunte qué subexpresiones se evalúan antes y cuáles después de cada uno de los tres incrementos de i.)

(3) No tengo idea. ¿Nadie le dijo al escritor del gestor de arranque que las NVRAM solo vienen en múltiplos de tamaño borrado?

Cuestiones relacionadas