Forum: Mikrocontroller und Digitale Elektronik erbitte Hilfe bei optimierung ISR


von Vlad T. (vlad_tepesch)


Lesenswert?

Hi,
Ich möchte eine 16bit-Software PWM bauen.

controller ist ein atmega168

Folgender Aufbau:

1
#define SOFT_PWM_CHANNELS 3
2
/** contains multiplexed pwmdata pwmVal-highbyte, pwmVal-lowByte, portVal
3
 * 2 additional fields because of loading of new ocrval
4
 */
5
static uint8_t    g_pwmData[3*SOFT_PWM_CHANNELS + 2];
6
static volatile uint8_t*   g_dataPtr;
7
8
9
ISR(TIMER1_COMPA_vect)
10
{
11
  PWM_RGB_PIN = *g_dataPtr;  // toggle pins 
12
  ++g_dataPtr;
13
  OCR1AH      = *g_dataPtr;  // load new compare value
14
  ++g_dataPtr;
15
  OCR1AL      = *g_dataPtr;
16
  ++g_dataPtr;
17
}
18
19
ISR(TIMER1_OVF_vect)
20
{
21
  g_dataPtr = g_pwmData;
22
  //g_pwmInd = 2; //-> zeigt auf pin
23
  PWM_RED_PORT |= ((1 << PWM_RED_BIT) | (1 << PWM_GREEN_BIT)| (1 << PWM_BLUE_BIT) );
24
  OCR1AH = *g_dataPtr;
25
  ++g_dataPtr;
26
  OCR1AL = *g_dataPtr;
27
  ++g_dataPtr;
28
}


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:
1
ISR(TIMER1_COMPA_vect)
2
{
3
     ef4:  1f 92         push  r1
4
     ef6:  0f 92         push  r0
5
     ef8:  0f b6         in  r0, 0x3f  ; 63
6
     efa:  0f 92         push  r0
7
     efc:  11 24         eor  r1, r1
8
     efe:  8f 93         push  r24
9
     f00:  af 93         push  r26
10
     f02:  bf 93         push  r27
11
     f04:  ef 93         push  r30
12
     f06:  ff 93         push  r31
13
  PWM_RGB_PIN = *g_dataPtr;  //  Pins togglen
14
     f08:  a0 91 86 01   lds  r26, 0x0186
15
     f0c:  b0 91 87 01   lds  r27, 0x0187
16
     f10:  fd 01         movw  r30, r26
17
     f12:  81 91         ld  r24, Z+
18
     f14:  89 b9         out  0x09, r24  ; 9
19
  ++g_dataPtr;
20
  OCR1AH      = *g_dataPtr;
21
     f16:  11 96         adiw  r26, 0x01  ; 1
22
     f18:  8c 91         ld  r24, X
23
     f1a:  80 93 89 00   sts  0x0089, r24
24
  ++g_dataPtr;
25
  OCR1AL      = *g_dataPtr;
26
     f1e:  81 81         ldd  r24, Z+1  ; 0x01
27
     f20:  80 93 88 00   sts  0x0088, r24
28
  ++g_dataPtr;
29
     f24:  32 96         adiw  r30, 0x02  ; 2
30
     f26:  f0 93 87 01   sts  0x0187, r31
31
     f2a:  e0 93 86 01   sts  0x0186, r30
32
}
33
     f2e:  ff 91         pop  r31
34
     f30:  ef 91         pop  r30
35
     f32:  bf 91         pop  r27
36
     f34:  af 91         pop  r26
37
     f36:  8f 91         pop  r24
38
     f38:  0f 90         pop  r0
39
     f3a:  0f be         out  0x3f, r0  ; 63
40
     f3c:  0f 90         pop  r0
41
     f3e:  1f 90         pop  r1
42
     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.

von Falk B. (falk)


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

von Vlad T. (vlad_tepesch)


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.

von Falk B. (falk)


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.

von Vlad T. (vlad_tepesch)


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.

von holger (Gast)


Lesenswert?

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

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

von Falk B. (falk)


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

von Falk B. (falk)


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

von Vlad T. (vlad_tepesch)


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:
1
  push r0
2
  in  r0, 0x3f
3
  push  r0
4
  ld   r0, Z+
5
  out  0x09, r0
6
  ld   r0, Z+
7
  sts  0x0089, r0
8
  ld   r0, Z+
9
  sts  0x0088, r0
10
  pop  r0
11
  out  0x3f, r0 
12
  pop  r0
13
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

von Vlad T. (vlad_tepesch)


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.

von Vlad T. (vlad_tepesch)


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.

von Christian T. (shuzz)


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.

von Vlad T. (vlad_tepesch)


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

von Vlad T. (vlad_tepesch)


Lesenswert?

unter zuhilfenahme der GPIORs zum sichern der Register lässst scih das 
ganze nochmal verkürzen.
1
in   0x2A, r0      // R0 -> GPIOR1
2
in   0x1E, 0x3f    // SREG -> GPIOR0
3
ld   r0, Z+        
4
out  0x09, r0      // r0 -> PIND 
5
ld   r0, Z+        
6
sts  0x0089, r0    // r0 -> OC1AH 
7
ld   r0, Z+        
8
sts  0x0088, r0    // r0 -> OC1AL
9
out  0x3f, 0x1E    // GPIOR0 -> SREG
10
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

von Vlad T. (vlad_tepesch)


Lesenswert?

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

von Oliver (Gast)


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

von Vlad T. (vlad_tepesch)


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.

von Stefan E. (sternst)


Lesenswert?

Vlad Tepesch schrieb:
1
in   0x2A, r0      // R0 -> GPIOR1
2
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.

von MWS (Gast)


Lesenswert?

1
in   0x1E, 0x3f    // SREG -> GPIOR0
2
...
3
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.

von Stefan E. (sternst)


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.

von Detlef _. (detlef_a)


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)
    :
    );
}

von Vlad T. (vlad_tepesch)


Lesenswert?

MWS schrieb:
>
1
> in   0x1E, 0x3f    // SREG -> GPIOR0
2
> ...
3
> out  0x3f, 0x1E    // GPIOR0 -> SREG
4
>
>
> 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?

von Stefan E. (sternst)


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.

von Vlad T. (vlad_tepesch)


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

von Stefan E. (sternst)


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:
1
uint8_t *ptr;

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

von Detlef _. (detlef_a)


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

von Vlad T. (vlad_tepesch)


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.

von Stefan E. (sternst)


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.

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.