CRC para verificación de datos de eeprom

4

Quería verificar la redundancia en eeprom y verificar los datos para detectar cualquier error ocurrido 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 comprobación en la memoria y hacer lo mismo para las siguientes ubicaciones de direcciones 15k-30k. Las dos ubicaciones de direcciones almacenan los mismos datos y se hacen 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 entiendo, el ' mensaje ' espera bytes y continúa el cálculo de CRC hasta que no se recibe el carácter. Si quisiera comprobar los dos bloques de memoria de eeprom como dije antes. ¿Cómo puedo agregar la memoria de eeprom a la variable de mensaje?

bien 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 a 15k de manera similar a como escribe eeprom * Necesito tus aportaciones para hacer este intento útil y gratificante. Saludos

    
pregunta Rookie91

2 respuestas

4

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

Este CRC-32 se puede utilizar universalmente, no está vinculado 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 anotar. Utiliza la función ficticia eeprom_read () que lee un bloque de datos de EEPROM. Comenzamos en la dirección EEPROM 0.

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 tengas la idea.

    
respondido por el Rev1.0
2

Si está utilizando un microcontrolador con RAM limitada, es probable que no quiera cargar una porción de datos de 16k en la memoria. Reorganizando el código anterior, puede probar la siguiente función (no probada) que lee el byte EEPROM byte dentro del bucle. La función read_eeprom es algo que inventé, así que tendrás que encontrar la función adecuada para tu 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 he reemplazado sus declaraciones de variables para usar stdint.h : es Probablemente es bueno leer sobre eso y usarlo. En algunos compiladores integrados, unsigned int no tendrá 32 bits, por ejemplo, por lo que esto hace que el código sea más portátil.

    
respondido por el PeterJ

Lea otras preguntas en las etiquetas