How do I get 120MHz cpu speed using crystal on the ATSAMD51

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

I'm planning on buying the ATSAMD51 series chip specifically the (ATSAMD51J20A-AU 64-pin) chip. I see it has an internal clock which I think is 48MHz if I'm understanding the data sheet correctly but I want to use the full 120MHz CPU speed.

 

The data sheet on the clock is by far amazingly complicated, I've been at this for over 3 or 4 hours and I can't make heads or tails of any of this. There's like a hundred variables over the clock, timers, inputs, outputs, multiplies, dividers, integers, fractions, open and closed loops. I'm more lost than I've ever been.

 

Like I said I just want to have the CPU run at 120MHz and I understand I have to buy a low powered crystal and pipe it through and have it multiplied using the chip's internal multiplier and do this other stuff to get the CPU at 120MHz.

 

What do I need to buy? Where do I need to hook it up? and What settings do I need to set to get the 120MHz CPU speed?

 

Because I'm completely and utterly loss trying to make anything out of the data sheet.

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

In theory, you can multiply the internal 32kHz and get 120MHz with no crystal at all.

 

See https://github.com/adafruit/ArduinoCore-samd/blob/master/cores/arduino/startup.c#L57

(While you're there, check out their schematics for SAMD51 boards as well.  ("Metro M4" and "Feather M4" have 64pins chips.  "ItsyBitsy M4" has a 48pin chip, "Grand Central" has the BIG chip.)

 

They seem to work.  Buy a board, and you'll have something that you can poke at with a scope to see if it's behaving the same as your own board.  (I'm all for "design your own board."  But at the same time, if there exists something cheap, accessible, and known to work, it seems wise to use it as an example...)

 

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

Thank you very much for the helpful reply! You said in theory it can be used, would it be advised to test that theory or be safe and get a crystal. The link you provided they use a 32K crystal but I'm not sure if that's for the cpu speed or an rtc counter. I don't mind buying a crystal I just don't have any idea which of the 3 oscillators to hook it into nor what speed of an oscillator or if it would take more than 1 oscillator. Also the oscillator code in the link looks like a huge garbled cryptic mess - why is a simple oscillator so extremely complicated. I still can't make heads or tails of this.

 

Like these are about half the clock/timer/oscillator variables and I'm still uncovering more littered across the manual and I have no idea how to just simply say "Hey, use a 120MHz for the CPU and you can get help from this oscillator"

XOSC0 VDDIO 
	XIN PA14
	XOUT PA15
XOSC1 VDDIO 
	XIN PB22
	XOUT PB23

DFLL
FDPLL0
FDPLL1

CLK_XOSC0
CLK_XOSC1
CLK_DFLL48M
CLK_DPLL0
CLK_DPLL1

XOSC32K VSWOUT 
	XIN32 PA00
	XOUT32 PA01
XOSC32K
OSCULP32K

 

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

But if you think it'd be better to skip the oscillator I'm also fine with that. I'm literally not using it for anything else, I'm not using USB or any devices or components that all need to be on the same clock so the oscillator if I got it would only ever be used for the CPU speed alone. Skipping it would simplify things if I can still get the 120MHz speed.

 

However we still have a cluster wreck of registers and settings to to multiple the clock speed. I still have little idea how to even do the multiplication or select the CPU speed or clock source and will have to carefully review the link you provided multiple times to understand some of it because there's just so many registers all for the clock speed and I can't tell which is which and they're all very cryptic. Even a Youtube video some a blog post that simplifies things and breaks them down would be amazingly helpful, anything but the data sheet.

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

Welcome to the world of modern microcontrollers! As westfw suggested, look at the arduino core code to see how they do it or you can look at the Atmel example projects. What you need to be aware of is that these might expect an external crystal. I would suggest you have a good look at these sources to get a feel of how it all works.
I would also suggest you start with a commercially available board first like an xplained. You get the debugger as well - you’ll need this. If you think setting up the clocks is tricky, then designing a pcb for these chips is even trickier - component selection, layout and placement is critical. The pcb is not simply an interconnect.

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

I think I'm slowly beginnign to understand this. It's still a cryptic wreck but I'm understanding more the different moving parts. Also the Metro M4 uses a 100-pin board, the feather is the closest to the processor I want which is idential in all except the flash memory (Has half the memory), outside of that the processor on the feather is identical and something I can more closely look as an example.

 

I can see all they use is one 32K crystal which tells me enough, they pipe the crystal in through a few moving parts including a multiplier and 2 of the generators one of which is the CPU clock cycle speed (Generator 0). So I'm understanding all this more but this is really honestly a lot more than I expected for a clock and is quite complex with a hundred or so registers, modules, ports, wires, etc... It's going to take me a good minute to understand any of this but buying a dev board or an adafruit feather m4 is a good idea. Also knowing that it's just one crystal - the 32K crystal is really helpful along with open hardware schematics and such so I can see how they use mostly the same chip (Extremely helpful).

 

Thank you guys so much for the help!

 

On a side note this brings me back to the days of programming for the Gameboy systems, although the complexity was only a fraction of this chip there were nonetheless many moving and sometimes cryptic parts all accessed via a unified address with lots of initial setup required before doing anything.

 

I am designing a pcb board with much help from the data sheet for a project I have in mind but I'm also taking my time with it because I want more hands on experience with the micro-controller and an already designed board before I jump into a custom board for the project I have in mind.

Last Edited: Sat. Aug 10, 2019 - 01:22 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The Adafruit code uses either the internal 32kHz oscillator (preprocessor symbol CRTSYTALLESS), or an external 32kHz crystal (32768Hz, actually - a common watch crystal.)

The "itsyBitsy" runs without a crystal...

(By using a crystal that matches the internal oscillator speed, they get to share all of the PLL/Multiplier code, just by selecting either the internal or external 32kHz.)

 

The SAM chips make it relatively safe to play with the clock source - unlike AVRs, you can't brick the chip by selecting the wrong clock - they ALWAYS start running on one of the internal clocks, and need explicit programming to switch.  The usual logic is something like:

 

  1. Chip resets, runs the default clock on GCLK0 (GCLK0 being the "main system clock")  (48MHz internal DFLL clock, undivided, for SAMD51)
  2. User code picks some other oscillator (higher precision, and/or matching the input requirements of the DFLL/DPLL)  Configure that oscillator and wait for it to start, on some other GCLK (The Adafruit code uses GCLK3)
  3. temporarily set GCLK0 to some other clock.   CPU is now running off of "other clock."
  4. Set up the DFLL or DPLL to multiple the clock set up in (2) to your desired frequency.  IIRC, there are some limitations on the output frequency of these features - DFLL always wants to output 48MHz,  DPLL has a larger range (96 to 200MHz on SAMD51) and there are also in the input references frequencies.  So for some SAMD10 experiments I did, there was an 8MHz input clock, which had to be divided down to an interim clock of 32kHz that the PLL needed, and then multipled by (2*F_CPU/F_INTERM) to get twice the CPU frequency (96MHz), and the divided by 2 to stay within allowed F_CPU...  Wait for the clock to be stable.
  5. So now the DPLL or DFLL is outputing the desired F_CPU, but it's not actually going anywhere.  That's fine...
  6. Set up appropriate Flash memory wait states.  Enable the cache memory if desired.
  7. Reconfigure GCLK0 to use the Fast clock.
  8. Configure some other GCLKs to "desirable" frequencies.  Adafruit has 120MHz on GCLK0, 48MHz (needed by USB?) on GCLK1, 100MHz on GCLK2, and the 32kHz on GCLK3.
  9. Turn on the clocks for the peripherals that you'll be using.

 

Info about this, of course, is spread out over half-a-dozen sections of the datasheet :-(  ("Clock System", "GCLK", "MCLK", "OSCCTRL", "OSC32KCTRL" - Oh, only 5?)

The last time I looked, ASF and Start didn't really make this much easier, and took a lot of code to do it.   :-(

 

 

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

Even if you don't want to use Atmel Studio, Atmel START gives you a nice interface to configure the clock sources, PLLs etc. You generate the project and upload it to your board for testing. Once you are happy with the configuration you can move over to you favorite IDE and copy just the initialization code from the Atmel START project.

 

I use 32k external XTAL, if you are designing custom PCB for the project then you should design in the XTAL and the 2 capacitors, later you can decide to use it or not!

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

They both sound worth investigating. Literally anything to make the clock stuff easier is a huge help. I understand if I'm wanting to do some pretty complex stuff with the clock sources and everything but if all I'm wanting to do is crank up the speed to 120MHz then I can settle with simplifying things as much as possible. I'll definitely look at both and the PCB tip. Thanks for the help.

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

sukuwc wrote:
Even if you don't want to use Atmel Studio, Atmel START gives you a nice interface to configure the clock sources, PLLs etc.

 

No argument from me.  I recommended START in another thread from the OP.

 

https://start.atmel.com/

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

I don't know if you are still searching for Initializing the clock at 120 MHZ but here my code to do it.  I made a LOOOOOT  of work and research to be able to clock it at this speed.  There is so many registers to configure, that's insane.  This is clocked from Internal.   There is some commented code, you can experiment with.  Good Luck!

 

Cedric

 

 

void ClockInitInt(void)
{
	//uint32_t PLLRATIO=4060;	//3730;  //122.776 MHZ
	uint32_t PLLRATIO=4061;	//3730;  //122.776 MHZ

	//Initialisation for 120 MHz (Or any speed you want, this code is set to 120 MHz) from the internal 32KHz Oscillator.

	// CONFIGURE FLASH MEMORY WAIT STATES
//	NVMCTRL->CTRLA.bit.RWS = 6; // 4WS allows up to 119 MHz, 5WS allows 120 MHz
	NVMCTRL->CTRLA.bit.RWS = 4; // 4WS allows up to 119 MHz, 5WS allows 120 MHz
	NVMCTRL->CTRLA.bit.AUTOWS = 0; // automatically determine the necessary wait states

//	NVMCTRL->CTRLA.bit.CACHEDIS0 = 1; // cache
//	NVMCTRL->CTRLA.bit.CACHEDIS1 = 1; // cache

	CMCC->CTRL.bit.CEN=0;			//Cache Disable //1=Enabled

	// CONFIGURE EXTERNAL 32K CRYSTAL OSCILLATOR
//	OSC32KCTRL->XOSC32K.bit.CGM = 1; // control gain mode: 1 = standard/XT 2 = high-speed/HS
//	OSC32KCTRL->XOSC32K.bit.STARTUP = 0; // oscillator startup time, 0 = 62 ms
//	OSC32KCTRL->XOSC32K.bit.ONDEMAND = 0; // always run
//	OSC32KCTRL->XOSC32K.bit.XTALEN = 1; // enable crystal driver circuit for XIN32/XOUT32 pins
//	OSC32KCTRL->XOSC32K.bit.EN32K = 1; // enable the 32 kHz output clock
//	OSC32KCTRL->XOSC32K.bit.ENABLE = 1;
//	while (!OSC32KCTRL->STATUS.bit.XOSC32KRDY); // wait until crystal oscillator is stable and ready to be used as a clock source
//	OSC32KCTRL->RTCCTRL.bit.RTCSEL = OSC32KCTRL_RTCCTRL_RTCSEL_XOSC32K_Val; // RTC should use the external 32K crystal

	// CONFIGURE MASTER CLOCK
	MCLK->CPUDIV.bit.DIV = 1; // use a divisor of 1 for the master clock

	//Configure ClockGen1 for PLL INTERNAL
	GCLK->GENCTRL[1].bit.SRC=4;     //Internal 32KHz Oscillator.
	GCLK->GENCTRL[1].bit.DIV = 1; // divisor 1 for the input clock from the PLL
	GCLK->GENCTRL[1].bit.GENEN = 1;

	GCLK->PCHCTRL[1].bit.GEN = 1;  //PERIPHERAL 1
	GCLK->PCHCTRL[1].bit.CHEN = 1;  //ENABLE CHANNEL

	// CONFIGURE PLL0
	OSCCTRL->Dpll[0].DPLLCTRLB.bit.REFCLK= 0; // use GCLK as the PLL reference clock
	OSCCTRL->Dpll[0].DPLLRATIO.reg = (3<<16) + PLLRATIO;  //3661; //3455; //113.273 MHZ.  multiply OSC32K by 3662.11 to get 120 MHz (actual multiplier is LDR + 1 + LDRFRAC/32)  3661
	//OSCCTRL->Dpll[0].DPLLRATIO.reg = (3<<16) + 1464; // multiply OSC32K by 1464 to get 48 MHz (actual multiplier is LDR + 1 + LDRFRAC/32)  1464

	// errata: When using a low-frequency input clock on FDPLLn, several FDPLL unlocks may occur while the output
	// frequency is stable. Workaround: when using a low-frequency input clock on FDPLLn, enable the lock bypass
	// feature to avoid FDPLL unlocks.
	OSCCTRL->Dpll[0].DPLLCTRLB.bit.LBYPASS = 1; // CLK_DPLL0 output clock is always on, and not dependent on frequency lock
	OSCCTRL->Dpll[0].DPLLCTRLA.bit.ONDEMAND = 0; // always run
	OSCCTRL->Dpll[0].DPLLCTRLA.bit.ENABLE = 1;

	while (!OSCCTRL->Dpll[0].DPLLSTATUS.bit.LOCK) ; // no point in checking DPLLSTATUS.bit.CLKRDY, because LBYPASS is enabled

	// CONFIGURE CLOCK GENERATOR 0
	GCLK->GENCTRL[0].bit.SRC = 7; // use PLL0 as the input
	GCLK->GENCTRL[0].bit.DIV = 1; // divisor 1 for the input clock from the PLL
	GCLK->GENCTRL[0].bit.GENEN = 1;

	// do peripheral clock initialization here...
}

 

Last Edited: Mon. Oct 14, 2019 - 09:51 PM