XMEGA128A1U PLL setup help

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

I'm using XMEGA128A1U with 4MHz external crystal. I want to use PLL to increase the speed to 16MHz here is the code I've for setting PLL,

static inline void SYS_ConfigXtal(void)
{
    OSC.XOSCCTRL = (uint8_t) (OSC_FRQRANGE_2TO9_gc | OSC_X32KLPM_bm  |
                              OSC_XOSCSEL_XTAL_16KCLK_gc);

    OSC.CTRL |= OSC_XOSCEN_bm;

    while( (OSC.STATUS & OSC_XOSCRDY_bm) == 0 )
    {

    }

    sysclk_set_prescalers(CLK_PSADIV_1_gc, CLK_PSBCDIV_1_1_gc);//(CLK_PSADIV_1_gc, CLK_PSBCDIV_1_1_gc);                 /* prescale the peripheral clock to 4 MHz */
    sysclk_set_source(CLK_SCLKSEL_XOSC_gc);
// XOSC src for PLL, 2x.
    OSC.PLLCTRL = OSC_PLLSRC_XOSC_gc | (OSC_PLLFAC_gm & 4);//2
    // Enable PLL
    OSC.CTRL |= OSC_PLLEN_bm;
    // Wait until PLL ready
    while (!(OSC.STATUS & OSC_PLLRDY_bm))
        ;
    // PLL as system clock, unlock CLK.CTRL first
    CCP = CCP_IOREG_gc;
    CLK.CTRL = CLK_SCLKSEL_gm & CLK_SCLKSEL_PLL_gc;

    sysclk_lock();
}

But on board it gives 4MHz clock, it means PLL setting are not valid(?), where I'm doing wrong?

Thanks

Attachment(s): 

Last Edited: Fri. Aug 12, 2016 - 12:28 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

I didn't find any error, but I haven't looked too closely either. Anyway, here's a snippet that does the same and works for me:

 

    OSC_XOSCCTRL = OSC_XOSCSEL_XTAL_16KCLK_gc |	OSC_FRQRANGE_2TO9_gc;
	OSC.CTRL |= OSC_XOSCEN_bm;
	while(!(OSC.STATUS & OSC_XOSCRDY_bm));
	CCP = CCP_IOREG_gc;
	CLK.CTRL = CLK_SCLKSEL_XOSC_gc;

	OSC.PLLCTRL = OSC_PLLSRC_XOSC_gc | 4; //set multiplication factor here
	OSC.CTRL |= OSC_PLLEN_bm;
	while (!(OSC.STATUS & OSC_PLLRDY_bm));
	CCP = CCP_IOREG_gc;
	CLK.CTRL = CLK_SCLKSEL_PLL_gc;

I hope this helps.

 

Cheers,

Patrick

"Some people die at 25 and aren't buried until 75." -Benjamin Franklin

 

What is life's greatest illusion?"  "Innocence, my brother." -Skyrim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks pawi777,

Tried the code snippet shared by you but still it remains at 4MHz. 

Its working properly for the 4Mhz frequency even though above PLL settings is there.

Is it like PLL setting is locked and it works on the XTAL value that is 4MHz.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

May I ask how you measure the Clock frequency?

"Some people die at 25 and aren't buried until 75." -Benjamin Franklin

 

What is life's greatest illusion?"  "Innocence, my brother." -Skyrim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Easiest way to check clock frequency is to blink a led or toggle a pin with _delay_ms. Is it blinking at the rate you expected? 1/2 the rate you expected? 

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I know I can measure it using PD7 but in my case PC7/PD7 and PE7 all are connected to input signals. 

on board it is 4MHz crystal connected the other features on this are UART communication, frequency input etc.

previously everything was working fine for 4MHz configuration.

Now I changed the PLL settings and then changed the UART baud rate configuration according to 16MHz and it worked well for couple of days and now it again worked with the 4MHz settings.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I recommend you follow Torby's advice to measure the clock speed. Be sure to disable all interrupts and don't forget to define F_CPU globally since _delay_ms depends on it!

"Some people die at 25 and aren't buried until 75." -Benjamin Franklin

 

What is life's greatest illusion?"  "Innocence, my brother." -Skyrim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Pawi777 and Torby for suggestions.

Problem is that it has two firmware loaded one is boot loader which runs @4MHz and the other is application which was running correctly @4MHz.

when I changed frequency in application firmware @16MHz then it was not working as per expectations. After that I've erased the chip and loaded application only and it started working @16MHz.

Now, my question is that is it possible to have bootloader and application firmware running at diff clock speed?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

yes it is possible to run them at different clock speeds. In fact, you can change the PLL factor as you please throughout the program. The problem is however, that you have to keep track of you changes because all peripherals depend on the main clock. So you will have  to adjust the prescalers as well. My suggestion is to keep running all peripherals on 4 MHz (if it is enough for your application) and only change the CPU clock.

 

Cheers

"Some people die at 25 and aren't buried until 75." -Benjamin Franklin

 

What is life's greatest illusion?"  "Innocence, my brother." -Skyrim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My suggestion is to keep running all peripherals on 4 MHz (if it is enough for your application) and only change the CPU clock.

That is not possible.  CLKper and CLKcpu are always the same.  CLKper2 and CLKper4 can be configured to run at 2x and 4x CLKper, respectively. 

 

Greg Muth

Portland, OR, US

Xplained/Pro/Mini Boards mostly

 

Make Xmega Great Again!

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Greg_Muth wrote:

My suggestion is to keep running all peripherals on 4 MHz (if it is enough for your application) and only change the CPU clock.

That is not possible.  CLKper and CLKcpu are always the same.  CLKper2 and CLKper4 can be configured to run at 2x and 4x CLKper, respectively. 

 

 

You're right, my bad. I mixed something up. So one has to adjust the prescalers of each peripheral individually where this is necessary.

"Some people die at 25 and aren't buried until 75." -Benjamin Franklin

 

What is life's greatest illusion?"  "Innocence, my brother." -Skyrim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This random behavior is interesting. Do you have defined the fuse values inside source code?

 

Maybe the program somehow jumps to the bootloader because of a bug. You can try to make a very short sample code that reproduces the behavior. You can try to erase everything from your application except of the clock setup to see if it works then.
 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

PLL settings issue is resolved by changing PLL settings in boot loader firmware to 16MHz.

Now I've other issue with freq measurement. I want to measure freq 0-50kHz which is working fine for freq > 5Hz but I cannot read freq < 5Hz it varies between 0-4Hz.

Xtal is 4MHz and with PLL 4 it gives 16MHz clock freq.

for freq > 100Hz I'm using prescaler 4 which gives me 16MHz/4 - 4MHz and 0.25uSec time.

for freq < 100Hz I'm using prescaler 256 which gives me 16MHz/256 - 62.5Khz and 16uSec time.

for freq < 5Hz I'm using prescaler 1024 which gives me 16MHz/1024 - 1.5Khz and 64uSec time.

Here is the settings

#define RPM_TIMER_LOW_FRQ (0.000256000f)
#define RPM_TIMER_MID_FRQ (0.000016000f)
#define RPM_TIMER_HIGH_FRQ (0.000000250f)
static inline void DS_ConfigureRPM(void)
{
    sysclk_enable_module(SYSCLK_PORT_C, SYSCLK_TC0);
    sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_EVSYS);
    sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_DMA);

	PORTD.PIN0CTRL = PORT_ISC_RISING_gc;                                        /* Configure PORTD as input on PA6, sense on rising edge. */
    PORTD.DIRCLR   = PIN0_bm;
	

    EVSYS_SetEventSource( 0, EVSYS_CHMUX_PORTD_PIN0_gc );                       /* Select PD0 as event channel 1 multiplexer input. */
    EVSYS_SetEventChannelFilter( 0, EVSYS_DIGFILT_1SAMPLE_gc );

    TC_SetPeriod( &TCC0, 0xFFFF );//0xffff                                              /* 0x7FFF on PER enables edge direction sensing, if bit 15 is 1 then it is last rising, otherwise if 0 then calculate period using last rising edge */
	TC0_ConfigInputCapture( &TCC0,  TC_EVSEL_CH0_gc, TC_EVACT_FRQ_gc);          /* Set timer to do a freq capture, on event channel 0 */
	TC0_EnableCCChannels(&TCC0, TC0_CCAEN_bm);
    TC_SetCount(&TCC0, 0);
    TC0_ConfigClockSource( &TCC0, TC_CLKSEL_DIV256_gc);//64_gc );

    TC0_SetOverflowIntLevel( &TCC0, TC_OVFINTLVL_OFF_gc );

	dma_enable();

	dma_channel_set_single_shot(&DS_RpmDmaChl);
	dma_channel_set_burst_length(&DS_RpmDmaChl, DMA_CH_BURSTLEN_2BYTE_gc);
	dma_channel_set_src_reload_mode(&DS_RpmDmaChl, DMA_CH_SRCRELOAD_BURST_gc );
	dma_channel_set_dest_reload_mode(&DS_RpmDmaChl, DMA_CH_DESTRELOAD_BLOCK_gc);
	dma_channel_set_src_dir_mode(&DS_RpmDmaChl, DMA_CH_SRCDIR_INC_gc);
	dma_channel_set_dest_dir_mode(&DS_RpmDmaChl, DMA_CH_DESTDIR_INC_gc);
	dma_channel_set_trigger_source(&DS_RpmDmaChl, DMA_CH_TRIGSRC_TCC0_CCA_gc);
	dma_channel_set_transfer_count(&DS_RpmDmaChl, (DS_FRQ_BUFF_LEN*2));
	//dma_channel_set_repeats(&DS_RpmDmaChl, 0);
	dma_channel_set_destination_address(&DS_RpmDmaChl, (U16)&DS_PulseFreqBuff[0]);
	dma_channel_set_source_address(&DS_RpmDmaChl, (U16)&TCC0.CCA);
	dma_channel_set_interrupt_level(&DS_RpmDmaChl, DMA_INT_LVL_OFF);

    DS_EnableRPM();
}

for diff freq configuration changes accordingly,

switch(DS_RPMTimerFreqMode)
    {
        case RPM_HIGH_MODE:
        {
            if( DS_RPMPulseFreq <= RPM_MODE_FREQ_MED )//freq <100Hz
            {
                TC0_ConfigClockSource( &TCC0, TC_CLKSEL_OFF_gc );
                TC_SetCount(&TCC0, 0);
				TC_SetPeriod( &TCC0, 0xFFFF );
                TC0_ConfigClockSource( &TCC0, TC_CLKSEL_DIV256_gc);//256//1024//64_gc );
                DS_RPMTimerFeq = RPM_TIMER_MID_FRQ;
                DS_RPMTimerFreqMode = RPM_MID_MODE;
                modechange = ENABLE;
            }
            break;
        }
        case RPM_MID_MODE:
        {
            if ( DS_RPMPulseFreq >= RPM_MODE_FREQ_HIGH )//Freq >100Hz
            {
                TC0_ConfigClockSource( &TCC0, TC_CLKSEL_OFF_gc );
                TC_SetCount(&TCC0, 0);
				TC_SetPeriod( &TCC0, 0xFFFF );
                TC0_ConfigClockSource( &TCC0, TC_CLKSEL_DIV4_gc); ////4//1_gc );
                DS_RPMTimerFeq = RPM_TIMER_HIGH_FRQ;
                DS_RPMTimerFreqMode = RPM_HIGH_MODE;
                modechange = ENABLE;
            }
            else if(DS_RPMPulseFreq <= RPM_MODE_FREQ_LOW) // freq < 5Hz
            {
                TC0_ConfigClockSource( &TCC0, TC_CLKSEL_OFF_gc );
                TC_SetCount(&TCC0, 0);
				TC_SetPeriod( &TCC0, 0xFFFF );
                TC0_ConfigClockSource( &TCC0, TC_CLKSEL_DIV1024_gc );
                DS_RPMTimerFeq = RPM_TIMER_LOW_FRQ;
                DS_RPMTimerFreqMode = RPM_LOW_MODE;
			    modechange = ENABLE;
            }
            break;
        }
        case RPM_LOW_MODE: // freq > 5Hz
        {
            if ( DS_RPMPulseFreq >= RPM_MODE_FREQ_LOW )
            {
                TC0_ConfigClockSource( &TCC0, TC_CLKSEL_OFF_gc );
                TC_SetCount(&TCC0, 0);
				TC_SetPeriod( &TCC0, 0xFFFF );
                TC0_ConfigClockSource( &TCC0, TC_CLKSEL_DIV256_gc); //256//1024//64_gc );
                DS_RPMTimerFeq = RPM_TIMER_MID_FRQ;
                DS_RPMTimerFreqMode = RPM_MID_MODE;
                modechange = ENABLE;
            }
            break;
        }
    }

Please suggest how I can configure it for reading 5Hz freq.