Reset frequency of SAMC21 clock not as expected

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

Hi all,

 

I've recently started using SAM MCUs, after a decade of using various AVRs - and have come a cropper pretty early on with clock setup (which seems to be fairly common!). I'm using a SAMC21 Xplained Pro board, with the SAMC21J18A. First order of business was to flash the onboard LED, without any help from START or ASF, as I feel blindly stumbling through with the use of START/ASF/CMSIS and not understanding the devices at register/bit level like I do with AVR is a road to nowhere.

 

I was expecting the below to toggle the onboard LED state at 0.4Hz (4MHz clock, 10M 'nop' loop). The LED flashes no problem, but at a ~12.5sec period.

 

The datasheet suggests I should have a 4MHz clock on start-up if I make no clock config changes

On any reset the synchronous clocks start to their initial state:
• OSC48M is enabled and divided by 12
• GCLK_MAIN uses OSC48M as source
• CPU and BUS clocks are undivided
On a power reset the GCLK starts to their initial state:
• All generic clock generators disabled except:
– The generator 0 (GCLK_MAIN) using OSC48M as source, with no division

 

int main(void)
{
    SystemInit();     /* Initialize the SAM system */
	REG_PORT_DIRSET0 = PORT_PA15;
	PORT->Group[0].PINCFG[PIN_PA15].bit.DRVSTR = 1;
	REG_PORT_OUTCLR0 = PORT_PA15;

    while (1){
	for (uint32_t n = 10000000; n > 0; n--){
		asm("nop");
	}
	REG_PORT_OUTTGL0 = PORT_PA15;
    }
}

 

FWIW, all 'SystemInit' that came pre-populated by Studio is doing, is setting the expected clock value of 4MHz into a variable.

 

/**
 * Initial system clock frequency. The System RC Oscillator (RCSYS) provides
 *  the source for the main clock at chip startup.
 */
#define __SYSTEM_CLOCK    (4000000)

uint32_t SystemCoreClock = __SYSTEM_CLOCK;/*!< System Clock Frequency (Core Clock)*/

/**
 * Initialize the system
 *
 * @brief  Setup the microcontroller system.
 *         Initialize the System and update the SystemCoreClock variable.
 */
void SystemInit(void)
{
        // Keep the default device state after reset
        SystemCoreClock = __SYSTEM_CLOCK;
        return;
}

Any ideas where I'm going wrong? Cheers.

This topic has a solution.
Last Edited: Tue. Oct 26, 2021 - 07:06 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That is not just executing 10 million NOPs.

The code (on my system) compiles to:

 1e0:	46c0      	nop			; (mov r8, r8)
 1e2:	3b01      	subs	r3, #1
 1e4:	2b00      	cmp	r3, #0
 1e6:	d1fb      	bne.n	1e0 <main+0x28>

 

 

 

David

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi David,

 

Thanks - same here... Just checked the ARMv6-M Thumb instruction set. Cycles per instruction; nop (1 cycle), subs (1 cycle), cmp (1 cycle) and bne (1, or 2? Footnote in the instruction set says "2 if taken, 1 if not-taken.").

 

So worst case, 1+1+1+2 = 5 cycles.

 

4MHz * 10s / 5 cycles = 8M cycles. This gives a 10sec period on the dot... thanks David. In hindsight, this was horribly obvious - it felt like I had to do be doing something wrong clock wise, given how many threads/videos/blog posts there are to do with configuring clocks.

 

 1d0:	46c0      	nop			; (mov r8, r8)
 1d2:	3b01      	subs	r3, #1
		for (uint32_t n = 1000000; n > 0; n--){
 1d4:	2b00      	cmp	r3, #0
 1d6:	d1fb      	bne.n	1d0 <main+0x24>

Though this does leave me with the question, what does "2 if taken, 1 if not-taken" mean in the instruction set documentation? https://developer.arm.com/docume...

 

Cheers

Last Edited: Tue. Oct 26, 2021 - 07:12 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jtw_11 wrote:
what does "2 if taken, 1 if not-taken"

BNE is a conditional branch - so it takes the branch, or not.

 

The timing is different if the branch is taken or not.

 

EDIT

 

Similar with AVRs

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Tue. Oct 26, 2021 - 08:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

jtw_11 wrote:
what does "2 if taken, 1 if not-taken"

BNE is a conditional branch - so it takes the branch, or not.

 

The timing is different if the branch is taken or not.

 

EDIT

 

Similar with AVRs

 

Got it, cheers. Fairly obvious with hindsight really...!