Hi,
Ich habe jetzt schon alles durchwühlt finde aber nichts.
Ich arbeite nicht oft mit EEPROM Routinen, insofern bin ich hier noch
etwas unerfahren, daher bitte um Nachsicht ;)
Ich habe einen AtMega16 mit einem Hauptprogramm gefüttert und suche
jetzt nach einer Möglichkeit per ISP das interne EEPROM mit Werten
(Zahlen <100) zu füttern, die einmalig zum Programmstart vom
Hauptprogramm ausgelesen werden.
Sinn ist, das ein User relativ einfach Werte per ISP und EEPROM
veränderen können muss, ohne jedoch mit dem Hauptprogramm überhaupt in
Berührung zu kommen.
Der User soll also im Idealfall ein seperates Projekt haben, wo er Werte
verändert, das Projekt compiliert und die .eep Datei auf den AVR
überträgt.
Ich habe schon versucht per
uint8_t light_index_1_s = eeprom_read_byte(&light_index_1_s);
die Variable auszulesen.
Um ein .eep Datei zu erzeugen habe ich ein seperates Projekt erstellt
und einfach eine Globale Variable
uint8_t light_index_1_s EEMEM = 5;
erzeugt. Die daraus compilierte .eep Datei habe ich dann hoffnungsvoll
per ISP übertragen, natürlich ohne Erfolg. Im Hauptprogramm war nichts
auslesbar.
Mir würde es schon reichen wenn mir jemand erklären würde, wie mein Plan
generell umsetzbar ist. Also wie genau ich manuell eine .eep Datei mit
Werten erzeuge, die ein davon unabhängiges Hauptprogramm dann auslesen
kann.
Dank im Voraus
Chris schrieb:> Mir würde es schon reichen wenn mir jemand erklären würde, wie mein Plan> generell umsetzbar ist. Also wie genau ich manuell eine .eep Datei mit> Werten erzeuge, die ein davon unabhängiges Hauptprogramm dann auslesen> kann.
Wird das EEPROM beim Programmieren des Chips (Flash) geschützt?
Chris schrieb:> Ich habe einen AtMega16 mit einem Hauptprogramm gefüttert und suche> jetzt nach einer Möglichkeit per ISP das interne EEPROM mit Werten> (Zahlen <100) zu füttern,...
Normalerweise benutzt man ein EEPROM zu dem Zwecke, daß man von der
Firmware aus sich darin Werte merken kann, die auch bei ausgeschaltetem
Gerät erhalten bleiben. Folglich muß sowieso irgend ein Lese- und
Schreib-Treiber für das EEPROM in der Firmware drin sein. Dazu kommt,
daß das Lesen und Schreiben des EEPROM's langsamer ist als der Zugriff
auf eine Variable im RAM. Also macht man es oftmals so, daß man ein
Datenfeld (bei C ein Struct) sich definiert, dazu im RAM eine Variable
anlegt und diese beim Einschalten mit den Werten aus dem EEPROM befüllt.
Man kann es daher auch so machen, daß man im Code ein konstantes
Datenfeld mit Defaultwerten anordnet und dieses in die Variable im RAM
kopiert, wenn irgendein Kriterium (z.B. ein Boolean 'daten_gelten') bei
den Daten im EEPROM anzeigt, daß die Daten nicht gelten. So eben bei der
frisch zusammengelöteten LP.
Deshalb ist es ein ziemlich unnützes Vorhaben, irgend eine spezielle
Möglichkeit zum Befüllen des EEPROM's per ISP sich ausdenken zu wollen.
Laß das die Firmware selber erledigen. Allenfalls ein Kommando dazu über
irgend eine Kommunikations-Schnittstelle wie z.B. UART.
W.S.
W.S. schrieb:> Normalerweise benutzt man ein EEPROM zu dem Zwecke, daß man von der> Firmware aus sich darin Werte merken kann, die auch bei ausgeschaltetem> Gerät erhalten bleiben. Folglich muß sowieso irgend ein Lese- und> Schreib-Treiber für das EEPROM in der Firmware drin sein. Dazu kommt,> daß das Lesen und Schreiben des EEPROM's langsamer ist als der Zugriff> auf eine Variable im RAM. Also macht man es oftmals so, daß man ein> Datenfeld (bei C ein Struct) sich definiert, dazu im RAM eine Variable> anlegt und diese beim Einschalten mit den Werten aus dem EEPROM befüllt.> Man kann es daher auch so machen, daß man im Code ein konstantes> Datenfeld mit Defaultwerten anordnet und dieses in die Variable im RAM> kopiert, wenn irgendein Kriterium (z.B. ein Boolean 'daten_gelten') bei> den Daten im EEPROM anzeigt, daß die Daten nicht gelten. So eben bei der> frisch zusammengelöteten LP.>> Deshalb ist es ein ziemlich unnützes Vorhaben, irgend eine spezielle> Möglichkeit zum Befüllen des EEPROM's per ISP sich ausdenken zu wollen.> Laß das die Firmware selber erledigen. Allenfalls ein Kommando dazu über> irgend eine Kommunikations-Schnittstelle wie z.B. UART.
Tinnef!
Man kann dort bspw. fortlaufende Seriennummern o.dergl hinterlegen.
Wenn man die EEP-Datei extern erzeugt, kann man sie auf dem gewünschten
Weg für jede (hausinterne Standrd-)Platine übertragen.
Danach kann man dann (bei geschütztem EEPROM) eine beliebige Firmare in
Abhängigkeit des Zielgerätes darauf installieren.
Schon komisch, dass wir das so bei AVR-basierenden Geräten handhaben.
Oder halt umgekehrt (erst die Firmware und dann denn EEPROM-Inhalt u.a.
mit Kalibrierdaten).
W.S. schrieb:> Deshalb ist es ein ziemlich unnützes Vorhaben, irgend eine spezielle> Möglichkeit zum Befüllen des EEPROM's per ISP sich ausdenken zu wollen.> Laß das die Firmware selber erledigen. Allenfalls ein Kommando dazu über> irgend eine Kommunikations-Schnittstelle wie z.B. UART.
Zumindest das belegen mit default Werten macht Sinn.
Chris schrieb:> uint8_t light_index_1_s EEMEM = 5;
Mache ich durchaus auch so.
Und das erzeugen und übertragen der *.eep ist problemlos.
Ich weiß also nicht, welche Sorgen du damit hast.
Chris schrieb:> uint8_t light_index_1_s = eeprom_read_byte(&light_index_1_s);
Hier sollten sich die Namen unterscheiden! (denke ich mal)
uint8_t temp = eeprom_read_byte(&light_index_1_s);
Chris schrieb:> Der User soll also im Idealfall ein seperates Projekt haben, wo er Werte> verändert, das Projekt compiliert und die .eep Datei auf den AVR> überträgt.
eXtreme Burner AVR könnte was für dich sein. Ist im Stile eines
Hex-Editors und hat 3 Reiter. Jeweils Einen für FLASH, EEPROM und Fuses.
Mittels USBasp kannst du über ISP dann das eep File in den Controller
schieben.
Ich nutze eXtrme Burner, wenn ich mehrere µC als Kleinserie mit dem
selben Hex-File befüllen will ;-)
Also aktuell habe ich versucht mit einem seperatem Projekt und
zum Beispiel:
uint8_t light_index_1_s EEMEM = 5;
einen Wert zu erzeugen, der dann nach compilieren in einer .eep Datei
steckt.
Soweit so gut. Das ganze habe ich dann im Atmel Studio direkt in den
EEPROM übertragen. Kein Problem
Mir ist nicht klar wie ich im Hauptprogramm den Wert gezielt aus dem
EEPROM lese, zumal EEMEM ja meines Wissens nach einfach einen freien
Platz im EEPROM sucht und den Wert dort ablegt, es gibt ja quasi keine
Adresse.
Gefühlt müsste das Ganze eine einfache Sache sein aber aktuell fehlt mir
komplett die Idee.
Zusammenfassend aber nochmal.
Programm A (Hauptprogramm) - wird einmal in den AVR geschoben und fertig
- der User kommt mit dem Programm nicht in Berührung, sieht also
nichtmal seinen Quelltext.
Programm B (EEPROM Werte) - ein kleines Extra Programm was nur darauf
abzielt einzelne Werte zu ändern und dann nach compilieren durch den
User per .eep ins EEPROM zu schieben.
Wenn man so will eine Liste Variablen die geändert werden können.
Das war es eigentlich ... eigentlich
Chris schrieb:> Mir ist nicht klar wie ich im Hauptprogramm den Wert gezielt aus dem> EEPROM lese, zumal EEMEM ja meines Wissens nach einfach einen freien> Platz im EEPROM sucht und den Wert dort ablegt, es gibt ja quasi keine> Adresse.
Doch natürlich gibt es eine Adresse!
Eben die Adresse, welcher der Linker dafür vorsieht.
Wenn du darauf wert legst, dass du die Adresse kennst/bestimmst.
solltest du mit Strukturen und offsetof() arbeiten.
https://en.wikipedia.org/wiki/Offsetof
Ich brauch auch nicht zwingend eine Adresse.
Vielmehr habe ich keine Ahnung wie das Hauptprogramm wieder an den Wert
kommen soll, der per .eep Datei übertragen wurde
Zb.
uint8_t light_index_1_s EEMEM = 5; per .eep ins EEPROM geschrieben
und im Hauptprogramm versucht mit
uint8_t temp = eeprom_read_byte(&light_index_1_s);
auszulesen führt nicht zum Erfolg .
Ok nein das das in einem Programm zusammen klappt ist klar.
Der Compiler weiß ja wo er "test" im EEPROM abgelegt hat und wo er dann
beim lesen suchen muss.
Ich habe dagegen das Hauptprogramm was nur zb. den folgenen Teil
enthält.
void setup()
1
{
2
3
Serial.begin(9600);
4
5
Serial.println(unsigned(&test));
6
7
Serial.println(eeprom_read_byte(&test));
8
9
}
Dann habe ich ein seperates Programm was der User mit Werten füllt also
zb.
byte test EEMEM = 5;
Dieses .eep wird dann ins EEPROM geschickt.
Ich gehe aktuell davon aus das das Problem darin liegt das (da beides
unabhängige Programme sind) beim Lesen einfach keine Zuordnung besteht.
Das Programm weiß also nicht wo es "test" im EEPROM finden soll.
Am Ende gibt der Compiler ja dem wert "test" auch einfach eine
adressierung die zum entsprechendem Speicherplatz im EEPROM führt.
Chris schrieb:> Ok nein das das in einem Programm zusammen klappt ist klar.
Das war mit bisher nicht klar, dass das bei dir funktioniert.
Dann Kommt Teil 2 eines meiner vorherigen Posts zur Geltung!
Chris schrieb:> Ich brauch auch nicht zwingend eine Adresse.
Die brauchst du nicht nur, sondern sie muss auch fest angenagelt werden!
Die Struktur muss in beiden Programmen angelegt werden um die Adressen
anzunageln.
(die Strukturdefinition sieht in C etwas anders aus)
1
#include<avr/eeprom.h>
2
3
4
structDatenImEEPROM
5
{
6
bytea;
7
byteb;
8
};
9
10
DatenImEEPROMimEeprom__attribute__((section(".eeprom"),used))EEMEM{7,5};// diese Zeile braucht es nur um die .eep zu erzeugen
bekomme ich für cue_1_m
"invalid conversion from 'unsigned int' to 'const uint8_t* {aka const
unsigned char*}' "
Die Datenabfrage für cue_1_s dagegen klappt tadellos.
Gehe mal davon aus das offsetof hier das Problem ist.
Der offset müsste für cue_1_m ja quasi cue_1_sekunde+cue_1_minute sein
?!
Eine Idee hierzu ?
Nochmal, die Fehlermeldung ist bis zur Unkenntlichkeit verstümmelt.
Der Code ist so verkürzt, dass die Fehlerquelle nicht zu sehen ist.
Ich bin voll auf Arduino, also nutze ich die Sprache C++!
Welche Sprache nutzt du?
Chris schrieb:> Cue1 imCue1 EEMEM __attribute__((section(".eeprom"),used)) ;
Die Zeile ist sicherlich überflüssig, wenn keine Vorbesetzungen für die
*.eep Datei gemacht werden.
Annahme 1:
Wenn die Adressen korrekt ermittelt werden, sind auch die Zugriffe auf
das EEPROM korrekt durchführbar.
Annahme 2:
Du verwendest C.
Also hier eine C Datei, mit Funktionen, welche die Adressen in der
Struktur ermitteln.
Die Ausgabe der Adressen erfolgt dann in einem Arduino C++ Programm.
Testen:
In der Arduino IDE ein Tab mit der *.c Datei anlegen, Inhalte
übertragen.
Selbstredend:
Die Adressen werden fehlerfrei ausgegeben.