Forum: Mikrocontroller und Digitale Elektronik Attiny85 EEprom


von clonephone82 (Gast)


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?
1
// irgendwo im main() ...
2
3
  // read device id
4
  current_device_id = eeprom_read_byte(&ee_byte_device_id);
5
  // calculate an check crc
6
  _crc8_ccitt_update(u8_tmp, current_device_id);
7
  // read device id crc
8
  current_device_id_crc = eeprom_read_byte(&ee_byte_device_id_crc);
9
10
  if (current_device_id_crc != u8_tmp)
11
  {
12
    update_device_id(DEFAULT_DEVICE_ID);
13
  }
14
  
15
  
16
  
17
//   
18
  
19
  
20
  static void update_device_id(uint8_t dev_id)
21
  {
22
    uint8_t tmp;
23
24
  #ifdef SUART_TX
25
    uputs("\r\nupdate dev_id:");
26
    itoa(dev_id, buffer, 10);
27
    uputs(buffer);
28
  #endif
29
30
    tmp = dev_id;
31
    eeprom_write_byte(&ee_byte_device_id, tmp);
32
    current_device_id = tmp;
33
    tmp = 0;
34
    _crc8_ccitt_update(tmp, dev_id);
35
    eeprom_write_byte(&ee_byte_device_id_crc, tmp);
36
    current_device_id_crc = tmp;
37
    show_id();
38
  }

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

Vielen Dank.

von spess53 (Gast)


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

von clonephone82 (Gast)


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.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


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.

von Georg G. (df2au)


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ß.

von clonephone82 (Gast)


Lesenswert?

@Mathias
Danke ja ich nehme mal an das wenn ich es so Deklariere:
1
/* Byte Device ID */
2
uint8_t ee_byte_device_id EEMEM;
3
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?

von Georg G. (df2au)


Lesenswert?

clonephone82 schrieb:
> Andere Idee was ich nehmen könnte?

Einfach nur das Komplement?

von c-hater (Gast)


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.

von clonephone82 (Gast)


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.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


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
von clonephone82 (Gast)


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.
1
/* Byte Device ID */
2
uint8_t ee_byte_dummy0 EEMEM;
3
uint8_t ee_byte_dummy1 EEMEM;
4
uint8_t ee_byte_device_id EEMEM;
5
uint8_t ee_byte_device_id_crc EEMEM;
6
7
8
// main ruft dann check id auf und das wars
9
check_id()
10
11
static void check_id(void)
12
{
13
  uint8_t tmp;
14
15
  // read device id
16
  current_device_id = eeprom_read_byte(&ee_byte_device_id);
17
  while(!eeprom_is_ready());
18
  current_device_id_checksum = eeprom_read_byte(&ee_byte_device_id_crc);
19
  // calculate checksum
20
  tmp = ~current_device_id;
21
22
#ifdef SUART_TX
23
  uputs("\r\ncheck_id:");
24
  itoa(current_device_id, buffer, 10);
25
  uputs(buffer);
26
#endif
27
28
  if(current_device_id_checksum != tmp)
29
  {
30
    update_id(DEFAULT_DEVICE_ID);
31
  }
32
}
33
34
static void update_id(uint8_t dev_id)
35
{
36
  uint8_t tmp;
37
38
  // write id
39
  tmp = dev_id;
40
  eeprom_update_byte(&ee_byte_device_id, tmp);
41
  current_device_id = tmp;
42
43
  // calculate checksum
44
  tmp = ~current_device_id;
45
46
  // check if eeprom is ready
47
  while(!eeprom_is_ready());
48
49
  // write checksum
50
  eeprom_update_byte(&ee_byte_device_id_crc, tmp);
51
  current_device_id_checksum = tmp;
52
53
  show_id();
54
}


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-and-eeprom-corruption

von c-hater (Gast)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.