SAMD20: More SERCOM USART configuration logic
This commit is contained in:
parent
4fc57e3c6a
commit
305df5ccf1
@ -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
|
||||
****************************************************************************/
|
||||
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user