Forum: Compiler & IDEs SRAM bei Start löschen


von Eder (Gast)


Lesenswert?

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!

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Was ist denn der Zweck?  Die von C benutzten Variablen werden
automatisch bereits gelöscht (bzw. passend initialisiert).

von Eder (Gast)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> 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.

von Eder (Gast)


Lesenswert?

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. (?)

von yalu (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

> 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.

von tom (Gast)


Lesenswert?

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

von MNR (Gast)


Lesenswert?

>>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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

>> 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).

von Eder (Gast)


Lesenswert?

> 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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Eder (Gast)


Lesenswert?

echt? na dann sollte man den SRAM also nicht nutzen oder ohne Pointer?
Wie beschreib ich den SRAM denn dann?

von Karl H. (kbuchegg)


Lesenswert?

> 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!

von Eder (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

> 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.

von Eder (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

> 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.

von Karl H. (kbuchegg)


Lesenswert?

> 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."

von peter dannegger (Gast)


Lesenswert?

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

von Nico Schümann (Gast)


Lesenswert?

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?

von Christoph _. (chris)


Lesenswert?

> 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.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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));

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> 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.

von Karl H. (kbuchegg)


Lesenswert?

> 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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> 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.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> 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.

von Karl H. (kbuchegg)


Lesenswert?

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
Noch kein Account? Hier anmelden.