Registro de acceso (lectura/escritura) en C

Tengo algunos malentendidos sobre los conceptos de registro del procesador. Hay un registro con dirección, digamos, 0x0345678. Este registro tiene 32 bits de ancho/largo (no importa ahora, qué palabra es la correcta). Como está escrito en el manual, hay algún tipo de tabla/matriz:

Posición Valor 0 111111...10b 1 111111...11b 2 7A ....................... 7 3F7C

Tengo que acceder al valor con la posición 2. Lo primero que hice fue:

#define REG 0x0345678

void somereadfunction()
{
   volatile unsigned int *pval = (volatile unsigned int *)REG;
   printf("%x", *(pval | 0x02));
}

Y como ya habrás adivinado, fue una suposición equivocada.

Otro intento fue este:

    for(unsigned int i = 0; i < 3; i++)
    {
        printf("i: %d, res: 0x%08X", i, *((volatile unsigned int *)REG));
    } 

Y funciona. Entonces, mi pregunta es, ¿por qué y cómo? ¿El procesador simplemente cambia el valor del registro con algún algoritmo mágico adentro, escrito por otro desarrollador? Estoy un poco confundido acerca de eso. Sé cómo acceder al tercer bit del registro usando algunas operaciones simples de bits, pero no entiendo, ¿cómo, simplemente llamando tres veces al registro, obtendremos el valor correcto?

Gracias de antemano por sus respuestas.

AGREGADO: el procesador es ARM 7. Usó el dispositivo i2c.

preguntado el 12 de junio de 12 a las 17:06

Es imposible saber exactamente qué está haciendo su procesador (o algún chip en su placa) sin saber qué es ese chip. Aparte de eso, sí, las "cosas" pueden almacenar el estado (incluida la cantidad de veces que se han leído sus puertos) y devolver cosas diferentes en momentos diferentes. -

@Mat, el procesador es ARM 7 -

¿Entonces? Tales cosas pueden suceder en cualquier cosa (ARM, x86, PPC, lo que sea). ¿A qué componente exacto estás accediendo? ¿Qué dice el documento donde encontraste esa dirección de registro? -

Bueno, como dije, el dispositivo I2C puede mantener el estado y devolver diferentes elementos dependiendo de cuántas veces lo lea. Los primeros dos valores son (probablemente) marcadores para que pueda determinar cuándo el dispositivo está comenzando un nuevo "ciclo". Lea los documentos detenidamente para ese dispositivo. -

@Mat, @user1415536: Esto no es un registrarse sino más bien un mapa de memoria FIFO / LIFO Puerto. Leerlo es una especie de equivalente a realizar una pop operación en alguna pila/ringbuffer oculto interno del dispositivo - la próxima vez que lo llame, pop algo más. No es tan inusual, pero debe documentarse en el manual del dispositivo. -

3 Respuestas

Por qué ?

Porque las personas que construyeron su dispositivo de hardware (que está conectado a su procesador ARM) probablemente declararon solo algunas direcciones que "pertenecen" al dispositivo. Luego, notaron que había más datos en el hardware que registros, y era demasiado tarde para cambiar el manual, por lo que decidieron que algunos registros tuvieran valores múltiples.

¿Cómo?

El hardware tiene un contador interno que cuenta los comandos de lectura del procesador. Cada vez que el procesador quiere leer del registro, el hardware le envía otro dato, indexado por el contador interno invisible, y aumenta el contador. El contador es de 3 bits, por lo que cuenta 0, 1,..., 7, 0, 1,... etc.

Entonces, si desea leer los datos con el índice 2, también debe leer todos los demás elementos de datos (3, 4, 5, 6 y 7) para restablecer el contador invisible.

Respondido el 12 de junio de 12 a las 17:06

Los registros de E/S asignados a la memoria cambian su contenido en función de las lecturas y escrituras en ellos. Sin embargo, la forma en que lo describiste es un poco extraña, generalmente uno escribe un valor en un registro de control para decirle al dispositivo a qué registro interno acceder y luego lee el valor desde otra ubicación.

Respondido el 12 de junio de 12 a las 17:06

pero funciona de esta manera. Sí, generalmente tiene que escribir algo, y solo después de eso puede leer el valor. - user1415536

lo siento. no puedo hacerlo Este manual sólo en papel. Pero como dijo Mat, los dispositivos i2c pueden hacer esas "cosas". - user1415536

*(pval | 0x02) debería ser realmente ser *(pval + 0x2) si está tratando de indexar en la segunda posición en esa matriz.

También puede establecer REG en la dirección correcta haciendo REG + 0x8 antes del lanzamiento para obtener el tercer valor de 32 bits en la posición 2.

Esto es cierto si esta arquitectura utiliza direccionamiento de bytes, lo que significa que cada dirección apunta a un byte de datos. Entonces puede leer un byte de datos de 0x345678, 0x345678+1, 0x345678+2, etc. Ahora, si está en una arquitectura de 32 bits, solo le preocupan 4 bytes cada vez. Entonces 0x345678 es la posición 0, 0x345682 es la posición 1 y así sucesivamente.

También debe tener en cuenta la alineación de la memoria, ya que no puede realizar un acceso no alineado. Por lo general, se alinea en límites de 4 bytes en una arquitectura de 32 bits.

Respondido el 12 de junio de 12 a las 18:06

Dados enteros de 32 bits, pval + 0x10 incrementará un puntero int sin firmar en 64 bytes (16 * sizeof(unsigned int)). Para conseguir la segunda posición debería usar pval + 0x02. - Dave Rager

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.