From 0fd29be0d2b3987c727412eec54c9362bb721792 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 17 Feb 2014 14:21:22 -0600 Subject: [PATCH] SAMD20: Now runs, but no serial output --- arch/arm/src/sam34/sam4l_gpio.h | 10 ++--- arch/arm/src/samd/chip/sam_gclk.h | 58 ++++++++++++------------- arch/arm/src/samd/sam_lowputc.c | 22 +++++----- arch/arm/src/samd/sam_port.c | 14 +++--- arch/arm/src/samd/sam_port.h | 8 ++-- arch/arm/src/samd/sam_serial.c | 37 ++++++++++++---- configs/samd20-xplained/README.txt | 12 ++--- configs/samd20-xplained/include/board.h | 15 ++++--- 8 files changed, 98 insertions(+), 78 deletions(-) diff --git a/arch/arm/src/sam34/sam4l_gpio.h b/arch/arm/src/sam34/sam4l_gpio.h index 314d28ab183..e4aa8e8f190 100644 --- a/arch/arm/src/sam34/sam4l_gpio.h +++ b/arch/arm/src/sam34/sam4l_gpio.h @@ -96,11 +96,11 @@ */ #define GPIO_PULL_SHIFT (20) /* Bits 20-21: Pull-up/down resistor control */ -#define GPIO_PULL_MASK (3 << GPIO_FUNC_SHIFT) -# define GPIO_PULL_NONE (0 << GPIO_FUNC_SHIFT) -# define GPIO_PULL_UP (1 << GPIO_FUNC_SHIFT) -# define GPIO_PULL_DOWN (2 << GPIO_FUNC_SHIFT) -# define GPIO_PULL_BUSKEEPER (3 << GPIO_FUNC_SHIFT) +#define GPIO_PULL_MASK (3 << GPIO_PULL_SHIFT) +# define GPIO_PULL_NONE (0 << GPIO_PULL_SHIFT) +# define GPIO_PULL_UP (1 << GPIO_PULL_SHIFT) +# define GPIO_PULL_DOWN (2 << GPIO_PULL_SHIFT) +# define GPIO_PULL_BUSKEEPER (3 << GPIO_PULL_SHIFT) /* Peripheral Function * diff --git a/arch/arm/src/samd/chip/sam_gclk.h b/arch/arm/src/samd/chip/sam_gclk.h index b95a914aaa2..946388e3565 100644 --- a/arch/arm/src/samd/chip/sam_gclk.h +++ b/arch/arm/src/samd/chip/sam_gclk.h @@ -82,36 +82,36 @@ #define GCLK_CLKCTRL_ID_SHIFT (0) /* Bits 0-5: Generic Clock Selection ID */ #define GCLK_CLKCTRL_ID_MASK (0x3f << GCLK_CLKCTRL_ID_SHIFT) # define GCLK_CLKCTRL_ID(n) ((n) << GCLK_CLKCTRL_ID_SHIFT) -# define GCLK_CLKCTRL_ID_DFLL48M (0 << GCLK_CLKCTRL_ID_SHIFT) /* DFLL48M Reference */ -# define GCLK_CLKCTRL_ID_WDT (1 << GCLK_CLKCTRL_ID_SHIFT) /* WDT */ -# define GCLK_CLKCTRL_ID_RTC (2 << GCLK_CLKCTRL_ID_SHIFT) /* RTC */ -# define GCLK_CLKCTRL_ID_EIC (3 << GCLK_CLKCTRL_ID_SHIFT) /* EIC */ -# define GCLK_CLKCTRL_ID_EVSYS(n) (((n)+4) << GCLK_CLKCTRL_ID_SHIFT) -# define GCLK_CLKCTRL_ID_EVSYS1 (5 << GCLK_CLKCTRL_ID_SHIFT) /* EVSYS_CHANNEL_1 */ -# define GCLK_CLKCTRL_ID_EVSYS1 (5 << GCLK_CLKCTRL_ID_SHIFT) /* EVSYS_CHANNEL_1 */ -# define GCLK_CLKCTRL_ID_EVSYS2 (6 << GCLK_CLKCTRL_ID_SHIFT) /* EVSYS_CHANNEL_2 */ -# define GCLK_CLKCTRL_ID_EVSYS3 (7 << GCLK_CLKCTRL_ID_SHIFT) /* EVSYS_CHANNEL_3 */ -# define GCLK_CLKCTRL_ID_EVSYS4 (8 << GCLK_CLKCTRL_ID_SHIFT) /* EVSYS_CHANNEL_4 */ -# define GCLK_CLKCTRL_ID_EVSYS5 (9 << GCLK_CLKCTRL_ID_SHIFT) /* EVSYS_CHANNEL_5 */ -# define GCLK_CLKCTRL_ID_EVSYS6 (10 << GCLK_CLKCTRL_ID_SHIFT) /* EVSYS_CHANNEL_6 */ -# define GCLK_CLKCTRL_ID_EVSYS7 (11 << GCLK_CLKCTRL_ID_SHIFT) /* EVSYS_CHANNEL_7 */ -# define GCLK_CLKCTRL_ID_SERCOMS (12 << GCLK_CLKCTRL_ID_SHIFT) /* SERCOMx_SLOW */ +# define GCLK_CLKCTRL_ID_DFLL48M (0 << GCLK_CLKCTRL_ID_SHIFT) /* DFLL48M Reference */ +# define GCLK_CLKCTRL_ID_WDT (1 << GCLK_CLKCTRL_ID_SHIFT) /* WDT */ +# define GCLK_CLKCTRL_ID_RTC (2 << GCLK_CLKCTRL_ID_SHIFT) /* RTC */ +# define GCLK_CLKCTRL_ID_EIC (3 << GCLK_CLKCTRL_ID_SHIFT) /* EIC */ +# define GCLK_CLKCTRL_ID_EVSYS(n) (((n)+4) << GCLK_CLKCTRL_ID_SHIFT) +# define GCLK_CLKCTRL_ID_EVSYS1 (5 << GCLK_CLKCTRL_ID_SHIFT) /* EVSYS_CHANNEL_1 */ +# define GCLK_CLKCTRL_ID_EVSYS1 (5 << GCLK_CLKCTRL_ID_SHIFT) /* EVSYS_CHANNEL_1 */ +# define GCLK_CLKCTRL_ID_EVSYS2 (6 << GCLK_CLKCTRL_ID_SHIFT) /* EVSYS_CHANNEL_2 */ +# define GCLK_CLKCTRL_ID_EVSYS3 (7 << GCLK_CLKCTRL_ID_SHIFT) /* EVSYS_CHANNEL_3 */ +# define GCLK_CLKCTRL_ID_EVSYS4 (8 << GCLK_CLKCTRL_ID_SHIFT) /* EVSYS_CHANNEL_4 */ +# define GCLK_CLKCTRL_ID_EVSYS5 (9 << GCLK_CLKCTRL_ID_SHIFT) /* EVSYS_CHANNEL_5 */ +# define GCLK_CLKCTRL_ID_EVSYS6 (10 << GCLK_CLKCTRL_ID_SHIFT) /* EVSYS_CHANNEL_6 */ +# define GCLK_CLKCTRL_ID_EVSYS7 (11 << GCLK_CLKCTRL_ID_SHIFT) /* EVSYS_CHANNEL_7 */ +# define GCLK_CLKCTRL_ID_SERCOMS (12 << GCLK_CLKCTRL_ID_SHIFT) /* SERCOMx_SLOW */ # define GCLK_CLKCTRL_ID_SERCOMC(n) (((n)+13) << GCLK_CLKCTRL_ID_SHIFT) -# define GCLK_CLKCTRL_ID_SERCOM0C (13 << GCLK_CLKCTRL_ID_SHIFT) /* SERCOM0_CORE */ -# define GCLK_CLKCTRL_ID_SERCOM1C (14 << GCLK_CLKCTRL_ID_SHIFT) /* SERCOM1_CORE */ -# define GCLK_CLKCTRL_ID_SERCOM2C (15 << GCLK_CLKCTRL_ID_SHIFT) /* SERCOM2_CORE */ -# define GCLK_CLKCTRL_ID_SERCOM3C (16 << GCLK_CLKCTRL_ID_SHIFT) /* SERCOM3_CORE */ -# define GCLK_CLKCTRL_ID_SERCOM4C (17 << GCLK_CLKCTRL_ID_SHIFT) /* SERCOM4_CORE */ -# define GCLK_CLKCTRL_ID_SERCOM5C (18 << GCLK_CLKCTRL_ID_SHIFT) /* SERCOM5_CORE */ -# define GCLK_CLKCTRL_ID_TC01 (19 << GCLK_CLKCTRL_ID_SHIFT) /* TC0,TC1 */ -# define GCLK_CLKCTRL_ID_TC23 (20 << GCLK_CLKCTRL_ID_SHIFT) /* TC2,TC3 */ -# define GCLK_CLKCTRL_ID_TC45 (21 << GCLK_CLKCTRL_ID_SHIFT) /* TC4,TC5 */ -# define GCLK_CLKCTRL_ID_TC67 (22 << GCLK_CLKCTRL_ID_SHIFT) /* TC6,TC7 */ -# define GCLK_CLKCTRL_ID_ADC (23 << GCLK_CLKCTRL_ID_SHIFT) /* ADC */ -# define GCLK_CLKCTRL_ID_ACDIG (24 << GCLK_CLKCTRL_ID_SHIFT) /* AC_DIG */ -# define GCLK_CLKCTRL_ID_ACANA (25 << GCLK_CLKCTRL_ID_SHIFT) /* AC_ANA */ -# define GCLK_CLKCTRL_ID_DAC (26 << GCLK_CLKCTRL_ID_SHIFT) /* DAC */ -# define GCLK_CLKCTRL_ID_PTC (27 << GCLK_CLKCTRL_ID_SHIFT) /* PTC */ +# define GCLK_CLKCTRL_ID_SERCOM0C (13 << GCLK_CLKCTRL_ID_SHIFT) /* SERCOM0_CORE */ +# define GCLK_CLKCTRL_ID_SERCOM1C (14 << GCLK_CLKCTRL_ID_SHIFT) /* SERCOM1_CORE */ +# define GCLK_CLKCTRL_ID_SERCOM2C (15 << GCLK_CLKCTRL_ID_SHIFT) /* SERCOM2_CORE */ +# define GCLK_CLKCTRL_ID_SERCOM3C (16 << GCLK_CLKCTRL_ID_SHIFT) /* SERCOM3_CORE */ +# define GCLK_CLKCTRL_ID_SERCOM4C (17 << GCLK_CLKCTRL_ID_SHIFT) /* SERCOM4_CORE */ +# define GCLK_CLKCTRL_ID_SERCOM5C (18 << GCLK_CLKCTRL_ID_SHIFT) /* SERCOM5_CORE */ +# define GCLK_CLKCTRL_ID_TC01 (19 << GCLK_CLKCTRL_ID_SHIFT) /* TC0,TC1 */ +# define GCLK_CLKCTRL_ID_TC23 (20 << GCLK_CLKCTRL_ID_SHIFT) /* TC2,TC3 */ +# define GCLK_CLKCTRL_ID_TC45 (21 << GCLK_CLKCTRL_ID_SHIFT) /* TC4,TC5 */ +# define GCLK_CLKCTRL_ID_TC67 (22 << GCLK_CLKCTRL_ID_SHIFT) /* TC6,TC7 */ +# define GCLK_CLKCTRL_ID_ADC (23 << GCLK_CLKCTRL_ID_SHIFT) /* ADC */ +# define GCLK_CLKCTRL_ID_ACDIG (24 << GCLK_CLKCTRL_ID_SHIFT) /* AC_DIG */ +# define GCLK_CLKCTRL_ID_ACANA (25 << GCLK_CLKCTRL_ID_SHIFT) /* AC_ANA */ +# define GCLK_CLKCTRL_ID_DAC (26 << GCLK_CLKCTRL_ID_SHIFT) /* DAC */ +# define GCLK_CLKCTRL_ID_PTC (27 << GCLK_CLKCTRL_ID_SHIFT) /* PTC */ #define GCLK_CLKCTRL_GEN_SHIFT (8) /* Bits 8-11: Generic Clock Generator */ #define GCLK_CLKCTRL_GEN_MASK (15 << GCLK_CLKCTRL_GEN_SHIFT) # define GCLK_CLKCTRL_GEN(n) ((n) << GCLK_CLKCTRL_GEN_SHIFT) /* Generic clock generator n */ diff --git a/arch/arm/src/samd/sam_lowputc.c b/arch/arm/src/samd/sam_lowputc.c index 38f1d8048ff..4d2b7192714 100644 --- a/arch/arm/src/samd/sam_lowputc.c +++ b/arch/arm/src/samd/sam_lowputc.c @@ -116,21 +116,21 @@ sam_wait_synchronization(const struct sam_usart_config_s * const config) static inline void sam_gclk_configure(const struct sam_usart_config_s * const config) { - uint8_t regval; + uint16_t regval; uint8_t glckcore; /* Set up the SERCOMn_GCLK_ID_CORE clock */ glckcore = (uint8_t)SERCOM_GCLK_ID_CORE(config->sercom); - regval = (glckcore << GCLK_CLKCTRL_ID_SHIFT); + regval = ((uint16_t)glckcore << GCLK_CLKCTRL_ID_SHIFT); /* Select and disable generic clock channel */ - putreg8(regval, SAM_GCLK_CLKCTRL); + putreg16(regval, SAM_GCLK_CLKCTRL); /* Wait for clock to become disabled */ - while ((getreg8(SAM_GCLK_CLKCTRL) & GCLK_CLKCTRL_CLKEN) != 0); + while ((getreg16(SAM_GCLK_CLKCTRL) & GCLK_CLKCTRL_CLKEN) != 0); /* Select the SERCOMn_GCLK_ID_CORE clock generator */ @@ -147,12 +147,12 @@ sam_gclk_configure(const struct sam_usart_config_s * const config) /* Write the new configuration */ - putreg8(regval, SAM_GCLK_CLKCTRL); + putreg16(regval, SAM_GCLK_CLKCTRL); /* Enable the GCLK */ regval |= GCLK_CLKCTRL_CLKEN; - putreg8(regval, SAM_GCLK_CLKCTRL); + putreg16(regval, SAM_GCLK_CLKCTRL); /* Set up the SERCOM_GCLK_ID_SLOW clock */ @@ -160,11 +160,11 @@ sam_gclk_configure(const struct sam_usart_config_s * const config) /* Select and disable generic clock channel */ - putreg8(regval, SAM_GCLK_CLKCTRL); + putreg16(regval, SAM_GCLK_CLKCTRL); /* Wait for clock to become disabled */ - while ((getreg8(SAM_GCLK_CLKCTRL) & GCLK_CLKCTRL_CLKEN) != 0); + while ((getreg16(SAM_GCLK_CLKCTRL) & GCLK_CLKCTRL_CLKEN) != 0); /* Select the SERCOM_GCLK_ID_SLOW clock generator */ @@ -181,12 +181,12 @@ sam_gclk_configure(const struct sam_usart_config_s * const config) /* Write the new configuration */ - putreg8(regval, SAM_GCLK_CLKCTRL); + putreg16(regval, SAM_GCLK_CLKCTRL); /* Enable the GCLK */ regval |= GCLK_CLKCTRL_CLKEN; - putreg8(regval, SAM_GCLK_CLKCTRL); + putreg16(regval, SAM_GCLK_CLKCTRL); } #endif @@ -317,7 +317,7 @@ sam_usart_configure(const struct sam_usart_config_s * const config) /* Write configuration to CTRLA */ - putreg32(ctrlb, config->base + SAM_USART_CTRLA_OFFSET); + putreg32(ctrla, config->base + SAM_USART_CTRLA_OFFSET); return OK; } #endif diff --git a/arch/arm/src/samd/sam_port.c b/arch/arm/src/samd/sam_port.c index 6241ae02284..42a7322276c 100644 --- a/arch/arm/src/samd/sam_port.c +++ b/arch/arm/src/samd/sam_port.c @@ -146,7 +146,7 @@ static inline void sam_configinput(uintptr_t base, port_pinset_t pinset) { /* Select the upper half word and adjust the bit setting */ - regval = PORT_WRCONFIG_HWSEL; + regval |= PORT_WRCONFIG_HWSEL; pin -= 16; } @@ -243,7 +243,7 @@ static inline void sam_configoutput(uintptr_t base, port_pinset_t pinset) { /* Select the upper half word and adjust the bit setting */ - regval = PORT_WRCONFIG_HWSEL; + regval |= PORT_WRCONFIG_HWSEL; pin -= 16; } @@ -320,7 +320,7 @@ static inline void sam_configperiph(uintptr_t base, port_pinset_t pinset) { /* Select the upper half word and adjust the bit setting */ - regval = PORT_WRCONFIG_HWSEL; + regval |= PORT_WRCONFIG_HWSEL; pin -= 16; } @@ -328,8 +328,8 @@ static inline void sam_configperiph(uintptr_t base, port_pinset_t pinset) /* Set the pin function */ - func = (pinset & PORT_FUNC_MASK) >> PORT_FUNC_SHIFT; - regval = (func << PORT_WRCONFIG_PMUX_SHIFT); + func = (pinset & PORT_FUNC_MASK) >> PORT_FUNC_SHIFT; + regval |= (func << PORT_WRCONFIG_PMUX_SHIFT); /* Check for pull-up/down selection */ @@ -386,7 +386,7 @@ static inline void sam_configreset(uintptr_t base, port_pinset_t pinset) /* Disable the I/O synchronizer */ - regval = getreg32(base + SAM_PORT_CTRL_OFFSET); + regval = getreg32(base + SAM_PORT_CTRL_OFFSET); regval &= ~bit; putreg32(regval, base + SAM_PORT_CTRL_OFFSET); @@ -401,7 +401,7 @@ static inline void sam_configreset(uintptr_t base, port_pinset_t pinset) { /* Select the upper half word and adjust the bit setting */ - regval = PORT_WRCONFIG_HWSEL; + regval |= PORT_WRCONFIG_HWSEL; pin -= 16; } diff --git a/arch/arm/src/samd/sam_port.h b/arch/arm/src/samd/sam_port.h index dce1d52c133..f8ff14e9537 100644 --- a/arch/arm/src/samd/sam_port.h +++ b/arch/arm/src/samd/sam_port.h @@ -106,10 +106,10 @@ */ #define PORT_PULL_SHIFT (20) /* Bits 20-21: Pull-up/down resistor control */ -#define PORT_PULL_MASK (3 << PORT_FUNC_SHIFT) -# define PORT_PULL_NONE (0 << PORT_FUNC_SHIFT) -# define PORT_PULL_UP (1 << PORT_FUNC_SHIFT) -# define PORT_PULL_DOWN (2 << PORT_FUNC_SHIFT) +#define PORT_PULL_MASK (3 << PORT_PULL_SHIFT) +# define PORT_PULL_NONE (0 << PORT_PULL_SHIFT) +# define PORT_PULL_UP (1 << PORT_PULL_SHIFT) +# define PORT_PULL_DOWN (2 << PORT_PULL_SHIFT) /* Peripheral Function * diff --git a/arch/arm/src/samd/sam_serial.c b/arch/arm/src/samd/sam_serial.c index 8ed18db04dc..3f8e9b1ba8c 100644 --- a/arch/arm/src/samd/sam_serial.c +++ b/arch/arm/src/samd/sam_serial.c @@ -660,15 +660,21 @@ static int sam_usart5_interrupt(int irq, void *context) static int sam_setup(struct uart_dev_s *dev) { + int ret = 0; #ifndef CONFIG_SUPPRESS_UART_CONFIG struct sam_dev_s *priv = (struct sam_dev_s*)dev->priv; - /* Configure the SERCOM as a USART */ + /* Configure the SERCOM as a USART. Don't reconfigure the console UART; + * that was already done in sam_lowputc.c. + */ - return sam_usart_initialize(priv->config); -#else - return OK; + if (!dev->isconsole) + { + ret = sam_usart_initialize(priv->config); + } #endif + + return ret; } /**************************************************************************** @@ -676,7 +682,7 @@ static int sam_setup(struct uart_dev_s *dev) * * Description: * Disable the USART. This method is called when the serial port is - * closed + * closed. The exception is the serial console which is never shutdown. * ****************************************************************************/ @@ -685,10 +691,14 @@ static void sam_shutdown(struct uart_dev_s *dev) struct sam_dev_s *priv = (struct sam_dev_s*)dev->priv; /* Resetting the SERCOM restores all registers to the reget state and - * disables the SERCOM. + * disables the SERCOM. Ignore any requests to shutown the console + * device (shouldn't happen). */ - sam_usart_reset(priv->config); + if (!dev->isconsole) + { + sam_usart_reset(priv->config); + } } /**************************************************************************** @@ -743,7 +753,13 @@ static void sam_detach(struct uart_dev_s *dev) struct sam_dev_s *priv = (struct sam_dev_s*)dev->priv; const struct sam_usart_config_s * const config = priv->config; + /* Disable interrupts at the SERCOM device and at the NVIC */ + + sam_disableallints(priv); up_disable_irq(config->irq); + + /* Detach the interrupt handler */ + irq_detach(config->irq); } @@ -933,6 +949,10 @@ static bool sam_txempty(struct uart_dev_s *dev) * serial console will be available during bootup. This must be called * before sam_serialinit. * + * NOTE: On this platform up_earlyserialinit() does not really do + * anything of consequence and probably could be eliminated with little + * effort. + * ****************************************************************************/ void up_earlyserialinit(void) @@ -956,11 +976,10 @@ void up_earlyserialinit(void) sam_disableallints(TTYS5_DEV.priv); #endif - /* Configuration whichever one is the console */ + /* Mark the serial console (if any) */ #ifdef HAVE_SERIAL_CONSOLE CONSOLE_DEV.isconsole = true; - sam_setup(&CONSOLE_DEV); #endif } diff --git a/configs/samd20-xplained/README.txt b/configs/samd20-xplained/README.txt index 8055911a7ca..c968c214f8c 100644 --- a/configs/samd20-xplained/README.txt +++ b/configs/samd20-xplained/README.txt @@ -405,12 +405,12 @@ Serial Consoles SERCOM4 is available on connectors EXT1 and EXT3 - PIN EXT1 EXT3 GPIO Function - ---- ---- ------ ----------- - 13 PB09 PB13 SERCOM4 / USART RX - 14 PB08 PB12 SERCOM4 / USART TX - 19 19 GND - 20 20 VCC + PIN EXT1 EXT3 GPIO Function + ---- ---- ---- ------------------ + 13 PB09 PB13 SERCOM4 / USART RX + 14 PB08 PB12 SERCOM4 / USART TX + 19 19 GND + 20 20 VCC If you have a TTL to RS-232 converter then this is the most convenient serial console to use. It is the default in all of these configurations. diff --git a/configs/samd20-xplained/include/board.h b/configs/samd20-xplained/include/board.h index e94db4d8dc4..216e38c0bfe 100644 --- a/configs/samd20-xplained/include/board.h +++ b/configs/samd20-xplained/include/board.h @@ -56,13 +56,14 @@ /* Clocking *************************************************************************/ /* Overview * - * OSC8M Output = 8MHz - * `- GCLK1 Input = 8MHz Prescaler = 1 output = 8MHz - * `- DFLL Input = 8MHz Multiplier = 6 output = 48MHz - * `- PM Input = 48Mhz CPU divider = 1 CPU frequency = 48MHz - * APBA divider = 1 APBA frequency = 48MHz - * APBB divider = 1 APBB frequency = 48MHz - * APBC divider = 1 APBC frequency = 48MHz + * OSC8M Output = 8MHz + * `- GCLK1 Input = 8MHz Prescaler = 1 output = 8MHz + * `- DFLL Input = 8MHz Multiplier = 6 output = 48MHz + * `- GCLK0 Input = 48MHz Prescaler = 1 output = 48MHz + * `- PM Input = 48Mhz CPU divider = 1 CPU frequency = 48MHz + * APBA divider = 1 APBA frequency = 48MHz + * APBB divider = 1 APBB frequency = 48MHz + * APBC divider = 1 APBC frequency = 48MHz * * The SAMD20 Xplained Pro has one on-board crystal: *