Ich möchte für einen RAM-Test in einer Routine einen Pointer aus dem RAM
in ein (bzw. zwei) Register kopieren. In etwa so:
1
uint8_t*pointerImRam;
2
...
3
voidRoutine()
4
{
5
uint8_t*registerpointerImRegister=pointerImRam;
6
...
7
}
Allerdings mag der Compiler den Qualifier "register" an dieser Stelle
nicht und sagt "expected unqualified-id before 'register'" und "expected
initializer before 'register'".
Ich kann mir zwar behelfen, indem ich anstatt eines Pointer ein uint16_t
verwende und später umcaste, aber gibt es denn keine Möglichkeit, einen
lokalen Pointer in ein Register zu kopieren?
Klingt irgendwie konfus.
Warum interessiert es dich, wo der Compiler die Zeiger anlegt?
In aller Regel wird er das ohnehin in Registern tun, er wär' ja
blöd, das nicht so zu machen.
Das Schlüsselwort „register“ war auch schon früher nur eine
Empfehlung. Seit die Compiler selbst gelernt haben, die Verwendung
der Variablen zu optimieren, ist es völlig überflüssig geworden.
Nitpick: „register“ ist eine storage class, kein qualifier.
Daher muss es auch am Anfang der Deklaration/Definition stehen.
Aber wie geschrieben, das Schlüsselwort ist überflüssig.
Jörg W. schrieb:> Klingt irgendwie konfus.
Es geht um einen RAM-Test. Dabei werden zyklisch alle Adressen im RAM
nacheinander mit bestimmten Mustern beschrieben und diese Muster
zurückgelesen.
Natürlich muß vorher der Inhalt der RAM-Adresse in ein CPU-Register
gesichert und danach wieder hergestellt werden, und natürlich muss das
ganz unter Interruptsperre erfolgen.
Die zu prüfende RAM-Adresse muss innerhalb des kritischen Abschnitts
ebenfalls in einem (bzw. beim AVR in mehreren) CPU-Register(n) liegen,
damit sie nicht während des Tests verfälscht wird.
>Nitpick: „register“ ist eine storage class, kein qualifier.>Daher muss es auch am Anfang der Deklaration/Definition stehen.
Hmmm... wenn ich
1
registeruint8_t*pointer;
definiere, wäre das dann nicht ein Zeiger auf ein "register uint8_t*"?
Alexander Tetzlaff schrieb:> Natürlich muß vorher der Inhalt der RAM-Adresse in ein CPU-Register> gesichert und danach wieder hergestellt werden, und natürlich muss das> ganz unter Interruptsperre erfolgen.
Wenn du ganz sicher gehen willst, dann schreib' das als inline asm.
Im von Veith verlinkten Thread findest du Beispiele.
Ansonsten einfach in C schreiben und danach verifizieren, dass der
Compiler in der Umsetzung wirklich nur Register benutzt.
> wäre das dann nicht ein Zeiger auf ein "register uint8_t*"?
Ja, wäre es nicht.
Aber wie schon geschrieben: „register“ ist (mit Ausnahme von
hartverdrahteten Registervariablen, einer GCC-eigenen Erweiterung)
überflüssig. Der Compiler benutzt es einfach nur als alternatives
Schlüsselwort für „auto“.
> Es geht um einen RAM-Test.
Über Sinn und Unsinn solcher Maßnahmen lässt sich streiten. Wer
sagt denn, wenn der RAM fehlerhaft ist, dass nicht auch Register
oder Rechenwerk gleichermaßen fehlerhaft sein könnten und daher
ein „pass“ für den RAM-Test ergeben, obwohl in Wirklichkeit doch
was kaputt ist?
Jörg W. schrieb:>> wäre das dann nicht ein Zeiger auf ein "register uint8_t*"?> Ja, wäre es nicht.
Okay, danke, das war mir nicht klar.
Bitte weiter nitpicken!
>Über Sinn und Unsinn solcher Maßnahmen lässt sich streiten.
Da hast Du recht, und streiten mag ich nicht.
(Die CPU muss in einem separaten Test geprüft werden.)
Alexander Tetzlaff schrieb:> Die CPU muss in einem separaten Test geprüft werden.
Schon klar. Mir ging's darum: ein sinnvoller Test müsste diese
Dinge von außen testen, nicht mit sich selbst. Das geht eben nur
in eine Controller praktisch nicht.
Wenn deine CPU kaputt ist und bei der Addition von 5 + 5 das Ergebnis
20 bringt, dann aber beim Vergleich auf 10 behauptet „ist gleich“
(schließlich ist sie ja kaputt), was hast du jetzt mit dem Test genau
gewonnen?
Solange nicht gerade statistisch erwiesen ist, dass der SRAM in
einem Controller sehr viel häufiger kaputt geht als die CPU
selbst, ist der RAM-Test daher ziemliche Augenauswischerei: so ein
RAM würde ja nicht mir nichts, dir nichts kaputt gehen, sondern
durch einen äußeren Einfluss. Dann ist es aber genauso zweifelhaft,
ob nicht der gleiche äußere Einfluss dazu geführt haben könnte, dass
die CPU ebenfalls geschädigt ist und den RAM-Test positiv erscheinen
lässt.
Jörg W. schrieb:> Solange nicht gerade statistisch erwiesen ist, dass der SRAM in> einem Controller sehr viel häufiger kaputt geht als die CPU> selbst, ist der RAM-Test daher ziemliche Augenauswischerei: so ein> RAM würde ja nicht mir nichts, dir nichts kaputt gehen, sondern> durch einen äußeren Einfluss. Dann ist es aber genauso zweifelhaft,> ob nicht der gleiche äußere Einfluss dazu geführt haben könnte, dass> die CPU ebenfalls geschädigt ist und den RAM-Test positiv erscheinen> lässt.
also bei normales PCs ist ein RAM Fehler eine sehr häufige
Fehlerursache. Dort mache ich auch bei merkwürdigen Fehlern zu erst ein
Ram-Test.
Beim Ram sind es doch die meisten Transistoren, damit ist die
Wahrscheinlichkeit sehr hoch das auch dort ein Defekt auftritt.
Peter II schrieb:> also bei normales PCs ist ein RAM Fehler eine sehr häufige> Fehlerursache.
Das ist aber DRAM, der ist pingelig im Timing der Ansteuerung.
Kann man mit dem im Controller verbauten SRAM nicht vergleichen.
Beim DRAM steckt die Information in einem (verdammt kleinen)
Kondensator, und die Ansteuerung benutzt pro Bit gerade mal einen
Transistor. Beim SRAM hat man (wimre) sechs Transistoren pro Bit,
und die Information steckt in einem statischen Spannungspegel, der
die Gates der Speicherzelle ansteuert.
Ich habe in der Tat schon kaputte Controller gesehen, aber noch
keinen, bei dem RAM oder CPU geschädigt worden wären. Was es schon
gab: Schädigung in den IO-Zellen bis hin zum Kurzschluss, zu hohe
Sleep-Ströme, lässt sich nicht mehr programmieren (vermutlich interne
Vpp-Erzeugung geschossen) und dergleichen Dinge.
Wogegen der RAM-Test ohnehin nicht helfen würde ist, dass durch
irgendeine Ursache (Spike auf der Versorgung oder sowas) eins oder
mehrere Bits kippen, obwohl die Zelle an sich in Ordnung ist.
Ich möchte mir erlauben, anzumerken, dass ein RAM-Test bei externem SRAM
durchaus sinnvoll ist (aus eigener leidvoller Erfahrung). Allerdings
muss dabei darauf geprüft werden, dass alle Leitung korrekt verbunden
sind, sprich ein Zugriff auf eine Adresse tatsächlich an dieser Adresse
rauskommt und nicht an einer anderen (z.B. wegen kalter Lötstelle an
einer Adressleitung).
Alexander Tetzlaff schrieb:> Ich möchte mir erlauben, anzumerken, dass ein RAM-Test bei externem SRAM> durchaus sinnvoll ist (aus eigener leidvoller Erfahrung).
Ja, bei externem RAM: keine Frage. Dann muss man aber keinerlei
Zirkus im Code veranstalten, solange die normalen Variablen alle
im internen RAM liegen.
Letztendlich liegen bei AVR Mikrocontrollern alle CPU Register im RAM,
und ich meine, dass das beim 8051 auch so war.
Dann ist es völlig egal, wie der Compiler den Speicher und die Register
nutzt.
> wäre das dann nicht ein Zeiger auf ein "register uint8_t*"?
Nein, "register" ist kein Qualifier sondern eine Speicherklasse wie
"static" oder "extern".
1
staticuint8_t*pointer;
ist kein Zeiger auf einen static sondern pointer selbst ist static.
Stefan U. schrieb:> Letztendlich liegen bei AVR Mikrocontrollern alle CPU Register im RAM
Nein. Sie sind nur über den RAM-Adressbereich zugreifbar, aber
trotzdem ist implementierungsmäßig ein Register etwas anderes als
RAM.
Das ist mir schon klar. Es gibt ASM Befehle für Register und es gibt
andere für RAM Zugriff.
Der TO möchte aber das RAM Testen und dabei sicherstellen, dass die
einige Pointer (CPU Register sind und) nicht im internen RAM liegen.
Genau das geht zumindestes bei AVR nicht, da alle Register über RAM
Adressen erreichbar sind, also (auch) im RAM liegen.
Wenn ich das GANZE RAM mit Testdaten überschreibe, dann überschreibe ich
auch die CPU Register und störe somit den Proghrammablauf.
Stefan U. schrieb:> Genau das geht zumindestes bei AVR nicht, da alle Register über RAM> Adressen erreichbar sind,
IO-Register sind auch über RAM-Adressen erreichbar, und die stehen
noch nach den CPU-Registern.
Die kann man unmöglich in einen RAM-Test mit einbeziehen, da es darin
einerseits oft Lücken gibt, andererseits genügend IO-Register, bei
denen man nicht 1:1 das wieder auslesen kann, was man reingeschrieben
hat.
> also (auch) im RAM liegen.
Nein. Nochmals: die Adressierungsmöglichkeit bedeutet nicht, dass
die Register deshalb „im RAM liegen“ würden.
Wo der RAM anfängt und wo er aufhört, ist für jeden AVR sauber genug
beschrieben, als dass man dies in einem RAM-Test berücksichtigen kann.
Noch ein Beispiel: bei einem ARM mit flachem 32-Bit-Adressraum
kommst du doch auch nicht auf die Idee, dass man beim RAM-Test alle
2^32 Adressen durchklingeln müsste …
Allenfalls waere die Anwendung noch interessant.
Wenn man nur beim Powerup pruft, was erwartet man ? Dass der Speicher
nur bei Power off/down kaputt geht ? Was soll die Laufzeit denn sein ?
Ich habe Controller in meinen Produkten im Betrieb, die laufen Monate,
oder sogar jahrelang durch.
Dann sollte man sich ueberlegen, welche Fehler erwartet man. Weshalb
sollten Fehler waehren des Abschaultens, oder ausgeschaltet seins
haeufer sein wie waehrend dem Betrieb ?
Erwartet man Fehler waehrend des Betriebes ? Dann muesste man den Test
periodisch machen. Dann sind wir aber bei den 3 Controllern, die sich
gegenseitig kontrollieren.
Jörg W. schrieb:> Stefan U. schrieb:>> Genau das geht zumindestes bei AVR nicht, da alle Register über RAM>> Adressen erreichbar sind,>> IO-Register sind auch über RAM-Adressen erreichbar, und die stehen> noch nach den CPU-Registern.>> Die kann man unmöglich in einen RAM-Test mit einbeziehen, da es darin> einerseits oft Lücken gibt, andererseits genügend IO-Register, bei> denen man nicht 1:1 das wieder auslesen kann, was man reingeschrieben> hat.>>> also (auch) im RAM liegen.>> Nein. Nochmals: die Adressierungsmöglichkeit bedeutet nicht, dass> die Register deshalb „im RAM liegen“ würden.>> Wo der RAM anfängt und wo er aufhört, ist für jeden AVR sauber genug> beschrieben, als dass man dies in einem RAM-Test berücksichtigen kann.
Wie das in der Hardware realisiert ist, lässt sich aus den Unterlagen
nicht erkennen. Die Ansteuerung muss ja nichts mit der Realisierung zu
tun haben. Gerade bei so hochvolumigen Micros werden die spannensten
Tricks umgesetzt, um die Fläche zu reduzieren.
Grundsätzlich ist es effizienter, das in einem SRAM zu realisieren, die
Speicher dort sind einfach kleiner als bei einer Realisierung mit
Flip-Flops. Das führt aber dann auch dazu, dass die leichter kaputt
gehen. Ausserdem ist der Zugriff über FF schneller.
Mag also sein, dass die 16MHz Variante das mit FF und die 8MHz Variante
mit SRAM hat. Mag auch sein, dass das sich über die Jahre ändert.
Aber grundsätzlich spricht ja nichts dagegen, das RAM mit so einem Test
zu testen, man ist zwar nicht sicher, ob alles in Ordnung ist, wenn der
Test funktioniert, aber wenn er nicht funktioniert, weiss man sicher das
etwas nicht in Ordnung ist. Was ja auch schon mal hilfreich ist.
Gruss
Axel
Axel L. schrieb:> Mag also sein, dass die 16MHz Variante das mit FF und die 8MHz Variante> mit SRAM hat.
Nein, das sind stets die gleichen Dies.
Wie es realisiert ist, ist auch ziemlich egal: dass man die Register
selbst nicht durch einen RAM-Test testen kann, sollte ziemlich
offensichtlich sein. Irgendwas braucht der Prozessor ja auf jeden
Fall zum Arbeiten, das kann man ihm nicht für einen Test unterm Popo
wegziehen.
p.s.: Beim Xmega hat man das memory mapping der CPU-Register dann
übrigens fallen gelassen. Dadurch ist dort auch der Offset 0x20
bei den IO-Registern verschwunden, den man sonst beim AVR zwischen
Adressierung per IN/OUT und Adressierung per STS/LDS hatte.
Axel L. schrieb:> Grundsätzlich ist es effizienter, das in einem SRAM zu realisieren, die> Speicher dort sind einfach kleiner als bei einer Realisierung mit> Flip-Flops.
SRAM sind FlipFlops.
Gruß
Jobst
Jobst M. schrieb:> Axel L. schrieb:>> Grundsätzlich ist es effizienter, das in einem SRAM zu realisieren, die>> Speicher dort sind einfach kleiner als bei einer Realisierung mit>> Flip-Flops.>> SRAM sind FlipFlops.>>> Gruß>> Jobst
Jain.
SRAMs sind ganz anders optimiert, werden wesentlich dichter gepackt, und
nicht zuletzt ganz anders getestet.
Daher sind sie auch empfindlicher als "normale" FF. Sie reagieren auch
viel empfindlicher auf Bitkipper im Betrieb durch Störeinstrahlung als
FF.
In kritischen Anwendungen werden SRAMs übrigens durchaus im laufenden
Betrieb getestet, bei FF habe ich das nur sehr selten gesehen.
Gruss
Axel
Jörg W. schrieb:> Axel L. schrieb:>> Mag also sein, dass die 16MHz Variante das mit FF und die 8MHz Variante>> mit SRAM hat.>> Nein, das sind stets die gleichen Dies.>
Woher weisst Du das ? Glaubst Du etwa, dass man die Dies selektiert und
damit dann 8 MHz und 16 MHz Bausteine bekommt ? Das stimmt definitiv
nicht, dann müsste der Prozess von Atmel grottenschlecht sein (und der
von TSMC ist garantiert nicht so schlecht).
> Wie es realisiert ist, ist auch ziemlich egal: dass man die Register> selbst nicht durch einen RAM-Test testen kann, sollte ziemlich> offensichtlich sein. Irgendwas braucht der Prozessor ja auf jeden> Fall zum Arbeiten, das kann man ihm nicht für einen Test unterm Popo> wegziehen.
Man braucht ja nur zwei bis drei Register zum Arbeiten.
Gilt natürlich wieder mein Satz von oben: Es mag sein, dass der Test
funktioniert, obwohl der Prozessor defekt ist, aber wenn der Test nicht
funktioniert, ist der Prozessor auf jeden Fall defekt.
Gruss
Axel
Axel L. schrieb:> Glaubst Du etwa, dass man die Dies selektiert und damit dann 8 MHz und> 16 MHz Bausteine bekommt ?
Ja, hat man so gemacht. Der Großteil davon dürfte ohnehin beide
Spezifikationen (also L/V oder 5-V-Typ) abgedeckt haben; man hat
auf diese Weise nur die Ausbeute verbessert, da man über die
gesamte Streubreite halt zwei Bereiche legen konnte.
Edit: es ist natürlich möglich, dass für die L/V- und Normaltypen
tatsächlich Prozessparameter leicht variiert worden sind. Aber
zumindest benutzen alle das gleiche Layout, darauf wollte ich mit
der vorigen Bemerkung hinaus.
Axel L. schrieb:> und der von TSMC ist garantiert nicht so schlecht
Seit den "A"-Typen, die bei TSMC laufen, gibt's die Unterscheidung
nach L- oder V-Typen ja auch nicht mehr.
Herbert schrieb:> Also mach es doch einfach in asm. Also wen für was asm gut ist dann für> sowas, die asm funtion kannst du eh in C verwenden.
Mag sein... das entschuldigt aber nicht, dass man den Unterschied
zwischen einem Modifier und einem Storage Class nicht kennt ;)
(Compiliert mal als Beispiel für einen ATmega1281.)
ramtest() benutzt intern ausschließlich Register für den Zugriff,
auf den Speicher wird nur zugegriffen, um ihn zu testen. Durch
.init3 läuft das Ganze, bevor die reguläre Initialisierung des
RAMs dann angeworfen wird. Bei Fehlern im Test verbleibt die CPU
am Ende des Tests in einer Endlosschleife.
Über Sinn und Unsinn dieser Maßnahme (insbesondere, wenn man sie
nur beim Start durchführt), wurde ja ausgiebig diskutiert.
Jörg W. schrieb:> Axel L. schrieb:>> Glaubst Du etwa, dass man die Dies selektiert und damit dann 8 MHz und>> 16 MHz Bausteine bekommt ?>> Ja, hat man so gemacht. Der Großteil davon dürfte ohnehin beide> Spezifikationen (also L/V oder 5-V-Typ) abgedeckt haben; man hat> auf diese Weise nur die Ausbeute verbessert, da man über die> gesamte Streubreite halt zwei Bereiche legen konnte.>
Woher weisst Du das (und hier meine ich wirklich wissen und nicht
vermuten oder vom Hörensagen). Alle Daten, die ich über Prozesse habe,
legen nahe, dass es bei einem ausgereiften Prozess niemals eine
Variation von 50% gibt. Wenn man die Prozessparameter so stark streuen
liesse, würden auch andere, kritische Werte aus der Toleranz fallen und
die Ausbeute leidet. Wir reden ja hier nicht von einem 7nm Prozess, wo
man noch zweistellige Ausfallraten hat, das hier dürfte ja noch eher
150nm oder ähnliches sein. Da kann man die Prozessparameter deutlich
genauer kontrollieren.
> Edit: es ist natürlich möglich, dass für die L/V- und Normaltypen> tatsächlich Prozessparameter leicht variiert worden sind. Aber> zumindest benutzen alle das gleiche Layout, darauf wollte ich mit> der vorigen Bemerkung hinaus.>
Warum sollte man das tun ? Die Ausbeute bei diesen Prozessen kann man
damit nicht mehr verbessern. Und man wird nicht an den Parametern
drehen, weil man damit die Ausbeute gefährdet. So ein Prozess wird in
der Mitte der Parameter gefahren, damit schön viele heile rauskommen.
Dagegen kann man durch Verwendung von High Speed bzw. High Density SRAM
(und evtl. auch Flash) die Chipfläche erheblich reduzieren.
> Axel L. schrieb:>> und der von TSMC ist garantiert nicht so schlecht>> Seit den "A"-Typen, die bei TSMC laufen, gibt's die Unterscheidung> nach L- oder V-Typen ja auch nicht mehr.
Wie gesagt, ich frage mich, woher dieses Wissen stammt (das interessiert
mich wirklich). Intel hat das früher so gemacht, aber Intel verwendet
auch Technologien, die an der Grenze des Machbaren liegen. Und schon
nach relativ kurzer Zeit liefen dann die "Low Speed" Varianten mit dem
Takt der High Speed Prozessoren, da fielen gar nicht mehr genügend
langsame Prozessoren aus der Fertigung.
Gruss
Axel
Jörg W. schrieb:> Nochmal BTT: ich versteh' die ganze Aufregung gar nicht.
Mein RAM-Test läuft permanent im Hintergrund.
Die Adresse, die ich als nächstes prüfen werde, steht selbst ja auch im
RAM.
Ich muss daher diese Adresse aus dem RAM in Register kopieren, und auch
den Inhalt der zu prüfenden Adresse in ein Register sichern.
Das funktioniert auch in C geschrieben perfekt, allerdings muss ich
sicherheitshalber den erzeugten Assembler-Code von Hand prüfen (was ein
klares Argument dafür ist, die Routine gleich in Assembler zu
schreiben).