GCC und LDS/STS auf Attiny10

#3475606
Lesenswert?

Ich kämpfa gerade mit avr-gcc 4.7.2 und einem Attiny 10. Der Compiler 
weigert sich, die kurzen 8-bit LDS und STS für den Speicherzugriff zu 
nutzen, sondern erzeugt stattdessen einen indirekten Zugriff über das 
Z-Register. Das ist natürlich kompletter Unsinn und bläht den Code 
unnötig auf.

Kann man dagegen etwas tun?

z.B.
1
      usbTxLen = wantLen;
2
 3e6:  ed e4         ldi  r30, 0x4D  ; 77
3
 3e8:  f0 e0         ldi  r31, 0x00  ; 0
4
 3ea:  30 83         st  Z, r19
statt:
1
     sts 0x4D,r19
#3476355
Lesenswert?

So funktioniert es immerhin als define:
1
         uint8_t out;
2
         uint8_t adr=1;
3

4
         asm volatile(      
5
          "         lds  %0,%1 \n\t"        
6
          : "=&d" (out)
7
          :  "M" (adr)
8
         );

Leider funktioniert es nicht, wenn "adr" ein Pointer auf eine Variable 
im Speicher ist:
1
main.c:160:10: warning: asm operand 1 probably doesn't match constraints [enabled by default]
2
main.c:160:10: error: impossible constraint in 'asm'

Wie bringe ich dem Compiler bei, dass die pointer konstant sind?
#3476606
Lesenswert?

Der code oben compiliert ohne Fehlermeldung.

Dieser aber nicht, trotz pointer auf static.
1
         uint8_t out;
2
         static uint8_t adr=1;
3

4
         asm volatile(      
5
          "         lds  %0,%1 \n\t"        
6
          : "=&d" (out)
7
          :  "M" ((uint8_t)&adr)
8
         );

Ich habe es aber jetzt auch so in den Speicher bekommen. Ich werde erst 
einmal abwarten, was vom Ateml support kommt, bevor ich Arbeit in 
Workarounds investiere.
#3476621
Lesenswert?

Und hier noch ein Aufreger. Cast von statischem 16 pointer auf 8 bit 
const:
1
#define usbMsgPtr_t uchar *
2
...
3
 usbMsgPtr = (usbMsgPtr_t)(&usbDescriptorDevice[12]); 
4
 340:  40 e2         ldi  r20, 0x20  ; 32
5
 342:  50 e0         ldi  r21, 0x00  ; 0
6
 344:  d4 2f         mov  r29, r20

Ich nehme an, das ist ein prinzipielles Problem durch die angenommene 16 
Bit Maschinenwortgröße?
#3477505
Lesenswert?

Falk Brunner schrieb:
> Naja, bei 1 K Flash kann man's auch gleich in ASM machen, da würde
> ich
> nicht so einen Würg Around mit dem Compiler veranstalten.

Klar, aber irgendwie ist es nicht der Sinn der Sache, existierende 
C-Programme in Assembler nachzuprogrammieren. Vor allem das Zuweisen der 
Register und die Optimierung von langen Switch/If-Konstrukten überlasse 
ich gerne dem C-Compiler. Das kann er aber besser, je mehr 
zusammenhängenden Code er sieht.

Ich hoffe ja, das Atmel die bestehenden Bugs im Compiler noch beseitigt, 
damit ich die Workaround wieder entfernen kann.

> Edit: Ich vermisse 100nF am AVR.

Du meinst den Aufbau auf dem Broadboard? Da verbergen sich etliche 
passive Bauteile auf den Rückseiten der Break-Out boards.
#3481626
Lesenswert?

Tim    schrieb:
> Lustig, es geht gleich weiter. AVR-GCC scheint für den ATtiny 10 andere
> calling conventions als diese hier:
>
> http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_reg_usage
>
> zu verwenden. Auf den normalen Cores können R18/R19 "geclobbered"
> werden, auf dem ATtiny 10 geht der compiler offenbar davon aus, dass
> diese erhalten bleiben. Nur wo ist das dokumentiert?

Hier die Antwort vom Atmel-Support. Das andere Problem schauen sie sich 
noch an.

1
As per current implementation (till Tool chain 3.4.3), below is the register conventions used for AVR_TINY devices:
2

3
r16 - Fixed/ TMP
4
r17 - Fixed/ ZERO
5
r18 - Callee saved
6
r19 - Callee saved
7
r20 - arg
8
r21 - arg
9
r22 - ret/ arg
10
r23 - ret/ arg
11
r24 - ret/ arg
12
r25 - ret/ arg
13
r26 - X
14
r27 - X
15
r28 - Y/ FP/ Callee saved
16
r29 - Y/ FP/ Callee saved
17
r30 - Z
18
r31 - Z
Persönliche Seite #3481740
Lesenswert?

hmmm, das scheint wirklich nur die mini-Tinys zu betreffen, etwa:
1
extern char c, d;
2

3
void f1 (void)
4
{
5
    c = d;
6
}

gibt:
1
f1:
2
  ldi r30,lo8(d)   ;  5  *movhi/5  [length = 2]
3
  ldi r31,hi8(d)
4
  ld r20,Z   ;  6  movqi_insn/4  [length = 1]
5
  ldi r30,lo8(c)   ;  7  *movhi/5  [length = 2]
6
  ldi r31,hi8(c)
7
  st Z,r20   ;  8  movqi_insn/3  [length = 1]
8
  ret   ;  15  return  [length = 1]


Und auch an anderen Stellen muß Atmel noch nachsitzen:
1
int f3 (const __flash int *p)
2
{
3
    return *p;
4
}
1
.s: Assembler messages:
2
.s:18: Error: illegal opcode elpm for mcu attiny10
3
.s:19: Error: register not supported
4
.s:20: Error: illegal opcode sbiw for mcu attiny10
5
.s:21: Error: illegal opcode elpm for mcu attiny10
6
.s:22: Error: register not supported

Zudem ist eine Meldung (:20) auch noch falsch: Es wird ADIW erzeugt, 
nicht SBIW.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren