Forum: Mikrocontroller und Digitale Elektronik Inline Assembler mit der Atmel AVR Toolchain


von Simon G. (sigro)


Lesenswert?

Hallo,
ich veruche folgende Funktion mit dem AVR Studio 7 und der 
mitgelieferten Toolchain zu überstzen:
1
static uint8 teste_sreg()
2
{
3
  uint8 ergebnis;
4
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
5
  {
6
  asm volatile (
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
  return ergebnis;
36
}

Wenn ich WinAVR benutze habe ich damit kein Problem.

Mit der Toolchain wir es jedoch zu folgendem "übersetzt":
1
  IN    r16, 63
2
  LDI   r17, 0x55
3
  OUT   63, r17
4
  LDI   r17, 0
5
  IN    r17, 63
6
  OUT   63, r16
7
  CPI   r17, 0x55
8
  BREQ  SR_0x2A_TST
9
  RJMP   FEHLER_SR
10
  SR_0x2A_TST:
11
  LDI   r17, 0x2A
12
  OUT   63, r17
13
  LDI   r17, 0x00
14
  IN    r17, 63
15
  OUT   63, r16
16
  CPI   r17, 0x2A
17
  BREQ  TEST_SR_OK
18
  RJMP   FEHLER_SR
19
  FEHLER_SR:
20
  LDI   r15, 1
21
  TEST_SR_OK:
22
  LDI   r15, 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

von Jan K. (madengineer)


Lesenswert?

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

von Simon G. (sigro)


Lesenswert?

Super, vielen Dank!

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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.

von Simon G. (sigro)


Lesenswert?

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!

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


Lesenswert?

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.

von Bernd K. (prof7bit)


Lesenswert?

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?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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

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.