SAMD20: Completes low-level USART logic
This commit is contained in:
parent
fdccfe930b
commit
cb6bf52939
@ -47,11 +47,12 @@
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include "chip.h"
|
||||
#include "chip/sam_sercom.h"
|
||||
|
||||
/********************************************************************************************
|
||||
* Pre-processor Definitions
|
||||
********************************************************************************************/
|
||||
/* USART register offsets ********************************************************************/
|
||||
/* USART register offsets *******************************************************************/
|
||||
|
||||
#define SAM_USART_CTRLA_OFFSET 0x0000 /* Control A register */
|
||||
#define SAM_USART_CTRLB_OFFSET 0x0000 /* Control B register */
|
||||
@ -63,7 +64,7 @@
|
||||
#define SAM_USART_STATUS_OFFSET 0x0000 /* Status register */
|
||||
#define SAM_USART_DATA_OFFSET 0x0000 /* Data register */
|
||||
|
||||
/* USART register addresses ******************************************************************/
|
||||
/* USART register addresses *****************************************************************/
|
||||
|
||||
#define SAM_USART0_CTRLA (SAM_SERCOM0_BASE+SAM_USART_CTRLA_OFFSET)
|
||||
#define SAM_USART0_CTRLB (SAM_SERCOM0_BASE+SAM_USART_CTRLB_OFFSET)
|
||||
@ -125,7 +126,7 @@
|
||||
#define SAM_USART5_STATUS (SAM_SERCOM5_BASE+SAM_USART_STATUS_OFFSET)
|
||||
#define SAM_USART5_DATA (SAM_SERCOM5_BASE+SAM_USART_DATA_OFFSET)
|
||||
|
||||
/* USART register bit definitions ************************************************************/
|
||||
/* USART register bit definitions ***********************************************************/
|
||||
|
||||
/* Control A register */
|
||||
|
||||
@ -193,6 +194,8 @@
|
||||
#define USART_INT_RXC (1 << 2) /* Bit 2: Receive complete interrupt */
|
||||
#define USART_INT_RXS (1 << 3) /* Bit 3: Receive start interrupt */
|
||||
|
||||
#define USART_INT_ALL (0x0f)
|
||||
|
||||
/* Status register */
|
||||
|
||||
#define USART_STATUS_PERR (1 << 0) /* Bit 0: Parity error */
|
||||
|
@ -55,8 +55,11 @@
|
||||
#include "up_arch.h"
|
||||
|
||||
#include "sam_config.h"
|
||||
|
||||
#include "chip/sam_pm.h"
|
||||
#include "chip/sam_gclk.h"
|
||||
#include "chip/sam_usart.h"
|
||||
|
||||
#include "sam_usart.h"
|
||||
|
||||
/****************************************************************************
|
||||
@ -100,11 +103,80 @@ sam_wait_synchronization(const struct sam_usart_config_s * const config)
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_USART
|
||||
static inline int
|
||||
static inline void
|
||||
sam_gclk_configure(const struct sam_usart_config_s * const config)
|
||||
{
|
||||
#warning Missing logic
|
||||
return -ENOSYS;
|
||||
uint8_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);
|
||||
|
||||
/* Select and disable generic clock channel */
|
||||
|
||||
putreg8(regval, SAM_GCLK_CLKCTRL);
|
||||
|
||||
/* Wait for clock to become disabled */
|
||||
|
||||
while ((getreg8(SAM_GCLK_CLKCTRL) & GCLK_CLKCTRL_CLKEN) != 0);
|
||||
|
||||
/* Select the SERCOMn_GCLK_ID_CORE clock generator */
|
||||
|
||||
regval |= config->gclkgen << GCLK_CLKCTRL_GEN_SHIFT;
|
||||
|
||||
#if 0 /* Not yet supported */
|
||||
/* Enable write lock if requested to prevent further modification */
|
||||
|
||||
if (config->wrlock)
|
||||
{
|
||||
regval |= GCLK_CLKCTRL_WRTLOCK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Write the new configuration */
|
||||
|
||||
putreg8(regval, SAM_GCLK_CLKCTRL);
|
||||
|
||||
/* Enable the GCLK */
|
||||
|
||||
regval |= GCLK_CLKCTRL_CLKEN;
|
||||
putreg8(regval, SAM_GCLK_CLKCTRL);
|
||||
|
||||
/* Set up the SERCOM_GCLK_ID_SLOW clock */
|
||||
|
||||
regval = (SERCOM_GCLK_ID_SLOW << GCLK_CLKCTRL_ID_SHIFT);
|
||||
|
||||
/* Select and disable generic clock channel */
|
||||
|
||||
putreg8(regval, SAM_GCLK_CLKCTRL);
|
||||
|
||||
/* Wait for clock to become disabled */
|
||||
|
||||
while ((getreg8(SAM_GCLK_CLKCTRL) & GCLK_CLKCTRL_CLKEN) != 0);
|
||||
|
||||
/* Select the SERCOM_GCLK_ID_SLOW clock generator */
|
||||
|
||||
regval |= config->gclkgen << GCLK_CLKCTRL_GEN_SHIFT;
|
||||
|
||||
#if 0 /* Not yet supported */
|
||||
/* Enable write lock if requested to prevent further modification */
|
||||
|
||||
if (config->wrlock)
|
||||
{
|
||||
regval |= GCLK_CLKCTRL_WRTLOCK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Write the new configuration */
|
||||
|
||||
putreg8(regval, SAM_GCLK_CLKCTRL);
|
||||
|
||||
/* Enable the GCLK */
|
||||
|
||||
regval |= GCLK_CLKCTRL_CLKEN;
|
||||
putreg8(regval, SAM_GCLK_CLKCTRL);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -142,11 +214,15 @@ sam_usart_configure(const struct sam_usart_config_s * const config)
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
/* Disable all USART interrupts */
|
||||
|
||||
putreg8(USART_INT_ALL, config->base + SAM_USART_INTENCLR_OFFSET);
|
||||
|
||||
/* Wait until synchronization is complete */
|
||||
|
||||
sam_wait_synchronization(config);
|
||||
|
||||
/* Set baud val */
|
||||
/* Set baud divisor */
|
||||
|
||||
putreg16((uint16_t)baud, config->base + SAM_USART_BAUD_OFFSET);
|
||||
|
||||
@ -223,7 +299,7 @@ sam_usart_configure(const struct sam_usart_config_s * const config)
|
||||
|
||||
/* Write configuration to CTRLB */
|
||||
|
||||
putreg32(ctrlb, SAM_USART5_CTRLB);
|
||||
putreg32(ctrlb, config->base + SAM_USART_CTRLB_OFFSET);
|
||||
|
||||
/* Wait until synchronization is complete */
|
||||
|
||||
@ -231,7 +307,7 @@ sam_usart_configure(const struct sam_usart_config_s * const config)
|
||||
|
||||
/* Write configuration to CTRLA */
|
||||
|
||||
putreg32(ctrlb, SAM_USART5_CTRLA);
|
||||
putreg32(ctrlb, config->base + SAM_USART_CTRLA_OFFSET);
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
@ -245,11 +321,98 @@ sam_usart_configure(const struct sam_usart_config_s * const config)
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_USART
|
||||
static inline int
|
||||
static inline void
|
||||
sam_pad_configure(const struct sam_usart_config_s * const config)
|
||||
{
|
||||
#warning Missing logic
|
||||
return -ENOSYS;
|
||||
/* Configure SERCOM pads */
|
||||
|
||||
if (config->pad0 != 0)
|
||||
{
|
||||
sam_configport(config->pad0);
|
||||
}
|
||||
|
||||
if (config->pad1 != 0)
|
||||
{
|
||||
sam_configport(config->pad1);
|
||||
}
|
||||
|
||||
if (config->pad2 != 0)
|
||||
{
|
||||
sam_configport(config->pad2);
|
||||
}
|
||||
|
||||
if (config->pad3 != 0)
|
||||
{
|
||||
sam_configport(config->pad3);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam_usart_internal
|
||||
*
|
||||
* 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
|
||||
int sam_usart_internal(const struct sam_usart_config_s * const config)
|
||||
{
|
||||
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 */
|
||||
|
||||
sam_gclk_configure(config);
|
||||
|
||||
/* Set configuration according to the board configuration */
|
||||
|
||||
ret = sam_usart_configure(config);
|
||||
if (ret == OK)
|
||||
{
|
||||
/* Configure USART pins */
|
||||
|
||||
sam_pad_configure(config);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam_usart_enable
|
||||
*
|
||||
* Description:
|
||||
* Enable the SERCOM USART (without enabling interrupts).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_USART
|
||||
static inline void
|
||||
sam_usart_enable(const struct sam_usart_config_s * const config)
|
||||
{
|
||||
uintptr_t regaddr;
|
||||
uint32_t regval;
|
||||
|
||||
/* Wait until synchronization is complete */
|
||||
|
||||
sam_wait_synchronization(config);
|
||||
|
||||
/* Enable USART module */
|
||||
|
||||
regaddr = config->base + SAM_USART_CTRLA_OFFSET;
|
||||
regval = getreg32(regaddr);
|
||||
regval |= USART_CTRLA_ENABLE;
|
||||
putreg32(regval, regaddr);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -268,7 +431,12 @@ sam_pad_configure(const struct sam_usart_config_s * const config)
|
||||
|
||||
void sam_lowsetup(void)
|
||||
{
|
||||
#warning Missing logic
|
||||
#ifdef HAVE_SERIAL_CONSOLE
|
||||
/* Configure and enable the console USART */
|
||||
|
||||
VERIFY(sam_usart_internal(&g_consoleconfig));
|
||||
sam_usart_enable(&g_consoleconfig);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -284,34 +452,17 @@ void sam_lowsetup(void)
|
||||
#ifdef HAVE_USART
|
||||
int sam_usart_initialize(const struct sam_usart_config_s * const config)
|
||||
{
|
||||
uint32_t regval;
|
||||
irqstate_t flags;
|
||||
int ret;
|
||||
|
||||
/* Enable clocking to the SERCOM module in PM */
|
||||
/* Just invoke the internal implementation, but with interrupts disabled
|
||||
* so that the operation is atomic.
|
||||
*/
|
||||
|
||||
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);
|
||||
flags = irqsave();
|
||||
ret = sam_usart_internal(config);
|
||||
irqrestore(flags);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -326,6 +477,23 @@ int sam_usart_initialize(const struct sam_usart_config_s * const config)
|
||||
#ifdef HAVE_SERIAL_CONSOLE
|
||||
void sam_lowputc(uint32_t ch)
|
||||
{
|
||||
#warning Missing logic
|
||||
uintptr_t base = g_consoleconfig.base;
|
||||
uintptr_t intflag = base + SAM_USART_INTFLAG_OFFSET;
|
||||
|
||||
/* Wait for the USART to be ready for new TX data */
|
||||
|
||||
while ((getreg8(intflag) & USART_INT_DRE) == 0);
|
||||
|
||||
/* Wait until synchronization is complete */
|
||||
|
||||
sam_wait_synchronization(&g_consoleconfig);
|
||||
|
||||
/* Write data to USART module */
|
||||
|
||||
putreg16((uint16_t)ch, base + SAM_USART_DATA_OFFSET);
|
||||
|
||||
/* Wait until data is sent */
|
||||
|
||||
while ((getreg8(intflag) & USART_INT_TXC) == 0);
|
||||
}
|
||||
#endif
|
||||
|
@ -65,7 +65,7 @@ const struct sam_usart_config_s g_usart0config =
|
||||
.parity = CONFIG_USART0_PARITY,
|
||||
.bits = CONFIG_USART0_BITS,
|
||||
.irq = SAM_IRQ_SERCOM0,
|
||||
.gclk = (BOARD_SERCOM0_SRCGCLKGEN >> GCLK_CLKCTRL_GEN_SHIFT),
|
||||
.gclkgen = (BOARD_SERCOM0_GCLKGEN >> GCLK_CLKCTRL_GEN_SHIFT),
|
||||
.stopbits2 = CONFIG_USART0_2STOP,
|
||||
.baud = CONFIG_USART0_BAUD,
|
||||
.pad0 = BOARD_SERCOM0_PINMAP_PAD0,
|
||||
@ -85,7 +85,7 @@ const struct sam_usart_config_s g_usart1config =
|
||||
.parity = CONFIG_USART1_PARITY,
|
||||
.bits = CONFIG_USART1_BITS,
|
||||
.irq = SAM_IRQ_SERCOM1,
|
||||
.gclk = (BOARD_SERCOM1_SRCGCLKGEN >> GCLK_CLKCTRL_GEN_SHIFT),
|
||||
.gclkgen = (BOARD_SERCOM1_GCLKGEN >> GCLK_CLKCTRL_GEN_SHIFT),
|
||||
.stopbits2 = CONFIG_USART1_2STOP,
|
||||
.baud = CONFIG_USART1_BAUD,
|
||||
.pad0 = BOARD_SERCOM1_PINMAP_PAD0,
|
||||
@ -105,7 +105,7 @@ const struct sam_usart_config_s g_usart2config =
|
||||
.parity = CONFIG_USART2_PARITY,
|
||||
.bits = CONFIG_USART2_BITS,
|
||||
.irq = SAM_IRQ_SERCOM2,
|
||||
.gclk = (BOARD_SERCOM2_SRCGCLKGEN >> GCLK_CLKCTRL_GEN_SHIFT),
|
||||
.gclkgen = (BOARD_SERCOM2_GCLKGEN >> GCLK_CLKCTRL_GEN_SHIFT),
|
||||
.stopbits2 = CONFIG_USART2_2STOP,
|
||||
.baud = CONFIG_USART2_BAUD,
|
||||
.pad0 = BOARD_SERCOM2_PINMAP_PAD0,
|
||||
@ -125,7 +125,7 @@ const struct sam_usart_config_s g_usart3config =
|
||||
.parity = CONFIG_USART3_PARITY,
|
||||
.bits = CONFIG_USART3_BITS,
|
||||
.irq = SAM_IRQ_SERCOM3,
|
||||
.gclk = (BOARD_SERCOM3_SRCGCLKGEN >> GCLK_CLKCTRL_GEN_SHIFT),
|
||||
.gclkgen = (BOARD_SERCOM3_GCLKGEN >> GCLK_CLKCTRL_GEN_SHIFT),
|
||||
.stopbits2 = CONFIG_USART3_2STOP,
|
||||
.baud = CONFIG_USART3_BAUD,
|
||||
.pad0 = BOARD_SERCOM3_PINMAP_PAD0,
|
||||
@ -145,7 +145,7 @@ const struct sam_usart_config_s g_usart4config =
|
||||
.parity = CONFIG_USART4_PARITY,
|
||||
.bits = CONFIG_USART4_BITS,
|
||||
.irq = SAM_IRQ_SERCOM4,
|
||||
.gclk = (BOARD_SERCOM4_SRCGCLKGEN >> GCLK_CLKCTRL_GEN_SHIFT),
|
||||
.gclkgen = (BOARD_SERCOM4_GCLKGEN >> GCLK_CLKCTRL_GEN_SHIFT),
|
||||
.stopbits2 = CONFIG_USART4_2STOP,
|
||||
.baud = CONFIG_USART4_BAUD,
|
||||
.pad0 = BOARD_SERCOM4_PINMAP_PAD0,
|
||||
@ -165,7 +165,7 @@ const struct sam_usart_config_s g_usart5config =
|
||||
.parity = CONFIG_USART5_PARITY,
|
||||
.bits = CONFIG_USART5_BITS,
|
||||
.irq = SAM_IRQ_SERCOM5,
|
||||
.gclk = (BOARD_SERCOM5_SRCGCLKGEN >> GCLK_CLKCTRL_GEN_SHIFT),
|
||||
.gclkgen = (BOARD_SERCOM5_GCLKGEN >> GCLK_CLKCTRL_GEN_SHIFT),
|
||||
.stopbits2 = CONFIG_USART5_2STOP,
|
||||
.baud = CONFIG_USART5_BAUD,
|
||||
.pad0 = BOARD_SERCOM5_PINMAP_PAD0,
|
||||
|
@ -56,19 +56,19 @@
|
||||
/* Pick the console USART configuration */
|
||||
|
||||
#if defined(CONFIG_USART0_SERIAL_CONSOLE)
|
||||
# define g_consoleconfig (&g_usart0config)
|
||||
# define g_consoleconfig (g_usart0config)
|
||||
#elif defined(CONFIG_USART1_SERIAL_CONSOLE)
|
||||
# define g_consoleconfig (&g_usart1config)
|
||||
# define g_consoleconfig (g_usart1config)
|
||||
#elif defined(CONFIG_USART2_SERIAL_CONSOLE)
|
||||
# define g_consoleconfig (&g_usart2config)
|
||||
# define g_consoleconfig (g_usart2config)
|
||||
#elif defined(CONFIG_USART3_SERIAL_CONSOLE)
|
||||
# define g_consoleconfig (&g_usart3config)
|
||||
# define g_consoleconfig (g_usart3config)
|
||||
#elif defined(CONFIG_USART4_SERIAL_CONSOLE)
|
||||
# define g_consoleconfig (&g_usart4config)
|
||||
# define g_consoleconfig (g_usart4config)
|
||||
#elif defined(CONFIG_USART5_SERIAL_CONSOLE)
|
||||
# define g_consoleconfig (&g_usart5config)
|
||||
# define g_consoleconfig (g_usart5config)
|
||||
#else
|
||||
# undef g_consoleconfig
|
||||
# undef g_consoleconfig
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
@ -82,7 +82,7 @@ struct sam_usart_config_s
|
||||
uint8_t parity; /* 0=none, 1=odd, 2=even */
|
||||
uint8_t bits; /* Number of bits (5-9) */
|
||||
uint8_t irq; /* SERCOM IRQ number */
|
||||
uint8_t gclk; /* Source GCLK generator */
|
||||
uint8_t gclkgen; /* Source GCLK generator */
|
||||
bool isconsole; /* True: The USART is the console device */
|
||||
bool stopbits2; /* True: Configure with 2 stop bits instead of 1 */
|
||||
uint32_t baud; /* Configured baud */
|
||||
|
@ -178,7 +178,7 @@
|
||||
* BOARD_DFLL_FINEVALUE - Value
|
||||
*
|
||||
* Closed loop mode only:
|
||||
* BOARD_DFLL_SRCGCLKGEN - See GCLK_CLKCTRL_GEN* definitions
|
||||
* BOARD_DFLL_GCLKGEN - See GCLK_CLKCTRL_GEN* definitions
|
||||
* BOARD_DFLL_MULTIPLIER - Value
|
||||
* BOARD_DFLL_MAXCOARSESTEP - Value
|
||||
* BOARD_DFLL_MAXFINESTEP - Value
|
||||
@ -198,7 +198,7 @@
|
||||
|
||||
/* DFLL closed loop mode configuration */
|
||||
|
||||
#define BOARD_DFLL_SRCGCLKGEN GCLK_CLKCTRL_GEN1
|
||||
#define BOARD_DFLL_GCLKGEN GCLK_CLKCTRL_GEN1
|
||||
#define BOARD_DFLL_MULTIPLIER 6
|
||||
#define BOARD_DFLL_QUICKLOCK 1
|
||||
#define BOARD_DFLL_TRACKAFTERFINELOCK 1
|
||||
@ -343,7 +343,7 @@
|
||||
|
||||
/* EDBG/CDC USART on SERCOM3 */
|
||||
|
||||
#define BOARD_SERCOM3_SRCGCLKGEN GCLK_CLKCTRL_GEN0
|
||||
#define BOARD_SERCOM3_GCLKGEN GCLK_CLKCTRL_GEN0
|
||||
#define BOARD_SERCOM3_MUXCONFIG (USART_CTRLA_RXPAD3 | USART_CTRLA_TXPAD2)
|
||||
#define BOARD_SERCOM3_PINMAP_PAD0 0
|
||||
#define BOARD_SERCOM3_PINMAP_PAD1 0
|
||||
|
Loading…
Reference in New Issue
Block a user