CRC para verificación de datos de eeprom

Quería verificar la redundancia en eeprom y verificar los datos en busca de errores o no y terminé leyendo el código CRC. Lo encontré útil pero tengo algunas dudas que necesitan claridad.

Mi objetivo es verificar las ubicaciones de direcciones de memoria 0-15k de eeprom y almacenar la suma de verificación en la memoria y hacer lo mismo para las siguientes ubicaciones de direcciones de 15k-30k. Las ubicaciones de ambas direcciones almacenan los mismos datos y se hace para que se utilice la memoria eeprom.

Bueno, cuando comencé a leer los documentos. Terminé con un código útil:

unsigned int crc32(unsigned char *message) {
  int i, j;
  unsigned int byte, crc;
  i = 0;
  crc = 0xFFFFFFFF;
  while (message[i] != 0) {
    byte = message[i]; // Get next byte.
    byte = reverse(byte); // 32-bit reversal.
    for (j = 0; j <= 7; j++) { // Do eight times.
      if ((int)(crc ^ byte) < 0)
        crc = (crc << 1) ^ 0x04C11DB7;
      else crc = crc << 1;
      byte = byte << 1; // Ready next msg bit.
    }
    i = i + 1;
  }
  return reverse(~crc);
}

Aquí, según tengo entendido, el ' mensaje ' espera bytes y continúa el cálculo de CRC hasta que no se recibe el carácter. Si quisiera revisar los dos bloques de memoria eeprom como dije antes. ¿Cómo puedo agregar la memoria eeprom a la variable del mensaje?

Bueno, mi otra * duda es si la lectura de eeprom tiene algún límite con respecto a la lectura de la dirección de lectura de 0-15k en un tramo en lugar de la escritura de eeprom * Necesito sus aportes para que este intento sea útil y gratificante Saludos

El código que ha pegado arriba asume que desea el CRC de una cadena de datos terminada en cero en la variable message. Pero desea el CRC de (casi) toda su EEPROM, así que simplemente reemplace la whilecláusula con un bucle sobre (la mayor parte) de su espacio de direcciones EEPROM, y message[i]con una lectura de la i-ésima palabra de 32 bits de su EEPROM. A diferencia de la escritura, leerlo no lo degradará. Recuerde excluir la parte de la EEPROM donde almacena la suma de verificación CRC para comparar.

Respuestas (2)

Si bien el enfoque sugerido por PeterJ está bien, es más limpio desacoplar la lógica de "capa de datos" (acceso a EEPROM) de la rutina CRC.

Este CRC-32 se puede usar universalmente, no está sujeto a un comportamiento específico del programa:

// CCITT CRC-32 (Autodin II) polynomial
uint32_t CalcCRC32(uint32_t crc, uint8_t *buffer, uint16_t length) {
    while(length--) {
        crc = crc ^ *buffer++; 

        for (uint8_t j=0; j < 8; j++) { 
           if (crc & 1) 
              crc = (crc >> 1) ^ 0xEDB88320; 
           else 
              crc = crc >> 1; 
        } 
    } 

   return crc; 
}

Luego, simplemente alimenta bloques de datos a la función CRC como mejor le parezca y según lo requiera su aplicación.

Este ejemplo de uso se acaba de escribir. Utiliza la función ficticia eeprom_read() que lee un bloque de datos de EEPROM. Empezamos en la dirección 0 de la EEPROM.

const uint8_t BLOCKLENGTH = 128;
uint32_t crc32;
uint8_t buffer[BLOCKLENGTH];    // temporary data buffer

crc32 = 0xFFFFFFFF;  // initial CRC value 

for (uint16_t i=0; i < NUMBEROFBLOCKS; i++) {
    eeprom_read(BLOCKLENGTH * i, buffer, BLOCKLENGTH);    // read block number i from EEPROM into buffer
    crc32 = CalcCRC32(crc32, buffer, BLOCKLENGTH);        // update CRC
}

// crc32 is your final CRC here

Tenga en cuenta que NUMBEROFBLOCKS es solo un marcador de posición. Espero que captes la idea.

Como su código no usa la ivariable, ¿por qué no solo while(length--)en lugar del primer bucle for?
@David: Tiene razón, siéntase libre de editar la función CalcCRC32(). Pegué el código de un proyecto anterior, donde obviamente lo perdí.
@Rev1-0 Decidí probar para ver si esto marcaría una diferencia práctica. Los resultados están en esta pregunta .
@David: Esta función de hecho sirvió como un buen ejemplo de que a menudo hay espacio para la optimización.
Bueno, en qué compilador se compiló este código. Bueno, probé en C18 para lo mismo y terminé con un error que apunta al bucle for. El error es: "8: Error: error de sintaxis". El mismo código con uint16 y otros reemplazados con largo.
@ Rookie91: ¿Se da cuenta de que solo se debe compilar el primer bloque de código (probado con GCC 4.3.3)? El segundo bloque fue solo un ejemplo de uso como se indica en la respuesta.
Entonces, si la longitud es mayor, entonces la memoria se cargará por completo, ¿verdad? Podría conducir a un problema de utilización de la memoria, ¿verdad? Por ejemplo: si está haciendo un Crc de 0-20k de memoria
@ Rookie91: No. De esto se trata mi ejemplo. El CRC se calcula bloque por bloque. El requisito de memoria depende del tamaño del bloque (de su elección). Podría calcular 20k en bloques de 200 bytes y repetir 100 veces. Esto solo requeriría (temporalmente) los 200 bytes adicionales de memoria.

Si está utilizando un microcontrolador con RAM limitada, probablemente no querrá intentar cargar una porción de datos de 16k en la memoria. Al reorganizar el código anterior, puede probar la siguiente función (no probada) que lee la EEPROM byte por byte dentro del ciclo. La función read_eepromes algo que inventé, por lo que deberá encontrar la función adecuada para su compilador.

#include <stdint.h>

uint32_t crc32(uint16_t start_address, uint16_t number_of_bytes) {
  uint8_t j;
  uint32_t crc, byte;
  crc = 0xFFFFFFFF;
  while (number_of_bytes--) {
    byte = read_eeprom(start_address++);
    byte = reverse(byte); // 32-bit reversal.
    for (j = 0; j <= 7; j++) { // Do eight times.
      if ((int32_t)(crc ^ byte) < 0)
        crc = (crc << 1) ^ 0x04C11DB7;
      else 
        crc = crc << 1;
      byte = byte << 1; // Ready next msg bit.
    }
  }
  return reverse(~crc);
}

También reemplacé sus declaraciones de variables para usar stdint.h ; probablemente sea bueno leer sobre eso y usarlo. En algunos compiladores integrados, unsigned intpor ejemplo, no será de 32 bits, por lo que esto hace que el código sea más portátil.

Confío en que lo contrario es solo una operación No (~)
@ Rookie91, sí, así es. No revisé mucho el código original que encontraste, pero no pude ver ningún problema obvio con él.