Hallo ich möchte das interne SRAM des m8515 bei Programmstart löschen lassen. In Assembler habe ich es folgendermaßen gelöst: ldi r26, LOW(start_sram) ldi r27, HIGH(start_sram) löschen: ldi temp, 0 st X+, temp cpi XH, HIGH(ende_sram) brne löschen cpi XL, LOW(ende_sram) brne löschen Jetzt will ich das in C machen aber mir fehlt der Durchblick mit den Pointern. So wird das doch gemacht oder? Gibts dort auch die sache mit dem X+ und den reservierten Registern 26 und 27 ? Eigentlich wäre das mit einer while Schleife doch machbar. Hat jeman einen Ansatz für mich? Danke!
Was ist denn der Zweck? Die von C benutzten Variablen werden automatisch bereits gelöscht (bzw. passend initialisiert).
hatte immermal das Problem dass nach dem einschalten das auslesen des SRAMs nicht immer Nullen waren. Wahrscheinlich waren durch Spannungsreste noch Werte in einigen Registern. Aber auch später müsste ich diese Pointer nutzen, weil ich das SRAM anschließend beschreiben will. Und das ginge ja dann in ähnlicher Weise.
> hatte immermal das Problem dass nach dem einschalten das auslesen > des SRAMs nicht immer Nullen waren. Das ist normal. SRAM-Zellen fallen mit einer hohen Wahrscheinlichkeit auf einen technologisch bedingten Vorzugswert beim Zuschalten der Betriebsspannung. > Aber auch später müsste ich diese Pointer nutzen, weil ich das SRAM > anschließend beschreiben will. Du sprichst in Rätseln. Vielleicht zäumst du mal bitte nicht das Pferd von hinten auf und fängst mit dem Unwesentlichen an, sondern beschreibst lieber, was du insgesamt tun möchtest. Mir scheint es, du willst in C so eine Art Assemblerprogrammierung erledigen. Das ist nicht der richtige Ansatz. Ich weiß, ``Real programmers are able to program FORTRAN in any language.'', aber das ist kein sinnvoller Stil.
Ich krieg das mit den Pointern nicht hin. Ich meine ein SRAM Register hat ja eine zugehörige Adresse. Beginnend bei 0x60. Angenommen ich will den SRAM in einem Rutsch löschen. for (adr_sram=0x60,adr_sram=<0x25F,adr_sram++) { register_sram = 0x00; register_sram++; } nur wie verknüpfe ich die Register mit den jeweiligen Adressen? Das wäre doch die Sache mit den Pointer, wenn ich irre. (?)
Bevor hier noch mehr über Sinn und Unsinn deines Unterfanges diskutiert wird, probier's mal folgendermaßen: uint8_t *ptr; uint8_t start = (uint8_t *)0x060, ende = (uint8_t *)0x25f; for (ptr=start, ptr<=ende, ptr++) *ptr = 0x00; oder #include <string.h> memset(start, 0x00, 0x200); Wenn's crasht, hast Du wahrscheinlich ein paar Speicherzellen überschrieben, die das C-Laufzeitsystem benutzt.
> Sinn und Unsinn deines Unterfanges
Genau das ist aber der springende Punkt:
Es macht keinen Sinn.
Globale Variablen zu initialisieren erledigt
bereits der Compiler. Für den C-Programmierer
heisst das einfach nur: die Variable definieren
und ev. eine Intialisierung hinschreiben, wenn der
Default von 0 nicht passend ist.
Hi, > Globale Variablen zu initialisieren erledigt > bereits der Compiler. Für den C-Programmierer Nicht ganz richtig! Sozusagen eine Urban legend der Programmierer! :-)) Erledigt wird das im crt0.o-Objekt. Warum: die main-Funktion ist keinesfalls der erste Code, der sofort nach dem Reset ausgeführt wird. Das ist, auch beim GCC, ein Stück Assemblercode, das Stack etc. und u.a. auch den VERWENDETEN RAM initialisiert, bei Vorbelegung durch kopieren aus dem .data-Segment, ohne Vorbelegung (.bss-Segment) durch eine Routine, die alles zu "0" schreibt (siehe anderes Posting oben!) Wer's nicht glaubt: Dump machen oder in's Map schauen! Das ist der Woodoo des Bootstrap-Codes! Und sicher auch die Lösung Deines Rätsels! RAM, der nicht verwendet wird, wird auch nicht initialisiert! Wäre Verschwendung von Rechenzeit! ;-) Wenn Du ihn verwenden willst, definier ihn in einem C-Modul, dann ist er auch "genullt". Oder ... ;-) schreib einen eigenen Bootstrap-Code! Denk dann aber bitte auch an die Linker-Description, sonst fährt Dein Code mit Dir U-Boot! (i.d.R. mein Tipp: laß die Finger davon, wenn Du nicht genau weißt, was Du da machst!) Schönen Tag noch, Thomas
>>uint8_t *ptr;
uint8_t start = (uint8_t *)0x060, ende = (uint8_t *)0x25f;
for (ptr=start, ptr<=ende, ptr++)
*ptr = 0x00;
Ja, und wenn eine dieser Variablen im SRAM liegt (was ziemlich
wahrscheinlich ist, denn sowohl der Stack als auch der Heap liegen im
SRAM, wo auch sonst), dürfte das nicht funktionieren. Sicherlich dürfte
der Compiler für die Schleife nur Register benutzen, aber etwas unsicher
ist das doch. Wenn mich nicht alles täuscht, gab es das Schlüsselwort
register, mit dem man den Compiler bitten kann, eine Variable im
Register zu halten. Muß er aber nicht, wenn er nicht will.
BTW, insgesamt zweckfreies Vorhaben...
Gruß,
Matthias
>> Globale Variablen zu initialisieren erledigt bereits der >> Compiler. Für den C-Programmierer > Nicht ganz richtig! Sozusagen eine Urban legend der Programmierer! > :-)) Naja, ,,der Compiler'' in diesem Sinne meint eher das, was der Standard als ,,the implementation'' bezeichnet, d. h. das Zusammenspiel aus Compiler und Standardbibliothek. In diesem Sinne stimmt die Aussage natürlich, dass sich das gesamte System um die Initialisierung globaler und statischer Variablen selbst kümmert. Klar kann man ein memset(..., 0, ...) irgendwo reinbauen, aber Sinn hat das so keinen, und man riskiert, dass man sich dabei was zermüllt (je nachdem, wo man es reinbaut).
> Wenn's crasht, hast Du wahrscheinlich ein paar Speicherzellen > überschrieben, die das C-Laufzeitsystem benutzt. Warum sollten im Bereich 0x60 bsi 0x25F was anderes als anwenderdefinierte Inhalte stehen? Das Laufzeitsystem wird hier wohl kaum etwas reinspeichern.
Auch das Laufzeitsystem benutzt ein paar globale Variablen. zb. malloc muss irgendwie den Speicher verwalten. rand() muss irgendwo den Seed halten Eine der Grundregeln in der Programmierung mit einer Hochsprache lautet nicht umsonst: Speicher der Dir nicht gehört(*): Finger weg. (*) damit ist gemeint: Der nicht explizit durch Variablen belegt wurde, bzw. mittels malloc() und Konsorten angefordert wurde.
echt? na dann sollte man den SRAM also nicht nutzen oder ohne Pointer? Wie beschreib ich den SRAM denn dann?
> na dann sollte man den SRAM also nicht nutzen
Du sollst die Details wo was im SRAM liegt dem Compiler überlassen!
Der kann das besser und zuverlässiger als du!
ach verstehe. In ASM (ganz oben) hab ich es aber wie es aussieht auch nach meinem Willen gemacht. Lief aber. Wenn ich es dem Compiler überlasse, weis ich dann wieviel Platz ich im SRAM habe? Das muss ich dringen wissen, um rechtzeitig, wenn der voll ist, die Daten wieder auszulesen um keine Daten zu verlieren.
Damit ist gemeint: Du schreibst ganz einfach int irgendwas; int main( void ) { /* und hier garantiert dir der C-Sprachstandard, dass 'irgendwas' zuverlässig den Wert 0 enthält */ } Der restliche SRAM Speicher steht nicht unter Deiner Kontrolle und daher sollst du den Ruhe lassen. In einer Hochsprache zu programmieren heisst auch, dass man etwas Kontrolle abgeben muss und an das Laufzeitsystem delegiert.
> Wenn ich es dem Compiler überlasse, weis ich dann wieviel Platz > ich im SRAM habe? Das kommt drauf an. Wenn du ne Menge Variablen definierst, dann sagt dir der Compiler beim Übersetzen, wieviele Bytes die belegen. Was der Compiler natürlich nicht einrechnen kann, ist wieviel Speicher zur Laufzeit durch dynamische Allokierung bzw. den Stack verbraucht werden. Wenn du dynamisch allokierst und kein Speicher mehr da ist, dann meldet Dir das malloc() indem es eine 0 zurückliefert.
Ich seh schon, der interne(!) SRAM ist wohl wirklich zu heiss um dort anzufassen. Zumal ich dann auch nicht weis wie ich die Speicherzellen adressieren soll, wenn ich nicht weis welche verfügbar sind. Ich müsste ja immer nachfragen: für nächstes Byte adressiere nächste FREIE SRAM-Adresse. Hat das hier noch niemand gemacht? In der Suche ergibt sich dort so wenig dazu. Werd wohl doch auf extern umsteigen müssen.
> In ASM (ganz oben) hab ich es aber wie es aussieht auch > nach meinem Willen gemacht In ASM bist du auch der alleinige Herr über die Maschine. In einer Hochsprache übernimmt das Laufzeitsystem die Verwaltung von Resourcen. Stell Dir mal folgende Analogie vor: Du hast eine Festplatte. Jetzt kommt Dein Programm daher und beschreibt irgendwelche Sektoren. Einfach so. Ging ja immer. Super. Nur gibts da halt noch die Kleinigkeit eines Dateisystems, dass sich um die Zuordnung von Sektoren zu Dateien, um die Verwaltung von Dateien, etc. kümmert. Was denkst du wird passieren, wenn du ohne Koordination mit diesem Dateisystem einfach irgend- welche Sektoren beschreibst? Genauso im Speicher. In ASM bist du als Programmierer für diese Verwaltung zuständig. In einer Hochsprache gibt es dafür über Mechanismen, mit denen man kooperieren muss, damit da kein Durcheinander entsteht.
> Ich müsste ja immer nachfragen: für nächstes Byte adressiere > nächste FREIE SRAM-Adresse. > Hat das hier noch niemand gemacht? Diese Frage stellt sich so in einer Hochsprache nicht. In einer Hochsprache lautet das ganz einfach: "Gib mir mal ein Byte oder Bytefeld mit der und der Größe. Wo du dieses Feld anlegst ist mir Wurscht, ich will nur einen Pointer drauf oder eben 0, wenn nichts mehr da ist."
In C sagst Du einfach:
1 | unsigned char blub[256]; |
Und schon hast Du die Variable "blub" zur alleinigen Verfügung. Wo sie steht, interessiert Dich nicht die Bohne. Denn das ist Sache des Compilers, wo immer er den Namen "blub" findet, ihn durch die entsprechende Adresse zu ersetzten. Und da die Variable 256 Elemente groß ist, ist ein Zugriff auf blub[0] ... blub[255] erlaubt. Und jetzt kommts: Ist die Variable global oder lokal statisch, wird sie genullt, ist sie lokal, dann nicht ! Vergiß das Denken in Adressen, denke in Variablen. Peter
demnach ist also char blafasel[150]; immer Null, während bei int meinefunktion() { char blafasel[150]; const char bla[150]; } blafasel aus Müll und bla aus Nullen besteht?
> blafasel aus Müll und bla aus Nullen besteht?
Ersetz const durch static und du hast (AFAIK) Recht.
Viel eindeutiger und leichter zu lesen wäre allerdings folgende
Syntax:
char foo[150] = {0};
Denn das funktioniert auch bei lokalen Variablen.
Wenn ich mich nicht irre, initialisiert char foo[150] = {0}; nur das erste Element des Arrays. Also enthält foo[1] nach wie vor Müll, wenn foo als automatische Variable angelegt wird. Möchte man auf Nummer sicher gehen, ist memset so unpraktisch nicht: memset(foo, 0, 150 * sizeof (char));
> Wenn ich mich nicht irre, initialisiert > char foo[150] = {0}; > nur das erste Element des Arrays. Selten, aber (zum Glück) irrst du dich diesmal. 6.7.8 Initialization ... Semantics ... 21 If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.
> Möchte man auf Nummer sicher gehen, ist memset so unpraktisch nicht: > memset(foo, 0, 150 * sizeof (char)); Dagegen hat auch niemand was. Wogegen wir aber wettern ist: Einfach über den kompletten SRAM drüberbügeln.
> Dagegen hat auch niemand was.
Es sei denn, man hat's eilig. Man sollte nicht den Zeitaufwand für
diese Tätigkeit unterschätzen. Ich habe mal eine zeitkritische
Funktion optimieren müssen. Die Laufzeit war 700 µs, gefordert waren
200 µs. Der größte Block, den ich ,am Stück' wegoptimieren konnte,
war ein memset(), mit dem ein etwas übereifriger Programmierer einen
internen Puffer erstmal ,,vorsichtshalber'' komplett genullt hat.
Das
war nicht nur zeitaufwändig, sondern eigentlich auch völlig
überflüssig, da 95 % dieses Puffers anschließend sowieso mit richtigen
Daten gefüllt worden sind.
Danke an Jörg für die Aufklärung. Man lernt nie aus. Trifft das auch bei C89 ("ANSI-C") zu oder ist das C99-spezifisch?
> Trifft das auch bei C89 ("ANSI-C") zu oder > ist das C99-spezifisch? Ich habe leider nichts da, um dort nachzusehen. Zumindest sehe ich es nicht in der Liste der Änderungen in C99 erwähnt.
Wenn mich mein Gedächtnis nicht trügt, dann war das bereits bei K&R C so.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.