summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-02-17 18:09:17 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-02-17 18:09:17 -0600
commit601422a19569fa1805e681be6a989c9a3a2e1cb4 (patch)
treec454c863eba2bc33de6146a8fff8b9cad3b99148
parent4227604c17a8dc26c8b0f679b79945eabb090e9f (diff)
downloadnuttx-601422a19569fa1805e681be6a989c9a3a2e1cb4.tar.gz
nuttx-601422a19569fa1805e681be6a989c9a3a2e1cb4.tar.bz2
nuttx-601422a19569fa1805e681be6a989c9a3a2e1cb4.zip
SAMD20: Fix BAUD calculation. Now comes up okay about 20% of the time
-rw-r--r--nuttx/arch/arm/src/samd/sam_lowputc.c56
-rw-r--r--nuttx/configs/samd20-xplained/nsh/defconfig5
2 files changed, 39 insertions, 22 deletions
diff --git a/nuttx/arch/arm/src/samd/sam_lowputc.c b/nuttx/arch/arm/src/samd/sam_lowputc.c
index 4d2b71927..376358e97 100644
--- a/nuttx/arch/arm/src/samd/sam_lowputc.c
+++ b/nuttx/arch/arm/src/samd/sam_lowputc.c
@@ -124,7 +124,7 @@ sam_gclk_configure(const struct sam_usart_config_s * const config)
glckcore = (uint8_t)SERCOM_GCLK_ID_CORE(config->sercom);
regval = ((uint16_t)glckcore << GCLK_CLKCTRL_ID_SHIFT);
- /* Select and disable generic clock channel */
+ /* Select and disable the SERCOMn_GCLK_ID_CORE generic clock */
putreg16(regval, SAM_GCLK_CLKCTRL);
@@ -132,9 +132,9 @@ sam_gclk_configure(const struct sam_usart_config_s * const config)
while ((getreg16(SAM_GCLK_CLKCTRL) & GCLK_CLKCTRL_CLKEN) != 0);
- /* Select the SERCOMn_GCLK_ID_CORE clock generator */
+ /* Select the SERCOMn_GCLK_ID_CORE source clock generator */
- regval |= config->gclkgen << GCLK_CLKCTRL_GEN_SHIFT;
+ regval |= (uint16_t)config->gclkgen << GCLK_CLKCTRL_GEN_SHIFT;
#if 0 /* Not yet supported */
/* Enable write lock if requested to prevent further modification */
@@ -149,7 +149,7 @@ sam_gclk_configure(const struct sam_usart_config_s * const config)
putreg16(regval, SAM_GCLK_CLKCTRL);
- /* Enable the GCLK */
+ /* Enable the SERCOMn_GCLK_ID_CORE generic clock */
regval |= GCLK_CLKCTRL_CLKEN;
putreg16(regval, SAM_GCLK_CLKCTRL);
@@ -158,7 +158,7 @@ sam_gclk_configure(const struct sam_usart_config_s * const config)
regval = (SERCOM_GCLK_ID_SLOW << GCLK_CLKCTRL_ID_SHIFT);
- /* Select and disable generic clock channel */
+ /* Select and disable the SERCOM_GCLK_ID_SLOW generic clock */
putreg16(regval, SAM_GCLK_CLKCTRL);
@@ -166,9 +166,9 @@ sam_gclk_configure(const struct sam_usart_config_s * const config)
while ((getreg16(SAM_GCLK_CLKCTRL) & GCLK_CLKCTRL_CLKEN) != 0);
- /* Select the SERCOM_GCLK_ID_SLOW clock generator */
+ /* Select the SERCOM_GCLK_ID_SLOW clock source generator */
- regval |= config->gclkgen << GCLK_CLKCTRL_GEN_SHIFT;
+ regval |= (uint16_t)config->gclkgen << GCLK_CLKCTRL_GEN_SHIFT;
#if 0 /* Not yet supported */
/* Enable write lock if requested to prevent further modification */
@@ -183,7 +183,7 @@ sam_gclk_configure(const struct sam_usart_config_s * const config)
putreg16(regval, SAM_GCLK_CLKCTRL);
- /* Enable the GCLK */
+ /* Enable the SERCOM_GCLK_ID_SLOW generic clock */
regval |= GCLK_CLKCTRL_CLKEN;
putreg16(regval, SAM_GCLK_CLKCTRL);
@@ -204,26 +204,42 @@ sam_usart_configure(const struct sam_usart_config_s * const config)
{
uint32_t ctrla;
uint32_t ctrlb;
- uint32_t baud;
-
- /* Check if baud is within the valid range. */
-
- if (config->baud > (config->frequency >> 1))
- {
- return -ERANGE;
- }
-
- /* Calculate BAUD divider from the source clock frequency and desired baud */
+ uint16_t baud;
+ uint64_t tmp;
+
+ /* Calculate BAUD divider from the source clock frequency and desired.
+ * baud. For asynchronous mode, the formula for the baud generation is
+ *
+ * Fbaud = (Frefclk / 16) * (1 - (BAUD / 65,536))
+ *
+ * Or,
+ *
+ * BAUD = 65,536 * (1 - 16 * (Fbaud / Fref))
+ * = 65,536 - 16 * 65,536 * Fbaud / Fref
+ *
+ * Example: Fref = 48MHz and Fbaud = 9600
+ *
+ * BAUD = 65,326
+ * Fbaud = 9600
+ *
+ * Example: Fref = 48MHz and Fbaud = 115,200
+ *
+ * BAUD = 63,019
+ * Fbaud = 115,219
+ */
- baud = (config->frequency / (2 * config->baud)) - 1;
+ tmp = (uint64_t)config->baud << 20;
+ tmp = (tmp + (config->frequency >> 1)) / config->frequency;
/* Verify that the calculated result is within range */
- if (baud > UINT16_MAX)
+ if (tmp < 1 || tmp > UINT16_MAX)
{
return -ERANGE;
}
+ baud = 65536 - (uint16_t)tmp;
+
/* Disable all USART interrupts */
putreg8(USART_INT_ALL, config->base + SAM_USART_INTENCLR_OFFSET);
diff --git a/nuttx/configs/samd20-xplained/nsh/defconfig b/nuttx/configs/samd20-xplained/nsh/defconfig
index 61abc85a7..26afb1c4e 100644
--- a/nuttx/configs/samd20-xplained/nsh/defconfig
+++ b/nuttx/configs/samd20-xplained/nsh/defconfig
@@ -249,6 +249,7 @@ CONFIG_NSH_MMCSDMINOR=0
# CONFIG_SAMD20_XPLAINED_IOMODULE is not set
# CONFIG_SAMD20_XPLAINED_OLED1MODULE is not set
# CONFIG_SAMD20_XPLAINED_USART4_EXT1 is not set
+# CONFIG_SAMD20_XPLAINED_USART4_EXT2 is not set
CONFIG_SAMD20_XPLAINED_USART4_EXT3=y
#
@@ -367,7 +368,7 @@ CONFIG_USART4_SERIAL_CONSOLE=y
#
CONFIG_USART3_RXBUFSIZE=64
CONFIG_USART3_TXBUFSIZE=64
-CONFIG_USART3_BAUD=9600
+CONFIG_USART3_BAUD=115200
CONFIG_USART3_BITS=8
CONFIG_USART3_PARITY=0
CONFIG_USART3_2STOP=0
@@ -379,7 +380,7 @@ CONFIG_USART3_2STOP=0
#
CONFIG_USART4_RXBUFSIZE=64
CONFIG_USART4_TXBUFSIZE=64
-CONFIG_USART4_BAUD=9600
+CONFIG_USART4_BAUD=115200
CONFIG_USART4_BITS=8
CONFIG_USART4_PARITY=0
CONFIG_USART4_2STOP=0