mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik erbitte Hilfe bei optimierung ISR


Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
Ich möchte eine 16bit-Software PWM bauen.

controller ist ein atmega168

Folgender Aufbau:

#define SOFT_PWM_CHANNELS 3
/** contains multiplexed pwmdata pwmVal-highbyte, pwmVal-lowByte, portVal
 * 2 additional fields because of loading of new ocrval
 */
static uint8_t    g_pwmData[3*SOFT_PWM_CHANNELS + 2];
static volatile uint8_t*   g_dataPtr;


ISR(TIMER1_COMPA_vect)
{
  PWM_RGB_PIN = *g_dataPtr;  // toggle pins 
  ++g_dataPtr;
  OCR1AH      = *g_dataPtr;  // load new compare value
  ++g_dataPtr;
  OCR1AL      = *g_dataPtr;
  ++g_dataPtr;
}

ISR(TIMER1_OVF_vect)
{
  g_dataPtr = g_pwmData;
  //g_pwmInd = 2; //-> zeigt auf pin
  PWM_RED_PORT |= ((1 << PWM_RED_BIT) | (1 << PWM_GREEN_BIT)| (1 << PWM_BLUE_BIT) );
  OCR1AH = *g_dataPtr;
  ++g_dataPtr;
  OCR1AL = *g_dataPtr;
  ++g_dataPtr;
}



Funktionsweise ist folgende:
die PWM-werte werden sortiert und werden mit den zu schaltendem Pins in 
das g_pwmData - Felg geschriegen geschrieben.

die overflow-routine schaltet alle Kanäle ein.
und läd den ersten Compare wert.
in der ISR werden die zugehörigen Kanäle abgeschalten und der nächste 
Wert geladen.

die ISRs müssen so kurz wie möglich sein, besonders die 
TIMER1_COMPA_vect, damit nahe beieinanderliegende PWM-Werte auch die 
Interupts bekommen und er nicht noch in dem letzten steckt.

Ich hätte angenommen, das das ganze mit load und store am anfang ende,
sowie 3
LD Rd, [X|Y|Z]+  Load Indirect and Post-Inc.
sowie 3 outs gegessen ist, aber das macht der Compiler daraus:
ISR(TIMER1_COMPA_vect)
{
     ef4:  1f 92         push  r1
     ef6:  0f 92         push  r0
     ef8:  0f b6         in  r0, 0x3f  ; 63
     efa:  0f 92         push  r0
     efc:  11 24         eor  r1, r1
     efe:  8f 93         push  r24
     f00:  af 93         push  r26
     f02:  bf 93         push  r27
     f04:  ef 93         push  r30
     f06:  ff 93         push  r31
  PWM_RGB_PIN = *g_dataPtr;  //  Pins togglen
     f08:  a0 91 86 01   lds  r26, 0x0186
     f0c:  b0 91 87 01   lds  r27, 0x0187
     f10:  fd 01         movw  r30, r26
     f12:  81 91         ld  r24, Z+
     f14:  89 b9         out  0x09, r24  ; 9
  ++g_dataPtr;
  OCR1AH      = *g_dataPtr;
     f16:  11 96         adiw  r26, 0x01  ; 1
     f18:  8c 91         ld  r24, X
     f1a:  80 93 89 00   sts  0x0089, r24
  ++g_dataPtr;
  OCR1AL      = *g_dataPtr;
     f1e:  81 81         ldd  r24, Z+1  ; 0x01
     f20:  80 93 88 00   sts  0x0088, r24
  ++g_dataPtr;
     f24:  32 96         adiw  r30, 0x02  ; 2
     f26:  f0 93 87 01   sts  0x0187, r31
     f2a:  e0 93 86 01   sts  0x0186, r30
}
     f2e:  ff 91         pop  r31
     f30:  ef 91         pop  r30
     f32:  bf 91         pop  r27
     f34:  af 91         pop  r26
     f36:  8f 91         pop  r24
     f38:  0f 90         pop  r0
     f3a:  0f be         out  0x3f, r0  ; 63
     f3c:  0f 90         pop  r0
     f3e:  1f 90         pop  r1
     f40:  18 95         reti

Hat jemand einen Tip warum der Compiler nicht das macht, was ich 
erwarte?
gibt es eine Möglichkeit, dem compiler zu sagen, dass er für den 
g_dataPtr eins der XYZ register fest alloziert und sonst nirgends 
verwendet?

Auch sichert er register, die gar nicht benötigt werden.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Vlad Tepesch (vlad_tepesch)

>Ich möchte eine 16bit-Software PWM bauen.
>controller ist ein atmega168

Optimist oder Rechenschwäche?

Mein Tipp. Lies mal was über LED-Fading und Soft-PWM, rechne 
nochmal nach und vergiss es.

MfG
Falk

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
naja prinzipiell ist es nur eine 12bit pwm, dh. die 12bit-WErte werden 
mit 16 multipliziert.

zumindest hatte ich mir erst mal 12bit vorgenommen, könnte auch noch 
versuchen auf 11 zu gehen, das würde die verfügbare Zeit von 16 auf 32 
Takte vergrößern.


rechnerisch sollte das möglich sein

der 16bit zähler läuft ohne Vorteiler und es wird immer der nächste 
compare wert gesetzt.

man kommt bei 8Mhz auf eine PWM-Frequenz von ~120Hz.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Vlad Tepesch (vlad_tepesch)

>naja prinzipiell ist es nur eine 12bit pwm,

Und warum schreibst du das nicht?

> dh. die 12bit-WErte werden mit 16 multipliziert.

Mogelpackung, die rein gar nichts bringt.

>zumindest hatte ich mir erst mal 12bit vorgenommen, könnte auch noch
>versuchen auf 11 zu gehen, das würde die verfügbare Zeit von 16 auf 32
>Takte vergrößern.

Ich sag mal viel mehr als 10 Bit ist kaum sinnvoll machbar. Und das 
reicht auch, siehe Artikel LED-Fading.

>man kommt bei 8Mhz auf eine PWM-Frequenz von ~120Hz.

Macht bei 12 Bit 16 Takte/PWM-Takt. Sportlich. Bleibt wenig Zeit für 
andere Sachen.

MFG
Falk

P S Vielleicht könnte man es wie die AVR-Videoausgabeterminals machen, 
mit Hilfe des SPI-Moduls. Da hat man den vollen Takt.

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Falk Brunner schrieb:
> Ich sag mal viel mehr als 10 Bit ist kaum sinnvoll machbar. Und das
> reicht auch, siehe Artikel LED-Fading.

das Fading soll aber extrem langsam sein.

>
>>man kommt bei 8Mhz auf eine PWM-Frequenz von ~120Hz.
>
> Macht bei 12 Bit 16 Takte/PWM-Takt. Sportlich. Bleibt wenig Zeit für
> andere Sachen.

für andere Sachen ist mehr als genug Zeit.
es gibt ja nur 3 Kanäle.
Das heißt pro PWM-Zyklus wird 3x die Compare-Routine aufgerufen und 
einmal die Overflow-Routine.

macht ~100 Takte pro PWM-Zyklus * 120Hz macht eine Auslastung von 0,15% 
bei 8Mhz

Das Problem ist nur, wie kriege ich die (eigendlich total mikrige) ISR 
klein.

Ich habe gehofft, das mir einer der ASM-Profis hier weiterhelfen kann.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>macht ~100 Takte pro PWM-Zyklus * 120Hz macht eine Auslastung von 0,15%
>bei 8Mhz

120Hz * 12Bit => 120 * 4096 => 491,5kHz PWM Frequenz!

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Vlad Tepesch (vlad_tepesch)

>das Fading soll aber extrem langsam sein.

Immer diese Extrawünsche. Dann nimm einen AVR mit drei 16-Bit 
Hardware-PWMs oder drei Tinys. Fettig.

MfG
Falk

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@holger (Gast)

>>macht ~100 Takte pro PWM-Zyklus * 120Hz macht eine Auslastung von 0,15%
>>bei 8Mhz

>120Hz * 12Bit => 120 * 4096 => 491,5kHz PWM Frequenz!

Richtig. Für Hardware ein Klacks. In Software schon SEHR heftig.

MFG
Falk

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Falk Brunner schrieb:
> @  Vlad Tepesch (vlad_tepesch)
>
>>das Fading soll aber extrem langsam sein.
>
> Immer diese Extrawünsche. Dann nimm einen AVR mit drei 16-Bit
> Hardware-PWMs oder drei Tinys. Fettig.
>
da habe ich noch keinen gefunden.

sollte möglichst klein und dip sein.

Aber hier ist der mega168 gessetzt.

Vielleich tkönnen wir uns auf das Problem konzentrieren.

Eine feste Allocation eines der XYZ-Register würde hier enorm helfen.
dann könnte es meiner Meinung nach so aussehen:
  push r0
  in  r0, 0x3f
  push  r0
  ld   r0, Z+
  out  0x09, r0
  ld   r0, Z+
  sts  0x0089, r0
  ld   r0, Z+
  sts  0x0088, r0
  pop  r0
  out  0x3f, r0 
  pop  r0
reti

das wären 25 Takte, würde immerhin für 11bit Reichen

aber wie überrede ich den compiler zu dieser festen Allokation und dazu 
den sinnlos großen Frame um die ISR wegzulassen

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
holger schrieb:
>>macht ~100 Takte pro PWM-Zyklus * 120Hz macht eine Auslastung von 0,15%
>>bei 8Mhz
>
> 120Hz * 12Bit => 120 * 4096 => 491,5kHz PWM Frequenz!

Mir scheint du hast das falsch verstanden.

es läuft ein 16bit-Timer bei 8Mhz ohne prescaler mit -> ~120 Hz

die pwm ist 12 bit, da aber der Prescaler recht grob ist werden die 
12bit werte gespreizt, damit zwischen zwei nebeneinanderliegenden Werten 
genug zeit für die PWM-administrierung bleibt (16 reichen nicht - wie 
gerade ermittelt)

Ich ätte auch einen prescaler von 8 nehmen können und alle 12bit-werte 
mit 2 multiplizieren können.


die PWM-LUT sieht also so aus:
0, 16, 16, 16, 32, 32, .. 65000

Das problem besteht also nur im unteren bereich der PWM. im oberen 
bereich sind die Compare-Werte sowso weit genug auseinander, das 
genügend zeit zum Umladen bleibt.

edit:
Das problem ist also nicht die Gesammtrechenzeit der PWM, sondern das 
Interupts verloren gehen, wenn 2 PWM-Werte dicht beieinander liegen und 
ISR boch nicht beendet ist, wenn der nächste Compare schon erreicht ist.

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vlad Tepesch schrieb:
> Ich ätte auch einen prescaler von 8 nehmen können und alle 12bit-werte
> mit 2 multiplizieren können.

hier hätte der timer aber im CTC modus bis 8196 laufen müssen, so dass 
man einen zusätzlichen outputcompare verliert.

Autor: Christian T. (shuzz)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vlad Tepesch schrieb:
> Falk Brunner schrieb:
>> @  Vlad Tepesch (vlad_tepesch)
>>
>>>das Fading soll aber extrem langsam sein.
>>
>> Immer diese Extrawünsche. Dann nimm einen AVR mit drei 16-Bit
>> Hardware-PWMs oder drei Tinys. Fettig.
>>
> da habe ich noch keinen gefunden.
>
> sollte möglichst klein und dip sein.
>
> Aber hier ist der mega168 gessetzt.
>

Auch wenn der gesetzt ist: Mega163 hat 2 16-Bit Timer mit je 2 
unabhängigen PWMs. Dafür halt keinen AD.

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christian T. schrieb:
> Auch wenn der gesetzt ist: Mega163 hat 2 16-Bit Timer mit je 2
> unabhängigen PWMs. Dafür halt keinen AD.

laut Datenblatt hat der (wie der Nachfolger auch) 2 8bit- und 1 
16bit-Timer
und insgesammt 3 PWM-Kanäle

Wie gesagt, ich such schon seit ner weile nach nem schön kleinen 
Controller in DIP mit 3 16bit pwm Kanälen.

Am liebsten wär mir ein 8Pinner.
wobei max. 24 auch noch ok wär.

aber 3 16bit pwm-Kanäle haben nur ndie dicken, dies auch gar nicht in 
DIP gibt

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
unter zuhilfenahme der GPIORs zum sichern der Register lässst scih das 
ganze nochmal verkürzen.
in   0x2A, r0      // R0 -> GPIOR1
in   0x1E, 0x3f    // SREG -> GPIOR0
ld   r0, Z+        
out  0x09, r0      // r0 -> PIND 
ld   r0, Z+        
sts  0x0089, r0    // r0 -> OC1AH 
ld   r0, Z+        
sts  0x0088, r0    // r0 -> OC1AL
out  0x3f, 0x1E    // GPIOR0 -> SREG
out  r0, 0x2A      // GPIOR1 -> R0

Ich glaube kürzer geht es nicht.
das sind jetzt 19 Takte


Ich habe leider immer noch keinen Plan, wie man dem Compiler verbietet 
das Z-Register zu benutzen.
wenn man dieses noch sichern/wiederherstellen muss und den Pointer erst 
da rein laden und zurück speichern muss macht das nochmal 16 Takte

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe diese Frage mal ins gcc Unterforum gepostet:
Beitrag "gcc verbieten bestimmte Register zu benutzen"

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ich glaube kürzer geht es nicht.
>das sind jetzt 19 Takte

Da kommen dann noch 7 Takte für die Interrupt-Verarbeitung hinzu (4 
Takte interrupt execution response time + 3 Takte für den Sprung in die 
ISR). Und nach dem Reti wird ein Befehl des Hauptprograms abgearbeitet, 
das sind dann nochmals 1 oder 2 Takte.

Oliver

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oliver schrieb:
> Da kommen dann noch 7 Takte für die Interrupt-Verarbeitung hinzu (4
> Takte interrupt execution response time + 3 Takte für den Sprung in die
> ISR).

> Und nach dem Reti wird ein Befehl des Hauptprograms abgearbeitet,
> das sind dann nochmals 1 oder 2 Takte.

könnten also auch 4 Takte sein, wenn er gerade an einem RET hängt
macht also zusätzliche 11

da das mit dem Register ach nicht zu klappen scheint kommen die oben 
erwähnten 16 also auch noch dazu


macht insgesamt 46 Takte.
und damit 46 16bit-PWM-Steps Mindestabstand zwischen 2 PWM-Stufen
Macht rund 10,5bit PWM

Oder ich lege die Stufen doch näher, fasse aber, wenn mehrere Kanäle 
näher zusammen liegen als 50 Takte diese zu einem Schaltvorgang 
zusammen.
Mal sehen, ob das auffällt.

Ich befürchte aber, dass das im ohnehin empfindlichen unteren Bereich 
auffällt.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vlad Tepesch schrieb:
in   0x2A, r0      // R0 -> GPIOR1
in   0x1E, 0x3f    // SREG -> GPIOR0

Das erste müsste ein out sein, und das zweite geht so grundsätzlich 
nicht. Du kannst nicht direkt den Inhalt von einem SFR zu einem anderen 
SFR verschieben.

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
in   0x1E, 0x3f    // SREG -> GPIOR0
...
out  0x3f, 0x1E    // GPIOR0 -> SREG

Ist Unsinn und unnötig wenn man keine Befehle verwendet, die das SREG 
verändern, ld, sts, in & out wie im dargestellten Code haben keinen 
Einfluss auf das SREG.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vlad Tepesch schrieb:
> Ich habe leider immer noch keinen Plan, wie man dem Compiler verbietet
> das Z-Register zu benutzen.
> wenn man dieses noch sichern/wiederherstellen muss und den Pointer erst
> da rein laden und zurück speichern muss macht das nochmal 16 Takte

Wieso 16? Ich komme auf 8.

Autor: Detlef _a (detlef_a)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

möglicherweise fällt einem ja noch ein anderer Algorithmus ein, der das 
Problem nahe beieinanderliegender Werte strukturell besser angeht, da 
gibts bestimmt was.

Assembler läßt sich in gcc schlank und sehr abstrakt einbinden, da 
kannst Du den uC an den zeitkritischen Stellen genau in die richtige 
Spur drücken.

Habe Beispielcode als Anschauungsmuster angehängt. (naked) spart Dir die 
push/pop Orgie.

Cheers
Detlef


/*********************************************************************** 
*******
*   Timer/Counter0 Compare 0 Interrupt Routine
************************************************************************ 
*******/

void SIG_OUTPUT_COMPARE0 (void) _attribute_ ((naked));
SIGNAL(SIG_OUTPUT_COMPARE0)
{

asm volatile (
    "push        r16                        \n\t"  // push!
    "push        r17                        \n\t"  // push!
    "push        r18                        \n\t"  // push!
          ::);

//PORTB=nextport; // Dett macht kein Jitter
asm volatile (
    "lds        r16,(nextport)               \n\t"  // nextport laden
    "out        0x05, r16                    \n\t"  // raus an PORTB
::);

//if(ledcnt0&1)nextport = nextport^(1<<5); // Output toggeln

asm volatile (
    "lds        r17,(ledcnt0)               \n\t"  // ledcnt0=1?
    "sbrs       r17, 0                      \n\t"  //
    "rjmp       .+8                         \n\t"  // skip it
    //"rjmp     weiter1                         \n\t"  // skip it
    "ldi        r18, 0x20                   \n\t"  // nextport toggeln
    "eor        r16, r18                    \n\t"  //
    "sts        (nextport), r16             \n\t"  // und abspeichern
    "weiter1:                               \n\t"  // und abspeichern
::);
/*
if(!(ledcnt0++))
if(!(ledcnt1++))
  nextport ^= (1<<7);
*/
asm volatile (
    "subi r17,0xff                          \n\t"  //ledcnt0 + 1
    "sts(ledcnt0),r17                       \n\t"  // abspeichern
    "cpi r17,0x01                           \n\t"  // ==1
    "brne .+22                              \n\t"  //
    "lds r17,(ledcnt1)                      \n\t"  //ledcnt1 laden
    "subi r17,0xff                          \n\t"  //ledcnt1 + 1
    "sts(ledcnt1),r17                       \n\t"  // abspeichern
    "cpi r17,0x01                           \n\t"  // ==1
    "brne .+8                               \n\t"  //
    "ldi r17,0x80                           \n\t"  // nextport Bit 
toggeln
    "eor        r16, r17                    \n\t"  //
    "sts(nextport),r16                      \n\t"  // abspeichern
::);


asm volatile (
    "pop         r18                        \n\t"  // pop!
    "pop         r17                        \n\t"  // pop!
    "pop         r16                        \n\t"  // pop!
    "reti                                   \n\t"  // pop!
          ::);

}


/*********************************************************************** 
*******/
inline void lr(SINT32 * w)
/*********************************************************************** 
*******/
{
register UINT8  c1,c2,c3;

// berchnet ((w<<16)-w)>>16
//    D0 C0 B0 A0 c2 c3
//  - c1 c1 D0 C0 B0 A0

asm volatile(
    "andi  %1,0      \n\t"  // nullen
    "andi  %2,0      \n\t"  // nullen
    "andi  %3,0      \n\t"  // nullen
    "sbrc  %D0,7     \n\t"  // sign extension
    "ori   %1,0xff   \n\t"

    "sub   %3 ,%A0    \n\t"
    "sbc   %2 ,%B0    \n\t"
    "sbc   %A0,%C0    \n\t"
    "sbc   %B0,%D0    \n\t"
    "sbc   %C0,%1     \n\t"
    "sbc   %D0,%1     \n\t"

    : "+d"(*w),"+d"(c1),"+d"(c2),"+d"(c3)
    :
    );
}

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
MWS schrieb:
>
> in   0x1E, 0x3f    // SREG -> GPIOR0
> ...
> out  0x3f, 0x1E    // GPIOR0 -> SREG
> 
>
> Ist Unsinn und unnötig wenn man keine Befehle verwendet, die das SREG
> verändern, ld, sts, in & out wie im dargestellten Code haben keinen
> Einfluss auf das SREG.

stimmt.
Ich hab nur im automatisch generierten Code geschaut und gesehen, dass 
da das Status-Regsiter gerettet wird und gedacht "stimmt, das muss auch"

Ich bin ein wenig schockiert über den gcc, dass er nicht nur die 
Register sichert, die wirklich verändert werden.
Gerade dass wär so einfach.

Stefan Ernst schrieb:
> Wieso 16? Ich komme auf 8.

push R30
push R31
ld   R30, Highbyteadresse von pointer
ld   R31, Lowbyteadresse  von pointer

...rest von oben

st   Highbyteadresse von pointer, R30
st   Lowbyteadresse  von pointer, R30
pop R31
pop R30

mach t 8 instructionen à 2 Takte = 16 zusätzliche Takte


Detlef _a schrieb:
> Habe Beispielcode als Anschauungsmuster angehängt. (naked) spart Dir die
> push/pop Orgie.

ok, Danke.
Das mit dem Naked habe ich schon mal irgendwo gesehen.


Detlef _a schrieb:
> möglicherweise fällt einem ja noch ein anderer Algorithmus ein, der das
> Problem nahe beieinanderliegender Werte strukturell besser angeht, da
> gibts bestimmt was.

Naheliegende Werte müssen ja nur beim setzen neuer PWM-Werte 
berücksichtigt werden, das ist an sich kein Problem, gleiche Werte 
werden ja auch schon zusammengefasst, man müsste nur die 
Gleichheitsbedingung anpassen.

Die Frage ist, wie es aussieht, wenn man die einfach gleichzeitig 
schaltet, da damit eine PWM-Stufe ja übersprungen wird.

Edit:
@detlef:
kanns du noch fix sagen, wie ich die Speziellen Register per namen 
(OC1AH, oder GPIOR0, ...) in den inline-Asm geben kann?

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vlad Tepesch schrieb:

> Stefan Ernst schrieb:
>> Wieso 16? Ich komme auf 8.
> ...
> mach t 8 instructionen à 2 Takte = 16 zusätzliche Takte

Peinlich, hatte ich doch glatt die push/pops vergessen. ;-)

> kanns du noch fix sagen, wie ich die Speziellen Register per namen
> (OC1AH, oder GPIOR0, ...) in den inline-Asm geben kann?

Ich sehe nicht, welchen Vorteil dir hier Inline-ASM bringen soll. Du 
machst dir die Sache einfacher, wenn du die ISR in eine separate 
ASM-Datei packst.

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst schrieb:
> Ich sehe nicht, welchen Vorteil dir hier Inline-ASM bringen soll. Du
> machst dir die Sache einfacher, wenn du die ISR in eine separate
> ASM-Datei packst.

Vorteile wären:
- die ISR da ist, wo sie thematisch hingehört.
- die benötigten Variablen sind direkt verfügbar.
  (wie bekomme ich in einer separaten asm-Date die Adresse der 
Pointer-Variablen)
- ein File weniger

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vlad Tepesch schrieb:

> - die benötigten Variablen sind direkt verfügbar.
>   (wie bekomme ich in einer separaten asm-Date die Adresse der
> Pointer-Variablen)

Variable in C-Datei:
uint8_t *ptr;

Zugriff in ASM-Datei:
lds r30, ptr
lds r31, ptr+1

Autor: Detlef _a (detlef_a)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> (wie bekomme ich in einer separaten asm-Date die Adresse der Pointer-Variablen)

über ein .extern Commando in der asm-Datei

>>kanns du noch fix sagen, wie ich die Speziellen Register per namen
(OC1AH, oder GPIOR0, ...) in den inline-Asm geben kann?

nee, weiß ich nicht aus dem Stehgreif, hägt auch davon ab, wie das 
#define OC1AH jetzt aussieht. Würde aber tippen entweder lds r10,(OC1AH) 
oder dasgleiche ohne Klammer, einfach ins produzierte Assemblerlisting 
kucken.

Cheers
Detlef

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Detlef _a schrieb:
> nee, weiß ich nicht aus dem Stehgreif, hägt auch davon ab, wie das
> #define OC1AH jetzt aussieht. Würde aber tippen entweder lds r10,(OC1AH)
> oder dasgleiche ohne Klammer, einfach ins produzierte Assemblerlisting
> kucken.

naja, so einfach war das nicht - hatte ich letztens gelesen.

der asm-Preprozessor geht über das inline-asm nicht mehr drüber und kann 
die nicht mehr ersetzen.
Irgendwie musste man die dem per % und M(SFR...) oder sowas 
reinreichen.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Detlef _a schrieb:
>>> (wie bekomme ich in einer separaten asm-Date die Adresse der 
Pointer-Variablen)
>
> über ein .extern Commando in der asm-Datei

Das hat aber nur einen rein dokumentarischen Zweck. Der Assembler 
betrachtet sowieso alle unbekannten Symbole als extern.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.