Beispiel #1
0
/**
 * \brief Set default clock (MCK = 24MHz).
 */
static void set_default_working_clock(void)
{
#if (SAMG)
	/* Switch MCK to slow clock  */
	pmc_switch_mck_to_sclk(PMC_MCKR_PRES_CLK_1);

	/*
	 * Configure PLL and switch clock.
	 * MCK = XTAL * (PLL_DEFAULT_MUL+1) / PLL_DEFAULT_DIV / MCK_DEFAULT_DIV
	 *     = 24 MHz
	 */
	example_switch_clock(PLL_DEFAULT_MUL, PLL_COUNT, PLL_DEFAULT_DIV,
			MCK_DEFAULT_DIV);
#else
	/* Switch MCK to slow clock  */
	pmc_switch_mck_to_sclk(PMC_MCKR_PRES_CLK_1);

	/* Switch mainck to external xtal */
	pmc_switch_mainck_to_xtal(0, BOARD_OSC_STARTUP_US);

	/*
	 * Configure PLL and switch clock.
	 * MCK = XTAL * (PLL_DEFAULT_MUL+1) / PLL_DEFAULT_DIV / MCK_DEFAULT_DIV
	 *     = 24 MHz
	 */
	example_switch_clock(PLL_DEFAULT_MUL, PLL_COUNT, PLL_DEFAULT_DIV,
			MCK_DEFAULT_DIV);

	/* Disable unused clock to save power */
	pmc_osc_disable_fastrc();
#endif

	/* Save current clock */
	g_ul_current_mck = 24000000; /* 24MHz */
}
Beispiel #2
0
/**
 * Restore clock settings
 */
__always_inline static void pmc_restore_clock_setting(
		uint32_t osc_setting,
		uint32_t pll0_setting,
		uint32_t pll1_setting,
		uint32_t mck_setting)
{
	uint32_t mckr;
	uint32_t pll_sr = 0;

	/* Switch MCK to slow clock  */
	pmc_switch_mck_to_sclk(PMC_MCKR_PRES_CLK_1);
	/* Switch mainck to external xtal */
	if (CKGR_MOR_MOSCXTBY == (osc_setting & CKGR_MOR_MOSCXTBY)) {
		/* Bypass mode */
		pmc_switch_mainck_to_xtal(PMC_OSC_BYPASS,
			pmc_us_to_moscxtst(BOARD_OSC_STARTUP_US,
				CHIP_FREQ_SLCK_RC));
		pmc_osc_disable_fastrc();
	} else if (CKGR_MOR_MOSCXTEN == (osc_setting & CKGR_MOR_MOSCXTEN)) {
		/* External XTAL */
		pmc_switch_mainck_to_xtal(PMC_OSC_XTAL,
			pmc_us_to_moscxtst(BOARD_OSC_STARTUP_US,
				CHIP_FREQ_SLCK_RC));
		pmc_osc_disable_fastrc();
	}

	if (pll0_setting & CKGR_PLLAR_MULA_Msk) {
		PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | pll0_setting;
		pll_sr |= PMC_SR_LOCKA;
	}
#if (SAM3S || SAM4S)
	if (pll1_setting & CKGR_PLLBR_MULB_Msk) {
		PMC->CKGR_PLLBR = pll1_setting;
		pll_sr |= PMC_SR_LOCKB;
	}
#elif (SAM3U || SAM3XA)
	if (pll1_setting & CKGR_UCKR_UPLLEN) {
		PMC->CKGR_UCKR = pll1_setting;
		pll_sr |= PMC_SR_LOCKU;
	}
#else
	UNUSED(pll1_setting);
#endif
	/* Wait MCK source ready */
	switch(mck_setting & PMC_MCKR_CSS_Msk) {
	case PMC_MCKR_CSS_PLLA_CLK:
		while (!(PMC->PMC_SR & PMC_SR_LOCKA));
		break;
#if (SAM3S || SAM4S)
	case PMC_MCKR_CSS_PLLB_CLK:
		while (!(PMC->PMC_SR & PMC_SR_LOCKB));
		break;
#elif (SAM3U || SAM3XA)
	case PMC_MCKR_CSS_UPLL_CLK:
		while (!(PMC->PMC_SR & PMC_SR_LOCKU));
		break;
#endif
	}

	/* Switch to faster clock */
	mckr = PMC->PMC_MCKR;
	/* Set PRES */
	PMC->PMC_MCKR = (mckr & ~PMC_MCKR_PRES_Msk)
		| (mck_setting & PMC_MCKR_PRES_Msk);
	while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
	/* Set CSS and others */
	PMC->PMC_MCKR = mck_setting;
	while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
	/* Waiting all restored PLLs ready */
	while (!(PMC->PMC_SR & pll_sr));
}
Beispiel #3
0
/**
 * \brief Change clock configuration.
 *
 * \param p_uc_str Hint string to be output on console before changing clock.
 */
static void user_change_clock(uint8_t *p_uc_str)
{
	uint8_t uc_key;
	uint32_t ul_id;

	/* Print menu */
	puts(CLOCK_LIST_MENU);

	while (uart_read(CONSOLE_UART, &uc_key)) {
	}
	printf("Select option is: %c\n\r\n\r", uc_key);
	if (p_uc_str) {
		puts((char const *)p_uc_str);
	}

	while (!uart_is_tx_empty(CONSOLE_UART)) {
	}

	if ((uc_key >= MIN_CLOCK_FAST_RC_ITEM) &&
			(uc_key <= MAX_CLOCK_FAST_RC_ITEM)) {
		ul_id = uc_key - MIN_CLOCK_FAST_RC_ITEM;

		/* Save current clock */
		g_ul_current_mck = g_fastrc_clock_list[ul_id][0];

		/* Switch MCK to Slow clock  */
		pmc_switch_mck_to_sclk(PMC_MCKR_PRES_CLK_1);

		/* Switch mainck to fast RC */
		pmc_osc_enable_fastrc(CKGR_MOR_MOSCRCF_8_MHz);
		pmc_switch_mainck_to_fastrc(g_fastrc_clock_list[ul_id][1]);

		/* Switch MCK to mainck */
		pmc_switch_mck_to_mainck(g_fastrc_clock_list[ul_id][2]);

		/* Disable unused clock to save power */
		pmc_osc_disable_xtal(0);
		example_disable_pll();

	} else if ((uc_key >= MIN_CLOCK_PLL_ITEM) &&
			(uc_key <= MAX_CLOCK_PLL_ITEM)) {
		ul_id = uc_key - MIN_CLOCK_PLL_ITEM;

		/* Save current clock */
		g_ul_current_mck = g_pll_clock_list[ul_id][0];

#if (SAMG)
		/* Switch MCK to main clock  */
		pmc_switch_mck_to_mainck(PMC_MCKR_PRES_CLK_1);
#else
		/* Switch MCK to slow clock  */
		pmc_switch_mck_to_sclk(PMC_MCKR_PRES_CLK_1);

		/* Switch mainck to external xtal */
		pmc_switch_mainck_to_xtal(0, BOARD_OSC_STARTUP_US);
#endif
		/* Configure PLL and switch clock */
		example_switch_clock(g_pll_clock_list[ul_id][1], PLL_COUNT,
				g_pll_clock_list[ul_id][2], g_pll_clock_list[ul_id][3]);

#if (!SAMG)
		/* Disable unused clock to save power */
		pmc_osc_disable_fastrc();
#endif
	} else {
		puts("Clock is not changed.\r");
	}
}
/**
 * \brief Application entry point for pmc_clock switch example.
 *
 * \return Unused (ANSI-C compatibility).
 */
int main(void)
{
	/* Initialize the SAM system */
	sysclk_init();
	board_init();

	/* Initialize the console uart */
	configure_console();

	/* Output example information */
	puts(STRING_HEADER);

	/* Configure PCK */
	ioport_set_pin_mode(GCLK_PIN, GCLK_PIN_MUX);
	ioport_disable_pin(GCLK_PIN);

	/* Configure the push button */
	configure_buttons();

	puts("-I- Press Button "BUTTON_NAME" to continue.\r\n");
	/* Wait for UART transmit done */
	while (!uart_is_tx_empty(CONF_UART)) {
	};
	for (gs_uc_wait_button = 1; gs_uc_wait_button;) {
	}

	puts("\n\r-I- Switch 8Mhz fast RC oscillator to be the source of the main clock \n\r"
			"-I- The master clock is main clock divided by 2\n\r"
			"-I- From now on, the UART baud rate is 2400bps. So please change the terminal setting before the next clock switch\r\n"
			"-I- Press Button "BUTTON_NAME" to switch next clock configuration... \r\n");
	/* Wait for UART transmit done */
	while (!uart_is_tx_empty(CONF_UART)) {
	};

	/* First switch to slow clock */
	pmc_switch_mck_to_sclk(PMC_MCKR_PRES_CLK_1);

#if (SAM3S || SAM4S || SAM4C)
	/* Then cut the PLL B */
	pmc_disable_pllbck();
#endif

	/* Switch the mainck clock to the Fast RC, parameter '1' stands for 8Mhz */
	pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_8_MHz);

	/* And finalize by switching to Fast RC */
	pmc_switch_mck_to_mainck(PMC_MCKR_PRES_CLK_2);

	/* The clock source for the UART is the PCK, so the uart needs re-configuration */
	config_uart_and_pck(PMC_PCK_CSS_MAIN_CLK, PMC_PCK_PRES_CLK_2,
			(CHIP_FREQ_MAINCK_RC_8MHZ / 2));

	for (gs_uc_wait_button = 1; gs_uc_wait_button;) {
	}

	puts("\n\r-I- Switch the XTAL 32K crystal oscillator to be the source of the slow clock\n\r"
			"-I- The master clock is slow clock\n\r"
			"-I- Press Button "BUTTON_NAME" to switch next clock configuration after it has been measured.\r\n");
	/* Wait for UART transmit done */
	while (!uart_is_tx_empty(CONF_UART)) {
	};

	/* Enable the External 32K oscillator */
	pmc_switch_sclk_to_32kxtal(PMC_OSC_XTAL);

	/* If a new value for CSS field corresponds to Main Clock or Slow Clock,
	 * program the CSS field first.
	 */
	pmc_switch_mck_to_sclk(PMC_MCKR_PRES_CLK_1);

	/* The clock source for the UART is the PCK, so the uart needs
	 *re-configuration.
	 */
	config_uart_and_pck(PMC_PCK_CSS_SLOW_CLK, PMC_PCK_PRES_CLK_1,
			BOARD_FREQ_SLCK_XTAL);

	for (gs_uc_wait_button = 1; gs_uc_wait_button;) {
	}

	/* Switch the mainck to the Fast RC, parameter '2' stands for 12Mhz */
	pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_12_MHz);

	/* If a new value for CSS field corresponds to Main Clock or Slow Clock,
	 * program the CSS field first.
	 */
	pmc_switch_mck_to_mainck(PMC_PCK_PRES_CLK_1);

	/* The clock source for the UART is the PCK, so the uart needs
	 * re-configuration.
	 */
	config_uart_and_pck(PMC_PCK_CSS_MAIN_CLK, PMC_PCK_PRES_CLK_1,
			CHIP_FREQ_MAINCK_RC_12MHZ);
	puts("\n\r-I- Switch 12Mhz fast RC oscillator to be the source of the main clock\n\r"
			"-I- The master clock is the main clock\n\r"
			"-I- Press Button "BUTTON_NAME" to switch next clock configuration after it has been measured.\r\n");

	for (gs_uc_wait_button = 1; gs_uc_wait_button;) {
	}
#if SAM4C
	puts("-I- Switch to 8.192Mhz PLLA clock as the source of the master clock \n\r"
			"-I- The master clock is PLLA clock divided by 2 \n\r"
			"-I- Press Button "BUTTON_NAME" to switch next clock configuration... \r\n");
	/* Wait for UART transmit done */
	while (!uart_is_tx_empty(CONF_UART)) {
	};

	/* Enable the PLLA clock, the mainck equals 32.768K * 250 = 8.192Mhz */
	pmc_enable_pllack((250 - 1), 0x3f, 1);
#else
	puts("-I- Switch to 128Mhz PLLA clock as the source of the master clock \n\r"
			"-I- The master clock is PLLA clock divided by 2 \n\r"
			"-I- Press Button "BUTTON_NAME" to switch next clock configuration... \r\n");
	/* Wait for UART transmit done */
	while (!uart_is_tx_empty(CONF_UART)) {
	};

	/* Enable the PLLA clock, the mainck equals 12Mhz * (32-1+1) / 3 = 128Mhz */
	pmc_enable_pllack((32 - 1), 0x3f, 3);
#endif
	/* If a new value for CSS field corresponds to PLL Clock, Program the PRES
	 * field first.
	 */
	pmc_switch_mck_to_mainck(PMC_MCKR_PRES_CLK_2);

	/* Delay for a while */
	/* Wait for UART transmit done */
	while (!uart_is_tx_empty(CONF_UART)) {
	};

	/* Then program the CSS field. */
	pmc_switch_mck_to_pllack(PMC_MCKR_PRES_CLK_2);

	/* The clock source for the UART is the PCK, so the uart needs
	 * re-configuration
	 */
	config_uart_and_pck(PMC_PCK_CSS_PLLA_CLK, PMC_PCK_PRES_CLK_2,
			PMC_CLOCK_SWITCHING_EXAMPLE_FIXED_PLLA/2);

	for (gs_uc_wait_button = 1; gs_uc_wait_button;) {
	}

	puts("\n\r-I- Switch the XTAL 32K crystal oscillator to be the source of the slow clock\n\r"
			"-I- The master clock is slow clock\n\r"
			"-I- Press Button "BUTTON_NAME" to switch next clock configuration...\r\n");
	/* Wait for UART transmit done */
	while (!uart_is_tx_empty(CONF_UART)) {
	};

	/* Switch slow clck to extern 32k xtal */
	pmc_switch_sclk_to_32kxtal(PMC_OSC_XTAL);

	/* Delay for a while to make sure the clock is stable */
	/* Wait for UART transmit done */
	while (!uart_is_tx_empty(CONF_UART)) {
	};

	/* If a new value for CSS field corresponds to Main Clock or Slow Clock,
	 * program the CSS field first.
	 */
	pmc_switch_mck_to_mainck(PMC_MCKR_PRES_CLK_2);

	/* Switch the mck to sclk but keep the PRES field same */
	pmc_switch_mck_to_sclk(PMC_MCKR_PRES_CLK_2);

	/* Then program the PRES field. */
	pmc_switch_mck_to_sclk(PMC_MCKR_PRES_CLK_1);

	/* The clock source for the UART is the PCK, so the uart needs
	 * re-configuration
	 */
	config_uart_and_pck(PMC_PCK_CSS_SLOW_CLK, PMC_PCK_PRES_CLK_1,
			BOARD_FREQ_SLCK_XTAL);

	for (gs_uc_wait_button = 1; gs_uc_wait_button;) {
	}

	/* Switch mainck to external xtal */
	pmc_switch_mainck_to_xtal(0, BOARD_OSC_STARTUP_US);
	/* If a new value for CSS field corresponds to Main Clock or Slow Clock,
	 * program the CSS field first.
	 */
	pmc_switch_mck_to_mainck(PMC_MCKR_PRES_CLK_1);
	/* Then program the PRES field. */
	pmc_switch_mck_to_mainck(PMC_MCKR_PRES_CLK_16);

	/* The clock source for the UART is the PCK, so the uart needs
	 * re-configuration.
	 */
	config_uart_and_pck(PMC_PCK_CSS_MAIN_CLK, PMC_PCK_PRES_CLK_16,
			(BOARD_FREQ_MAINCK_XTAL / 16));
#if SAM4C
	puts("\n\r-I- Switch the external 8MHz crystal oscillator to be the source of the main clock\n\r"
			"-I- The master clock is main  clock divided by 16\n\r"
			"-I- Press Button "BUTTON_NAME" to switch next clock configuration...\r\n");
#else
	puts("\n\r-I- Switch the external 12MHz crystal oscillator to be the source of the main clock\n\r"
			"-I- The master clock is main  clock divided by 16\n\r"
			"-I- Press Button "BUTTON_NAME" to switch next clock configuration...\r\n");
#endif

#if (SAM3S || SAM4S || SAM4C)
	for (gs_uc_wait_button = 1; gs_uc_wait_button;) {
	}

	puts("-I- Switch to 96Mhz PLLB clock as the source of the master clock\n\r"
			"-I- The master clock is PLLB clock divided by 2 \r");
	/* Wait for UART transmit done */
	while (!uart_is_tx_empty(CONF_UART)) {
	};

#if SAM4C
	/* Enable the PLLB clock, the mainck equals (8Mhz * (11+1) / 1) = 96Mhz
	 * with the initialize counter be 0x3f
	 */
	 pmc_enable_pllbck(11, 0x3f, 1);
#else
	/* Enable the PLLB clock, the mainck equals (12Mhz * (7+1) / 1) = 96Mhz
	 * with the initialize counter be 0x3f
	 */
	pmc_enable_pllbck(7, 0x3f, 1);
#endif

	/* If a new value for CSS field corresponds to PLL Clock, Program the PRES
	 * field first.
	 */
	pmc_switch_mck_to_mainck(PMC_MCKR_PRES_CLK_2);

	/* Then program the CSS field. */
	pmc_switch_mck_to_pllbck(PMC_MCKR_PRES_CLK_2);

	/* The clock source for the UART is the PCK, so the uart needs
	 * re-configuration.
	 */
#if SAM4C
	config_uart_and_pck(PMC_PCK_CSS_PLLB_CLK, PMC_PCK_PRES_CLK_2,
			(BOARD_FREQ_MAINCK_XTAL * 12 / 2));
#else
	config_uart_and_pck(PMC_PCK_CSS_PLLB_CLK, PMC_PCK_PRES_CLK_2,
			(BOARD_FREQ_MAINCK_XTAL * 8 / 2));
#endif
	puts("-I- Press Button "BUTTON_NAME" to switch next clock configuration...\r\n");
#endif

	for (gs_uc_wait_button = 1; gs_uc_wait_button;) {
	}
	puts("\r\n\r\n-I- Done.\r\n");
	/* Wait for UART transmit done */
	while (!uart_is_tx_empty(CONF_UART)) {
	};

	while (1) {
	}
}