Forum: Compiler & IDEs Schreiben einer Float ins EEPROM beim atXmega / Reset


von EEPROM (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Forum,
beim Schreiben ins EEPROM vom atXmega kommt es bei mir zu einem Reset 
des Prozessors. Dies ist ja auch in Errata AVR1008 beschrieben. Aber ich 
schaffe es nicht, den IdleMode zu integrieren. Bei der AVR1008 Datei ist 
die Funktion __sleep(); vorhanden, welche mein Compiler (WinAVR) nicht 
kennt, somit kann ich diesen Teil nicht implementieren. Kann mir jemand 
von euch den Code um den Idle-Mode nach dem Schreiben ins EEPROM von 
2,4µs zu bekommen geben. Ich verwende den atXmega64 A3. Laut dem Errata 
kann es nach dem Schreiben in das EEPROM innerhalb von 2,5µs zu einem 
Falschausführen vom Code kommen, deshalb soll man den µC in den 
Idle-Mode schicken und entweder durch den Timer oder durch den 
EEPROM-ready Interrupt wieder aus dem Idle Mode zurück holen. Diese 
Implementierung macht mir Probleme.
Verwende ich die Libary von Joachim Rath (xeeprom.h) macht mein 
Prozessor ebenfalls (manchmal) einen Reset nach dem schreiben. Hier ist 
ebenfalls nicht die Routine mit dem Idle-Mode integriert.

Danke für eure Hilfe im Voraus.

EEPROM

von Joachim R. (jorath)


Lesenswert?

Mahlzeit,

versuche mal:

#include <avr/sleep.h>          //Power Management and Sleep Modes
...
set_sleep_mode(SLEEP_MODE_IDLE);       // idle modus
sleep_enable();                        // aktivieren
sleep_cpu();                           // auf nächsten Interrupt warten

MfG

von EEPROM (Gast)


Lesenswert?

Hallo,
ich hab den Tipp von Joachim Rath umgesetzt und auch Seine xeeprom.h 
eingesetzt. (Datei siehe oben eingebunden.) Mein Source Code sieht 
auszugsweise so aus:
1
....
2
.....
3
#include “xeeprom.h“  // *.h Datei zum EEPROM ansprechen von Joachim Rath (GNU)
4
...
5
main
6
...
7
8
clock_init();      // Clock auf 30 MHz stellen
9
EEpromInit();      // EEPROM Inistialisieren
10
usart_init();      // UART Initialisieren
11
sei();          // Interrupt enable
12
13
    sprintf (buffer,"Beginn auslesen");
14
    usart_sendstring(buffer);
15
    {
16
    usart_sendstring("\r"); // Return auf die Serielle schicken
17
    usart_sendstring("\n"); // New line ausgeben
18
19
    a = EEpromReadFloat(50);
20
  
21
    wait_ms(1);   // Zeitschleife von x ms
22
23
    sprintf (buffer,"Start Zahl 1 aus EEPROM: %f    ", a);
24
    usart_sendstring(buffer);
25
    
26
    wait_ms(1000);    // Zeitschleife von x ms
27
28
29
    usart_sendstring("\r");
30
    usart_sendstring("\n");
31
  
32
    a = 5;
33
  
34
    sprintf (buffer,"Beginn mit dem Schreiben");  
35
    usart_sendstring(buffer);
36
37
    usart_sendstring("\r");    // Return auf der Seriellen ausgeben
38
    usart_sendstring("\n");    // NewLine ausgeben
39
    
40
    EEpromWriteByte(50,a);   // Ab hier oder in den nächsten Zeilen muss der Fehler liegen.
41
    set_sleep_mode(SLEEP_MODE_IDLE);       // idle modus
42
    sleep_enable();                        // aktivieren
43
    sleep_cpu();                           // auf nächsten Interrupt warten
44
  
45
46
    wait_ms(1000);    // Zeitschleife von x ms
47
48
    sprintf (buffer,"Written 1");
49
    usart_sendstring(buffer);
50
    
51
    a= 99; // bewusst andere Zahl eingegeben.  
52
    usart_sendstring("\r");
53
    usart_sendstring("\n");
54
55
    sprintf (buffer,"Written End");
56
    usart_sendstring(buffer);
57
    
58
    usart_sendstring("\r");
59
    usart_sendstring("\n");
60
  
61
    a = EEpromReadByte(50);
62
    
63
    sprintf (buffer,"Zahl 1 aus EEPROM: %f    ", a);
64
    usart_sendstring(buffer);
65
    
66
    wait_ms(1000);    
67
68
    usart_sendstring("\r");
69
    usart_sendstring("\n");
70
    
71
    sprintf (buffer,"Auslesen Ende");
72
    usart_sendstring(buffer);


Als Ergebnis bekomme ich auf der Seriellen Schnittstelle:

Reginn auslesen
Start Zahl 1 aus EEPROM: 5
Beginn mit dem Schreiben

Beginn mit dem Schreiben

Beginn mit dem Schreiben

Beginn mit dem Schreiben

Beginn mit dem Schreiben

Beginn mit dem Schreiben

Beginn mit dem Schreiben

Beginn mit dem Schreiben

Beginn mit dem Schreiben

Dies lässt für mich den Schluss zu, dass er irgendwie zurück springt und 
später hängen bleibt.
Was ab ich in der Implementierung falsch gemacht?

Gruß
EEPROM

von Oliver (Gast)


Lesenswert?

Setz das
1
set_sleep_mode(SLEEP_MODE_IDLE);       // idle modus
2
sleep_enable();                        // aktivieren

mal an den Anfang von main. Du hast nur 2.5us Zeit, in den idle-mode zu 
kommen, da sind alle unnötigen Befehle dazwischen zu viel.

Ansonsten
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=88416

Oliver

von Joachim R. (jorath)


Lesenswert?

Nabend,

EEPROM schrieb:
> Mein Source Code sieht auszugsweise so aus:

sei so gut und poste ein nachvollziehbares Projekt. Mit einem Auszug ist 
es schwer einen Workaround zu finden, der dann allen nutzt.

MfG

von EEPROM (Gast)


Angehängte Dateien:

Lesenswert?

Sorry, dass ich nicht gleich das ganze Programm gemailt hab.
Ich hab die Änderung von Oliver schon eingepflegt. Aber er macht immer 
noch diese mir unklaren Sprünge/Resets.
Das:
Start Zahl 1 aus EEPROM: 5
Beginn mit dem Schreiben
BBeginn auslesen
Start Zahl 1 aus EEPROM: 5
Beginn mit dem Schreiben
BBeginn auslesen
Start Zahl 1 aus EEPROM: 5
Beginn mit dem Schreiben
BBeginn auslesen
Start Zahl 1 aus EEPROM: 5
Beginn mit dem Schreiben
BBeginn auslesen
Start Zahl 1 aus EEPROM: 5
Beginn mit dem Schreiben

Ist die Ausgabe auf der Seriellen Schnittstelle. Danach bleibt das 
Programm hängen.

Gruß
EEPROM

von Joachim R. (jorath)


Lesenswert?

Moin,

entweder bin ich blind oder

>Start Zahl 1 aus EEPROM: 5
>Beginn mit dem Schreiben
>BBeginn auslesen
>Start Zahl 1 aus EEPROM: 5
>Beginn mit dem Schreiben
>BBeginn auslesen
>...
passt nicht zum geposteten Code.

>while(1)  // hier verharren, wenn Schreib und Lesen auf EEPROM erledigt
>  {;}

nach einem Durchlauf ist schluss. Es sei denn der Watchdog ist aktiv 
(Fuses)

Bau dir eine whund.h mit folgendem Inhalt:

#undef wdt_enable
static inline void
wdt_enable(uint8_t value)       // Watchdog ein
{
 uint8_t wdt = WDT_ENABLE_bm | WDT_CEN_bm | value;
 CCP = CCP_IOREG_gc;
 WDT.CTRL = wdt;
 while(WDT.STATUS & WDT_SYNCBUSY_bm);
}
#undef wdt_disable
static inline void
wdt_disable(void)               // Watchdog abschalten
{
 uint8_t wdt = (WDT.CTRL & ~WDT_ENABLE_bm) | WDT_CEN_bm;
 CCP = CCP_IOREG_gc;
 WDT.CTRL = wdt;
}

... und schalte den WD am Anfang der main() aus.
Compileroptimierung muss eingeschaltet sein.

MfG

von EEPROM (Gast)


Lesenswert?

Danke für deine Hilfe,
jetzt klappt es ;-). Ich musste noch mit der Compileroptimierung 
spielen.

Gruß
EEPROM

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.