Forum: µC & Digital Electronics AVR clock prescaler (CLKPR) and gcc code optimization

von Peter-Jan P. (pjp)

Rate this post
-1 useful
not useful
Since I spend the last two days trying to get the clock prescaler to 
work I wanted to share my results. Everything I write here has been 
tested with an attiny2313. Anyway this problem exists with other AVR 
microcontrollers as well.

To set for clock prescaling factor it is necessary to access the CLKPR 
twice within 4 clock cycles. First you set the highest bit (CLKPCE) to 1 
and all others to 0. Then you write the actual value for CLKPR. avr-gcc 
code could look like this:
  CLKPR = (1<<CLKPCE);
  CLKPR = 1;

As long as code optimizatin is used (gcc option -Os) everything works as 
expected. If no optimization is used (-O0), the above code has no 
effect. The clock prescaling factor isn't changed. The reason for this 
can be found in the respective assembler code.
With optimization you get:
  ldi r24,lo8(-128)   ;  tmp44,
  out 70-32,r24   ; ,, tmp44
  ldi r24,lo8(1)   ;  tmp46,
  out 70-32,r24   ; ,, tmp46
without optimization this becomes
  ldi r24,lo8(70)   ;  D.2172,
  ldi r25,hi8(70)   ;  D.2172,
  ldi r18,lo8(-128)   ;  tmp54,
  movw r30,r24   ; , D.2172
  st Z,r18   ; , tmp54
  ldi r24,lo8(70)   ;  D.2173,
  ldi r25,hi8(70)   ;  D.2173,
  ldi r18,lo8(1)   ;  tmp55,
  movw r30,r24   ; , D.2173
  st Z,r18   ; , tmp55

Obviously the register access (the lines with "st Z,r18") is not done 
within 4 clock cycles.

If you do not want to use code optimization, you can circumvent the 
problem by using an inline assembler statement like this one:
  asm volatile (
    "st Z,%1" "\n\t"
    "st Z,%2"
    : :
    "z" (&CLKPR),
    "r" ((uint8_t) (1<<CLKPCE)),
    "r" ((uint8_t) 1)  // new CLKPR value

von MWS (Guest)

Rate this post
-1 useful
not useful
> Since I spend the last two days trying to get the clock prescaler to
> work I wanted to share my results.

Since you've spent two days senselessly, as you either forgot to, or you 
don't know how to read the documentation, there's a certain chance 
you'll do it next time more clever.

Anyway, it doesn't make you look smarter, if you post the same proof 
that you had blinders on, in English too.

Beitrag "AVR clock prescaler (CLKPR) und gcc-Codeoptimierung"

The solution is simple: use clock_prescale_set(x) from power.h

von DFA (Guest)

Rate this post
0 useful
not useful

I am new to ATMEL and found your posting here very helpful.  I do not 
bash people for not reading documentation or missing some particular 
part of the documentation.  I would not have known to go to a seemingly 
unrelated file like "power.h" to find out about setting the clock 

Keep up your good work here. I look forward to seeing what you discover.



Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]

Bild automatisch verkleinern, falls nötig
Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.