AVR hängt sich auf bei Unterspannung während EEPROM-Schreibzugriff

Gast #3747473
Lesenswert?

Hallo,

für eine Applikation verwende ich einen Atmel ATMEGA64A bei einer 
Betriebsspannung von 5.0 V. Die Brown-Out-Detection ist aktiviert und 
für 4.0 V konfiguriert.

Leider passiert es trotzdem, dass sich der Controller bei Unterspannung 
während eines EEPROM-Schreibzugriffs aufhängt.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3

4
#define EEPROM_BUFFER_SIZE      128
5
#define EEPROM_BUFFER_MASK      ( EEPROM_BUFFER_SIZE - 1 )
6

7
static volatile uint16_t s_eepromBuffAdr [EEPROM_BUFFER_SIZE];
8
static volatile uint8_t s_eepromBuffData [EEPROM_BUFFER_SIZE];
9
static volatile uint8_t s_eepromHead = 0;
10
static volatile uint8_t s_eepromTail = 0;
11

12
ISR ( EE_READY_vect )
13
{
14
  uint8_t tmptail = 0;
15
  
16
  if ( s_eepromHead != s_eepromTail )
17
  {
18
    // calculate and store new buffer index
19
    tmptail = ( s_eepromTail + 1 ) & EEPROM_BUFFER_MASK;
20
    s_eepromTail = tmptail;
21
    // get one byte from buffer and write it to EEPROM
22
    EEAR = s_eepromBuffAdr [tmptail];   // address
23
    EEDR = s_eepromBuffData [tmptail];  // data   
24
    // master write enable
25
    EECR |= (1<<EEMWE);   
26
    // strobing eeprom write
27
    EECR |= (1<<EEWE);
28
  }
29
   
30
  else
31
  {   
32
    // disabling eeprom ready interrupt
33
    EECR &= ~(1<<EERIE);
34
  }
35
}
36

37
void eeprom_write_byte_isr ( uint8_t *dst, uint8_t src )
38
{
39
  uint8_t tmphead = 0;
40

41
  tmphead  = ( s_eepromHead + 1 ) & EEPROM_BUFFER_MASK;
42

43
  while ( tmphead == s_eepromTail );    // waiting for free space buffer
44

45
  s_eepromBuffAdr [tmphead] = (uint16_t) dst;
46
  s_eepromBuffData [tmphead] = src;
47
  s_eepromHead = tmphead;
48

49
  EECR |= (1<<EERIE);                   // enable interrupt
50
}

Für Ideen und Kommentare bin ich dankbar.

Gruß Marc
Gast #3747514
Lesenswert?

Volker schrieb:
> Ich frag mal vorsichtig gegen:
> Was sollte der AVR bei Unterspannung deiner Meinung nach sonst machen?
> Einfach weiterlaufen? :-)

Da habe ich mich wohl etwas ungeschickt ausgedrückt. Der 
Spannungseinbruch ist nur von kurzer Dauer. Normalerweise sollte der 
Brown-Out-Detector den Controller bei Spannungseinbruch zurücksetzen. Im 
konkreten Fall bleibt er aber stehen. Aktuell umgehe ich dieses Problem, 
indem ich den internen Watchdog aktiviere.
Gast #3747535
Lesenswert?

Volker schrieb:
> Du meinst also daß die BOD nicht anspricht und der Controller im
> while ( tmphead == s_eepromTail );
>
> hängen bleibt?

Korrekt. Wobei ich bisher noch nicht prüfen konnte ob der Controller 
genau an dieser Stelle hängen bleibt.

Andere Timer-Interrupts (z.B. ein 10-ms-Timer) werden auch nicht mehr 
ausgeführt.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren