SAMC21 - change SYSTEM_OSC48M_DIV

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

The SAMC21 Xplained runs at 4MHz.  I would like to change to 48MHz if possible.

 

Does anyone have an example of changing the OSC48M to 48MHz?
 

Last Edited: Thu. Oct 15, 2015 - 11:31 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have have the Xplained board running at 48MHz, but it locks up on reset.  Had to change the divisor and flash wait states (as per the datasheet, electrical characteristics, NVM. I am sure I am missing something on the reset procedure.

 

It does 1,000,000 BAUD to my pc (PuTTY).  (best was 200,000 BAUD at 4MHz).

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

see my post in ASF  https://www.avrfreaks.net/forum/confclockh-different-different-examples-asf327

 

Using the conf_clock.h file from the CAN Example works and no reset problem. 

Last Edited: Thu. Sep 17, 2015 - 12:54 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
void SetupMainClock(void)
{
    //Enable the 32.768 khz external crystal oscillator
    REG_SYSCTRL_XOSC32K = (SYSCTRL_XOSC32K_ENABLE);
    REG_SYSCTRL_XOSC32K |= (SYSCTRL_XOSC32K_STARTUP(5) | SYSCTRL_XOSC32K_AAMPEN | SYSCTRL_XOSC32K_EN32K | SYSCTRL_XOSC32K_XTALEN | SYSCTRL_XOSC32K_ENABLE);
    
    //Wait for the crystal oscillator to start up
    while((REG_SYSCTRL_PCLKSR & (SYSCTRL_PCLKSR_XOSC32KRDY)) == 0);
    
    //Configure GCLK Generator 1 to use the 32k crystal as input, and feed this clock to the DFLL48M FLL
    REG_GCLK_GENDIV = ((1 << GCLK_GENDIV_DIV_Pos) | (1 << GCLK_GENDIV_ID_Pos));
    REG_GCLK_GENCTRL = ((1 << GCLK_GENCTRL_ID_Pos) | (GCLK_GENCTRL_SRC_XOSC32K) | (GCLK_GENCTRL_GENEN));
    REG_GCLK_CLKCTRL = ((GCLK_CLKCTRL_GEN_GCLK1) | (GCLK_CLKCTRL_CLKEN) | (GCLK_CLKCTRL_ID(0))) ;
    
    //Configure the FDLL48MHz FLL, we will use this to provide a clock to the CPU
    //Set the course and fine step sizes, these should be less than 50% of the values used for the course and fine values (P150)
    REG_SYSCTRL_DFLLCTRL = (SYSCTRL_DFLLCTRL_ENABLE); //Enable the DFLL
    REG_SYSCTRL_DFLLMUL = (SYSCTRL_DFLLMUL_CSTEP(5) | SYSCTRL_DFLLMUL_FSTEP(10)); 	
    REG_SYSCTRL_DFLLMUL |= (SYSCTRL_DFLLMUL_MUL(1465)); //1465 * 32768 is approx 48MHZ
    REG_SYSCTRL_DFLLCTRL |= (SYSCTRL_DFLLCTRL_MODE);
    
    //Wait and see if the DFLL output is good . . .
    while((REG_SYSCTRL_PCLKSR & (SYSCTRL_PCLKSR_DFLLLCKC)) == 0);
    
    //Set flash wait state to 1, which we need to do at 48MHz
    REG_NVMCTRL_CTRLB |= (NVMCTRL_CTRLB_RWS(1));
    
    //For generic clock generator 0, select the DFLL48 Clock as input
    REG_GCLK_GENDIV = ((1 << GCLK_GENDIV_DIV_Pos) | (0 << GCLK_GENDIV_ID_Pos));
    REG_GCLK_GENCTRL = ((0 << GCLK_GENCTRL_ID_Pos) | (GCLK_GENCTRL_SRC_DFLL48M) | (GCLK_GENCTRL_GENEN));
    REG_GCLK_CLKCTRL = ((GCLK_CLKCTRL_GEN_GCLK0) | (GCLK_CLKCTRL_CLKEN)) ;
}
Here is some non-asf code that I use on the SAMR21 for setting up the main clock for 48MHz, hopefully it can point you in the right direction.

If you're using ASF, neither of us know what your code is really doing :)
Have I just solved your problem ? My bitcoin address: 1EpGuPa2VtUVWjGmgWRmFicNKMFZSGhfLr

Last Edited: Thu. Sep 17, 2015 - 09:34 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks, I will study this.

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

Is there a way to set main clock to 48MHz without using an external crystal oscillator? Just setting divisor and wait states locks up on reset. I am a litte bit confused about this :D

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

Is there a way to set main clock to 48MHz without using an external crystal oscillator?

 I think you should be able to divide one of the internal clocks down to ~32kHz, and then multiply it back up to 48MHz with the PLL.  (the main trick is that you have to divide the clock way down first; you can't just multiple an 8MHz internal clock by 6 to get 48MHz, because the PLL input has restrictions.)

Here's a thread for code for a D10; it generates 48MHz (and other frequencies) from an 8MHz clock input, but I don't see any reason that it couldn't work with the 8MHz internal clock instead...

(not using ASF though, although that should be possible too.)

 

 

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

Thanks for the answer westfw.

I am using the SAM C21 which has 48 MHz internal clock. I can run at 24 MHz without any problems (Divisor = 2) but setting the divisor to 1 results in a lockup on reset. Do i have to go the same way u proposed (divide clock down to 32kHz and then multiply) or is there one secret setting i missing so far?

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

Ah; I don't think you should need anything fancy to just set the main clock to be the undivided 48MHz internal oscillator.

What code are you actually using?  ASF-based or raw registers?  (after all, doesn't the main clock default to using the 48MHz internal oscillator?  (but also zero wait states?  Hmm.))

 

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

I'm using an ASF-based Code. The default code was like this:

 

/* System clock bus configuration */
#  define CONF_CLOCK_FLASH_WAIT_STATES            0
#  define CONF_CLOCK_CPU_DIVIDER                  SYSTEM_MAIN_CLOCK_DIV_1

 

/* SYSTEM_CLOCK_SOURCE_OSC48M configuration - Internal 48MHz oscillator */
#  define CONF_CLOCK_OSC48M_FREQ_DIV              SYSTEM_OSC48M_DIV_12        
#  define CONF_CLOCK_OSC48M_ON_DEMAND             true
#  define CONF_CLOCK_OSC48M_RUN_IN_STANDBY        false

 

and I changed it to:

 

/* System clock bus configuration */
#  define CONF_CLOCK_FLASH_WAIT_STATES            2
#  define CONF_CLOCK_CPU_DIVIDER                  SYSTEM_MAIN_CLOCK_DIV_1

 

/* SYSTEM_CLOCK_SOURCE_OSC48M configuration - Internal 48MHz oscillator */
#  define CONF_CLOCK_OSC48M_FREQ_DIV              SYSTEM_OSC48M_DIV_1       
#  define CONF_CLOCK_OSC48M_ON_DEMAND             true
#  define CONF_CLOCK_OSC48M_RUN_IN_STANDBY        false

 

Thought this should be it but it's just working once....stoping Debuging and start it again leads to an error Message Waiting for device to reset...

Im new into working with microcontrollers. Do you think writing a raw register code could solve the problem? I will try this but im not sure if i am able to write in raw registers :D Thanks for your help :)

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

Is there anybody out there who got the SAM C21 running stable at 48 MHz from the internal 48MHz Oscillator? I am still stucked with this issue. It will work the first time but after stop and restart debugging or pressing the reset Button the device will be timed out. I found a note in the datasheet. Could this be the problem?

 

When a System Reset is applied, the OSC48MDIV register is reset, but the value is not synchronized. This may result in the system clock running too fast.

Errata reference: 14497

Fix/Workaround:

Do not write OSC48MDIV to lower than 0xB. Do not run the device faster than 4MHz when running from external oscillators

 

Best Regards

Makoja

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

I am having the same problem, it seems that the internal RC needs more clock cycles to stabilize than are available to configure... For me it is a hardware error. I will modify my project and put an external xt of 1Mhz and then multiply with the PLL.

 

Regards!
FS.

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

frog_jr has helped me with the same problem and I will post the solution here in case anyone needs. It set the internal RC to provide the GCLK with 48MHz, what have been impossible (at least for me) with ASF code (it only works with 24MHz)...

 

void ClocksInit(void) {
    // Set flash wait states for operation at 48 MHz @ 5V
    NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_RWS(1) | NVMCTRL_CTRLB_MANW;        //
     while ((OSCCTRL->STATUS.reg & OSCCTRL_STATUS_OSC48MRDY) == 0 );       // Wait until ready
 
    // Default setting for OSC48M
    OSCCTRL->OSC48MCTRL.reg = OSCCTRL_OSC48MCTRL_ONDEMAND | OSCCTRL_OSC48MCTRL_ENABLE;
    OSCCTRL->OSC48MDIV.reg = OSCCTRL_OSC48MDIV_DIV(1 - 1) | OSCCTRL_OSC48MCTRL_RUNSTDBY;   // 48MHz

    REG_OSCCTRL_OSC48MSTUP = 0x07;              // ~21uS startup
    while (OSCCTRL->OSC48MSYNCBUSY.reg);        // Wait until synced
    while ((OSCCTRL->STATUS.reg & OSCCTRL_STATUS_OSC48MRDY) == 0 );        // Wait until ready

    // Default setting for GEN0 (DIV => 0 & 1 are both 1)
    GCLK->GENCTRL[0].reg = GCLK_GENCTRL_SRC_OSC48M | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_DIV(1);    // 48MHz
    GCLK->GENCTRL[2].reg = GCLK_GENCTRL_SRC_OSC48M | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_DIV(6);    // 8MHz
}

Regards!
FS.