Forum: Mikrocontroller und Digitale Elektronik Anfängerfrage avr/interrupt.h


von Alexander M. (a_lexander)


Lesenswert?

Hallo Zusammen,

Ich hatte mir eben die avr/interrupt.h Datei angeschaut, um zu 
verstehen, wie der sei() Befehl definiert ist.

Eigentlich dachte ich mir da steht sowas wie:
1
void sei()
2
{
3
  SREG = SREG | (1 << SREG_I);
4
}

Stattdessen steht aber folgendes:
1
#if defined(__DOXYGEN__)
2
/** \def sei()
3
    \ingroup avr_interrupts
4
5
    Enables interrupts by setting the global interrupt mask. This function
6
    actually compiles into a single line of assembly, so there is no function
7
    call overhead.  However, the macro also implies a <i>memory barrier</i>
8
    which can cause additional loss of optimization.
9
10
    In order to implement atomic access to multi-byte objects,
11
    consider using the macros from <util/atomic.h>, rather than
12
    implementing them manually with cli() and sei().
13
*/
14
#define sei()
15
#else  /* !DOXYGEN */
16
# define sei()  __asm__ __volatile__ ("sei" ::: "memory")
17
#endif /* DOXYGEN */

Kann mir einer bitte bestätigen, dass meine Idee auch richtig wäre? Mit 
dem Interrupt-Flag im SREG werden ja die Interrupts frei gegeben? Der 
einzige Unterschied wäre, dass meine Idee vielleicht ein bisschen 
ineffizienter in der Ausführung wäre, oder nicht?

2. Wenn nein, wie kann ich diesen Begriff verstehen?
1
# define sei()  __asm__ __volatile__ ("sei" ::: "memory")

Zudem die Frage, was das mit dem DOXYGEN auf sich hat... Wann / wo wird 
denn das definiert und was soll das bringen?

Danke :)

Grüße

von STK500-Besitzer (Gast)


Lesenswert?

Alexander M. schrieb:
> Zudem die Frage, was das mit dem DOXYGEN auf sich hat... Wann / wo wird
> denn das definiert und was soll das bringen?

Doxygen ist ein Werkyeug zum Erstellen von Dokumentation, das Quellcode 
"lesen" kann.

von Einer K. (Gast)


Lesenswert?

Alexander M. schrieb:
> DOXYGEN
Das findest du raus....
Kurzform: DOXYGEN generiert Dokumentationen aus dem Quellcode.

Alexander M. schrieb:
> 2. Wenn nein, wie kann ich diesen Begriff verstehen?# define sei()
> _asm__ __volatile_ ("sei" ::: "memory")
Steht doch da im Kommentar haarklein beschrieben.

von Alexander M. (a_lexander)


Lesenswert?

Danke :)

Dann verstehe ich das - glaube ich - mit dem Doxygen. Da geht's dann 
speziell z.B. um folgende Seite:
https://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html

Aber für die Quellcode-Erzeugung müsste ja Doxygen dann aus sein, oder?

Grüße

von Falk B. (falk)


Lesenswert?

Alexander M. schrieb:
> Aber für die Quellcode-Erzeugung müsste ja Doxygen dann aus sein, oder?

Nö. Doxygen ist ein extra Programm, das den Quelltext scannt und daraus 
automatisch Dokumention erstellt. Es hat mit dem Compiler nix zu tun, 
wenn gleich natürlich Doxygen die C-Syntax kennt. Alle Doxygenkommentare 
sind normale C/C++ Kommentare, die der Compiler ignoriert.

von Frank M. (framucoder)


Lesenswert?

Ja _DOXYGEN_ ist beim einfachen Compilieren nicht definiert. Das 
scheint mit hier auch eher ein Workaround zu sein, da DOXYGEN wohl nicht 
mit allen AVR spezifischen Besonderheiten klar kommt. Normalerweise ist 
das viele #if define(...) ... #else ... #endif nicht nötig für DOXYGEN.

Deine Anweisung sollte theoretisch auch funktionieren, benötigt aber 
mehrere Assembler Befehle. Ich bin kein AVR Assembler Experte aber wenn 
ich das richtig überblicke wären mindestens 3 Befehle dafür notwendig.

Grob etwa:
* lade SREG in ein Arbeitsregister
* setze bit im Arbeitsregister
* schreibe Arbeitsregister zurück nach SREG

Der AVR kennt aber einen speziellen Befehl dafür, eben sei.
Mit der _asm_ Anweisung kann man direkt im C Code beliebige Assembler 
Befehle eingeben.

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


Lesenswert?

Alexander M. schrieb:
> Eigentlich dachte ich mir da steht sowas wie:
1
> void sei()
2
> {
3
>   SREG = SREG | (1 << SREG_I);
4
> }

Wenn überhaupt, dann würde da sowas stehen wie
1
static __inline__ __attribute__((__always_inline__))
2
void sei (void)
3
{
4
  SREG = SREG | (1 << SREG_I);
5
}

"static" weil der Code in einem Header steht. Ohne "static" könnte es 
mehrere Definitionen geben, wenn mehrere Module sei() verwenden und die 
Funktion nicht geinlinet wird.  Das würde in Linkerfehler (multiple 
definitions of sei) resultieren.

Außerdem will man auf jeden Fall vermeiden, dass es einen 
Funktionsaufruf gibt.  Das kostet nur Zeit und Platz und erhöht die 
Registerlast im Caller beträchtlich.  Caller, die Leaf-Funktionen sind 
(günstig) verlieren diesen Status (ungünstig).

Dann heißt die Funktion "sei", und es gibt eine AVR-Instruktion namens 
"sei".  Man würde also erwarten, dass die Funktion eben diesen Befehl 
einfügt, folglich eine inline Assembly Zeile genau wie sie in 
avr/interrupt.h zu finden ist. Oder eine Builtin-Funktion die gleiches 
erledigt wie __builtin_avr_sei() (ab v4.7):

http://gcc.gnu.org/onlinedocs/gcc/AVR-Built-in-Functions.html

Und SREG |= 1 << SREG_I ist ungünstig, weil der Compiler daraus
1
in  Rd, SREG
2
ori Rd, 1 << 7
3
out SREG, Rd
machen muss.  Das sind 3 Instruktionen, 3 Ticks und Erhöhung der 
Registerlast um 1 d-Register.  SEI hingegen bewirkt das gleiche mit 1 
Instruktion in 1 Tick und ohne ein Register zu brauchen.

> Stattdessen steht aber folgendes:
> [...] Enables interrupts by setting the global interrupt mask.
> This function [...]

Hier ist die Doku falsch, da es sich bei sei() nicht um eine Funktion 
handelt sondern um ein funktionsähnliches Makro.

Hier wäre eine richtige Funktion (als static inline wie oben) ganz klar 
zu bevorzugen, vor allem wenn der Header als C++ verwendet wird:  Falls 
eine Klasse eine Methode sei() hat, würde der Präprozessor eine 
Makro-Ersetzung machen -> Bummer.

Leider verwendet die avr-libc diese Unart auch an anderen Stellen wie 
bei abs(), siehe etwa

http://savannah.nongnu.org/bugs/?57114

von Peter D. (peda)


Lesenswert?

CLI, SEI sind eigenständige CPU-Befehle.
Ein Löschen, Setzen auf andere Art kann Seiteneffekte haben.

von ck (Gast)


Lesenswert?

Peter D. schrieb:
> CLI, SEI sind eigenständige CPU-Befehle.
> Ein Löschen, Setzen auf andere Art kann Seiteneffekte haben.

Nein, CLI und SEI sind Assembler-Mnemonics
und in diesen Fall nur Aliase zu den Mnemonics  "BSET s" und "BCLR s"

Hier die 16-Bit Opcodes der Befehle:

CLI: 1001 0100 1111 1000
SEI: 1001 0100 0111 1000


BCLR s: 1001 0100 1sss 1000
BSET s: 1001 0100 0sss 1000

Wobei s die Bitnummer im SREG ist. Und das Interrupt Enable Bit, ist das 
7. Bit

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

ck schrieb:
> Peter D. schrieb:
>> CLI, SEI sind eigenständige CPU-Befehle.
>> Ein Löschen, Setzen auf andere Art kann Seiteneffekte haben.
>
> Nein, CLI und SEI sind Assembler-Mnemonics
> und in diesen Fall nur Aliase zu den Mnemonics  "BSET s" und "BCLR s"

Feenstaub interessiert hier nicht.

Sondern es geht darum, dass SEI / CLI was anderes ist als IN + BitOP + 
OUT, was bei Operationan auf SREG, wie von Alexander M. vorgeschlagen, 
erzeugt wird.

von ck (Gast)


Lesenswert?

Bei AVR ist nur relevant ob das I-Flag im SREG gesetzt ist oder nicht.
Über welche Operation dies passiert ist egal.

Schau dir an, wie die Makros ATOMIC_BLOCK "util/atomic.h" aufgebaut ist.

Da passiert genau das, da wird das SREC-Register gesichert, CLI 
aufgerufen und später der gesicherter Wert wieder zurückgeschrieben.

von Stefan F. (Gast)


Lesenswert?

Ich weiß nicht wovon ihr phantasiert, aber mein avr-gcc 5.4.0 mach aus 
sei() und cli() die entsprechenden Assembler-Befehle:
1
stefan@stefanpc:~/Downloads$ cat test.c 
2
#include <avr/interrupt.h>
3
4
int main()
5
{
6
    sei();
7
    cli();
8
}
9
10
stefan@stefanpc:~/Downloads$ avr-gcc -mmcu=atmega328 -O1 test.c
11
12
stefan@stefanpc:~/Downloads$ avr-objdump -h -S a.out 
13
14
a.out:     file format elf32-avr
15
16
Sections:
17
Idx Name          Size      VMA       LMA       File off  Algn
18
  0 .data         00000000  00800100  0000008e  00000102  2**0
19
                  CONTENTS, ALLOC, LOAD, DATA
20
  1 .text         0000008e  00000000  00000000  00000074  2**1
21
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
22
  2 .comment      00000011  00000000  00000000  00000102  2**0
23
                  CONTENTS, READONLY
24
  3 .note.gnu.avr.deviceinfo 0000003c  00000000  00000000  00000114  2**2
25
                  CONTENTS, READONLY
26
  4 .debug_info   000005f4  00000000  00000000  00000150  2**0
27
                  CONTENTS, READONLY, DEBUGGING
28
  5 .debug_abbrev 000005a2  00000000  00000000  00000744  2**0
29
                  CONTENTS, READONLY, DEBUGGING
30
  6 .debug_line   0000001a  00000000  00000000  00000ce6  2**0
31
                  CONTENTS, READONLY, DEBUGGING
32
  7 .debug_str    00000208  00000000  00000000  00000d00  2**0
33
                  CONTENTS, READONLY, DEBUGGING
34
35
Disassembly of section .text:
36
37
00000000 <__vectors>:
38
   0:  0c 94 34 00   jmp  0x68  ; 0x68 <__ctors_end>
39
   4:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
40
   8:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
41
   c:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
42
  10:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
43
  14:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
44
  18:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
45
  1c:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
46
  20:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
47
  24:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
48
  28:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
49
  2c:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
50
  30:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
51
  34:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
52
  38:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
53
  3c:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
54
  40:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
55
  44:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
56
  48:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
57
  4c:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
58
  50:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
59
  54:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
60
  58:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
61
  5c:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
62
  60:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
63
  64:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
64
65
00000068 <__ctors_end>:
66
  68:  11 24         eor  r1, r1
67
  6a:  1f be         out  0x3f, r1  ; 63
68
  6c:  cf ef         ldi  r28, 0xFF  ; 255
69
  6e:  d8 e0         ldi  r29, 0x08  ; 8
70
  70:  de bf         out  0x3e, r29  ; 62
71
  72:  cd bf         out  0x3d, r28  ; 61
72
  74:  0e 94 40 00   call  0x80  ; 0x80 <main>
73
  78:  0c 94 45 00   jmp  0x8a  ; 0x8a <_exit>
74
75
0000007c <__bad_interrupt>:
76
  7c:  0c 94 00 00   jmp  0  ; 0x0 <__vectors>
77
78
00000080 <main>:
79
  80:  78 94         sei
80
  82:  f8 94         cli
81
  84:  80 e0         ldi  r24, 0x00  ; 0
82
  86:  90 e0         ldi  r25, 0x00  ; 0
83
  88:  08 95         ret
84
85
0000008a <_exit>:
86
  8a:  f8 94         cli
87
88
0000008c <__stop_program>:
89
  8c:  ff cf         rjmp  .-2        ; 0x8c <__stop_program>
90
stefan@stefanpc:~/Downloads$

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Stefan ⛄ F. schrieb:
> Ich weiß nicht wovon ihr phantasiert, aber mein avr-gcc 5.4.0 mach aus
> sei() und cli() die entsprechenden Assembler-Befehle:

Es geht darum, dass SREG = SREG | (1 << SREG_I) kein SEI generiert.

Und nicht darum, ob sei() ein SEI erzeugt.

ck schrieb:
> Bei AVR ist nur relevant ob das I-Flag im SREG gesetzt ist oder nicht.
> Über welche Operation dies passiert ist egal.

Also Ausführungezeit, Speicherverbrauch und Registerbelegung spielen 
schon ne Rolle in jedem realen Programm.  Find ich zumindest.

> Schau dir an, wie die Makros ATOMIC_BLOCK "util/atomic.h" aufgebaut ist.
>
> Da passiert genau das, da wird das SREC-Register gesichert, CLI
> aufgerufen und später der gesicherter Wert wieder zurückgeschrieben.

Genau.  Es wird CLI verwendet um das I-Flag zu löschen und eben nicht 
per Operation auf SREG.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Johann L. schrieb:
> ck schrieb:
>> Peter D. schrieb:
>>> CLI, SEI sind eigenständige CPU-Befehle.
>>> Ein Löschen, Setzen auf andere Art kann Seiteneffekte haben.
>>
>> Nein, CLI und SEI sind Assembler-Mnemonics
>> und in diesen Fall nur Aliase zu den Mnemonics  "BSET s" und "BCLR s"
>
> Feenstaub interessiert hier nicht.

Interessiert und wie, dasselbe Problem hatte ich mit CLR reg.
Da kamen dann gleich die Korinthenkacker mit klugen Erklärungen wie:
 dieser Befehl existiert gar nicht, das ist ein EOR reg mit sich
 selbst, du hast keine Ahnung und ähnliches (vielleicht erkennt sich
 ein Moderator hier).

 Meine Versuche zu erklären, dass CLR übersichtlicher, kürzer und
 praktisch selbsterklärend ist, scheiterten kläglich...
 Also, BCLR 7 ist demzufolge weitaus übersichtlicher und zeugt von
 überlegenem Assemblerwissen, wogegen CLI nur Unwissende benutzen...

: Bearbeitet durch User
von c-hater (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Ich weiß nicht wovon ihr phantasiert, aber mein avr-gcc 5.4.0 mach aus
> sei() und cli() die entsprechenden Assembler-Befehle:
[...]

Auch dann, wenn _DOXYGEN_ definiert ist?

Darauf wollte der Fragesteller wohl eigentlich hinaus. Also auch ich 
lese das erstmal so, dass in diesem Fall dies zur "Anwendung" kommt:

#define sei()

d.h. ein function-like Makro, was genau garnix tut, also insbesondere 
keinen Code erzeugt, weder ein Asm-"sei" noch sonst irgendwas.

Nein, dieser Schrott ist alles andere als selbsterklärend. Hier wird der 
Prepzessor vergewaltigt zur Generierung fast nutzloser Pseudo-Doku. Mit 
dem Seiteneffekt, dass man den Code nicht mehr leicht lesen kann. Das 
kann's ja wohl nicht sein...

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

c-hater schrieb:
> #define sei()
>
> d.h. ein function-like Makro, was genau garnix tut, also insbesondere
> keinen Code erzeugt,

Nö.  Nennt sich "Synopsis".

Man sieht daran, dass es ein funkcion-like Makro ist, dass genau 0 
Argumente bekommt.

Bei sei() könnte man die Definition noch hinzutun, aber mach das mal bei 
ausgewachsenen, konditionalen Makros wie pgm_read_dword.  Das will man 
in der Doku nicht sehen.  Was man da lesen will ist

* Wie wird es verwendet?

* Was macht es?

Bei einer echten Funktion würde man ja auch nur den Prototyp 
hinschreiben und nicht die ganze Implementation ausbreiten.

Beitrag #6496210 wurde von einem Moderator gelöscht.
Beitrag #6496233 wurde von einem Moderator gelöscht.
von c-hater (Gast)


Lesenswert?

Johann L. schrieb im Beitrag #6496233:
> ...und schon ist unser Herzchen wieder ganz bei sich.

Genau wie du: Wenn es darum geht, den ganzen C/C++-Wahnsinn auf die 
Ebene logisch denkender Menschen herunterzubrechen, hast du erhebliche 
Artikulationsprobleme...

Also, du C-Verliebter, erkläre doch bitte mal, woran man bei diesem 
Konstrukt einfach erkennen kann, dass letztlich immer doch der 
#else-Zweig "ausgeführt" wird. (Gemeint ist natürlich: zur Compiletime)

ICH weiss natürlich, dass das so ist und kann auch erklären, warum das 
so ist.

Aber aus dem Quelltext kann man das definitiv nicht einfach entnehmen...

Sowas halte ich für eine extreme Sprach-Vergewaltigung. Ja, sie ist 
möglich, und ist nach der Sprachdefinition legal. Aber sie ist KRANK, 
KRANK, KRANK.

Allein die Möglichkeit dafür macht die Sprache KRANK, KRANK, KRANK.

von Stefan F. (Gast)


Lesenswert?

c-hater schrieb:
> Aber aus dem Quelltext kann man das definitiv nicht einfach entnehmen...

Wenn man fremden Code liest, muss man mir so etwas klar kommen. Aufregen 
bringt da gar nichts. Wer meint es besser machen zu können: Nur zu. Wenn 
es wirklich signifikant besser ist, wird es bald zum Standard.

Man kann den Compiler dazu bringen, den Quelltext des effektiv wirksamen 
C Codes nach Auflösung aller Makros auszugeben. Der wäre dann leichter 
lesbar. Und speziell für dich: Der Compiler kann auch den generierten 
Assembler Code ausgeben.

Damit kann er schon zwei Dinge, die du bei fast keiner anderen 
Programmiersprache finden wirst.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Stefan ⛄ F. schrieb:
> Aufregen bringt da gar nichts.

c-hater liest Code, genau um sich aufzuregen.

Wenn er sich über Code nicht aufregt, hat der Code seinen Sinn verfehlt.

von Axel S. (a-za-z0-9)


Lesenswert?

ck schrieb:
> Peter D. schrieb:
>> CLI, SEI sind eigenständige CPU-Befehle.
>> Ein Löschen, Setzen auf andere Art kann Seiteneffekte haben.
>
> Nein, CLI und SEI sind Assembler-Mnemonics

Haarspalterei

> und in diesen Fall nur Aliase zu den Mnemonics  "BSET s" und "BCLR s"

Die Frage ist doch eher, wer hier der Alias für wen ist. Ich bin (sicher 
nicht als einziger) der Überzeugung, daß SEI/CLI die primären Mnemonics 
sind. Jede CPU, die Interrupts unterstützt, hat einen Maschinenbefehl, 
der Interrupts atomar ein- bzw. ausschaltet. Es ist nur folgerichtig, 
daß dieser Befehl entsprechend benannt ist.

Daß andererseits ein solcher binärer (an oder aus) Zustand irgendwo in 
einem einzelnen Bit gespeichert wird, ist ebenso trivial. Und wenn das 
Bit in einem öffentlich zugänglichen Register steht, dann gibt es auch 
eine Möglichkeit, einen alternativen Mnemonic zu kreieren.

Im Prinzip mag ich, was der AVR Assembler da macht: alternative 
Mnemonics für die gleiche Instruktion zu erlauben. Wenn man das richtig 
einsetzt, kann man die Lesbarkeit eines Programms signifikant erhöhen. 
Andererseits kann man durch das sture Beharren darauf, daß nur eine der 
ALternativen "richtig" wäre, das Verständnis eines Programms auch 
erschweren.

von Falk B. (falk)


Lesenswert?

Axel S. schrieb:
> Andererseits kann man durch das sture Beharren darauf, daß nur eine der
> ALternativen "richtig" wäre, das Verständnis eines Programms auch
> erschweren.

Hab dich nicht so, so ne Turingmaschine ist doch quasi Hochsprache^3!!! 
;-)

von ck (Gast)


Lesenswert?

Axel S. schrieb:
> Die Frage ist doch eher, wer hier der Alias für wen ist. Ich bin (sicher
> nicht als einziger) der Überzeugung, daß SEI/CLI die primären Mnemonics
> sind. Jede CPU, die Interrupts unterstützt, hat einen Maschinenbefehl,
> der Interrupts atomar ein- bzw. ausschaltet. Es ist nur folgerichtig,
> daß dieser Befehl entsprechend benannt ist.

Nochmal, für die AVR-CPU ist es nur relevant, ob das I-Bit im SREG 
gesetzt ist oder nicht.
Und ein Atomarer Befehl für das Setzen und Löschen ist BSET 7 und BCLR 
7. SEI/CLI sind dann Aliase dafür, die auch zur besseren Lesbarkeit des 
Programms beitragen.

Wenn du das AVR Instruction Set Handbuch durch gehst, wirst du 
feststellen das es viele solcher Aliase gibt. Ein "CLR Rd" ist nur eine 
spezialform von "EOR Rd,Rr" wo Rd und Rr identisch sind. Es kommt in 
beiden Fällen der gleiche Opcode raus.

Und ein read-modify-write auf SREG um das I-Flag zu ändern funktioniert 
ebenfalls. Es hat den gleichen Effekt. Ist aber natürlich nicht Atomar 
und brauch mehr Programcode.

von Stefan F. (Gast)


Lesenswert?

ck schrieb:
> Nochmal, für die AVR-CPU ist es nur relevant, ob das I-Bit im SREG
> gesetzt ist oder nicht.

Für mich ist hingegen relevant, ob Interrupts erlaubt sind, oder 
nicht. Die Programmiersprache ist mein Diener, nicht umgekehrt.

von Axel S. (a-za-z0-9)


Lesenswert?

ck schrieb:
> Axel S. schrieb:
>> Die Frage ist doch eher, wer hier der Alias für wen ist. Ich bin (sicher
>> nicht als einziger) der Überzeugung, daß SEI/CLI die primären Mnemonics
>> sind. Jede CPU, die Interrupts unterstützt, hat einen Maschinenbefehl,
>> der Interrupts atomar ein- bzw. ausschaltet. Es ist nur folgerichtig,
>> daß dieser Befehl entsprechend benannt ist.
>
> Nochmal, für die AVR-CPU ist es nur relevant, ob das I-Bit im SREG
> gesetzt ist oder nicht.

Nochmal: das ist bekannt und unbestritten und trivial.

> Und ein Atomarer Befehl für das Setzen und Löschen ist BSET 7 und BCLR
> 7. SEI/CLI sind dann Aliase dafür, die auch zur besseren Lesbarkeit des
> Programms beitragen.

Nochmal: Mnemonics sind im Prinzip beliebig. Allerdings heißen sie nicht 
umsonst so. Der Name kommt vom griechischen mnēmoniká = Gedächtnis. 
Der wesentliche Punkt bei der Wahl eines Mnemonics ist, daß er gut 
merkbar sein sollte und die Wirkung des Maschinenbefehls gut beschreibt.

Deswegen ist SEI besser [1] als BSET 7
CLR reg ist besser als EOR reg,reg
ADDI reg,10 ist besser als SUBI reg,-10

> Wenn du das AVR Instruction Set Handbuch durch gehst, wirst du
> feststellen das es viele solcher Aliase gibt.

Und nochmal: das ist bekannt. Uns allen. Du bist nicht weise, nur 
Durchschnitt.


[1] noch besser wäre EI statt SEI für enable interrupts. Und dann 
natürlich auch DI statt CLI. Bin ich alt?

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Der 8051 hat dafür keinen Befehl. Da muß man schreiben:
1
EA = 1; // bzw.
2
EA = 0;
Das EA-Bit wird beim Interrupteintritt nicht gelöscht, bzw. beim RETI 
nicht gesetzt. Die Interruptlogik merkt sich intern den gerade aktiven 
Interruptlevel.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Axel S. schrieb:
> [1] noch besser wäre EI statt SEI für enable interrupts. Und dann
> natürlich auch DI statt CLI.

EI und DI wären auch meiner Meinung nach besser, weil eindeutiger.
Ich glaube, die Atmel Leute wollten konsequent sein mit CLx und SEx.
Also CL+I für Interrupt, CL+T für T-Flag, CL+R für Register usw.
Und SE+I für Interrupt, SE+T für T-Flag, SE+R für Register usw.

Mich persönlich haben immer die BLD und BST genervt, muss immer noch
überlegen was wohin geladen wird.

> Bin ich alt?
Hat in diesem Fall nichts mit Alter zu tun, eher mit Logik.

von W.S. (Gast)


Lesenswert?

Axel S. schrieb:
>> Nein, CLI und SEI sind Assembler-Mnemonics
>
> Haarspalterei
>
>> und in diesen Fall nur Aliase zu den Mnemonics  "BSET s" und "BCLR s"
>
> Die Frage ist doch eher, wer hier der Alias für wen ist. Ich bin (sicher
> nicht als einziger) der Überzeugung, daß SEI/CLI die primären Mnemonics
> sind. Jede CPU, die Interrupts unterstützt, hat einen Maschinenbefehl,
> der Interrupts atomar ein- bzw. ausschaltet. Es ist nur folgerichtig,
> daß dieser Befehl entsprechend benannt ist.

Ach nö, das alles ist nur mal wieder eine Frage des "Stallgeruches", 
also dem näheren Umfeld geschuldet. EI und DI sind in den klassischen 
Gefilden von Intel eher Mode und SEI und CLI haben sich eben die 
Atmel-Leute ausgedacht. Leute aus dem jeweils anderen Basislager 
empfinden das gegenseitig als unleserlich.

Und deine Ansicht, daß jede CPU, die Interrupts unterstützt, auch 
einen generellen Befehl zum ein- und ausschalten hat, stimmt so auch 
nicht. Beim klassischen ARM ist sowas zum Beispiel an den Betriebsmodus 
geknüpft, also ob die CPU grad Code im User-Modus abarbeitet oder im 
Supervisor-Modus ist oder im Interruptmodus oder im Fast-Interrupt-Modus 
und so weiter. Dazu gibt es dann auch unterschiedliche Stacks (und 
z.T. unterschiedliche Registersätze). Nur so als Beispiel.

Ich halte es ohnehin für ausgesprochen schlechten Stil, mit sowas wie 
EI/DI bzw. SEI/CLI im Programm herumzutoben. Wenn Interrupts, dann 
sollten die eben immer eingeschaltet sein. IMMER! Das geht. Es sind 
lediglich nur Anfänger, die damit nicht klarkommen, weil sie noch zu 
wenig Programmierkenntnisse haben. Das Argument "ja wenn ich doch grad 
genau DIES machen will, dann MUSS ich.." gilt nicht. Man macht eben 
nicht "DIES", sondern man macht es anders.

Ich stell mir grad mal vor, wie so einer bei einer CPU programmieren 
wollte, die im User-Mode sowas wie DI/EI schlichtweg nicht ausführt oder 
gar eine Exception wirft, wenn man das probiert.

W.S.

von Oliver S. (oliverso)


Lesenswert?

W.S. schrieb:
> Ich halte es ohnehin für ausgesprochen schlechten Stil, mit sowas wie
> EI/DI bzw. SEI/CLI im Programm herumzutoben

Das sei dir unbenommen, aber wenn es der Prozessor erfordert, dann ist 
das so. Ganz ohne geht es nicht.

Oliver

von Axel S. (a-za-z0-9)


Lesenswert?

Marc V. schrieb:
> Axel S. schrieb:
...
>> Bin ich alt?
> Hat in diesem Fall nichts mit Alter zu tun, eher mit Logik.

Ich habe die Mnemonics EI und DI sozusagen "mit der Muttermilch 
eingesaugt", weil die erste Architektur, zu der ich ein intimes 
Verhältnis hatte, die verwendet hat. Es war der Z80.
(genauer gesagt: der U880)

: Bearbeitet durch User
von Axel S. (a-za-z0-9)


Lesenswert?

W.S. schrieb:
> Ach nö, das alles ist nur mal wieder eine Frage des "Stallgeruches",
> also dem näheren Umfeld geschuldet. EI und DI sind in den klassischen
> Gefilden von Intel eher Mode und SEI und CLI haben sich eben die
> Atmel-Leute ausgedacht.

Du hast meinen Punkt nicht verstanden. Ein Mnemonic soll möglichst klar 
und eindeutig beschreiben, welche Wirkung ein Maschinenbefehl hat. 
SEI/CLI respektive EI/DI beeinflussen die Interruptlogik dahingehend, 
daß die Interrupts akzeptiert oder nicht. Die Worte enable bzw. 
disable sind da eindeutig und unmißverständlich. Bei set (bit) und 
clear (bit) weiß ich zwar sofort, ob das Bit gesetzt ist oder nicht. 
Aber ich brauche immer noch zusätzliches Wissen darüber, ob das gesetzte 
Bit Interrupts nun erlaubt, oder sperrt. Nur durch Lesen des Codes 
erfahre ich das nicht.

Und deswegen ist EI der bessere Mnemonic gegenüber SEI.

> Ich halte es ohnehin für ausgesprochen schlechten Stil, mit sowas wie
> EI/DI bzw. SEI/CLI im Programm herumzutoben.

Das ist Unsinn. Bevor man Interrupts enabled, muß man praktisch immer 
irgendwas initialisieren oder konfigurieren. Und da AVR (um diese 
Architektur geht es ja in diesem Thread) keine atomaren Zugriffe auf 
Werte länger als 8 Bit erlaubt, braucht man hin und wieder auch mal eine 
CLI/SEI Klammer um einen solchen Zugriff. Natürlich zweckmäßigerweise in 
ein Makro gekapselt.

von Falk B. (falk)


Lesenswert?

Axel S. schrieb:
> (genauer gesagt: der U880)

Klingt wie ein U-Boot ;-)
(Jaja, ich weiß daß das die Ostzonenkopie vom Z80 war, incl. aller 
Fehler)

von Falk B. (falk)


Lesenswert?

Axel S. schrieb:
>> Ich halte es ohnehin für ausgesprochen schlechten Stil, mit sowas wie
>> EI/DI bzw. SEI/CLI im Programm herumzutoben.
>
> Das ist Unsinn.

Dein Gespräch mit W.S. ist es nicht weniger . . .

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Marc V. schrieb:
> Mich persönlich haben immer die BLD und BST genervt, muss immer noch
> überlegen was wohin geladen wird.

Load: Vom Speicher ins CPU-Register laden

Store: Wert vom CPU-Register in den Speicher schreiben.

SREG ist zwar kein normaler Speicher, kann aber so zugegriffen werden, 
insbesondere auch via LDS und STS wenn man die RAM-Adresse von SREG 
verwendet.  LDS und STS lädt bzw. speichert alle Bits, BLD und BST eben 
nur das T-Bit von SREG.

Also ganz einfach zu merken :-)

von Falk B. (falk)


Lesenswert?

Johann L. schrieb:
> Load: Vom Speicher ins CPU-Register laden

[Eselsbrücke]
Wenn ich einen "geladen" habe, ist der Fusel im Kopp (CPU) und nicht 
mehr in der Flasche (Speicher).
[/Eselsbrücke]

;-)

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Falk B. schrieb:
> Wenn ich einen "geladen" habe, ist der Fusel im Kopp (CPU) und nicht
> mehr in der Flasche (Speicher).

Und wenn ich einen geladen habe, ist mir das alles so was von egal...

von Rainer V. (a_zip)


Lesenswert?

...und wenn ich dann noch traurig bin, dann trink ich noch 'n Korn...
der gute Heinz wußte auch schon wie es geht :-)
Gruß Rainer

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.