mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Attiny85 EEprom


Autor: clonephone82 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Zusammen,

Für ein kleines Projekt welches mit einem Attiny85 aufgebaut ist möchte 
ich die Geräte ID im EEProm speichern. Bei der Inbetriebnahme soll 0xff 
als ID ins EEPROM geschrieben werden sofern die ID noch nicht bereits 
gültig abgelegt ist.

Um zu erkennen ob die ID gültig ist oder nicht rechne ich noch 1 Byte 
CRC über die 1 Byte ID und speichere diese zusätzlich ab.... leider 
funktioniert das nicht immer ab und zu ist aufeinmal wieder 0xff als ID 
also muss die CRC nicht gestimmt haben beim einschalten.

Was mache ich hier für ein Denkfehler?

// irgendwo im main() ...

  // read device id
  current_device_id = eeprom_read_byte(&ee_byte_device_id);
  // calculate an check crc
  _crc8_ccitt_update(u8_tmp, current_device_id);
  // read device id crc
  current_device_id_crc = eeprom_read_byte(&ee_byte_device_id_crc);

  if (current_device_id_crc != u8_tmp)
  {
    update_device_id(DEFAULT_DEVICE_ID);
  }
  
  
  
//   
  
  
  static void update_device_id(uint8_t dev_id)
  {
    uint8_t tmp;

  #ifdef SUART_TX
    uputs("\r\nupdate dev_id:");
    itoa(dev_id, buffer, 10);
    uputs(buffer);
  #endif

    tmp = dev_id;
    eeprom_write_byte(&ee_byte_device_id, tmp);
    current_device_id = tmp;
    tmp = 0;
    _crc8_ccitt_update(tmp, dev_id);
    eeprom_write_byte(&ee_byte_device_id_crc, tmp);
    current_device_id_crc = tmp;
    show_id();
  }
  

Hat vielleicht jemand eine ander Idee wie ich das mit der ID lösen 
könnte?

Vielen Dank.

Autor: spess53 (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Hi

Du hast einmal

>  _crc8_ccitt_update(u8_tmp, current_device_id);

und beim zweiten mal

>    tmp = 0;
>    _crc8_ccitt_update(tmp, dev_id);

Sieh in deiner CRC-Lib nach, was dort mit tmp gemacht wird.

MfG spess

Autor: clonephone82 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Okay der Name ist irreführend ist geändert. Aber u8_tmp wird bei der 
initialisierung auf 0 gesetzt.

Also ich kann da das Problem nicht erkennen.

Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn es in Hardware passiert, stelle auch sicher, das der BrownOut Reset 
aktiviert ist. Adresse 0 des EEPROM ist sonst öfter mal Opfer - das war 
bei alten AVRs ein richtiger Bug, sollte heute nicht mehr passieren. Da 
du die Deklaration deiner EEPROM Zelle nicht gepostet hast, kann ich dir 
nur empfehlen, trotz allem an die erste Adresse (also die 0) im EEPROM 
ein dummy zu setzen.

Autor: Georg G. (df2au)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
CRC über 1 Byte ist nicht unbedingt eine sinnvolle Lösung, schon 
überhaupt nicht mit den Lib-Routinen. Wenn es unbedingt CRC sein muss, 
sieh dir die Lib an und mach den einen XOR zu Fuß.

Autor: clonephone82 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Mathias
Danke ja ich nehme mal an das wenn ich es so Deklariere:
/* Byte Device ID */
uint8_t ee_byte_device_id EEMEM;
uint8_t ee_byte_device_id_crc EEMEM;

Dann ist die ID jetzt wohl auf Adresse 0.

@Georg
Okay meinst du generell weil nur 1 Byte? Die Lib routine 
_crc8_ccitt_update brauche ich sowieso für was anderes von demher wegen 
dem platz wäre es unproblematisch. Andere Idee was ich nehmen könnte?

Autor: Georg G. (df2au)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
clonephone82 schrieb:
> Andere Idee was ich nehmen könnte?

Einfach nur das Komplement?

Autor: c-hater (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Georg G. schrieb:

> Einfach nur das Komplement?

So ist es, denn das bietet die maximale mögliche Redundanz, wenn man für 
ein Byte Nutzdaten ein Byte Prüfsumme speichern will und läßt sich 
obendrein innerhalb eines einzigen Taktes berechnen.

Autor: clonephone82 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich habe das jetzt umgebaut wie vorgeschlagen aber noch keine 
wirkliche Verbesserung zu erkennen. Jetzt ist mir gerade noch 
aufgefallen, dass ich nicht nur Platinen habe bei denen die  ID verloren 
geht also auf 0xff zurück gesetzt wird - nein ich hab sogar Platinen bei 
denen das Flash zerschossen wird.

Das habe ich gerade erst bemerkt. Eine Platine hat sich gar nicht mehr 
bemerkbar gemacht deshalb wollte ich diese neu flashen dazu brauchte ich 
für den fastboot keinen reset was ja dann heißt es war nur der 
Bootloader drauf.

Kann das sein nur weil ich BrownOut Fuse nicht gesetzt habe?

Das ganze ist wirklich komisch wie kann ich bitte mit dem Programm das 
Flash zerschießen.

Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
clonephone82 schrieb:
> Kann das sein nur weil ich BrownOut Fuse nicht gesetzt habe?

Mach doch mal die Gegenprobe mit BOD.
Die Schreibstrategie für dein EEPROM ist ja aus den Programmstückchen 
nicht herauszulesen, also wann und wie oft du schreibst. Am sichersten 
wäre vermutlich, die Device ID per Programmer zu schreiben und in der 
Firmware nur noch zu lesen. Wenn z.B. dein Programm Amok läuft und bei 
der Evaluierung der ID rumirrt, könntest du aus Versehen schon hunderte 
von Schreibvorgängen haben.
Und, wie gesagt, vermeide Adresse 0.

: Bearbeitet durch User
Autor: clonephone82 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja das werde ich natürlich machen - habe aber gerade keine Möglichkeit 
dazu - programmer nicht dabei.

Ja das ist ja nichts großartiges - verstehe es nicht ich hatte noch nie 
solche Probleme mit einem EEPROM.... wobei ich muss zugeben ich hab noch 
nie das interne EEPROM verwendet bisher.
/* Byte Device ID */
uint8_t ee_byte_dummy0 EEMEM;
uint8_t ee_byte_dummy1 EEMEM;
uint8_t ee_byte_device_id EEMEM;
uint8_t ee_byte_device_id_crc EEMEM;


// main ruft dann check id auf und das wars
check_id()

static void check_id(void)
{
  uint8_t tmp;

  // read device id
  current_device_id = eeprom_read_byte(&ee_byte_device_id);
  while(!eeprom_is_ready());
  current_device_id_checksum = eeprom_read_byte(&ee_byte_device_id_crc);
  // calculate checksum
  tmp = ~current_device_id;

#ifdef SUART_TX
  uputs("\r\ncheck_id:");
  itoa(current_device_id, buffer, 10);
  uputs(buffer);
#endif

  if(current_device_id_checksum != tmp)
  {
    update_id(DEFAULT_DEVICE_ID);
  }
}

static void update_id(uint8_t dev_id)
{
  uint8_t tmp;

  // write id
  tmp = dev_id;
  eeprom_update_byte(&ee_byte_device_id, tmp);
  current_device_id = tmp;

  // calculate checksum
  tmp = ~current_device_id;

  // check if eeprom is ready
  while(!eeprom_is_ready());

  // write checksum
  eeprom_update_byte(&ee_byte_device_id_crc, tmp);
  current_device_id_checksum = tmp;

  show_id();
}



update_id() kann dann auch noch extern über rs232 aufgerufen werden. Die 
Probleme habe ich aber definitiv beim lesen würde ich sagen bzw. eben 
deshalb weil die ID nicht gültig ist und dann eben neu geschrieben wird.

Naja eventuell könnte ich diese auch noch mehrfach ablagen und ein 
voting machen so wie hier erklärt. 
http://www.avrfreaks.net/forum/brown-out-detection...

Autor: c-hater (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
clonephone82 schrieb:

> Kann das sein nur weil ich BrownOut Fuse nicht gesetzt habe?

Natürlich. Ein abstürzender µC kann natürlich seinen eigenen Speicher 
beliebig verwursten. Tipp: das ist nicht auf den EEPROM beschränkt, 
sondern kann durchaus auch den Flash treffen.

Primäres Gegenmittel ist natürlich die Optimierung der Versorgung. Nur 
soviel Bypass-Kapazität vorsehen, wie unbedingt für den Betrieb der 
Hardware nötig ist und kein bissel mehr...

Ohne diese bewußte und zielgerichtete Optimierung der Hardware ist ein 
aktiver BOD praktisch Pflicht. Lediglich für extreme Energiesparer muss 
man i.d.R. darauf verzichten. Wenn das der Fall ist, dann sollte man die 
Zeit des Verzichtes nach Möglichkeit wenigstens auf die Schlafzeit 
beschränken. Leider hat man diese Möglichkeit bei älteren AVR8-Devices 
nicht...

Wenn kein aktiver BOD möglich ist und auch keine Optimierung der 
Versorgung, dann bleibt nur noch eins: das Programm so zu gestalten, 
dass die statistische Wahrscheinlichkeit für einen fälschlichen 
Schreibzugriff auf EEPROM oder Flash minimiert wird.

Das ist allerdings schon in Assemblerprogrammen nicht ganz einfach und 
ziemlich aufwendig umzusetzen und in höheren Sprachen sogar weitgehend 
unmöglich. Da kann man höchstens mal ein paar besonders gefährliche 
Pattern in konstanten Daten entschärfen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.