SAMD20: More SERCOM USART configuration logic

This commit is contained in:
Gregory Nutt 2014-02-15 17:53:55 -06:00
parent 4fc57e3c6a
commit 305df5ccf1
4 changed files with 243 additions and 8 deletions

View File

@ -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", 42129JSAM12/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
****************************************************************************/
@ -57,17 +75,196 @@
* Private Functions
****************************************************************************/
/****************************************************************************
* 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

View File

@ -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
/****************************************************************************

View File

@ -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

View File

@ -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 */
};