Forum: Mikrocontroller und Digitale Elektronik Wie Assembler Code in eine ISR (C, AS7, GCC, ATmega)


von AC (Gast)


Lesenswert?

Hallo Leute,

ich bin blutiger Anfänger also alles bitte ganz langsam.

Ich programmiere gerade in C eine ADC-Sample-Routine und habe von 
jemanden der das gleiche Projekt in BASCOM programmiert hat seine Timer0 
Comapare ISR in Assembler bekommen. Diese muss ich genauso d.h. in 
Assembler in meinen Code implementieren.
Ich habe das ganze wie unten zu sehen eingegeben aber die Syntax ist 
falsch und ich bekomme ständig Compilerfehler. Ich muss den Teil mit den 
Variablen irgendwie anders schreiben aber hab kein schimmer wie? Könnte 
mir jemand hierbei behilflich sein?

Habe global dafür 3 variablen:
1
volatile uint16_t sample_counter = 0;
2
volatile uint16_t audio_samples_buffer[1024];
3
volatile uint16_t Audio_sample_adress = 0;

Und hier meine ISR:
1
ISR(TIMER0_COMPA_vect)
2
{  
3
asm volatile(
4
5
      "push R27"  "\n\t"                              //X-Register High-Byte
6
      "push R26"  "\n\t"                              //X-Register Low-Byte
7
      "push R21"  "\n\t"
8
      "push R20"  "\n\t"
9
      "in   R20,SREG"  "\n\t"
10
      "push R20"  "\n\t"
11
      "in   R20,RAMPZ"  "\n\t"            //Kann auskommentiert werden
12
      "push R20"  "\n\t"                //Kann auskommentiert werden
13
14
15
      "LDS R20,ADCL"  "\n\t"                          //Load R20,R21 with ADCL,ADCH
16
      "LDS R21,ADCH"  "\n\t"
17
18
      "LDS R26,{Audio_sample_adress}"  "\n\t"         //Load X-Register pair with momentary audio_sample_adress
19
      "LDS R27,{Audio_sample_adress}+1"  "\n\t"
20
      "ST X+,R20"  "\n\t"                             //Store Low- and High-Byte of ADC-Sample to Audio-Sample-Array with Adress in X-Pointer; Post-Increment X-Counter
21
      "ST X+,R21"  "\n\t"
22
      "STS {Audio_sample_adress},R26"  "\n\t"         //Store incremented X-Register back to Audio_sample_adress
23
      "STS {Audio_sample_adress}+1,R27"  "\n\t"
24
25
      //*** Decrement Sample-Counter ***
26
      "LDS R26,{sample_counter}"  "\n\t"              //Load Sample-Counter to R26,R27
27
      "LDS R27,{sample_counter}+1"  "\n\t"
28
      "SBIW R26,1"  "\n\t"                            //Subtract 1
29
30
      "STS {sample_counter},R26"  "\n\t"              //Store back decremented Sample-Counter
31
      "LDS {sample_counter}+1,R27"  "\n\t"
32
33
      "BRNE jump_out"  "\n\t"                         //Jump to end of ISR if result<>0
34
35
      //*** Reset ADC-Interrupt Enable bit in ADCSRA as a flag for "ADC-Ready" ***
36
      "LDS R26, ADCSRA"  "\n\t"                       //Load R26 with ADCSRA
37
      "ANDI R26, &B11110111"  "\n\t"          //Reset bit 3 = ADIE by AND mith mask
38
      "STS ADCSRA,R26"  "\n\t"               //Store R26 back to ADCSRA
39
40
41
      //Jump_out:
42
      "POP R20"  "\n\t"                //Kann auskommentiert werden
43
      "OUT RAMPZ , R20"  "\n\t"            //Kann auskommentiert werden
44
      "POP R20"  "\n\t"
45
      "OUT SREG , R20"  "\n\t"
46
      "POP R20"  "\n\t"
47
      "POP R21"  "\n\t"
48
      "POP R26"  "\n\t"
49
      "POP R27"  "\n\t"
50
51
      "RETI"  "\n\t"                  //Return from ISR
52
);
53
}

Danke

von kein-inline-ASM-Profi (Gast)


Lesenswert?

Oh je. So einfach geht das nicht. Wie der Zugriff auf Register oder SRAM 
geschieht, ist z.B hier beschrieben. Ich muß es auch erst 10x lesen, 
bevor ich es raffe.

von Ziegenpeter (Gast)


Lesenswert?

AC schrieb:
> "LDS R26,{Audio_sample_adress}"  "\n\t"

Hast du's so versucht?:
1
"LDS R26,Audio_sample_adress \n\t"

Interessant wäre auch zu wissen, was der Compiler sagt. Warum schreibst 
du das nicht dazu?

von Ziegenpeter (Gast)


Lesenswert?

1
"STS {sample_counter},R26"  "\n\t"              //Store back decremented Sample-Counter
2
"LDS {sample_counter}+1,R27"  "\n\t"
Außerdem müsste hier das LDS ein STS sein.

von Thomas E. (picalic)


Lesenswert?

Sorry, ich finde solchen Inline-Assemblecode grausig! Zumindest, wenn es 
mehr, als 1-2 Befehle sind. Besser eine "richtige" ASM-Datei in das 
Projekt einbinden.

von AC (Gast)


Lesenswert?

Ziegenpeter schrieb:
> Hast du's so versucht?:"LDS R26,Audio_sample_adress \n\t"

Danke, hat schon viel gebracht. Habe alle geschweiften klammern 
umgeschrieben.

Jetzt bekomme ich noch 6 Errors:

garbage at end of the line (3x)
constant value required
bad expression

von AC (Gast)


Lesenswert?

Sorry, ich habe diesen Code wie gesagt bekommen, weil er in die ISR 
muss. Ob jetzt direkt oder über externe Datei ist mir egal...nur ich 
dachte nicht das dieser Schritt mich so lange aufhält und ich an meinem 
eigentlichen Projekt jetzt erstmal nicht weiter machen kann.

von AC (Gast)


Lesenswert?

Ziegenpeter schrieb:
> "STS {sample_counter},R26"  "\n\t"              //Store back decremented
> Sample-Counter
> "LDS {sample_counter}+1,R27"  "\n\t"
> Außerdem müsste hier das LDS ein STS sein.

Das hat jetzt auch noch einen Error weniger gebracht.

Was bedeutet denn "garbage at end of line"?
1
ISR(TIMER0_COMPA_vect)
2
{  
3
asm volatile(
4
5
      "push R27"  "\n\t"                              //X-Register High-Byte
6
      "push R26"  "\n\t"                              //X-Register Low-Byte
7
      "push R21"  "\n\t"
8
      "push R20"  "\n\t"
9
      "in   R20,SREG"  "\n\t"
10
      "push R20"  "\n\t"
11
      "in   R20,RAMPZ"  "\n\t"            //Kann auskommentiert werden
12
      "push R20"  "\n\t"                //Kann auskommentiert werden
13
14
15
      "LDS R20,ADCL"  "\n\t"                          //Load R20,R21 with ADCL,ADCH
16
      "LDS R21,ADCH"  "\n\t"
17
18
      "LDS R26,Audio_sample_adress \n\t"         //Load X-Register pair with momentary audio_sample_adress
19
      "LDS R27,Audio_sample_adress +1 \n\t"
20
      "ST X+,R20"  "\n\t"                             //Store Low- and High-Byte of ADC-Sample to Audio-Sample-Array with Adress in X-Pointer; Post-Increment X-Counter
21
      "ST X+,R21"  "\n\t"
22
      "STS Audio_sample_adress,R26  \n\t"         //Store incremented X-Register back to Audio_sample_adress
23
      "STS Audio_sample_adress+1,R27  \n\t"
24
25
      //*** Decrement Sample-Counter ***
26
      "LDS R26,sample_counter} \n\t"              //Load Sample-Counter to R26,R27
27
      "LDS R27,sample_counter}+1  \n\t"
28
      "SBIW R26,1"  "\n\t"                            //Subtract 1
29
30
      "STS sample_counter,R26  \n\t"              //Store back decremented Sample-Counter
31
      "STS sample_counter+1,R27  \n\t"        //LDS in STS geändert laut forum
32
33
      "BRNE jump_out"  "\n\t"                         //Jump to end of ISR if result<>0
34
35
      //*** Reset ADC-Interrupt Enable bit in ADCSRA as a flag for "ADC-Ready" ***
36
      "LDS R26, ADCSRA"  "\n\t"                       //Load R26 with ADCSRA
37
      "ANDI R26, &B11110111"  "\n\t"          //Reset bit 3 = ADIE by AND mith mask
38
      "STS ADCSRA,R26"  "\n\t"               //Store R26 back to ADCSRA
39
40
41
      //Jump_out:
42
      "POP R20"  "\n\t"                //Kann auskommentiert werden
43
      "OUT RAMPZ , R20"  "\n\t"            //Kann auskommentiert werden
44
      "POP R20"  "\n\t"
45
      "OUT SREG , R20"  "\n\t"
46
      "POP R20"  "\n\t"
47
      "POP R21"  "\n\t"
48
      "POP R26"  "\n\t"
49
      "POP R27"  "\n\t"
50
51
      "RETI"  "\n\t"                  //Return from ISR
52
);
53
}

von Georg G. (df2au)


Lesenswert?

Du musst die ISR als "naked" deklarieren, sonst haut dir der Compiler 
noch Prolog und Epilog dazu.

von AC (Gast)


Lesenswert?

Habe tatsächlich noch 2 geschweifte Klammern übersehen, sorry!

Da bleibt jetzt noch 1 mal der Fehler "garbage at end of line" und bad 
expression.

von Georg G. (df2au)


Lesenswert?

AC schrieb:
> Was bedeutet denn "garbage at end of line"?

Genau das, was da steht: Müll am Ende der Zeile. Irgendetwas nicht 
Druckbares hat sich da eingeschlichen.

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


Lesenswert?

Wofür denn das umständliche Assembler-Gewurschtel?

Das hier:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
uint16_t *Audio_sample_adress;
5
uint16_t sample_counter;
6
7
ISR(ADC_vect)
8
{
9
    *Audio_sample_adress = ADC;
10
    if (--sample_counter == 0)
11
        ADCSRA &= ~_BV(ADIE);  // no more interrupts
12
}

ergibt compiliert (für einen ATmega128 - ich sehe RAMPZ bei dir):
1
.global __vector_21
2
        .type   __vector_21, @function
3
__vector_21:
4
        push r1
5
        push r0
6
        in r0,__SREG__
7
        push r0
8
        clr __zero_reg__
9
        in r0,__RAMPZ__
10
        push r0
11
        push r24
12
        push r25
13
        push r30
14
        push r31
15
/* prologue: Signal */
16
/* frame size = 0 */
17
/* stack size = 8 */
18
.L__stack_usage = 8
19
        in r24,0x4
20
        in r25,0x4+1
21
        lds r30,Audio_sample_adress
22
        lds r31,Audio_sample_adress+1
23
        std Z+1,r25
24
        st Z,r24
25
        lds r24,sample_counter
26
        lds r25,sample_counter+1
27
        sbiw r24,1
28
        sts sample_counter+1,r25
29
        sts sample_counter,r24
30
        or r24,r25
31
        brne .L1
32
        in r24,0x6
33
        andi r24,lo8(8)
34
        out 0x6,r24
35
.L1:
36
/* epilogue start */
37
        pop r31
38
        pop r30
39
        pop r25
40
        pop r24
41
        pop r0
42
        out __RAMPZ__,r0
43
        pop r0
44
        out __SREG__,r0
45
        pop r0
46
        pop r1
47
        reti
48
        .size   __vector_21, .-__vector_21
49
        .comm   sample_counter,2,1
50
        .comm   Audio_sample_adress,2,1
51
        .ident  "GCC: (GNU) 5.4.0"

Ich seh' da jetzt nicht so große Unterschiede zu deinem handgefeilten
Assemblercode, dass sich der Zirkus irgendwie lohnen würde.

: Bearbeitet durch Moderator
von René H. (Gast)


Lesenswert?

Jörg W. schrieb:
> (für einen ATmega128 - ich sehe RAMPZ bei dir)

Diesen Rückschluss wirst einem Anfänger erklären müssen.

Grüsse,
René

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


Lesenswert?

René H. schrieb:
> Diesen Rückschluss wirst einem Anfänger erklären müssen.

Controller mit maximal 64 KiB Flash haben kein RAMPZ. ;)

von AC (Gast)


Lesenswert?

Jörg W. schrieb:
> Wofür denn das umständliche Assembler-Gewurschtel?
>
> Das hier:
> #include <avr/io.h>
> #include <avr/interrupt.h>
>
> uint16_t *Audio_sample_adress;
> uint16_t sample_counter;
>
> ISR(ADC_vect)
> {
>     *Audio_sample_adress = ADC;
>     if (--sample_counter == 0)
>         ADCSRA &= _BV(ADIE);  // no more interrupts
> }

Das heisst, ich würde mir den ganzen Assembler Code mit deiner ISR 
sparen?

Das Ganze ist zeitkritisch und alle ISR müssen in Assembler programmiert 
werden (Aussage von meinem Auftraggeber des Techniker Projektes)...

Das Prorogramm soll mit Timer0 im CTC Modus mit einer Samplerate von 
10kHz werte ins Array schreiben. Mit diesen Werten soll später eine 
Sinuswelle gezeichnet, TrueRMS berechnet werden und zum krönenden 
Abschluss eine FFT realisiert werden.

von AC (Gast)


Lesenswert?

Ach, und es ist ein ATmega1284P :) ...ihr seid stark!

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


Lesenswert?

AC schrieb:
> Das heisst, ich würde mir den ganzen Assembler Code mit deiner ISR
> sparen?

Ja.

> Das Ganze ist zeitkritisch und alle ISR müssen in Assembler programmiert
> werden

Naja, wirklich klein ist das Original nun auch nicht gerade.

Zugegeben, der Compiler generiert drei oder vier Befehle mehr, aber
man müsste dann schon die Erbsen zählen gehen um zu sehen, ob die das
Kraut fett machen dass es sich lohnt, irgendwelchen Assemblercode
dafür handzufeilen.

> (Aussage von meinem Auftraggeber des Techniker Projektes)

Wann hat der das letzte Mal einen aktuellen Compiler und dessen
generierten Code gesehen?

Also wenn es vorgeschrieben ist, weil es zu einer studentischen Übung
gehört, dann musst du die ISR natürlich in Assemblercode hacken.  Dann
nimm aber besser gleich eine separate Assemblerdatei.  Wenn's nur
wegen der Performance ist, würde ich erstmal analysieren, ob nicht das
Compilat genauso hinreichend ist.  Dass der äquivalente C-Code besser
lesbar ist, wird wohl kaum einer bestreiten wollen. :-)

Ich zähle jetzt irgendwie reichlich 60 Takte für das Compilat, das
wären bei angenommenen 16 MHz CPU-Takt etwa 4 µs, sagen wir 5 µs (der
Interrupt hat ja auch noch einen Overhead).  Bei 10 kHz Aufruffrequenz
braucht diese ISR folglich 50 ms pro Sekunde oder 5 % der CPU-Zeit.

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


Lesenswert?

AC schrieb:

Btw:

> Habe global dafür 3 variablen:volatile uint16_t sample_counter = 0;
> volatile uint16_t audio_samples_buffer[1024];
> volatile uint16_t Audio_sample_adress = 0;

"volatile" würde ich die allerdings nicht machen, wenn die ISR in
C geschrieben wird, sonst zwingst du den Compiler zu deutlich
schlechterem Code.

Audio_sample_adress hat übrigens den falschen Typ; das sollte ein
Zeiger sein, kein Integer (so habe ich es in meinem Beispiel auch).

Ich vermute, dass "sample_counter" vom herumliegenden Programm zur
Synchronisation benutzt wird, oder?  Dann kann *) man diese Variable
natürlich "volatile" machen, dann muss in der ISR jedoch mit einer
Schattenkopie davon gearbeitet werden:
1
ISR(ADC_vect)
2
{
3
    *Audio_sample_adress = ADC;
4
    uint16_t sc = sample_counter;
5
    if (--sc == 0)
6
        ADCSRA &= ~_BV(ADIE);  // no more interrupts
7
    sample_counter = sc;
8
}

Das vermeidet die Pessimierung des Variablenzugriffs, die sonst
eintreten würde.  Denk aber dran, dass du außerhalb der ISR auf
diese Variable über die atomic-Makros (<util/atomic.h>) zugreifen
musst, ansonsten bekommst du subtile Fehler in dein Programm, wenn
der Interrupt genau in der Mitte des 16-bit-Zugriffs reinhaut.

*) Man kann auch den Speicherzugriff nur außerhalb erzwingen, aber
das geht jetzt ein bisschen zu weit.

: Bearbeitet durch Moderator
von Ziegenpeter (Gast)


Lesenswert?

Falls dir die c Version von Jörg Wunsch nicht reicht,
das Garbage ist warscheinlich das hier: &B11110111
Ist wahrscheinlich BASCOM Schreibweise, in c/asm müsste das 0b11110111 
sein.

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


Lesenswert?

Er hat aber noch mehr Fehler drin, Labels, die nicht definiert
sind, Zugriff auf SREG, was der Assembler so nicht kennt etc. pp.

War mir angesichts des geringen Nutzeffekts jetzt zu viel, mir das
im Detail anzusehen.

von AC (Gast)


Lesenswert?

Jörg W. schrieb:
> Also wenn es vorgeschrieben ist, weil es zu einer studentischen Übung
> gehört, dann musst du die ISR natürlich in Assemblercode hacken.

Nein, das ist es eben nicht...er ist nur der Meinung das dieser asm code 
zeit unkritisch ist und ich mit C Probleme haben werde.

Der Atmega läuft mit 20MHz. Könntest du mir deinen Code noch etwas 
erklären?

Ich muss die Werte ja in ein Array[1024] abspeichern, das müsste ich 
noch mit einer for Schleife erledigen?

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


Lesenswert?

AC schrieb:

> Der Atmega läuft mit 20MHz.

Dann wird die Zeitbilanz noch 20 % besser als meine Rechnung.

> Könntest du mir deinen Code noch etwas
> erklären?

Naja, was ist denn daran so viel zu erklären?

Es ist eigentlich schlicht das Äquivalent deines Assemblercodes,
nicht weniger, aber auch nicht mehr.

> Ich muss die Werte ja in ein Array[1024] abspeichern, das müsste ich
> noch mit einer for Schleife erledigen?

Hat deine Assemblerversion doch auch nicht. ;-)

Eine for-Schleife kannst du nur innerhalb einer Funktion benutzen,
du musst hier jedoch das Weiterzählen über die einzelnen ISR-Aufrufe
hinweg machen.

Das Initialisieren von Audio_sample_adress und sample_counter muss
natürlich vor dem ersten Interrupt passieren; das ist daher weder
in meiner C-ISR noch in deinem geposteten Assemblercode enthalten.

> er ist nur der Meinung das dieser asm code zeit unkritisch ist und ich
> mit C Probleme haben werde.

Dann solltest du natürlich in der Arbeit bei der Diskussion des
Programms darauf eingehen, wie groß der vom Compiler erzeugte Code
tatsächlich ist und wie lange er braucht (also im Prinzip das, was ich
oben überschlagen habe, nur exakt nachgerechnet).

: Bearbeitet durch Moderator
von AC (Gast)


Lesenswert?

Ziegenpeter schrieb:
> Falls dir die c Version von Jörg Wunsch nicht reicht,
> das Garbage ist warscheinlich das hier: &B11110111
> Ist wahrscheinlich BASCOM Schreibweise, in c/asm müsste das 0b11110111
> sein.

Jep, das wurde in BASCOM geschrieben. Wenn ich Notation in 0b11110111 
ändere spuckt mir der compiler tastächlich noch mehr Fehler aus:

undefined reference to SREG
undefined reference to RAMPZ
undefined reference to ADCL
undefined reference to ADCH
undefined reference to jump out
undefined reference to ADCSRA und noch ein paar mehr, insg 12.


Der Timer0 läuft im CTC im 10kHz. bzw. löst die ISR richtig aus. Jetzt 
muss ich irgendwie die Werte abspeichern...

Was mach ich denn jetzt am besten?

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


Lesenswert?

AC schrieb:
> Der Timer0 läuft im CTC im 10kHz. bzw. löst die ISR richtig aus.

Meine ISR ist übrigens für den ADC, nicht für den Timer.
Schließlich willst du ja ADC-Werte lesen, die solltest du dann lesen,
wenn der ADC auch fertig mit der Wandlung ist.

Deine gepostete ISR ist da irgendwie inkonsistent: sie gehört zum
Timer, aber wenn alle Wandlungen fertig sind, setzt sie (was ich
wieder korrekt finde) das ADIE im ADCSRA zurück.  Dennoch würde jedoch
der Timer fleißig weiter Interrupts triggern, folglich munter weiter
Audio_sample_adress erhöhen und an die entsprechende Stelle schreiben …

Wenn du den Timer als Trigger für den ADC benutzen willst, dann solltest
du dir im ADC das "auto trigger"-Feature ansehen und dort den Timer
als Triggerquelle nehmen, aber die Ergebnisse in der ADC-ISR lesen.

: Bearbeitet durch Moderator
von AC (Gast)


Lesenswert?

Jep, der ADC wird noch mit auto-trigger und timer compare match und die 
Variablen vor jedem sample zyklus initialisiert...ich denke, dass ich 
das hinkriegen würde aber die ISR an sich macht mir kopfzerbrechen, 
weswegen ich das mit dem inline assembler zuerst testen wollte.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Mach's in Assembler. avr-gcc -x assembler-with-cpp ...
1
#define __SFR_OFFSET 0
2
#include <avr/io.h>
3
4
.text
5
6
.type   TIMER0_COMPA_vect, @function
7
.global TIMER0_COMPA_vect
8
9
TIMER0_COMPA_vect:
10
11
    push R27
12
    push R26
13
    push R21
14
    push R20
15
    in   R20, SREG
16
    push R20
17
    in   R20, RAMPZ
18
    push R20
19
20
    LDS R20, ADCL
21
    LDS R21, ADCH
22
23
    LDS R26, Audio_sample_adress
24
    LDS R27, Audio_sample_adress+1
25
    ST  X+, R20
26
    ST  X+, R21
27
    STS Audio_sample_adress, R26
28
    STS Audio_sample_adress+1, R27
29
30
    LDS R26, sample_counter
31
    LDS R27, sample_counter+1
32
    SBIW R26, 1
33
    STS sample_counter, R26
34
    STS sample_counter+1, R27
35
36
    BRNE jump_out
37
38
    LDS  R26, ADCSRA
39
    ANDI R26, 0b11110111
40
    STS  ADCSRA, R26
41
42
jump_out:
43
    POP R20
44
    OUT RAMPZ, R20
45
    POP R20
46
    OUT SREG, R20
47
    POP R20
48
    POP R21
49
    POP R26
50
    POP R27
51
52
    RETI
53
54
.size TIMER0_COMPA_vect, . - TIMER0_COMPA_vect


Kommentare sind Hausaufgabe.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

...und PUSH / POP von RAMPZ sind überflüssig.

von Blubber (Gast)


Lesenswert?

AC schrieb:
> Das Prorogramm soll mit Timer0 im CTC Modus mit einer Samplerate von
> 10kHz werte ins Array schreiben.


Dafür braucht man keine assembler isr :)

Das geht lockerst in prosa c

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Blubber schrieb:
> AC schrieb:
>> Das Prorogramm soll mit Timer0 im CTC Modus mit einer Samplerate von
>> 10kHz werte ins Array schreiben.
>
> Dafür braucht man keine assembler isr :)

In BASCOM vermutlich schon :-P

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


Lesenswert?

AC schrieb:
> aber die ISR an sich macht mir kopfzerbrechen

Das verstehe ich nun wirklich nicht.  Was ist an drei Zeile C-Code,
die nur das Äquivalent deines länglichen Assemblerpamphlets sind,
nun so schwer zu verstehen?

von \r\n (Gast)


Lesenswert?

AC schrieb:
> "push R27"  "\n\t"                 //X-Register High-Byte

Ich würde erstmal hinterfragen wollen, was die albernen "\n\t" am Ende 
jeder Zeile sollen.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

\r\n schrieb:
> AC schrieb:
>> "push R27"  "\n\t"                 //X-Register High-Byte
>
> Ich würde erstmal hinterfragen wollen, was die albernen "\n\t" am Ende
> jeder Zeile sollen.

Das ist ein Zeilenumbruch.

Assemblerbefehle mussen duch einen solchen oder ein $ getrennt werden.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Jörg W. schrieb:
> Ich seh' da jetzt nicht so große Unterschiede zu deinem handgefeilten
> Assemblercode, dass sich der Zirkus irgendwie lohnen würde.

Der Code scheitert daran, folgendes Konstrukt nachzubilden

> "STS sample_counter,R26"   "\n\t" //Store back decremented Sample-Counter
> "LDS sample_counter+1,R27" "\n\t

SCNR

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


Lesenswert?

Johann L. schrieb:
> Der Code scheitert daran, folgendes Konstrukt nachzubilden

:-)))

von AC (Gast)


Lesenswert?

Moin zusammen,

sorry das ich mich gestern nicht mehr gemeldet habe, war unterwegs und 
musste/muss mich noch in "Zeiger" einlesen und die ADC Register 
einstellen/verstehen.

Werde das ganze jetzt erstmal mit dem C Code versuchen:

Jörg W. schrieb:
> ISR(ADC_vect)
> {
>     *Audio_sample_adress = ADC;
>     uint16_t sc = sample_counter;
>     if (--sc == 0)
>         ADCSRA &= ~_BV(ADIE);  // no more interrupts
>     sample_counter = sc;
> }


hauptsache ich bekomme das erstmal irgendwie zum laufen zu bringen, das 
mir irgendwelche Werte ausgegeben werden.

Johann L. schrieb:
> Mach's in Assembler. avr-gcc -x assembler-with-cpp ...
> #define __SFR_OFFSET 0
> #include <avr/io.h>
>
> .text
>
> .type   TIMER0_COMPA_vect, @function
> .global TIMER0_COMPA_vect
>
> TIMER0_COMPA_vect:
>
>     push R27
>     push R26
>     push R21
>     push R20
>     in   R20, SREG
>     push R20
>     in   R20, RAMPZ
>     push R20
>
>     LDS R20, ADCL
>     LDS R21, ADCH
>
>     LDS R26, Audio_sample_adress
>     LDS R27, Audio_sample_adress+1
>     ST  X+, R20
>     ST  X+, R21
>     STS Audio_sample_adress, R26
>     STS Audio_sample_adress+1, R27
>
>     LDS R26, sample_counter
>     LDS R27, sample_counter+1
>     SBIW R26, 1
>     STS sample_counter, R26
>     STS sample_counter+1, R27
>
>     BRNE jump_out
>
>     LDS  R26, ADCSRA
>     ANDI R26, 0b11110111
>     STS  ADCSRA, R26
>
> jump_out:
>     POP R20
>     OUT RAMPZ, R20
>     POP R20
>     OUT SREG, R20
>     POP R20
>     POP R21
>     POP R26
>     POP R27
>
>     RETI
>
> .size TIMER0_COMPA_vect, . - TIMER0_COMPA_vect

Das habe ich auch mit einer externen .S Datei versucht, was aber auch 
nicht funktioniert und bei mir noch mehr Fragezeichen aufwirft.

von Wohin (Gast)


Lesenswert?

AC schrieb:
>       "BRNE jump_out"  "\n\t"      //Jump to end of ISR if result<>0
> ...
>        "LDS {sample_counter}+1,R27"  "\n\t"
>
>       //Jump_out:
>       "POP R20"  "\n\t"                //Kann auskommentiert werden

> und ich bekomme ständig Compilerfehler.

Vielleicht vermisst der Assembler das Label für das Sprungziel?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

AC schrieb:
> Johann L. schrieb:
>> Mach's in Assembler. avr-gcc -x assembler-with-cpp ...
>> #define __SFR_OFFSET 0
>> #include <avr/io.h>
>> ...
>
> Das habe ich auch mit einer externen .S Datei versucht, was aber auch
> nicht funktioniert

Ich habe lediglich deinen Code nach GNU-Assembler übertragen.  Lässt 
sich Problemlos für einen ATmega168 assemblieren.

Die Bugs, die aufs Original-Posting zurückgehen, musst schon selbst 
beheben...

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


Lesenswert?

Mir dünkt, dass der TE erstmal lernen sollte zu verstehen, was in der
ISR überhaupt passiert, statt die ganze Zeit nur irgendwelchen fremden
Code trial&error-mäßig durchzuprobieren.

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.