ソースを参照

SAM E54 XPlained Pro: free up DPLL1 for application

Jean Gressmann 5 年 前
コミット
bcf9c8cb27

+ 2 - 3
hw/bsp/same54xplainedpro/board.mk

@@ -13,11 +13,10 @@ CFLAGS += \
   -D__SAME54P20A__ \
   -DCONF_CPU_FREQUENCY=$(CONF_CPU_FREQUENCY) \
   -DCFG_TUSB_MCU=OPT_MCU_SAME5X \
+  -DSAME54XPLAINEDPRO=1 \
+  -DBOARD_NAME="\"Microchip SAM E54 Xplained Pro\""
 
 
-
-#  -DSVC_Handler=SVCall_Handler
-
 # All source paths should be relative to the top level.
 LD_FILE = hw/bsp/$(BOARD)/same54p20a_flash.ld
 

+ 32 - 15
hw/bsp/same54xplainedpro/same54xplainedpro.c

@@ -58,7 +58,6 @@ void USB_3_Handler(void)
 #define LED_PIN PIN_PC18
 #define BUTTON_PIN PIN_PB31
 #define BOARD_SERCOM SERCOM2
-#define BOARD_NAME "Microchip SAM E54 Xplained Pro"
 
 static inline void init_clock(void)
 {
@@ -72,16 +71,11 @@ static inline void init_clock(void)
 		OSCCTRL_XOSCCTRL_ENABLE;
 	while(0 == OSCCTRL->STATUS.bit.XOSCRDY1);
 
-	OSCCTRL->Dpll[0].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_DIV(5) | OSCCTRL_DPLLCTRLB_REFCLK_XOSC1; /* 12MHz / 12 = 1Mhz, input = XOSC1 */
-	OSCCTRL->Dpll[0].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0x0) | OSCCTRL_DPLLRATIO_LDR((CONF_CPU_FREQUENCY / 1000000)-1); /* multiply to get CONF_CPU_FREQUENCY (default = 120MHz) */
+	OSCCTRL->Dpll[0].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_DIV(2) | OSCCTRL_DPLLCTRLB_REFCLK_XOSC1; /* 12MHz / 6 = 2Mhz, input = XOSC1 */
+	OSCCTRL->Dpll[0].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0x0) | OSCCTRL_DPLLRATIO_LDR((CONF_CPU_FREQUENCY / 1000000 / 2) - 1); /* multiply to get CONF_CPU_FREQUENCY (default = 120MHz) */
 	OSCCTRL->Dpll[0].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_RUNSTDBY | OSCCTRL_DPLLCTRLA_ENABLE;
 	while(0 == OSCCTRL->Dpll[0].DPLLSTATUS.bit.CLKRDY); /* wait for the PLL0 to be ready */
 
-	OSCCTRL->Dpll[1].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_DIV(5) | OSCCTRL_DPLLCTRLB_REFCLK_XOSC1; /* 12MHz / 12 = 1Mhz, input = XOSC1 */
-	OSCCTRL->Dpll[1].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0x0) | OSCCTRL_DPLLRATIO_LDR(47); /* multiply by 48 -> 48 MHz */
-	OSCCTRL->Dpll[1].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_RUNSTDBY | OSCCTRL_DPLLCTRLA_ENABLE;
-	while(0 == OSCCTRL->Dpll[1].DPLLSTATUS.bit.CLKRDY); /* wait for the PLL1 to be ready */
-
 	/* configure clock-generator 0 to use DPLL0 as source -> GCLK0 is used for the core */
 	GCLK->GENCTRL[0].reg =
 		GCLK_GENCTRL_DIV(0) |
@@ -91,14 +85,37 @@ static inline void init_clock(void)
 		GCLK_GENCTRL_IDC;
 	while(1 == GCLK->SYNCBUSY.bit.GENCTRL0); /* wait for the synchronization between clock domains to be complete */
 
-	/* configure clock-generator 1 to use DPLL1 as source -> for use with some peripheral */
-	GCLK->GENCTRL[1].reg =
+	// configure GCLK2 for 12MHz from XOSC1
+	GCLK->GENCTRL[2].reg =
 		GCLK_GENCTRL_DIV(0) |
 		GCLK_GENCTRL_RUNSTDBY |
 		GCLK_GENCTRL_GENEN |
-		GCLK_GENCTRL_SRC_DPLL1 |
-		GCLK_GENCTRL_IDC ;
-	while(1 == GCLK->SYNCBUSY.bit.GENCTRL1); /* wait for the synchronization between clock domains to be complete */
+		GCLK_GENCTRL_SRC_XOSC1 |
+		GCLK_GENCTRL_IDC;
+	while(1 == GCLK->SYNCBUSY.bit.GENCTRL2); /* wait for the synchronization between clock domains to be complete */
+
+	 /* setup DFLL48M to use GLCK2 */
+	GCLK->PCHCTRL[OSCCTRL_GCLK_ID_DFLL48].reg = GCLK_PCHCTRL_GEN_GCLK2 | GCLK_PCHCTRL_CHEN;
+
+	OSCCTRL->DFLLCTRLA.reg = 0;
+	while(1 == OSCCTRL->DFLLSYNC.bit.ENABLE);
+
+	OSCCTRL->DFLLCTRLB.reg = OSCCTRL_DFLLCTRLB_MODE | OSCCTRL_DFLLCTRLB_WAITLOCK;
+	OSCCTRL->DFLLMUL.bit.MUL = 4; // 4 * 12MHz -> 48MHz
+
+	OSCCTRL->DFLLCTRLA.reg =
+		OSCCTRL_DFLLCTRLA_ENABLE |
+		OSCCTRL_DFLLCTRLA_RUNSTDBY;
+	while(1 == OSCCTRL->DFLLSYNC.bit.ENABLE);
+
+	// setup 48 MHz GCLK3 from DFLL48M
+	GCLK->GENCTRL[3].reg =
+		GCLK_GENCTRL_DIV(0) |
+		GCLK_GENCTRL_RUNSTDBY |
+		GCLK_GENCTRL_GENEN |
+		GCLK_GENCTRL_SRC_DFLL |
+		GCLK_GENCTRL_IDC;
+	while(1 == GCLK->SYNCBUSY.bit.GENCTRL3);
 }
 
 static inline void uart_init(void)
@@ -107,7 +124,7 @@ static inline void uart_init(void)
 	gpio_set_pin_function(PIN_PB25, PINMUX_PB25D_SERCOM2_PAD0);
 
 	MCLK->APBBMASK.bit.SERCOM2_ = 1;
-	GCLK->PCHCTRL[SERCOM2_GCLK_ID_CORE].reg = GCLK_PCHCTRL_GEN_GCLK1 | GCLK_PCHCTRL_CHEN; /* setup SERCOM to use GLCK1 -> 48MHz */
+	GCLK->PCHCTRL[SERCOM2_GCLK_ID_CORE].reg = GCLK_PCHCTRL_GEN_GCLK3 | GCLK_PCHCTRL_CHEN;
 
 	BOARD_SERCOM->USART.CTRLA.bit.SWRST = 1; /* reset and disable SERCOM -> enable configuration */
 	while (BOARD_SERCOM->USART.SYNCBUSY.bit.SWRST);
@@ -201,7 +218,7 @@ void board_init(void)
 	 * The USB module requires a GCLK_USB of 48 MHz ~ 0.25% clock
 	 * for low speed and full speed operation.
 	 */
-	hri_gclk_write_PCHCTRL_reg(GCLK, USB_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN);
+	hri_gclk_write_PCHCTRL_reg(GCLK, USB_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK3_Val | GCLK_PCHCTRL_CHEN);
 	hri_mclk_set_AHBMASK_USB_bit(MCLK);
 	hri_mclk_set_APBBMASK_USB_bit(MCLK);