mikrocontroller.net

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


Autor: EEPROM (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Joachim Rath (jorath)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: EEPROM (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
....
.....
#include xeeprom.h  // *.h Datei zum EEPROM ansprechen von Joachim Rath (GNU)
...
main
...

clock_init();      // Clock auf 30 MHz stellen
EEpromInit();      // EEPROM Inistialisieren
usart_init();      // UART Initialisieren
sei();          // Interrupt enable

    sprintf (buffer,"Beginn auslesen");
    usart_sendstring(buffer);
    {
    usart_sendstring("\r"); // Return auf die Serielle schicken
    usart_sendstring("\n"); // New line ausgeben

    a = EEpromReadFloat(50);
  
    wait_ms(1);   // Zeitschleife von x ms

    sprintf (buffer,"Start Zahl 1 aus EEPROM: %f    ", a);
    usart_sendstring(buffer);
    
    wait_ms(1000);    // Zeitschleife von x ms


    usart_sendstring("\r");
    usart_sendstring("\n");
  
    a = 5;
  
    sprintf (buffer,"Beginn mit dem Schreiben");  
    usart_sendstring(buffer);

    usart_sendstring("\r");    // Return auf der Seriellen ausgeben
    usart_sendstring("\n");    // NewLine ausgeben
    
    EEpromWriteByte(50,a);   // Ab hier oder in den nächsten Zeilen muss der Fehler liegen.
    set_sleep_mode(SLEEP_MODE_IDLE);       // idle modus
    sleep_enable();                        // aktivieren
    sleep_cpu();                           // auf nächsten Interrupt warten
  

    wait_ms(1000);    // Zeitschleife von x ms

    sprintf (buffer,"Written 1");
    usart_sendstring(buffer);
    
    a= 99; // bewusst andere Zahl eingegeben.  
    usart_sendstring("\r");
    usart_sendstring("\n");

    sprintf (buffer,"Written End");
    usart_sendstring(buffer);
    
    usart_sendstring("\r");
    usart_sendstring("\n");
  
    a = EEpromReadByte(50);
    
    sprintf (buffer,"Zahl 1 aus EEPROM: %f    ", a);
    usart_sendstring(buffer);
    
    wait_ms(1000);    

    usart_sendstring("\r");
    usart_sendstring("\n");
    
    sprintf (buffer,"Auslesen Ende");
    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

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Setz das
set_sleep_mode(SLEEP_MODE_IDLE);       // idle modus
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&f...

Oliver

Autor: Joachim Rath (jorath)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: EEPROM (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Joachim Rath (jorath)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: EEPROM (Gast)
Datum:

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

Gruß
EEPROM

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.