1

I've wrote a small program that runs on an XMEGA :

    #include <avr/io.h>
    #include <stdio.h>

    #ifndef F_CPU
    #define F_CPU 32000000UL
    #endif
    void system_clock_init(void){
        CCP = CCP_IOREG_gc;  /* allow changing CLK.CTRL */
        OSC.CTRL = OSC_RC32MEN_bm; /* Enabling the 32MHz RC oscillator */
        while (!(OSC.STATUS & OSC_RC32MRDY_bm)); /* wait for ready */
        CCP = CCP_IOREG_gc;/* allow changing CLK.CTRL */
        CLK.CTRL = CLK_SCLKSEL_RC32M_gc ;/* system clock is internal 32MHz RC */

    }

  int main (void)
    {
        // Insert system clock initialization code here (sysclk_init()).
       system_clock_init();
       PORTR.DIR = 0x02;

     while(1) {

        PORTR.OUTTGL = PIN1_bm;
    }
  }

the program should toggle an LED, but when I use the scope I measure a signal of 2ms , which mean that uC clock is : 1 MHz ?? which wonders me because I think that the program is correct ?

and idea what am I missing here ?

Bence Kaulics
  • 6,353
  • 12
  • 33
  • 60
Engine
  • 669
  • 2
  • 13
  • 29

2 Answers2

1

Check the assembly code generated, when you enable changes to clock system, you have a total of 4 CPU cycles to make the necessary writes (check the user guide for your particular XMEGA device). In my personal experience, I have seen that the compiler without any optimizations will produce code that takes more than 4 CPU to make the write the clock system registers. Try enabling optimizations to the code or make the changes to the clock system using in-line assembly.

Kvegaoro
  • 3,141
  • 17
  • 14
  • thanks for your answer. I'm new to this world so how can I black from optimizing the code ? – Engine Apr 16 '15 at 14:15
  • It depends on the IDE/toolchain you are using. I'm assuming that you are using Atmel studio in which case you would go to the project propeties, go to the toolchain tab, under AVR/GNU compiler, pick the optimization section, finally under the optimization level drop down, pick one of the available optimization options. – Kvegaoro Apr 16 '15 at 14:20
  • thanks a lot I think that the right way but it's not enough because now I have a period of 900us instead of 31,25 ns – Engine Apr 16 '15 at 14:32
  • Have you check what the clock pre-scaler defaults are your particular Xmega device??? – Kvegaoro Apr 16 '15 at 15:09
  • Also, are you sure you are looking at the correct units in your time measurements, because in your question you claim a 2ms period of your output signal but that gives 1/2ms = 500Hz, no where even close the the 1Mhz clock period you claim. Also the period of your signal if the micro was running at 32Mhz would not be 31.25ns but twice that, it takes 2 clock cycles to swing the pin hi and then low. – Kvegaoro Apr 16 '15 at 15:19
0

Well, I see a couple of possible issues here. The first is that you may be turning off the 2 MHz internal oscillator. You should use |= instead of just = when you enable that. The chip may be falling back on a 32 kHz internal oscillator as a result. This may not be the issue, but that's what I use in my 'standard' xmega init code (https://github.com/alexforencich/templates/blob/master/xmega.cpp/main.cpp#L126).

The other possible issue is that your init code is actually working fine, but the frequency measuring code is not working the way you expect. It's possible that loop takes several clock cycles to execute and this is throwing off your measurements. What I would recommend is using the _delay_ms or _delay_us functions to make a much longer delay - say, 500 ms - so it's very obvious which clock source you're running off of. With this setup, try commenting out the 32 MHz switchover and see if the blink frequency changes.

alex.forencich
  • 40,694
  • 1
  • 68
  • 109