mirror of
https://github.com/apache/nuttx.git
synced 2026-06-05 15:58:59 +08:00
SAMD20: More SERCOM USART configuration logic
This commit is contained in:
@@ -4,6 +4,15 @@
|
|||||||
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* 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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
* are met:
|
* are met:
|
||||||
@@ -41,14 +50,23 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "up_arch.h"
|
||||||
|
|
||||||
#include "sam_config.h"
|
#include "sam_config.h"
|
||||||
|
#include "chip/sam_pm.h"
|
||||||
|
#include "chip/sam_usart.h"
|
||||||
#include "sam_usart.h"
|
#include "sam_usart.h"
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef OK
|
||||||
|
# define OK 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -57,17 +75,196 @@
|
|||||||
* Private Functions
|
* 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
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: sam_lowsetup
|
* Name: sam_lowsetup
|
||||||
*
|
*
|
||||||
* Description:
|
* 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)
|
void sam_lowsetup(void)
|
||||||
{
|
{
|
||||||
@@ -75,17 +272,46 @@ void sam_lowsetup(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: sam_usartconfig
|
* Name: sam_usart_initialize
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Set the configuration of a SERCOM for provided USART configuration.
|
* 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
|
#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
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -81,16 +81,18 @@ extern "C"
|
|||||||
void sam_lowsetup(void);
|
void sam_lowsetup(void);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: sam_usartconfig
|
* Name: sam_usart_initialize
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Set the configuration of a SERCOM for provided USART configuration.
|
* 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
|
#ifdef HAVE_USART
|
||||||
struct sam_usart_config_s;
|
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
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ const struct sam_usart_config_s g_usart0config =
|
|||||||
.pad2 = BOARD_SERCOM0_PINMAP_PAD2,
|
.pad2 = BOARD_SERCOM0_PINMAP_PAD2,
|
||||||
.pad3 = BOARD_SERCOM0_PINMAP_PAD3,
|
.pad3 = BOARD_SERCOM0_PINMAP_PAD3,
|
||||||
.muxconfig = BOARD_SERCOM0_MUXCONFIG,
|
.muxconfig = BOARD_SERCOM0_MUXCONFIG,
|
||||||
|
.frequency = BOARD_SERCOM0_FREQUENCY,
|
||||||
.base = SAM_SERCOM0_BASE,
|
.base = SAM_SERCOM0_BASE,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@@ -92,6 +93,7 @@ const struct sam_usart_config_s g_usart1config =
|
|||||||
.pad2 = BOARD_SERCOM1_PINMAP_PAD2,
|
.pad2 = BOARD_SERCOM1_PINMAP_PAD2,
|
||||||
.pad3 = BOARD_SERCOM1_PINMAP_PAD3,
|
.pad3 = BOARD_SERCOM1_PINMAP_PAD3,
|
||||||
.muxconfig = BOARD_SERCOM1_MUXCONFIG,
|
.muxconfig = BOARD_SERCOM1_MUXCONFIG,
|
||||||
|
.frequency = BOARD_SERCOM1_FREQUENCY,
|
||||||
.base = SAM_SERCOM1_BASE,
|
.base = SAM_SERCOM1_BASE,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@@ -111,6 +113,7 @@ const struct sam_usart_config_s g_usart2config =
|
|||||||
.pad2 = BOARD_SERCOM2_PINMAP_PAD2,
|
.pad2 = BOARD_SERCOM2_PINMAP_PAD2,
|
||||||
.pad3 = BOARD_SERCOM2_PINMAP_PAD3,
|
.pad3 = BOARD_SERCOM2_PINMAP_PAD3,
|
||||||
.muxconfig = BOARD_SERCOM2_MUXCONFIG,
|
.muxconfig = BOARD_SERCOM2_MUXCONFIG,
|
||||||
|
.frequency = BOARD_SERCOM2_FREQUENCY,
|
||||||
.base = SAM_SERCOM2_BASE,
|
.base = SAM_SERCOM2_BASE,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@@ -130,6 +133,7 @@ const struct sam_usart_config_s g_usart3config =
|
|||||||
.pad2 = BOARD_SERCOM3_PINMAP_PAD2,
|
.pad2 = BOARD_SERCOM3_PINMAP_PAD2,
|
||||||
.pad3 = BOARD_SERCOM3_PINMAP_PAD3,
|
.pad3 = BOARD_SERCOM3_PINMAP_PAD3,
|
||||||
.muxconfig = BOARD_SERCOM3_MUXCONFIG,
|
.muxconfig = BOARD_SERCOM3_MUXCONFIG,
|
||||||
|
.frequency = BOARD_SERCOM3_FREQUENCY,
|
||||||
.base = SAM_SERCOM3_BASE,
|
.base = SAM_SERCOM3_BASE,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@@ -149,6 +153,7 @@ const struct sam_usart_config_s g_usart4config =
|
|||||||
.pad2 = BOARD_SERCOM4_PINMAP_PAD2,
|
.pad2 = BOARD_SERCOM4_PINMAP_PAD2,
|
||||||
.pad3 = BOARD_SERCOM4_PINMAP_PAD3,
|
.pad3 = BOARD_SERCOM4_PINMAP_PAD3,
|
||||||
.muxconfig = BOARD_SERCOM4_MUXCONFIG,
|
.muxconfig = BOARD_SERCOM4_MUXCONFIG,
|
||||||
|
.frequency = BOARD_SERCOM4_FREQUENCY,
|
||||||
.base = SAM_SERCOM4_BASE,
|
.base = SAM_SERCOM4_BASE,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@@ -168,6 +173,7 @@ const struct sam_usart_config_s g_usart5config =
|
|||||||
.pad2 = BOARD_SERCOM5_PINMAP_PAD2,
|
.pad2 = BOARD_SERCOM5_PINMAP_PAD2,
|
||||||
.pad3 = BOARD_SERCOM5_PINMAP_PAD3,
|
.pad3 = BOARD_SERCOM5_PINMAP_PAD3,
|
||||||
.muxconfig = BOARD_SERCOM5_MUXCONFIG,
|
.muxconfig = BOARD_SERCOM5_MUXCONFIG,
|
||||||
|
.frequency = BOARD_SERCOM5_FREQUENCY,
|
||||||
.base = SAM_SERCOM5_BASE,
|
.base = SAM_SERCOM5_BASE,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ struct sam_usart_config_s
|
|||||||
port_pinset_t pad2; /* Pin configuration for PAD2 */
|
port_pinset_t pad2; /* Pin configuration for PAD2 */
|
||||||
port_pinset_t pad3; /* Pin configuration for PAD3 */
|
port_pinset_t pad3; /* Pin configuration for PAD3 */
|
||||||
uint32_t muxconfig; /* Pad multiplexing configuration */
|
uint32_t muxconfig; /* Pad multiplexing configuration */
|
||||||
|
uint32_t frequency; /* Source clock frequency */
|
||||||
uintptr_t base; /* SERCOM base address */
|
uintptr_t base; /* SERCOM base address */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user