Hallo,
ich veruche folgende Funktion mit dem AVR Studio 7 und der
mitgelieferten Toolchain zu überstzen:
1
staticuint8teste_sreg()
2
{
3
uint8ergebnis;
4
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
5
{
6
asmvolatile(
7
"IN r16, %[SR]""\n\t"// Sichere das CPU-SR in r16
8
"LDI r17, 0x55""\n\t"// 0x55 Muster
9
"OUT %[SR], r17""\n\t"// Schreibe Muster ins CPU-SR
10
"LDI r17, 0""\n\t"// Lösche r17
11
"IN r17, %[SR]""\n\t"// Lese CPU-SR in r17
12
"OUT %[SR], r16""\n\t"// Schreibe CPU-SR Wert zurück
13
"CPI r17, 0x55""\n\t"// Vergleiche Wert mit 0x55 Muster
14
"BREQ SR_0x2A_TST""\n\t"// Wenn gleich -> 0x2A Test
15
"RJMP FEHLER_SR""\n\t"// sonst -> Fehler
16
"SR_0x2A_TST:""\n\t"// 0x2A Test:
17
"LDI r17, 0x2A""\n\t"// 0x2A Muster
18
"OUT %[SR], r17""\n\t"// Schreibe Muster ins CPU-SR
19
"LDI r17, 0x00""\n\t"// Lösche r17
20
"IN r17, %[SR]""\n\t"// Lese CPU-SR in r17
21
"OUT %[SR], r16""\n\t"// Schreibe CPU-SR Wert zurück
22
"CPI r17, 0x2A""\n\t"// Vergleiche Wert mit 0x2A Muster
23
"BREQ TEST_SR_OK""\n\t"// Wenn gleich -> SR ok
24
"RJMP FEHLER_SR""\n\t"// sonst -> fehler
25
"FEHLER_SR:""\n\t"// Fehler:
26
"LDI %[ERG], %[TST_FAIL]""\n\t"// return TST_FAIL
27
"TEST_SR_OK:""\n\t"// SR ok:
28
"LDI %[ERG], %[TST_OK]""\n\t"// return TST_OK
29
:[ERG]"=r"(ergebnis)// return Wert
30
:[SR]"M"(_SFR_IO_ADDR(SREG)),// Adresse des SREG
31
[TST_OK]"M"(TEST_OK),// Rückgabewert bei Test ok
32
[TST_FAIL]"M"(TEST_SR_FAIL)// Rückgabewert bei Fehler
33
:"r16","r17","r30","r31");// Benutzte Register
34
}
35
returnergebnis;
36
}
Wenn ich WinAVR benutze habe ich damit kein Problem.
Mit der Toolchain wir es jedoch zu folgendem "übersetzt":
1
INr16,63
2
LDIr17,0x55
3
OUT63,r17
4
LDIr17,0
5
INr17,63
6
OUT63,r16
7
CPIr17,0x55
8
BREQSR_0x2A_TST
9
RJMPFEHLER_SR
10
SR_0x2A_TST:
11
LDIr17,0x2A
12
OUT63,r17
13
LDIr17,0x00
14
INr17,63
15
OUT63,r16
16
CPIr17,0x2A
17
BREQTEST_SR_OK
18
RJMPFEHLER_SR
19
FEHLER_SR:
20
LDIr15,1
21
TEST_SR_OK:
22
LDIr15,0
und es wird der Fehler:
"register number above 15 required"
mehrfach ausgegeben. er bezieht sich auf die zeilen mit LDI 15, ...
Was kann ich machen, dass der Code auch mit der Toolchain funktioniert?
Vielen Dank!
Simon
Hallo Simon,
das Problem ist die LDI-Instriktion, da diese nur mit den sogenannten
oberen Registern funktioniert, also R16 bis R31.
So schlägt dann die Zuweisung
LDI %[ERG], %[TST_FAIL] fehl, weil der Assembler [ERG] das Register
R15 zuweist. Um das zu verhindern, musst du das Contraint
: [ERG] "=r" (ergebnis) // return Wert
in
: [ERG] "=a" (ergebnis) // return Wert
Damit sagst du dem Compiler, das er eines der oberen Register nehmen
soll.
Nachlesen kannst du das zum Beispiel hier:
http://www.nongnu.org/avr-libc/user-manual/inline_asm.html
Der Code soll testen, ob das SREG noch "funktioniert"? So ein Code ist,
äh ich sag jetzt mal — akademisch: Wenn das SREG nicht mehr
"funktioniert" dann hüpft dein Programm bei jedem bedingten Sprung eher
zufällig und bei Berechnungen kommt auch unsinn raus weil die ganzen
Flags spinnen.
Die richtige Constraint für LDI ist übrigens "=d" (auch wenn "=a" nicht
falsch ist).
Außerdem fällt der Code von FEHLER_SR durch auf TEST_SR_OK.
Explizite Labels können dir auch Probleme machen. Nimm lokale Labels
wie 0: oder bau %= in die Labels ein.
Für ein Überblick über Constraints siehe
http://rn-wissen.de/wiki/index.php/Inline-Assembler_in_avr-gcc#Instruktionen_und_Constraints
So nen Spaghetti kann auch gerne in blankem Assembler stehen, inline
sind solche Monster irgendwie ätzend.
Johann L. schrieb:> Der Code soll testen, ob das SREG noch "funktioniert"? So ein Code ist,> äh ich sag jetzt mal — akademisch: Wenn das SREG nicht mehr> "funktioniert" dann hüpft dein Programm bei jedem bedingten Sprung eher> zufällig und bei Berechnungen kommt auch unsinn raus weil die ganzen> Flags spinnen.
Die Hoffnung ist, dass sich dadurch der diagnosedeckungsgrad leicht
erhöht und der TÜV zufrieden ist.
Johann L. schrieb:> Die richtige Constraint für LDI ist übrigens "=d" (auch wenn "=a" nicht> falsch ist).
Danke, darüber hatte ich heute auch schon nachgedacht nachdem mir
madengineer den den Link gegeben hat.
Johann L. schrieb:> Außerdem fällt der Code von FEHLER_SR durch auf TEST_SR_OK.
Oh, das ist peinlich, ist bis jetzt keinem aufgefallen.
Johann L. schrieb:> Explizite Labels können dir auch Probleme machen. Nimm lokale Labels> wie 0: oder bau %= in die Labels ein.
Sehr guter Vorschlag!
Johann L. schrieb:> Für ein Überblick über Constraints siehe>> http://rn-wissen.de/wiki/index.php/Inline-Assembler_in_avr-gcc#Instruktionen_und_Constraints>
Danke!
Simon G. schrieb:> Die Hoffnung ist, dass sich dadurch der diagnosedeckungsgrad leicht> erhöht und der TÜV zufrieden ist.
Naja, aber gerade bei SREG ist das völlig zweifelhaft. Wie Johann
schon schreibt, wenn das Ding aus irgendeinem Grunde kaputt wäre,
warum sollte es dann genau so kaputt sein, dass dein Code das auch
entdeckt? Im SREG ist ja beispielsweise das Z-Flag drin, welches
durch den Code benutzt wird … ist dieses immer gesetzt (sodass BREQ
immer springt), dann würde der Code ein vermeintlich fehlerfreies
SREG diagnostizieren, obwohl es in Wirklichkeit kaputt ist.
OK, dem könnte man noch begegnen, indem man die Bedingungen am Ende
vertauscht (sodass es noch ein BRNE gibt), aber der Aufrufer muss
ja auch den Ergebniscode auswerten können – und sich dafür wieder auf
das SREG verlassen.
Ich glaube, man muss einfach akzeptieren, dass es in so einem Prozessor
Dinge gibt, die er nicht selbst diagnostizieren kann.
Simon G. schrieb:> Die Hoffnung ist, dass sich dadurch der diagnosedeckungsgrad leicht> erhöht und der TÜV zufrieden ist.
Alter Schwede.
Also je mehr obskure WTF???s wie den oben zu sehenden man in den Code
einbaut desto "sicherer" wird das ganze und der TÜV ist zufrieden?
Simon G. schrieb:> Johann L. schrieb:>> Der Code soll testen, ob das SREG noch "funktioniert"? So ein Code ist,>> äh ich sag jetzt mal — akademisch: Wenn das SREG nicht mehr>> "funktioniert" dann hüpft dein Programm bei jedem bedingten Sprung eher>> zufällig und bei Berechnungen kommt auch unsinn raus weil die ganzen>> Flags spinnen.>> Die Hoffnung ist, dass sich dadurch der diagnosedeckungsgrad leicht> erhöht und der TÜV zufrieden ist.
*räusper*
Ich war davon ausgegangen es sei ein Lernprogramm mit dem du bissl am
SREG rumspielst...
Der TÜV lässt sich mit solchen Nebelkerzen überzeugen???
Eine Prüfsumme über den non-volatile Speicher lass ich mir ja noch
gefallen.
Eine Prüfsumme über den RAM auch, nur ist das kaum gescheit in Software
zu realisieren. Wie lange lässt man z.B. eine RAM-Einheit anhängen bis
man sie wieder kontrolliert? 1ns? 1ms? 10s? Und was macht man
währentdessen, IRQs sperren vielleicht?
Das einzig sinnvolle ist da nen µC zu verwenden, der ECC in Hardware
mitbringt; z.B. 1-Bit Fehlerkorrektur (pro Word) und 2-3 Bit
Fehlererkennung.
Und wie soll der Inhalt von SFRs geprüft werden? Einfach mal n bissl an
den Ports rumkonfigurieren und dann schauen, ob die SFRs noch den
gleichen Wert haben?
> Johann L. schrieb:>> Außerdem fällt der Code von FEHLER_SR durch auf TEST_SR_OK.>> Oh, das ist peinlich, ist bis jetzt keinem aufgefallen.
Mal ganz frank und frei: Vielleicht solltet ihr erstmal auf
(Inline-)Assembler verzichten um wen von der Qualität des Produkts zu
überzeugen...