Forum: Mikrocontroller und Digitale Elektronik AVR clock prescaler (CLKPR) und gcc-Codeoptimierung


You were forwarded to this site from EmbDev.net. Back to EmbDev.net
von Peter-Jan P. (pjp)


Lesenswert?

Da der Clock Prescaler mich die letzten zwei Tage beschäftigt hat, habe 
ich mal meine Ergebnisse zusammengetragen. Alles was ich hier schreibe, 
habe ich am attiny2313 ausprobiert, das Problem besteht aber auch bei 
anderen AVR µCs.


Um den Faktor des clock prescalers einzustellen, muss man innerhalb von 
4 Taktzyklen zweimal auf das Register CLKPR zugreifen: im ersten Zugriff 
setzt man das höchste Bit (CLKPCE) auf 1 alle anderen auf 0, im zweiten 
Zugriff stellt man den Teilungsfaktor ein. Mit avr-gcc code sieht das 
etwa so aus:
1
  CLKPR = (1<<CLKPCE);
2
  CLKPR = 1;

Sofern man Code-Optimierung benutzt (gcc Schalter -Os), funktioniert das 
auch wie erwartet, verwendet man keine Optimierung (-O0), funktioniert 
es auf einmal nicht mehr. Der Faktor des clock prescalers wird einfach 
nicht geändert. Den Grund dafür kann man im Assemblerlisting finden.
Mit Optimierung erhält man:
1
  ldi r24,lo8(-128)   ;  tmp44,
2
  out 70-32,r24   ; ,, tmp44
3
  ldi r24,lo8(1)   ;  tmp46,
4
  out 70-32,r24   ; ,, tmp46

Ohne Optimierung wird daraus:
1
  ldi r24,lo8(70)   ;  D.2172,
2
  ldi r25,hi8(70)   ;  D.2172,
3
  ldi r18,lo8(-128)   ;  tmp54,
4
  movw r30,r24   ; , D.2172
5
  st Z,r18   ; , tmp54
6
  ldi r24,lo8(70)   ;  D.2173,
7
  ldi r25,hi8(70)   ;  D.2173,
8
  ldi r18,lo8(1)   ;  tmp55,
9
  movw r30,r24   ; , D.2173
10
  st Z,r18   ; , tmp55

Man erkennt direkt, dass die Zugriffe auf das Register CLKPR (das sind 
die Zeilen mit "st Z,r18") nicht mehr innerhalb von 4 Taktzyklen 
erfolgt.

Sofern man nicht auf die Optimierung zurückgreifen möchte, lässt sich 
das Problem umgehen, indem man den Zugriff per inline assembler 
realisiert:
1
  asm volatile (
2
    "st Z,%1" "\n\t"
3
    "st Z,%2"
4
    : :
5
    "z" (&CLKPR),
6
    "r" ((uint8_t) (1<<CLKPCE)),
7
    "r" ((uint8_t) 1)  // neuer Wert für CLKPR
8
  );

von MWS (Gast)


Lesenswert?

Um solcherlei zu umschiffen, gibt's in der power.h das Makro 
clock_prescale_set(x).

Und das hättest Du jetzt leichter rausgebracht, als diesen Aufsatz hier 
zu schreiben :D

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.