summaryrefslogtreecommitdiff
path: root/nuttx/arch/arm/src/samd
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-02-15 17:53:55 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-02-15 17:53:55 -0600
commit6bd712c5ac72488374b471b688c4bf5ee017335b (patch)
tree708adba2ed764491420147fd570a8a50e02a8f72 /nuttx/arch/arm/src/samd
parentbddb0325a9da22d350926b53cd05ca99ac3b8fb8 (diff)
downloadnuttx-6bd712c5ac72488374b471b688c4bf5ee017335b.tar.gz
nuttx-6bd712c5ac72488374b471b688c4bf5ee017335b.tar.bz2
nuttx-6bd712c5ac72488374b471b688c4bf5ee017335b.zip
SAMD20: More SERCOM USART configuration logic
Diffstat (limited to 'nuttx/arch/arm/src/samd')
-rw-r--r--nuttx/arch/arm/src/samd/sam_lowputc.c238
-rw-r--r--nuttx/arch/arm/src/samd/sam_lowputc.h6
-rw-r--r--nuttx/arch/arm/src/samd/sam_usart.c6
-rw-r--r--nuttx/arch/arm/src/samd/sam_usart.h1
4 files changed, 243 insertions, 8 deletions
diff --git a/nuttx/arch/arm/src/samd/sam_lowputc.c b/nuttx/arch/arm/src/samd/sam_lowputc.c
index 58c043fc7..7c10b61ec 100644
--- a/nuttx/arch/arm/src/samd/sam_lowputc.c
+++ b/nuttx/arch/arm/src/samd/sam_lowputc.c
@@ -4,6 +4,15 @@
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
+ * References:
+ * 1. "Atmel SAM D20J / SAM D20G / SAM D20E ARM-Based Microcontroller
+ * Datasheet", 42129J–SAM–12/2013
+ * 2. Atmel sample code. This code has an ASF license with is compatible
+ * with the NuttX BSD license, but includes the provision that this
+ * code not be used in non-Atmel products. That sample code was used
+ * only as a reference so I believe that only the NuttX BSD license
+ * applies.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -41,14 +50,23 @@
#include <stdint.h>
#include <assert.h>
+#include <errno.h>
+
+#include "up_arch.h"
#include "sam_config.h"
+#include "chip/sam_pm.h"
+#include "chip/sam_usart.h"
#include "sam_usart.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
+#ifndef OK
+# define OK 0
+#endif
+
/****************************************************************************
* Private Data
****************************************************************************/
@@ -58,16 +76,195 @@
****************************************************************************/
/****************************************************************************
+ * Name: sam_wait_synchronization
+ *
+ * Description:
+ * Wait until the SERCOM USART reports that it is synchronized.
+ *
+ ****************************************************************************/
+
+#ifdef HAVE_USART
+static void
+sam_wait_synchronization(const struct sam_usart_config_s * const config)
+{
+ while ((getreg16(config->base + SAM_USART_STATUS_OFFSET) & USART_STATUS_SYNCBUSY) != 0);
+}
+#endif
+
+/****************************************************************************
+ * Name: sam_gclk_configure
+ *
+ * Description:
+ * Configure the SERCOM USART source clock.
+ *
+ ****************************************************************************/
+
+#ifdef HAVE_USART
+static inline int
+sam_gclk_configure(const struct sam_usart_config_s * const config)
+{
+#warning Missing logic
+ return -ENOSYS;
+}
+#endif
+
+/****************************************************************************
+ * Name: sam_usart_configure
+ *
+ * Description:
+ * Configure the SERCOM USART operating mode (as a normal UART).
+ *
+ ****************************************************************************/
+
+#ifdef HAVE_USART
+static inline int
+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 */
+
+ baud = (config->frequency / (2 * config->baud)) - 1;
+
+ /* Verify that the calculated result is within range */
+
+ if (baud > UINT16_MAX)
+ {
+ return -ERANGE;
+ }
+
+ /* Wait until synchronization is complete */
+
+ sam_wait_synchronization(config);
+
+ /* Set baud val */
+
+ putreg16((uint16_t)baud, config->base + SAM_USART_BAUD_OFFSET);
+
+ /* Configure the USART CTRLA and CTRLB registers */
+
+ ctrla = (USART_CTRLA_MODE_INTUSART | (uint32_t)config->muxconfig |
+ USART_CTRLA_ASYNCH | USART_CTRLA_CPOL_NORMAL |
+ USART_CTRLA_LSBFIRST);
+ ctrlb = (USART_CTRLB_TXEN | USART_CTRLB_RXEN);
+
+ /* Set the number of stop bits */
+
+ if (config->stopbits2)
+ {
+ ctrlb |= USART_CTRLB_SBMODE;
+ }
+
+ /* Set the USART word size */
+
+ switch (config->bits)
+ {
+ case 5:
+ ctrlb |= USART_CTRLB_CHSIZE_5BITS;
+ break;
+
+ case 6:
+ ctrlb |= USART_CTRLB_CHSIZE_6BITS;
+ break;
+
+ case 7:
+ ctrlb |= USART_CTRLB_CHSIZE_7BITS;
+ break;
+
+ default:
+ case 8:
+ break;
+
+ case 9:
+ ctrlb |= USART_CTRLB_CHSIZE_9BITS;
+ break;
+ }
+
+ /* Set parity mode */
+
+ switch (config->parity)
+ {
+ default:
+ case 0: /* None */
+ break;
+
+ case 1: /* Odd */
+ ctrlb |= USART_CTRLB_PODD;
+ /* Fall through */
+
+ case 2: /* Even */
+ ctrla |= USART_CTRLA_FORM_PARITY;
+ break;
+ }
+
+#if 0 /* Not supported */
+ /* Set run mode during device sleep */
+
+ if (config->runinstandby)
+ {
+ /* Enable in sleep mode */
+
+ ctrla |= USART_CTRLA_RUNSTDBY;
+ }
+#endif
+
+ /* Wait until synchronization is complete */
+
+ sam_wait_synchronization(config);
+
+ /* Write configuration to CTRLB */
+
+ putreg32(ctrlb, SAM_USART5_CTRLB);
+
+ /* Wait until synchronization is complete */
+
+ sam_wait_synchronization(config);
+
+ /* Write configuration to CTRLA */
+
+ putreg32(ctrlb, SAM_USART5_CTRLA);
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: sam_pad_configure
+ *
+ * Description:
+ * Configure the SERCOM USART pads.
+ *
+ ****************************************************************************/
+
+#ifdef HAVE_USART
+static inline int
+sam_pad_configure(const struct sam_usart_config_s * const config)
+{
+#warning Missing logic
+ return -ENOSYS;
+}
+#endif
+
+/****************************************************************************
* Public Functions
****************************************************************************/
-/************************************************************************************
+/****************************************************************************
* Name: sam_lowsetup
*
* Description:
- * Called at the very beginning of _start. Performs low level initialization.
+ * Called at the very beginning of _start. Performs low level
+ * initialization.
*
- ************************************************************************************/
+ ****************************************************************************/
void sam_lowsetup(void)
{
@@ -75,17 +272,46 @@ void sam_lowsetup(void)
}
/****************************************************************************
- * Name: sam_usartconfig
+ * Name: sam_usart_initialize
*
* Description:
* Set the configuration of a SERCOM for provided USART configuration.
+ * This configures the SERCOM as a USART, but does not configure USART
+ * interrupts or enable the USART.
*
*****************************************************************************/
#ifdef HAVE_USART
-void sam_usartconfig(const struct sam_usart_config_s *config)
+int sam_usart_initialize(const struct sam_usart_config_s * const config)
{
-#warning Missing logic
+ uint32_t regval;
+ int ret;
+
+ /* Enable clocking to the SERCOM module in PM */
+
+ regval = getreg32(SAM_PM_APBCMASK);
+ regval |= PM_APBCMASK_SERCOM(config->sercom);
+ putreg32(regval, SAM_PM_APBCMASK);
+
+ /* Configure the GCCLK for the SERCOM module */
+
+ ret = sam_gclk_configure(config);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ /* Set configuration according to the board configuration */
+
+ ret = sam_usart_configure(config);
+ if(ret < 0)
+ {
+ return ret;
+ }
+
+ /* Configure USART pins */
+
+ return sam_pad_configure(config);
}
#endif
diff --git a/nuttx/arch/arm/src/samd/sam_lowputc.h b/nuttx/arch/arm/src/samd/sam_lowputc.h
index af553fae5..cefd3ea03 100644
--- a/nuttx/arch/arm/src/samd/sam_lowputc.h
+++ b/nuttx/arch/arm/src/samd/sam_lowputc.h
@@ -81,16 +81,18 @@ extern "C"
void sam_lowsetup(void);
/****************************************************************************
- * Name: sam_usartconfig
+ * Name: sam_usart_initialize
*
* Description:
* Set the configuration of a SERCOM for provided USART configuration.
+ * This configures the SERCOM as a USART, but does not configure USART
+ * interrupts or enable the USART.
*
*****************************************************************************/
#ifdef HAVE_USART
struct sam_usart_config_s;
-void sam_usartconfig(const struct sam_usart_config_s *config);
+int sam_usart_initialize(const struct sam_usart_config_s * const config);
#endif
/****************************************************************************
diff --git a/nuttx/arch/arm/src/samd/sam_usart.c b/nuttx/arch/arm/src/samd/sam_usart.c
index 2d9180eb9..dae8c851b 100644
--- a/nuttx/arch/arm/src/samd/sam_usart.c
+++ b/nuttx/arch/arm/src/samd/sam_usart.c
@@ -73,6 +73,7 @@ const struct sam_usart_config_s g_usart0config =
.pad2 = BOARD_SERCOM0_PINMAP_PAD2,
.pad3 = BOARD_SERCOM0_PINMAP_PAD3,
.muxconfig = BOARD_SERCOM0_MUXCONFIG,
+ .frequency = BOARD_SERCOM0_FREQUENCY,
.base = SAM_SERCOM0_BASE,
};
#endif
@@ -92,6 +93,7 @@ const struct sam_usart_config_s g_usart1config =
.pad2 = BOARD_SERCOM1_PINMAP_PAD2,
.pad3 = BOARD_SERCOM1_PINMAP_PAD3,
.muxconfig = BOARD_SERCOM1_MUXCONFIG,
+ .frequency = BOARD_SERCOM1_FREQUENCY,
.base = SAM_SERCOM1_BASE,
};
#endif
@@ -111,6 +113,7 @@ const struct sam_usart_config_s g_usart2config =
.pad2 = BOARD_SERCOM2_PINMAP_PAD2,
.pad3 = BOARD_SERCOM2_PINMAP_PAD3,
.muxconfig = BOARD_SERCOM2_MUXCONFIG,
+ .frequency = BOARD_SERCOM2_FREQUENCY,
.base = SAM_SERCOM2_BASE,
};
#endif
@@ -130,6 +133,7 @@ const struct sam_usart_config_s g_usart3config =
.pad2 = BOARD_SERCOM3_PINMAP_PAD2,
.pad3 = BOARD_SERCOM3_PINMAP_PAD3,
.muxconfig = BOARD_SERCOM3_MUXCONFIG,
+ .frequency = BOARD_SERCOM3_FREQUENCY,
.base = SAM_SERCOM3_BASE,
};
#endif
@@ -149,6 +153,7 @@ const struct sam_usart_config_s g_usart4config =
.pad2 = BOARD_SERCOM4_PINMAP_PAD2,
.pad3 = BOARD_SERCOM4_PINMAP_PAD3,
.muxconfig = BOARD_SERCOM4_MUXCONFIG,
+ .frequency = BOARD_SERCOM4_FREQUENCY,
.base = SAM_SERCOM4_BASE,
};
#endif
@@ -168,6 +173,7 @@ const struct sam_usart_config_s g_usart5config =
.pad2 = BOARD_SERCOM5_PINMAP_PAD2,
.pad3 = BOARD_SERCOM5_PINMAP_PAD3,
.muxconfig = BOARD_SERCOM5_MUXCONFIG,
+ .frequency = BOARD_SERCOM5_FREQUENCY,
.base = SAM_SERCOM5_BASE,
};
#endif
diff --git a/nuttx/arch/arm/src/samd/sam_usart.h b/nuttx/arch/arm/src/samd/sam_usart.h
index b61a45b46..9d63e3563 100644
--- a/nuttx/arch/arm/src/samd/sam_usart.h
+++ b/nuttx/arch/arm/src/samd/sam_usart.h
@@ -91,6 +91,7 @@ struct sam_usart_config_s
port_pinset_t pad2; /* Pin configuration for PAD2 */
port_pinset_t pad3; /* Pin configuration for PAD3 */
uint32_t muxconfig; /* Pad multiplexing configuration */
+ uint32_t frequency; /* Source clock frequency */
uintptr_t base; /* SERCOM base address */
};