Forum: Compiler & IDEs [AVR] "Undokumentierte" Synchronisationsprimitive XCH, LAC, LAS, LAT in gcc


von Hanno (Gast)


Lesenswert?

Hi.

Der Eine oder Andere ist vllt. schon auf die relativ neuen Instruktionen 
im AVR Instruction Set gestoßen:

LAC – Load And Clear
LAS – Load And Set
LAT – Load And Toggle
XCH – Exchange

Diese Operationen ermöglichen eine simple, effiziente und sehr elegante 
Implementierung von Synchronisierungsoperationen, z.B. zwischen "main()" 
und ISRs.

AVR Studio 5 kennt diese Instruktionen aber (zumindest im 
gcc-Inline-Assembler) noch nicht - obwohl der Disassembler sie korrekt 
darstellt.

Es scheint keine Übersicht zu geben, welche AVRs diese Befehle 
unterstützen und welche nicht. Deshalb bin ich auf die Idee gekommen, 
ein bisschen zu testen:

Ein ATmega1284P (Bj. 50/2010) unterstützt die Befehle jedenfalls weder 
im Simulator noch auf der echten Hardware.

Bei einem ATxmega128A3 funktionieren sie dagegen zumindest im Simulator.

Mich würde interessieren, auf welcher AVR-Hardware die Befehle außerdem 
noch implementiert sind - evtl. eben auch undokumentiert. (Atmels Doku 
hängt ja manchmal etwas hinterher...)
Deshalb lade ich alle herzlich ein, auf den AVRs, die sie gerade zur 
Hand haben, einmal zu probieren, ob's geht oder nicht.

Um die Instruktionen auch ohne Assembler-/Compiler-Unterstützung nutzen 
zu können, habe ich ein paar cpp-Macros gebastelt:
1
#define ASM_LAC_OPCODE(reg) ((0b1001001000000110) | (reg << 4))
2
#define ASM_LAS_OPCODE(reg) ((0b1001001000000101) | (reg << 4))
3
#define ASM_LAT_OPCODE(reg) ((0b1001001000000111) | (reg << 4))
4
#define ASM_XCH_OPCODE(reg) ((0b1001001000000100) | (reg << 4))
5
6
#define xstr(s) str(s)
7
#define str(s) #s
8
9
#define __ASM_WORD(opcode) ".word " xstr( opcode ) " \n"
10
11
#define ASM_LAC(reg) __ASM_WORD(ASM_LAC_OPCODE(reg))
12
#define ASM_LAS(reg) __ASM_WORD(ASM_LAS_OPCODE(reg))
13
#define ASM_LAT(reg) __ASM_WORD(ASM_LAT_OPCODE(reg))
14
#define ASM_XCH(reg) __ASM_WORD(ASM_XCH_OPCODE(reg))
(für "reg" wird die Nummer des gewünschten Registers übergeben: 0 für 
r0, 1 für r1, ..., 31 für r31)

Mit diesen lässt sich im gcc-Inline-Assembler ein entsprechender Opcode 
einbauen, z.B.:
1
asm volatile (
2
  "mov r0, r24 \n"
3
  ASM_XCH(0)
4
  "mov r25, r0 \n"
5
: : : "r0", "r25" );
was übersetzt wird zu:
1
  mov r0, r24
2
  xch r0
3
  mov r25, r0

Ein einfacher Funktionstest könnte dann so aussehen:
1
volatile uint8_t flag;
2
3
...
4
5
uint8_t valIn;
6
uint8_t valOut;
7
  
8
flag = 0xf0;
9
valIn = 0x0f; // Muss != flag sein!
10
11
asm volatile (
12
  "mov r0, %[valIn] \n"
13
  ASM_XCH(0)
14
  "mov %[valOut], r0 \n"
15
:  [valOut] "=&r" (valOut)
16
:  [valIn] "r" (valIn),
17
  [flag] "z" (&flag)
18
: "r0" );
19
20
if ( valOut == valIn ) {
21
  // Schade, nichts passiert :-/
22
} else {
23
  // Glueckwunsch: Die Operation wird unterstuetzt! :)
24
}

Ich bitte um Feedback, falls jemand weitere Informationen zur 
Verfügbarkeit dieser interessanten Befehle auf AVR-Hardware hat! :)

Viele Grüße
 Hanno

: Verschoben durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Hanno schrieb:

> AVR Studio 5 kennt diese Instruktionen aber (zumindest im
> gcc-Inline-Assembler) noch nicht - obwohl der Disassembler sie korrekt
> darstellt.

Die binutils unterstützen diese Instruktionen noch nicht. Wenn der 
Disassembler sie darstellen kann (avr-objdump), dann hat A wohl 
Unterstützigs dafür eingebau — was etwa 1 Zeile pro Befehl in 
include/opcode/avr.h werden dürfte. Die Codierung ist die gleiche wie 
für ASR, ROR, LSR, COM, DEC, INC, NEG, POP, PUSH.

> Mich würde interessieren, auf welcher AVR-Hardware die Befehle außerdem
> noch implementiert sind

M.W. Xmega.

> Um die Instruktionen auch ohne Assembler-/Compiler-Unterstützung nutzen
> zu können, ...

Wenn sie disassembliert werden können, also im BFD implementiert sind 
und avr-objdump sie kennt, sollte avr-as sie doch auch assemblieren 
können?

> Ein einfacher Funktionstest könnte dann so aussehen:
>
> volatile uint8_t flag;
> ...
> uint8_t valIn;
> uint8_t valOut;
>
> flag = 0xf0;
> valIn = 0x0f; // Muss != flag sein!

Warum das? Es muss doch auch funcktionieren, wenn beide gleich sind.


> :  [valOut] "=&r" (valOut)

Nein, hier kein early-clobber! So:

> :  [valOut] "=r" (valOut)


Sinnvoll wäre eine Unterstützung in Form von Built-ins wie 
__builtin_avr_atomic_exchange() der auf die entsprechende Funktion 
abbildet falls vorhanden und ansonsten eine kleine Instruktionssequenz 
einfügt. Damit wären die Built-ins auf allen AVRs verfügbar, analog zu 
__builtin_avr_fmul die auch da sind, wenn es kein FMUL-Befehl gibt.

Ausserdem könnte der Compiler optimieren, wenn Befehl/Maske/Adresse für 
SBI bzw. CBI passt.

@Admin: Das passt besser nach "GCC".

von Noname (Gast)


Lesenswert?

Nanu. Ist das nicht schonmal diskutiert worden?
Beitrag "AVR: Undokumentierte LAT Instruktion?"

Danach sind lediglich andere Mnemonics verwendet worden, aber die 
Befehle selbst sind, nach deren Operationscode, nicht neu.

von Noname (Gast)


Lesenswert?

Hm. Scheint doch nicht das selbe zu sein. Die Operationscodes sind 
unterschiedlich.

von Hanno (Gast)


Lesenswert?

>> valIn = 0x0f; // Muss != flag sein!

> Warum das? Es muss doch auch funcktionieren, wenn beide gleich sind.

Natürlich! - Aber wenn beide Werte gleich sind, hat XCH keine sichtbaren 
Auswirkungen und man kann nicht testen, ob es unterstützt wird oder nur 
als unbekannter Opcode übersprungen wurde :)

von Peter D. (peda)


Lesenswert?

Hanno schrieb:
> Ein ATmega1284P (Bj. 50/2010) unterstützt die Befehle jedenfalls weder
> im Simulator noch auf der echten Hardware.

Stehen ja auch nicht in dessen Datenblatt.

Die standard AVRs werden, wie es scheint, nicht mehr weiterentwickelt. 
Also brauchst Du Dir keine Sorgen um die neuen Befehle zu machen.

Ich finde es nicht besonders clever von Atmel, neue Features in MCs 
einzubauen, die nicht pin- und spannungskompatibel zu den etablierten 
AVR-Serien sind.


Peter

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:

> Ich finde es nicht besonders clever von Atmel, neue Features in MCs
> einzubauen, die nicht pin- und spannungskompatibel zu den etablierten
> AVR-Serien sind.

Wieso?

Die Xmega waren noch nie binärkompatibel zu den klassischen AVRs. Wenn 
du von "Classic" nach "Xmega" wechselst, muss eh aller C-Code neu 
übersetzt werden bzw. der asm-Code angepasst werden...

Und mit der Begründung hätten AVRs heute immer noch kein MUL-Befehl.

von Hanno (Gast)


Lesenswert?

>> Ein ATmega1284P (Bj. 50/2010) unterstützt die Befehle jedenfalls weder
>> im Simulator noch auf der echten Hardware.

> Stehen ja auch nicht in dessen Datenblatt.

Stimmt natürlich. - In der Instruction Set Doku steht aber bei denen 
auch nicht der Hinweis, dass die nicht auf allen AVRs verfügbar sind. 
Anders also als z.B. für MUL & Andere.
Soviel zur Atmel-Dokumentation.

Jedenfalls hatte ich gehofft, dass die Kommandos vllt. ohne gesonderte 
Doku in neuere (mega-)AVRs eingeflossen sind. - Sowas passiert ja 
schonmal, wenn neuere und ältere Produktreihen in der 
Entwicklung/Fertigung konsolidiert werden, um Kosten zu sparen.

von Peter D. (peda)


Lesenswert?

Johann L. schrieb:
> Die Xmega waren noch nie binärkompatibel zu den klassischen AVRs.

Das neu Compilieren stört mich nicht. Aber daß ich neue Schaltungen und 
neue Platinen entwickeln und testen muß, ist sehr ärgerlich.
Wir haben nur kleine Serien, da wirken sich solche Kosten erheblich aus.

Wenn ein neuer MC nach außen kompatibel wäre, würde das die Kosten und 
auch das Risiko erheblich senken. Falls der neue MC dann doch nicht 
geht, kann man ihn einfach wieder durch den alten ersetzen und muß nicht 
nen Haufen bestückter Platinen wegschmeißen.


Peter

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:
> Johann L. schrieb:
>> Die Xmega waren noch nie binärkompatibel zu den klassischen AVRs.
>
> Das neu Compilieren stört mich nicht. Aber daß ich neue Schaltungen und
> neue Platinen entwickeln und testen muß, ist sehr ärgerlich.
> Wir haben nur kleine Serien, da wirken sich solche Kosten erheblich aus.

ah, Du meinst mit "neuen Features" also solche, die die physikalischen 
Eigenschaften betreffen, nicht "interne" Features wie die o.g. neuen 
Instruktionen?

von Peter D. (peda)


Lesenswert?

Ich meine natürlich neue interne Features (Peripherie, Instruktionen), 
wie es früher bei den AVRs erfolgte, z.B.:
ATtiny15 -> ATtiny85
ATtiny26 -> ATtiny861
ATmega8 -> ATmega328p
ATmega16 -> ATmega1284p
ATmega128 -> ATmega2561

Kunden sind naturgemäß nie zufrieden und wollen zusätzliche Funktionen. 
Und wenn man dazu auf der Platine nur nen anderen Chip bestücken muß, 
ist das ein riesen Vorteil gegenüber alles komplett neu zu machen.
Auch gewinnt man damit Zeit, der Kunde erhält erstmal nur das Gerät mit 
dem neuen Chip und das Firmwareupdate mit den Zusatzfunktionen wird 
nachgereicht.

Ist ein Hersteller aber nicht mehr kompatibel, verliert er die 
Kundenbindung. Wenn ich erst ne neue Schaltung machen muß, dann kann ich 
auch gleich einen völlig anderen MC nehmen.
Und so wirds bei uns wohl auch laufen, NXP Cortex M3 ist angedacht.


Peter

von deka-dent (Gast)


Lesenswert?

So verständlich deine Forderungen auch sein mögen, sie passen nicht mehr 
zum gegenwärtigen Zeitgeist. Die Entwicklungszyklen werden immer kürzer, 
so auch der gepflegte lifecycle. Produkte werden mit heißer Nadel 
rausgehauen, Hauptsache es besteht Hoffnung, dass sie die 
Gewährleistungsfristen mit annehmbaren Risiken überstehen. Danach soll 
der Kunde neue und bessere Versionen des Produkts kaufen. Geworben wird 
mit servicefreundlichem Replacement. Ein Produkt, dass mehrere Jahre 
unbeschadet übersteht ist nicht mehr gewollt. Ein Qualitätsmanagement 
ist erstrangig dazu da, das Produkt gerade noch so ausreichend zu 
produzieren, dass juristische Risiken des Herstellers minimiert werden 
können. All dies hat natürlich auch Auswirkungen auf die Beschaffung von 
Bauteilen. Die Produktvielfalt explodiert, während die Verfügbarkeit 
immer kürzer wird.

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


Lesenswert?

Peter Dannegger schrieb:
> Wenn ein neuer MC nach außen kompatibel wäre

Das stehst du als Hersteller irgendwann nicht mehr durch.  Der Wunsch
nach neuen Features kollidiert dann so stark mit dem nach der
Rückwärtskompatibilität, dass die Auflösung nur in "mach was völlig
Neues" bestehen kann.  Das hat Atmel mit dem Xmega letztlich getan.

Der Grund dafür ist, dass man für die Weiterentwicklung unbedingt
kleinere Strukturgrößen im Prozess braucht (schließlich willst du
ja nicht den exorbitanten Preis größerer Chips bezahlen), dass aber
Prozesse mit kleinerer Strukturgröße notgedrungen nicht mehr so
spannungsfeste Bauteile bringen.  Was denkst du, warum die Core-
Spannungen aktueller Desktop-CPUs irgendwo im Bereich von 1 V
angekommen sind?  Weil die Prozesse so klein sind.

OK, man hätte die Masse- und Betriebsspannungspins noch irgendwie
pinkompatibel lassen können, da gebe ich dir Recht.  Vielleicht auch
noch JTAG, aber schon PDI als Ablösung für ISP ist ja hinreichend
anders.

deka-dent schrieb:
> Produkte werden mit heißer Nadel
> rausgehauen, Hauptsache es besteht Hoffnung, dass sie die
> Gewährleistungsfristen mit annehmbaren Risiken überstehen.

Mit Verlaub, aber das, was du da von dir gibst, ist reines Gesülze
und hat mit der Realität eines Halbleiterherstellers herzlich wenig
zu tun.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Jörg Wunsch schrieb:
> deka-dent schrieb:
>> Produkte werden mit heißer Nadel
>> rausgehauen, Hauptsache es besteht Hoffnung, dass sie die
>> Gewährleistungsfristen mit annehmbaren Risiken überstehen.
>
> Mit Verlaub, aber das, was du da von dir gibst, ist reines Gesülze
> und hat mit der Realität eines Halbleiterherstellers herzlich wenig
> zu tun.

Das bezog sich wohl auf irgendwelche Billig- oder Wegwerf-Produkte, die 
mit diesen ICs hergestellt werden?

von (prx) A. K. (prx)


Lesenswert?

Jörg Wunsch schrieb:

> Was denkst du, warum die Core-
> Spannungen aktueller Desktop-CPUs irgendwo im Bereich von 1 V
> angekommen sind?  Weil die Prozesse so klein sind.

Die sind dort angekommen, weil man dank kleiner Strukturen mit 
niedrigeren Spannungen arbeiten kann und aufgrund der Verlustwärme 
arbeiten muss.

Mit einem höher auflösenden Herstellungsprozess kann man aber auch 
grössere Strukturen erzeugen, nur umgekehrt geht es nicht. Die 
Transistoren der I/O-Pins sind aufgrund der viel grösseren Last in jedem 
Prozess viel grösser als rein interne mit nur lokaler Verbindung. Zudem 
sind unterschiedliche Power Supply Domains mittlerweile nicht nur bei 
PC-Prozessoren verbreitet, sondern auch bei Controllern.

Freilich geht der Trend weg von 5V, unübersehbar und überall. Die Frage 
war also eher, ob man noch 5V-Kompatibilität einbaut oder nicht. Wenn 
man die verwirft, dann kann man auch den nächsten Schritt gehen und eine 
einengende Pinkompatibilität aufgeben. Irgendwann muss man es wohl, und 
das ist der beste Zeitpunkt.

Für den Anwender wiederum ist das natürlich der logische Zeitpunkt, um 
sich auch man anderswo umzusehen. Wenn man sowieso schon ein Redesign 
braucht.

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


Lesenswert?

A. K. schrieb:
> Zudem
> sind unterschiedliche Power Supply Domains mittlerweile nicht nur bei
> PC-Prozessoren verbreitet, sondern auch bei Controllern.

Richtig, aber wenn du nicht mit externen Schaltreglern anfangen
willst, dann verheizt man am Ende einen Haufen Energie in einem
Linearregler, wenn die Differenz zu groß wird.  Ist also alles
irgendwo ein Kompromiss.

> Freilich geht der Trend weg von 5V, unübersehbar und überall.

Ja, so sehe ich das auch.

> Wenn man sowieso schon ein Redesign
> braucht.

Wobei man es ja nicht zwangsläufig muss, schließlich hat Atmel ja
keineswegs die MegaAVR-Linie irgendwie abgekündigt oder dergleichen.
Wenn man bei 5 V bleiben will, kann man also durchaus weiterhin so
arbeiten wie bisher.

Vorteil des Übergangs vom MegaAVR zum Xmega ist, dass man im
Wesentlichen mit den gleichen Tools weiterarbeiten kann.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Hanno schrieb:

> die relativ neuen Instruktionen im AVR Instruction Set
>
> LAC – Load And Clear
> LAS – Load And Set
> LAT – Load And Toggle
> XCH – Exchange
>
> [...] Um die Instruktionen auch ohne Assembler-/Compiler-Unterstützung
> nutzen zu können, habe ich ein paar cpp-Macros gebastelt:
>
1
#define ASM_LAC_OPCODE(reg) ((0b1001001000000110) | (reg << 4))
2
#define ASM_LAS_OPCODE(reg) ((0b1001001000000101) | (reg << 4))
3
#define ASM_LAT_OPCODE(reg) ((0b1001001000000111) | (reg << 4))
4
#define ASM_XCH_OPCODE(reg) ((0b1001001000000100) | (reg << 4))
5
6
#define xstr(s) str(s)
7
#define str(s) #s
8
9
#define __ASM_WORD(opcode) ".word " xstr( opcode ) " \n"
10
11
#define ASM_LAC(reg) __ASM_WORD(ASM_LAC_OPCODE(reg))
12
#define ASM_LAS(reg) __ASM_WORD(ASM_LAS_OPCODE(reg))
13
#define ASM_LAT(reg) __ASM_WORD(ASM_LAT_OPCODE(reg))
14
#define ASM_XCH(reg) __ASM_WORD(ASM_XCH_OPCODE(reg))

> Ich bitte um Feedback, falls jemand weitere Informationen zur
> Verfügbarkeit dieser interessanten Befehle auf AVR-Hardware hat! :)


Inzwischen sind die Befehle in den binutils verfügbar. Bei Interesse 
kann ich einen Link auf eine Windows-Toolchain posten mit

• avr-gcc 4.7.1
• binutils 2.23
• AVR-libc 1.8.1

Nach den Patches zu urteilen dürften auch neuere Versionen der 
Atmel-Tools diese Instruktionen kennen — zumindest die binutils.

Damit sieht der Code dann zum Beispiel so aus:
1
#include <avr/io.h>
2
3
static inline __attribute__((__always_inline__))
4
uint8_t xch (uint8_t volatile *p, uint8_t x)
5
{
6
    __asm volatile ("xch %a1,%0" : "+r"(x) : "z"(p) : "memory");
7
    return x;
8
}
9
10
int main (void)
11
{
12
    return xch (&PORTB.DIR, 0);
13
}

Der erzeugte Code mit -Os -mmcu=atxmega16a4
 
1
main:
2
  ldi r24,0
3
  ldi r30,lo8(32)
4
  ldi r31,lo8(6)
5
/* #APP */
6
 ;  6 "" 1
7
  xch Z,r24
8
 ;  0 "" 2
9
/* #NOAPP */
10
  ldi r25,0
11
  ret

Und das Disassembly:
 
1
0000018a <main>:
2
 18a:  80 e0         ldi  r24, 0x00  ; 0
3
 18c:  e0 e2         ldi  r30, 0x20  ; 32
4
 18e:  f6 e0         ldi  r31, 0x06  ; 6
5
 190:  84 93         xch  Z, r24
6
 192:  90 e0         ldi  r25, 0x00  ; 0
7
 194:  08 95         ret

von Dosmo (Gast)


Lesenswert?

A. K. schrieb:
> Für den Anwender wiederum ist das natürlich der logische Zeitpunkt, um
> sich auch man anderswo umzusehen. Wenn man sowieso schon ein Redesign
> braucht.

Ich bin auch ein Anhänger des ATMega und wollte auch den Schritt zum 
XMega gehen. Stattdessen bin ich dann beim PIC24 gelandet, der meines 
Erachtens ein wirklich sehr guter (16Bit) µC ist.

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.