Hallo liebe Gemeinde!
Ich möchte gerne ins Flash meines Controllers schreiben und zwar während
der Laufzeit, genauer genommen will ich einen Offset aufnehmen und
diesen ins Flash schreiben.
Ich benutze einen MSP, aber es geht mehr um das generelle Verständnis.
Ich habe ein Code-Example, an welches ich mich halte, würde es jedoch
gerne auch komplett verstehen.
Die ganze Konfiguration des Flash-Controllers ist nicht von Bedeutung,
ich werde es hier nicht anführen, da sich dann wahrscheinlich eh nur die
MSP-Cracks angesprochen fühlen.
Ich gehe mal von eine Funktion zum Schreiben aus:
1
voidwrite_segment(uint8_tvalue)
2
{
3
uint8_t*flash_ptr;
4
5
flash_ptr=(uint8_t*)0x01000;
6
7
*flash_ptr=0;// Dummy-Write
8
9
*flash_ptr=value;
10
}
Das habe ich jetzt mehr oder weniger abgeschrieben aus dem Example (eher
mehr) - das ganze Gedöns drumherum mit warten ob busy und so mal nicht
mit aufgeschrieben...so nun geht es mal wieder um die Pointer und
Addressen:
Was genau mache ich hier:
1
uint8_t*flash_ptr;
Ich lege eine Variable fest, aber als Pointer. Was genau heisst das
jetzt? Was ist genau der Unterschied ob mit oder ohne den Stern? Ich
sage ja quasi dem Compiler, dass es sich hierbei um einen Zeiger
handelt, nur in wie fern behandelt er ihn jetzt anders?
Die nächste Zeile:
1
flash_ptr=(uint8_t*)0x01000;
0x01000 ist ja die Adresse, an die ich schreiben will. Wieso benutze ich
für den flash_ptr jetzt nicht mehr den Stern? Und noch interessanter,
was macht dieses (uint8_t *)? Das ist ja ein Cast, aber zu was caste ich
die Adresse da jetzt?
Nun dies:
1
*flash_ptr=value;
Mit dem Stern sage ich, dass die Zuweisung, welche rechts nebem dem "="
steht, als Inhalt gewertet werden soll, oder - also quasi an die
Flash-Pointer-Addresse den Wert von "value" ablege.
Und vor allem, wie würde es aussehen, wenn ich die Adresse mit übergeben
wollen würde? Wie würde die in der Funktionszeile aussehen?
1
voidwrite_segment(uint16_t*adress,uint8_tvalue)
2
{
3
*adress=0;
4
5
*adress=value
6
}
Sehr kurz, oder?
Ich komme mit diesen Pointern nicht so wirklich klar, leider auch nicht
mit literarischer Hilfe. Ich weiß nie, wo "*", wo "&" usw.
Wäre toll, wenn mir einer da mal helfen könnte.
Aber das haut so garnicht hin - der Compiler meckert wieder wegen
Pointer-Fehlern.
Ich weiß einfach nicht, wo ich was übergeben muss - kann mir da einer
helfen? Wo mit Stern und wo ohne?
FEHLER:
a value of type "int" cannot be used to initialize an entity of type
"uint16_t *"
und das bezieht sich hier drauf:
Was für einen MSP verwendest Du?
Mir scheint, Du solltest deine C-Kenntnisse was Pointer angeht deutlich
verbessern. Mit welcher "literarischen Hilfe", bzw. Tutorials zu Zeigern
kommst Du nicht klar?
Das größte Problem im Verständnis ist beim Anfänger oft in der
Deklaration des Pointers zu suchen.
Generell ist der Stern "*" ein Symbol für:
"Gib mir den Wert des Speichers auf den der Pointer zeigt".
Ohne Stern ist gemeint:
"Gib mir die Adresse auf die der Pointer zeigt.
Nicht in der Deklaration. Hier ist es einfach nur ein Merkmal für:
"Nicht eine Variable, sondern ein Zeiger auf eine Variable"
In der kombinierten Deklaration/initialisierung schreibt man
uint16_t *adress = 0x01000;
Man sollte (als Anfänger, die Initialisierung von der Deklaration
trennen!
Also besser schreiben:
uint16_t *adress; // lokale Variable die irgendwo hin zeigt.
adress = 0x01000; // Hier wird die Variable initialisiert.
Sie zeigt ab jetzt auf den Speicher an Adresse 0x01000;
mit *adress = 20; werden an Speicherstelle 0x01000 und 0x01001 Daten
gespeichert die die Zahl 20 repräsentieren.
wäre es ein Pointer vom Typ uint32_t würde die Zahl 20 and die
Speicherstellen 0x01000 - 0x01003 gespeichert die die Zahl 20
repräsentieren.
Das ist der Grund warum man dem Pointer überhaupt einen Typ mitgibt.
Noch ein Beispiel:
Was ist das hier ?:
uint16_t* adress, lalla;
Nein das sind nicht zwei Pointer! adress ist ein Pointer, während lalla
eine simple Variable vom Typ uint16_t ist.
Ich hoffe es hilft ein Bischen,
Gruß THaala
wenn du bei value= 0xaabbccdd einsetzt!
0x1000 dd
0x1001 cc
0x1002 bb
0x1003 aa
und beim lesen:
1. return_value= 0xdd
2. return_value= 0xdd cc
3. return_value= 0xdd cc bb
4. return_value= 0xdd cc bb aa
nimm mal öfters Bleistift und Papier zu Hand und teste deinen Code.
Das hilft.
mfg
Stephan
Nachtrag:
Dein Compiler fehler.....
>> a value of type "int" cannot be used to initialize an entity of type>> "uint16_t *">> und das bezieht sich hier drauf:>> uint16_t *adress = 0x01000;
... wird mit folgender Modifikation verschwinden:
uint16_t *adress;
adress = (uint16_t *)0x01000;
Gruß THaala
So, da melde ich mich auch mal wieder zurück.
sunburner schrieb:> Mir scheint, Du solltest deine C-Kenntnisse was Pointer angeht deutlich> verbessern. Mit welcher "literarischen Hilfe", bzw. Tutorials zu Zeigern> kommst Du nicht klar?
Also ich habe mir schon alles Mögliche zu Pointern durchgelesen, aber
allein vol Lesen halten sich meine Erfolge in Grenzen - der praktische
Erfolg wäre lehrreicher für mich :-) Trotzdem, ich arbeite mit dem Buch
von Kernigham und Ritchie.
sunburner schrieb:> Was für einen MSP verwendest Du?
Einen F2418.
Thilo Haala schrieb:> Also besser schreiben:> uint16_t *adress; // lokale Variable die irgendwo hin zeigt.> adress = 0x01000; // Hier wird die Variable initialisiert.>> Sie zeigt ab jetzt auf den Speicher an Adresse 0x01000;>> mit *adress = 20; werden an Speicherstelle 0x01000 und 0x01001 Daten> gespeichert die die Zahl 20 repräsentieren.>> wäre es ein Pointer vom Typ uint32_t würde die Zahl 20 and die> Speicherstellen 0x01000 - 0x01003 gespeichert die die Zahl 20> repräsentieren.
Das macht Sinn. Kurze und gute Erklärung :-)
Da ich ja bei mir die Adresse im Flash beschreiben will, werde ich also
nach diesem Schema den Pointer initialisieren. Also erst
1
uint16_t*adress;
um ihm zu sagen, dass es einen Zeiger auf einen Speicherbereich gibt,
welcher 2 Bytes lang ist und dann weiterhin mit
1
adress=0x01000;
zur Kenntnis gebe, dass die zwei Bytes ab 0x01000 gemeint sind.
Thilo Haala schrieb:> uint16_t* adress, lalla;
Dass das zwei verschiedene Sachen sind, habe ich auch gelesen.
Stephan schrieb:> wenn du bei value= 0xaabbccdd einsetzt!>> 0x1000 dd> 0x1001 cc> 0x1002 bb> 0x1003 aa>> und beim lesen:>> 1. return_value= 0xdd> 2. return_value= 0xdd cc> 3. return_value= 0xdd cc bb> 4. return_value= 0xdd cc bb aa
OK, stimmt, wenn ich mal drüber nachdenke, dann hast du natürlich recht,
alles falsch herum zurückgeholt.
Thilo Haala schrieb:> Dein Compiler fehler.....>>>> a value of type "int" cannot be used to initialize an entity of type>>> "uint16_t *">>>> und das bezieht sich hier drauf:>>>> uint16_t *adress = 0x01000;>> ... wird mit folgender Modifikation verschwinden:>> uint16_t *adress;> adress = (uint16_t *)0x01000;
Das verstehe ich wieder nicht! Weiter oben wurde es ja so geschrieben:
1
uint16_t*adress;// lokale Variable die irgendwo hin zeigt.
2
adress=0x01000;// Hier wird die Variable initialisiert.
Aber da hat der Compiler ja gemeckert. Was bewirkt also dieses
vorangestellte, in Klammern gesetzte und wiederholte "adress = (uint16_t
*) 0x01000"?
Morgen und schönen Sonntag!
Ich wollte den Thread hier nochmal hochholen - sorry, aber ich wär echt
dankbar, wenn mir einer das erklären könnte.
Danke schön!
Fritz Box schrieb:> Aber da hat der Compiler ja gemeckert. Was bewirkt also dieses> vorangestellte, in Klammern gesetzte und wiederholte "adress = (uint16_t> *) 0x01000"?
Wie der Compiler ja schon freundlicherweise mitgeteilt hat, entspricht
der Ausdruck 0x01000 eben keinem Datentyp, der äquivalent zu einem
Pointerinhalt ist.
Folglich muss er, bevor er einem Pointer zugewiesen werden kann, in
einen Datentyp konvertiert werden, der zum Pointer kompatibel ist. Am
besten sind natürlich gleiche Typen.
Denkfaule schreiben bei so etwas natürlich lieber (void *)0x01000, weil
das für alle Pointer-Typen passt, aber das solltest Du vorerst
vermeiden.
Andreas Schweigstill schrieb:> Folglich muss er, bevor er einem Pointer zugewiesen werden kann, in> einen Datentyp konvertiert werden, der zum Pointer kompatibel ist. Am> besten sind natürlich gleiche Typen.
Aber ich habe doch vorher mit "uint16_t *adress;" gesagt, dass ich einen
unsigned int, also einen Wert zwischen 0 und 65535 habe.
Wenn ich jetzt hexadezimal 0x01000 zuweise, dann entspricht das doch
4096. Wieso passt das dann nicht, bzw. wieso muss die 4096 erst nochmals
mit (uint16_t *) initialisiert werden. Und vorallem wieso nochmal mit
Stern. Ich schreibe ja eigentlich nicht den Inhalt der Variable an der
Stelle, sondern die Addresse.
Fritz Box schrieb:> Aber ich habe doch vorher mit "uint16_t *adress;" gesagt, dass ich einen> unsigned int, also einen Wert zwischen 0 und 65535 habe.
Nein, das hast Du nicht getan!
Du hast eine Variable definiert, die auf eine Speicherstelle zeigt, in
der ein uint16_t abgelegt werden kann.
Lies Dir noch einmal ein paar Bücher über C durch. Und anschließend noch
einmal. Und noch einmal.
Probiere ein bisschen herum. Studiere die Beispiele der Lehrbücher.
Verwende anfangs keinen Microcontroller, sondern arbeite auf dem
Hostsystem, egal ob Windows, Linux, BS/2000 oder VMS.
Es macht doch allmählich keinen Sinn mehr, die Diskussion
weiterzuführen. Du hast hinreichend viele Hinweise erhalten. Wenn diese
Hinweise nicht ausreichen und Du nicht in der Lage bist, den
Lehrinhalten und Hinweisen zu folgen, ist Softwareentwicklung nicht die
richtige Beschäftigung für Dich.
Andreas Schweigstill schrieb:> und Du nicht in der Lage bist, den> Lehrinhalten und Hinweisen zu folgen, ist Softwareentwicklung nicht die> richtige Beschäftigung für Dich
Na herzlichen Dank! Nur weil ich was nicht direkt verstehe - du hast es
garantiert von Anfang an gekonnt. Hätte ich eine gute Erklärung, dann
wäre es ein für alle mal vom Tisch.
Tut mir Leid, wenn ich Leute damit nerve, weil es für diejenigen
langweilig und trivial ist, ich bin halt noch nicht so weit und zu
denjenigen, denen das Programmieren in die Krippe gelegt wurde gehöre
ich leider nicht. Du scheinst ja schon eine Firma zu haben, also auch
schon etwas länger dabei zu sein - natürlich kannst du dann mehr.
Ich wette, du kannst auch manche Sachen nicht, wäre mal interessant, ob
du auch jedesmal so abgespeist wirst.
Danke danke!