From bcf9c8cb27d223e2b0078daf7e3311db3bb4bd82 Mon Sep 17 00:00:00 2001 From: Jean Gressmann Date: Thu, 11 Mar 2021 18:19:08 +0100 Subject: [PATCH 1/5] SAM E54 XPlained Pro: free up DPLL1 for application --- hw/bsp/same54xplainedpro/board.mk | 5 +-- hw/bsp/same54xplainedpro/same54xplainedpro.c | 47 +++++++++++++------- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/hw/bsp/same54xplainedpro/board.mk b/hw/bsp/same54xplainedpro/board.mk index 508ab20f8..1200fd9f4 100644 --- a/hw/bsp/same54xplainedpro/board.mk +++ b/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 diff --git a/hw/bsp/same54xplainedpro/same54xplainedpro.c b/hw/bsp/same54xplainedpro/same54xplainedpro.c index a1d920757..0bdd477d2 100644 --- a/hw/bsp/same54xplainedpro/same54xplainedpro.c +++ b/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); From 01ec0d49ca24cda458d4c2fa4bb5f751ebd4b336 Mon Sep 17 00:00:00 2001 From: Jean Gressmann Date: Thu, 11 Mar 2021 18:20:58 +0100 Subject: [PATCH 2/5] SAM E54 XPlained Pro: use proper defines SPI->USART for board init --- hw/bsp/same54xplainedpro/same54xplainedpro.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/bsp/same54xplainedpro/same54xplainedpro.c b/hw/bsp/same54xplainedpro/same54xplainedpro.c index 0bdd477d2..70ea7d438 100644 --- a/hw/bsp/same54xplainedpro/same54xplainedpro.c +++ b/hw/bsp/same54xplainedpro/same54xplainedpro.c @@ -144,7 +144,7 @@ static inline void uart_init(void) // BOARD_SERCOM->USART.BAUD.reg = SERCOM_USART_BAUD_FRAC_FP(0) | SERCOM_USART_BAUD_FRAC_BAUD(26); /* 48000000/(16*115200) = 26.041666667 */ BOARD_SERCOM->USART.BAUD.reg = SERCOM_USART_BAUD_BAUD(63019); /* 65536*(1−16*115200/48000000) */ - BOARD_SERCOM->SPI.CTRLA.bit.ENABLE = 1; /* activate SERCOM */ + BOARD_SERCOM->USART.CTRLA.bit.ENABLE = 1; /* activate SERCOM */ while (BOARD_SERCOM->USART.SYNCBUSY.bit.ENABLE); /* wait for SERCOM to be ready */ } @@ -152,7 +152,7 @@ static inline void uart_send_buffer(uint8_t const *text, size_t len) { for (size_t i = 0; i < len; ++i) { BOARD_SERCOM->USART.DATA.reg = text[i]; - while((BOARD_SERCOM->USART.INTFLAG.reg & SERCOM_SPI_INTFLAG_TXC) == 0); + while((BOARD_SERCOM->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_TXC) == 0); } } @@ -160,7 +160,7 @@ static inline void uart_send_str(const char* text) { while (*text) { BOARD_SERCOM->USART.DATA.reg = *text++; - while((BOARD_SERCOM->USART.INTFLAG.reg & SERCOM_SPI_INTFLAG_TXC) == 0); + while((BOARD_SERCOM->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_TXC) == 0); } } From a2006ce21466d50e92c62f85a3802262938e3b84 Mon Sep 17 00:00:00 2001 From: Jean Gressmann Date: Sun, 21 Mar 2021 09:38:02 +0100 Subject: [PATCH 3/5] SAM 54 Xplained Pro: remove board specific define --- hw/bsp/same54xplainedpro/board.mk | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/bsp/same54xplainedpro/board.mk b/hw/bsp/same54xplainedpro/board.mk index 1200fd9f4..046ebbf66 100644 --- a/hw/bsp/same54xplainedpro/board.mk +++ b/hw/bsp/same54xplainedpro/board.mk @@ -13,7 +13,6 @@ CFLAGS += \ -D__SAME54P20A__ \ -DCONF_CPU_FREQUENCY=$(CONF_CPU_FREQUENCY) \ -DCFG_TUSB_MCU=OPT_MCU_SAME5X \ - -DSAME54XPLAINEDPRO=1 \ -DBOARD_NAME="\"Microchip SAM E54 Xplained Pro\"" From 1a5a1136559aa8a78ec42cd49e3a7c28e55b711c Mon Sep 17 00:00:00 2001 From: Jean Gressmann Date: Sun, 21 Mar 2021 09:43:29 +0100 Subject: [PATCH 4/5] SAM54 Xplained Pro: reduce board setup code for maintenance The board now runs off the internal oscillator at 48 MHz. This is sufficient to run the TinyUSB examples. A better performing clock setup is keep in the file as init_clock_xtal() as an example. --- hw/bsp/same54xplainedpro/board.mk | 2 +- hw/bsp/same54xplainedpro/same54xplainedpro.c | 22 ++++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/hw/bsp/same54xplainedpro/board.mk b/hw/bsp/same54xplainedpro/board.mk index 046ebbf66..89d6ce012 100644 --- a/hw/bsp/same54xplainedpro/board.mk +++ b/hw/bsp/same54xplainedpro/board.mk @@ -1,6 +1,6 @@ DEPS_SUBMODULES = hw/mcu/microchip -CONF_CPU_FREQUENCY ?= 120000000 +CONF_CPU_FREQUENCY ?= 48000000 CFLAGS += \ -mthumb \ diff --git a/hw/bsp/same54xplainedpro/same54xplainedpro.c b/hw/bsp/same54xplainedpro/same54xplainedpro.c index 70ea7d438..52e1b25f3 100644 --- a/hw/bsp/same54xplainedpro/same54xplainedpro.c +++ b/hw/bsp/same54xplainedpro/same54xplainedpro.c @@ -59,7 +59,19 @@ void USB_3_Handler(void) #define BUTTON_PIN PIN_PB31 #define BOARD_SERCOM SERCOM2 -static inline void init_clock(void) +/** Initializes the clocks from the external 12 MHz crystal + * + * The goal of this setup is to preserve the second PLL + * for the application code while still having a reasonable + * 48 MHz clock for USB / UART. + * + * GCLK0: CONF_CPU_FREQUENCY (default 120 MHz) from PLL0 + * GCLK1: unused + * GCLK2: 12 MHz from XOSC1 + * DFLL48M: closed loop from GLCK2 + * GCLK3: 48 MHz + */ +static inline void init_clock_xtal(void) { /* configure for a 12MHz crystal connected to XIN1/XOUT1 */ OSCCTRL->XOSCCTRL[1].reg = @@ -118,13 +130,14 @@ static inline void init_clock(void) while(1 == GCLK->SYNCBUSY.bit.GENCTRL3); } +/* Initialize SERCOM2 for 115200 bps 8N1 using a 48 MHz clock */ static inline void uart_init(void) { gpio_set_pin_function(PIN_PB24, PINMUX_PB24D_SERCOM2_PAD1); 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_GCLK3 | GCLK_PCHCTRL_CHEN; + GCLK->PCHCTRL[SERCOM2_GCLK_ID_CORE].reg = GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN; BOARD_SERCOM->USART.CTRLA.bit.SWRST = 1; /* reset and disable SERCOM -> enable configuration */ while (BOARD_SERCOM->USART.SYNCBUSY.bit.SWRST); @@ -167,7 +180,8 @@ static inline void uart_send_str(const char* text) void board_init(void) { - init_clock(); + // Uncomment this line to run off the XTAL + // init_clock_xtal(); SystemCoreClock = CONF_CPU_FREQUENCY; @@ -218,7 +232,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_GCLK3_Val | GCLK_PCHCTRL_CHEN); + hri_gclk_write_PCHCTRL_reg(GCLK, USB_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK0_Val | GCLK_PCHCTRL_CHEN); hri_mclk_set_AHBMASK_USB_bit(MCLK); hri_mclk_set_APBBMASK_USB_bit(MCLK); From 1f9b7b0c4832a2d740bbfe9b437065ea3d24407a Mon Sep 17 00:00:00 2001 From: Jean Gressmann Date: Sun, 21 Mar 2021 09:48:49 +0100 Subject: [PATCH 5/5] SAM54 Xplained Pro: update board setup documentation --- hw/bsp/same54xplainedpro/same54xplainedpro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/bsp/same54xplainedpro/same54xplainedpro.c b/hw/bsp/same54xplainedpro/same54xplainedpro.c index 52e1b25f3..4c38fc6eb 100644 --- a/hw/bsp/same54xplainedpro/same54xplainedpro.c +++ b/hw/bsp/same54xplainedpro/same54xplainedpro.c @@ -180,7 +180,7 @@ static inline void uart_send_str(const char* text) void board_init(void) { - // Uncomment this line to run off the XTAL + // Uncomment this line and change the GCLK for UART/USB to run off the XTAL. // init_clock_xtal(); SystemCoreClock = CONF_CPU_FREQUENCY;