Exemple #1
0
/**
 * \brief Configure 48MHz Clock for USB
 */
static void _ConfigureUsbClock(void)
{
    /* Enable PLLB for USB */
    PMC->CKGR_PLLBR = CKGR_PLLBR_DIVB(1)
                      | CKGR_PLLBR_MULB(7)
                      | CKGR_PLLBR_PLLBCOUNT_Msk;
    while((PMC->PMC_SR & PMC_SR_LOCKB) == 0);
    /* USB Clock uses PLLB */
    PMC->PMC_USB = PMC_USB_USBDIV(1)       /* /2   */
                   | PMC_USB_USBS;           /* PLLB */
}
Exemple #2
0
// Configure 48MHz Clock for USB
void usb_configure_clock_48mhz(void) {
    // Use PLLB for USB

#if (BOARD_MAINOSC == 16000000)
	PMC->CKGR_PLLBR = CKGR_PLLBR_DIVB(1) |
                      CKGR_PLLBR_MULB(5) |
                      CKGR_PLLBR_PLLBCOUNT_Msk;
    while((PMC->PMC_SR & PMC_SR_LOCKB) == 0);

	//               divide by 2         use PLLB
	PMC->PMC_USB = PMC_USB_USBDIV(1) | PMC_USB_USBS;
#elif (BOARD_MAINOSC == 12000000)
	PMC->CKGR_PLLBR = CKGR_PLLBR_DIVB(1) |
                      CKGR_PLLBR_MULB(7) |
                      CKGR_PLLBR_PLLBCOUNT_Msk;
    while((PMC->PMC_SR & PMC_SR_LOCKB) == 0);

	//               divide by 2         use PLLB
	PMC->PMC_USB = PMC_USB_USBDIV(1) | PMC_USB_USBS;
#endif
}
Exemple #3
0
static inline void sam_pmcsetup(void)
{
    uint32_t regval;

    /* Enable main oscillator (if it has not already been selected) */

    if ((getreg32(SAM_PMC_CKGR_MOR) & PMC_CKGR_MOR_MOSCSEL) == 0)
    {
        /* "When the MOSCXTEN bit and the MOSCXTCNT are written in CKGR_MOR to
         *  enable the main oscillator, the MOSCXTS bit in the Power Management
         *  Controller Status Register (PMC_SR) is cleared and the counter starts
         *  counting down on the slow clock divided by 8 from the MOSCXTCNT
         *  value. ... When the counter reaches 0, the MOSCXTS bit is set,
         *  indicating that the main clock is valid."
         */

        putreg32(BOARD_CKGR_MOR, SAM_PMC_CKGR_MOR);
        sam_pmcwait(PMC_INT_MOSCXTS);
    }

    /* "Switch to the main oscillator.  The selection is made by writing the
     *  MOSCSEL bit in the Main Oscillator Register (CKGR_MOR). The switch of
     *  the Main Clock source is glitch free, so there is no need to run out
     *  of SLCK, PLLACK or UPLLCK in order to change the selection. The MOSCSELS
     *  bit of the power Management Controller Status Register (PMC_SR) allows
     *  knowing when the switch sequence is done."
     *
     *   MOSCSELS: Main Oscillator Selection Status
     *             0 = Selection is done
     *             1 = Selection is in progress
     */

    putreg32((BOARD_CKGR_MOR | PMC_CKGR_MOR_MOSCSEL), SAM_PMC_CKGR_MOR);
    sam_pmcwait(PMC_INT_MOSCSELS);

    /* "Select the master clock. "The Master Clock selection is made by writing
     *  the CSS field (Clock Source Selection) in PMC_MCKR (Master Clock Register).
     *  The prescaler supports the division by a power of 2 of the selected clock
     *  between 1 and 64, and the division by 3. The PRES field in PMC_MCKR programs
     *  the prescaler. Each time PMC_MCKR is written to define a new Master Clock,
     *  the MCKRDY bit is cleared in PMC_SR. It reads 0 until the Master Clock is
     *  established.
     */

    regval  = getreg32(SAM_PMC_MCKR);
    regval &= ~PMC_MCKR_CSS_MASK;
    regval |= PMC_MCKR_CSS_MAIN;
    putreg32(regval, SAM_PMC_MCKR);
    sam_pmcwait(PMC_INT_MCKRDY);

    /* Setup PLLA and wait for LOCKA */

    putreg32(BOARD_CKGR_PLLAR, SAM_PMC_CKGR_PLLAR);
    sam_pmcwait(PMC_INT_LOCKA);

#ifdef CONFIG_SAMV7_USBDEVHS
    /* UTMI configuration: Enable port0, select 12/16 MHz MAINOSC crystal source */

#if BOARD_MAINOSC_FREQUENCY == 12000000
    putreg32(UTMI_CKTRIM_FREQ_XTAL12, SAM_UTMI_CKTRIM);
#elif BOARD_MAINOSC_FREQUENCY == 16000000
    putreg32(UTMI_CKTRIM_FREQ_XTAL16, SAM_UTMI_CKTRIM);
#else
#  error ERROR: Unrecognized MAINSOSC frequency
#endif

#ifdef CONFIG_SAMV7_USBDEVHS_LOWPOWER
    /* Enable UTMI Clocking. The USBHS can work in two modes:
     *
     * - Normal mode where High speed, Full speed and Low speed are available.
     * - Low-power mode where only Full speed and Low speed are available.
     *
     * Only the Low-power mode is mode is supported by the logic here.  Normal
     * mode logic is handled in the function sam_usbclock().
     */

    /* UTMI Low-power mode, Full/Low Speed mode
     *
     * Enable the 48MHz FS Clock.
     */

    putreg32(PMC_USBCLK, SAM_PMC_SCER);

    /* Select the UTMI PLL as the USB PLL clock input (480MHz) with divider
     * to get to 48MHz.  UPLL output frequency is determined only by the
     * 12/16MHz crystal selection above.
     */

    regval = PMC_USB_USBS_UPLL;

    if ((getreg32(SAM_PMC_MCKR) & PMC_MCKR_PLLADIV2) != 0)
    {
        /* Divider = 480 Mhz / 2 / 48 Mhz = 5 */

        regval |=  PMC_USB_USBDIV(4);
    }
    else
    {
        /* Divider = 480 Mhz / 1 / 48 Mhz = 10 */

        regval |=  PMC_USB_USBDIV(9);
    }

    putreg32(regval, SAM_PMC_USB);

    /* Enable the UTMI PLL with the maximum start-up time */

    regval = PMC_CKGR_UCKR_UPLLEN | PMC_CKGR_UCKR_UPLLCOUNT_MAX;
    putreg32(regval, SAM_PMC_CKGR_UCKR);

    /* Wait for LOCKU */

    sam_pmcwait(PMC_INT_LOCKU);

#endif /* CONFIG_SAMV7_USBDEVHS_LOWPOWER */
#endif /* CONFIG_SAMV7_USBDEVHS */

    /* Switch to the fast clock and wait for MCKRDY */

    putreg32(BOARD_PMC_MCKR_FAST, SAM_PMC_MCKR);
    sam_pmcwait(PMC_INT_MCKRDY);

    putreg32(BOARD_PMC_MCKR, SAM_PMC_MCKR);
    sam_pmcwait(PMC_INT_MCKRDY);
}
Exemple #4
0
/**
 * \brief Switch UHP (USB) clock source selection to PLLB clock.
 *
 * \param ul_usbdiv Clock divisor.
 */
void pmc_switch_uhpck_to_pllbck(uint32_t ul_usbdiv)
{
	PMC->PMC_USB = PMC_USB_USBDIV(ul_usbdiv) | PMC_USB_USBS;
}
Exemple #5
0
/**
 * \brief Switch UDP (USB) clock source selection to UPLL clock.
 *
 * \param ul_usbdiv Clock divisor.
 */
void pmc_switch_udpck_to_upllck(uint32_t ul_usbdiv)
{
	PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(ul_usbdiv);
}
// ペリフェラルの初期化
// RTX RTOSの開始前に呼ばれる
extern "C" void init(void){
	// WDTを無効にする
	WDT->WDT_MR		= WDT_MR_WDIDLEHLT | WDT_MR_WDDBGHLT | (0xFFF << WDT_MR_WDD_Pos) | WDT_MR_WDDIS | (0xFFF << WDT_MR_WDV_Pos);
	
	// RSWDTは標準で無効になっている
	
	// BODリセットは標準で有効になっている
	
	// 1度、強制的にリセットする(OpenOCDによるデバッグのため)
	if (RESET_GPBR == 0){
		RESET_GPBR = 1;
		RSTC->RSTC_CR = RSTC_CR_KEY_PASSWD | RSTC_CR_PERRST | RSTC_CR_PROCRST;
	}else{
		RESET_GPBR = 0;
	}
	
	// FPUを有効にする
	SCB->CPACR		= 0x00F00000;
	
	// キャッシュを有効にする(キャッシュはROMとFlash領域のみ有効)
	//CMCC->CMCC_CTRL	= CMCC_CTRL_CEN;
	
	// フラッシュのウェイト数を設定
	EFC->EEFC_FMR	= EEFC_FMR_CLOE | EEFC_FMR_FWS(5);	// 最大129MHz
	
	// システムクロックを設定
	// SLCK=32kHz, MAINCK=12MHz, PLLACK=240MHz, USB_48M=48MHz, MCK=120MHz
	PMC->CKGR_MOR	= CKGR_MOR_MOSCSEL | CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCRCF_4_MHz | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTBY;
	while(~PMC->PMC_SR & PMC_SR_MOSCSELS);
	PMC->CKGR_MOR	= CKGR_MOR_MOSCSEL | CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTBY;
	PMC->CKGR_PLLAR	= CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(20) | CKGR_PLLAR_PLLACOUNT(16) | CKGR_PLLAR_DIVA(1);
	while(~PMC->PMC_SR & PMC_SR_LOCKA);
	PMC->PMC_USB	= PMC_USB_USBDIV(5 - 1);
	PMC->PMC_MCKR	= PMC_MCKR_PRES_CLK_2 | PMC_MCKR_CSS_MAIN_CLK;
	while(~PMC->PMC_SR & PMC_SR_MCKRDY);
	PMC->PMC_MCKR	= PMC_MCKR_PRES_CLK_2 | PMC_MCKR_CSS_PLLA_CLK;
	while(~PMC->PMC_SR & PMC_SR_MCKRDY);
	
	// クロック供給を有効にする
	// 31:AFEC1, 30:AFEC0, 23:TC2, 22:TC1, 21:TC0, 20:DMAC, 12:PIOD, 10:PIOB, 9:PIOA, 7:UART0
	// 36:PWM, 35:UDP
	PMC->PMC_PCER0	= PMC_PCER0_PID31 | PMC_PCER0_PID30 | PMC_PCER0_PID23 | PMC_PCER0_PID22 | PMC_PCER0_PID21 | PMC_PCER0_PID20 | PMC_PCER0_PID12 | PMC_PCER0_PID10 | PMC_PCER0_PID9 | PMC_PCER0_PID7;
	PMC->PMC_PCER1	= PMC_PCER1_PID36 | PMC_PCER1_PID35;
	PMC->PMC_SCER	= PMC_SCER_UDP;
	
	// NVICのベクターをRAMに移動
	NVIC_Migration();
	
	// I/Oピンの初期化
	clDigitalIOInitializer IOInitializer;
	IOInitializer.Set(PIN_HOST_TX, DIR_IN, OUT_LOW, PINMODE_PU);
	IOInitializer.Set(PIN_HOST_RX, DIR_OUT, OUT_HIGH);
	IOInitializer.Set(PIN_CAM1_CLK, DIR_OUT, OUT_LOW);
	IOInitializer.Set(PIN_CAM2_CLK, DIR_OUT, OUT_LOW);
	IOInitializer.Set(PIN_CAM1_SI, DIR_OUT, OUT_LOW);
	IOInitializer.Set(PIN_CAM2_SI, DIR_OUT, OUT_LOW);
	IOInitializer.Set(PIN_CAM1_A0P, DIR_IN, OUT_LOW, PINMODE_PU);
	IOInitializer.Set(PIN_CAM2_A0P, DIR_IN, OUT_LOW, PINMODE_PU);
	IOInitializer.Set(PIN_USB_VBUS, DIR_IN, OUT_LOW);
	IOInitializer.Set(PIN_nSW1, DIR_IN, OUT_LOW, PINMODE_PU);
	IOInitializer.Set(PIN_LED1, DIR_OUT, OUT_LOW);
	IOInitializer.Set(PIN_LED_ENABLE, DIR_OUT, OUT_LOW);
	IOInitializer.Mux(PIN_HOST_TX, PINMUX_A, PIO_DISABLE);
	IOInitializer.Mux(PIN_HOST_RX, PINMUX_A, PIO_DISABLE);
	IOInitializer.Mux(PIN_CAM1_CLK, PINMUX_A, PIO_DISABLE);
	IOInitializer.Mux(PIN_CAM2_CLK, PINMUX_B, PIO_DISABLE);
	IOInitializer.Apply();
	
	/* OSリソースの作成を伴わないデバイスインスタンスの初期化を行う */
	
	
	
	
	
}
static inline void sam_usbclockconfig(void)
{
#if defined(CONFIG_SAMA5_EHCI) || defined(CONFIG_SAMA5_OHCI) || \
    defined(CONFIG_SAMA5_UDPHS)

  /* We can either get the clock from the UPLL or from PLLA.  In this latter
   * case, however, the PLLACK frequency must be a multiple of 48MHz.
   */

#if defined(BOARD_USE_UPLL)
  uint32_t regval;

  /* The USB Host High Speed requires a 480 MHz clock (UPLLCK) for the
   * embedded High-speed transceivers. UPLLCK is the output of the 480 MHz
   * UTMI PLL (UPLL).  The source clock of the UTMI PLL is the Main OSC output:
   * Either the 12MHz internal oscillator on a 12MHz crystal.  The Main OSC
   * must be 12MHz because the UPLL has a built-in 40x multiplier.
   *
   * For High-speed operations, the user has to perform the following:
   *
   *   1) Enable UHP peripheral clock, bit (1 << AT91C_ID_UHPHS) in
   *      PMC_PCER register.
   *   2) Write CKGR_PLLCOUNT field in PMC_UCKR register.
   *   3) Enable UPLL, bit AT91C_CKGR_UPLLEN in PMC_UCKR register.
   *   4) Wait until UTMI_PLL is locked. LOCKU bit in PMC_SR register
   *   5) Enable BIAS, bit AT91C_CKGR_BIASEN in PMC_UCKR register.
   *   6) Select UPLLCK as Input clock of OHCI part, USBS bit in PMC_USB
   *      register.
   *   7) Program the OHCI clocks (UHP48M and UHP12M) with USBDIV field in
   *      PMC_USB register. USBDIV must be 9 (division by 10) if UPLLCK is
   *      selected.
   *   8) Enable OHCI clocks, UHP bit in PMC_SCER register.
   *
   * Steps 2 through 7 performed here.  1 and 8 are performed in the EHCI
   * driver is initialized.
   */

  /* 2) Write CKGR_PLLCOUNT field in PMC_UCKR register. */

  regval = PMC_CKGR_UCKR_UPLLCOUNT(BOARD_CKGR_UCKR_UPLLCOUNT);
  putreg32(regval, SAM_PMC_CKGR_UCKR);

  /* 3) Enable UPLL, bit AT91C_CKGR_UPLLEN in PMC_UCKR register. */

  regval |= PMC_CKGR_UCKR_UPLLEN;
  putreg32(regval, SAM_PMC_CKGR_UCKR);

  /* 4) Wait until UTMI_PLL is locked. LOCKU bit in PMC_SR register */

  sam_pmcwait(PMC_INT_LOCKU);

  /* 5) Enable BIAS, bit AT91C_CKGR_BIASEN in PMC_UCKR register. */

  regval |= PMC_CKGR_UCKR_BIASCOUNT(BOARD_CKGR_UCKR_BIASCOUNT);
  putreg32(regval, SAM_PMC_CKGR_UCKR);

  regval |= PMC_CKGR_UCKR_BIASEN;
  putreg32(regval, SAM_PMC_CKGR_UCKR);

  /* 6) Select UPLLCK as Input clock of OHCI part, USBS bit in PMC_USB
   *    register.
   */

  regval = PMC_USB_USBS_UPLL;
  putreg32(regval, SAM_PMC_USB);

  /* 7) Program the OHCI clocks (UHP48M and UHP12M) with USBDIV field in
   *    PMC_USB register. USBDIV must be 9 (division by 10) if UPLLCK is
   *    selected.
   *
   * REVISIT:  The divisor of 10 produces a rate that is too high with
   * SAMA5D3.  A divisor of 5, however, seems to work just fine for the
   * SAMA5D3.  The SAMA5D4, on the other hand, needs the divisor of 10.
   * No idea why?  Let the board.h file decide which to use.
   */

  regval |= PMC_USB_USBDIV(BOARD_UPLL_OHCI_DIV-1);
  putreg32(regval, SAM_PMC_USB);

#else /* BOARD_USE_UPLL */
  /* For OHCI Full-speed operations only, the user has to perform the
   * following:
   *
   *   1) Enable UHP peripheral clock, bit (1 << AT91C_ID_UHPHS) in PMC_PCER
   *      register.
   *   2) Select PLLACK as Input clock of OHCI part, USBS bit in PMC_USB
   *      register.
   *   3) Program the OHCI clocks (UHP48M and UHP12M) with USBDIV field in
   *      PMC_USB register. USBDIV value is calculated regarding the PLLACK
   *      value and USB Full-speed accuracy.
   *   4) Enable the OHCI clocks, UHP bit in PMC_SCER register.
   *
   * Steps 2 and 3 are done here.  1 and 2 are performed with the OHCI
   * driver is initialized.
   */

  putreg32(BOARD_OHCI_INPUT | BOARD_OHCI_DIVIDER << PMC_USB_USBDIV_SHIFT,
          SAM_PMC_USB);

#endif /* BOARD_USE_UPLL */
#endif /* CONFIG_SAMA5_EHCI ||CONFIG_SAMA5_OHCI) || CONFIG_SAMA5_UDPHS */
}