SAMD20: Move some common SERCOM logic to a separate file where it can be shared

This commit is contained in:
Gregory Nutt 2014-02-19 14:47:04 -06:00
parent c55ac71603
commit 916308efc1
10 changed files with 344 additions and 140 deletions

View File

@ -6618,3 +6618,7 @@
* drivers/lcd/mio283qt9a.c: Bug fix from Toby Duckwork (2014-2-19).
* fs/fs_rename.c: 'rename' can now be used to rename nodes in the
pseudo-filesystem (2014-2-19).
* arch/arm/src/samd/sam_sercom.c: Move some common SERCOM logic
from the USART-specific files to a share-able file where it can
also be used by SPI and I2C drivers (2014-2-19).

View File

@ -69,7 +69,8 @@ endif
CHIP_ASRCS =
CHIP_CSRCS = sam_clockconfig.c sam_idle.c sam_irq.c sam_lowputc.c
CHIP_CSRCS += sam_port.c sam_serial.c sam_start.c sam_timerisr.c sam_usart.c
CHIP_CSRCS += sam_port.c sam_sercom.c sam_serial.c sam_start.c
CHIP_CSRCS += sam_timerisr.c sam_usart.c
ifeq ($(CONFIG_NUTTX_KERNEL),y)
CHIP_CSRCS += sam_userspace.c

View File

@ -95,101 +95,6 @@ sam_wait_synchronization(const struct sam_usart_config_s * const config)
}
#endif
/****************************************************************************
* Name: sam_gclk_configure
*
* Description:
* Configure the SERCOM USART source clock.
*
* Two generic clocks are used by the SERCOM: GCLK_SERCOMx_CORE and
* GCLK_SERCOMx_SLOW. The core clock (GCLK_SERCOMx_CORE) is required to
* clock the SERCOM while operating as a master, while the slow clock
* (GCLK_SERCOM_SLOW) is only required for certain functions. SERCOM
* modules must share the same slow GCLK channel ID.
*
* The baud-rate generator runs off the GCLK_SERCOMx_CORE clock (or,
* optionally, external clock).
*
****************************************************************************/
#ifdef HAVE_USART
static inline void
sam_gclk_configure(const struct sam_usart_config_s * const config)
{
uint16_t regval;
uint8_t glckcore;
/* Set up the SERCOMn_GCLK_ID_CORE clock */
glckcore = (uint8_t)SERCOM_GCLK_ID_CORE(config->sercom);
regval = ((uint16_t)glckcore << GCLK_CLKCTRL_ID_SHIFT);
/* Select and disable the SERCOMn_GCLK_ID_CORE generic clock */
putreg16(regval, SAM_GCLK_CLKCTRL);
/* Wait for clock to become disabled */
while ((getreg16(SAM_GCLK_CLKCTRL) & GCLK_CLKCTRL_CLKEN) != 0);
/* Select the SERCOMn_GCLK_ID_CORE source clock generator */
regval |= (uint16_t)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 */
putreg16(regval, SAM_GCLK_CLKCTRL);
/* Enable the SERCOMn_GCLK_ID_CORE generic clock */
regval |= GCLK_CLKCTRL_CLKEN;
putreg16(regval, SAM_GCLK_CLKCTRL);
/* Set up the SERCOM_GCLK_ID_SLOW clock */
regval = (SERCOM_GCLK_ID_SLOW << GCLK_CLKCTRL_ID_SHIFT);
/* Select and disable the SERCOM_GCLK_ID_SLOW generic clock */
putreg16(regval, SAM_GCLK_CLKCTRL);
/* Wait for clock to become disabled */
while ((getreg16(SAM_GCLK_CLKCTRL) & GCLK_CLKCTRL_CLKEN) != 0);
/* Select the SERCOM_GCLK_ID_SLOW clock source generator */
regval |= (uint16_t)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 */
putreg16(regval, SAM_GCLK_CLKCTRL);
/* Enable the SERCOM_GCLK_ID_SLOW generic clock */
regval |= GCLK_CLKCTRL_CLKEN;
putreg16(regval, SAM_GCLK_CLKCTRL);
}
#endif
/****************************************************************************
* Name: sam_usart_configure
*
@ -396,11 +301,12 @@ int sam_usart_internal(const struct sam_usart_config_s * const config)
regval |= PM_APBCMASK_SERCOM(config->sercom);
putreg32(regval, SAM_PM_APBCMASK);
/* Configure the GCCLK for the SERCOM module */
/* Configure the GCLKs for the SERCOM module */
sam_gclk_configure(config);
sercom_coreclk_configure(config->sercom, config->gclkgen, false);
sercom_slowclk_configure(config->gclkgen);
/* Set configuration according to the board configuration */
/* Set USART configuration according to the board configuration */
ret = sam_usart_configure(config);
if (ret == OK)

View File

@ -1,4 +1,4 @@
/************************************************************************************
/****************************************************************************
* arch/arm/src/samd/sam_lowputc.h
*
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
@ -31,29 +31,29 @@
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
************************************************************************************/
****************************************************************************/
#ifndef __ARCH_ARM_SRC_SAMD_SAM_LOWPUTC_H
#define __ARCH_ARM_SRC_SAMD_SAM_LOWPUTC_H
/************************************************************************************
/****************************************************************************
* Included Files
************************************************************************************/
****************************************************************************/
#include <nuttx/config.h>
#include "sam_config.h"
/************************************************************************************
/****************************************************************************
* Pre-processor Definitions
************************************************************************************/
****************************************************************************/
/************************************************************************************
/****************************************************************************
* Public Types
************************************************************************************/
****************************************************************************/
/************************************************************************************
/****************************************************************************
* Public Data
************************************************************************************/
****************************************************************************/
#ifndef __ASSEMBLY__
@ -66,17 +66,18 @@ extern "C"
#define EXTERN extern
#endif
/************************************************************************************
* Public Functions
************************************************************************************/
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/************************************************************************************
/****************************************************************************
* 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);
@ -88,7 +89,7 @@ void sam_lowsetup(void);
* 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;
@ -102,7 +103,7 @@ int sam_usart_initialize(const struct sam_usart_config_s * const config);
* Reset the USART SERCOM. This restores all SERCOM register to the
* initial state and disables the SERCOM.
*
*****************************************************************************/
****************************************************************************/
#ifdef HAVE_USART
struct sam_usart_config_s;
@ -115,7 +116,7 @@ void sam_usart_reset(const struct sam_usart_config_s * const config);
* Description:
* Output one character to the USART using a simple polling method.
*
*****************************************************************************/
****************************************************************************/
#ifdef HAVE_SERIAL_CONSOLE
void sam_lowputc(uint32_t ch);

View File

@ -0,0 +1,182 @@
/****************************************************************************
* arch/arm/src/samd/sam_lowputc.c
*
* 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
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <stdbool.h>
#include "up_arch.h"
#include "sam_config.h"
#include "chip/sam_pm.h"
#include "chip/sam_gclk.h"
#include "chip/sam_sercom.h"
#include "sam_sercom.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: sercom_coreclk_configure
*
* Description:
* Configure the SERCOM core source clock.
*
* Two generic clocks are used by the SERCOM: GCLK_SERCOMx_CORE and
* GCLK_SERCOMx_SLOW. The core clock (GCLK_SERCOMx_CORE) is required to
* clock the SERCOM while operating as a master, while the slow clock
* (GCLK_SERCOM_SLOW) is only required for certain functions. SERCOM
* modules must share the same slow GCLK channel ID.
*
* The baud-rate generator runs off the GCLK_SERCOMx_CORE clock (or,
* optionally, external clock).
*
****************************************************************************/
void sercom_coreclk_configure(int sercom, int gclkgen, bool wrlock)
{
uint16_t regval;
uint8_t glckcore;
/* Set up the SERCOMn_GCLK_ID_CORE clock */
glckcore = (uint8_t)SERCOM_GCLK_ID_CORE(sercom);
regval = ((uint16_t)glckcore << GCLK_CLKCTRL_ID_SHIFT);
/* Select and disable the SERCOMn_GCLK_ID_CORE generic clock */
putreg16(regval, SAM_GCLK_CLKCTRL);
/* Wait for clock to become disabled */
while ((getreg16(SAM_GCLK_CLKCTRL) & GCLK_CLKCTRL_CLKEN) != 0);
/* Select the SERCOMn_GCLK_ID_CORE source clock generator */
regval |= (uint16_t)gclkgen << GCLK_CLKCTRL_GEN_SHIFT;
/* Write the new configuration */
putreg16(regval, SAM_GCLK_CLKCTRL);
/* Enable the SERCOMn_GCLK_ID_CORE generic clock, optionally locking
* further writes to this GCLK.
*/
regval |= GCLK_CLKCTRL_CLKEN;
if (wrlock)
{
regval |= GCLK_CLKCTRL_WRTLOCK;
}
putreg16(regval, SAM_GCLK_CLKCTRL);
}
/****************************************************************************
* Name: sercom_slowclk_configure
*
* Description:
* Configure the SERCOM slow source clock.
*
* Two generic clocks are used by the SERCOM: GCLK_SERCOMx_CORE and
* GCLK_SERCOMx_SLOW. The core clock (GCLK_SERCOMx_CORE) is required to
* clock the SERCOM while operating as a master, while the slow clock
* (GCLK_SERCOM_SLOW) is only required for certain functions. SERCOM
* modules must share the same slow GCLK channel ID.
*
****************************************************************************/
void sercom_slowclk_configure(int gclkgen)
{
uint16_t regval;
/* Set up the SERCOM_GCLK_ID_SLOW clock */
regval = (SERCOM_GCLK_ID_SLOW << GCLK_CLKCTRL_ID_SHIFT);
/* Select and disable the SERCOM_GCLK_ID_SLOW generic clock */
putreg16(regval, SAM_GCLK_CLKCTRL);
/* Wait for clock to become disabled */
while ((getreg16(SAM_GCLK_CLKCTRL) & GCLK_CLKCTRL_CLKEN) != 0);
/* Select the SERCOM_GCLK_ID_SLOW clock source generator */
regval |= (uint16_t)gclkgen << GCLK_CLKCTRL_GEN_SHIFT;
/* Write the new configuration */
putreg16(regval, SAM_GCLK_CLKCTRL);
/* Enable the GCLK_SERCOM_SLOW generic clock and lock further
* writes to this GCLK. When this bit is written, it will lock
* further writes to the generic clock pointed by the CLKCTRL.ID. The
* generic clock generator pointed by CLKCTRL.GEN and the GENDIV.DIV
* will also be locked.
*
* We lock the SERCOM slow clock because it is common to all SERCOM modules
* and, once set, should not be changed again.
*/
regval |= (GCLK_CLKCTRL_WRTLOCK | GCLK_CLKCTRL_CLKEN);
putreg16(regval, SAM_GCLK_CLKCTRL);
}

View File

@ -0,0 +1,115 @@
/****************************************************************************
* arch/arm/src/samd/sam_sercom.h
*
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __ARCH_ARM_SRC_SAMD_SAM_SERCOM_H
#define __ARCH_ARM_SRC_SAMD_SAM_SERCOM_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdbool.h>
#include "sam_config.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Types
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
#ifndef __ASSEMBLY__
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: sercom_coreclk_configure
*
* Description:
* Configure the SERCOM core source clock.
*
* Two generic clocks are used by the SERCOM: GCLK_SERCOMx_CORE and
* GCLK_SERCOMx_SLOW. The core clock (GCLK_SERCOMx_CORE) is required to
* clock the SERCOM while operating as a master, while the slow clock
* (GCLK_SERCOM_SLOW) is only required for certain functions. SERCOM
* modules must share the same slow GCLK channel ID.
*
* The baud-rate generator runs off the GCLK_SERCOMx_CORE clock (or,
* optionally, external clock).
*
****************************************************************************/
void sercom_coreclk_configure(int sercom, int gclkgen, bool wrlock);
/****************************************************************************
* Name: sercom_slowclk_configure
*
* Description:
* Configure the SERCOM slow source clock.
*
* Two generic clocks are used by the SERCOM: GCLK_SERCOMx_CORE and
* GCLK_SERCOMx_SLOW. The core clock (GCLK_SERCOMx_CORE) is required to
* clock the SERCOM while operating as a master, while the slow clock
* (GCLK_SERCOM_SLOW) is only required for certain functions. SERCOM
* modules must share the same slow GCLK channel ID.
*
****************************************************************************/
void sercom_slowclk_configure(int gclkgen);
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_ARM_SRC_SAMD_SAM_SERCOM_H */

View File

@ -1,4 +1,4 @@
/************************************************************************************
/****************************************************************************
* arch/arm/src/samd/sam_serial.h
*
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
@ -31,37 +31,37 @@
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
************************************************************************************/
****************************************************************************/
#ifndef __ARCH_ARM_SRC_SAMD_SAM_SERIAL_H
#define __ARCH_ARM_SRC_SAMD_SAM_SERIAL_H
/************************************************************************************
/****************************************************************************
* Included Files
************************************************************************************/
****************************************************************************/
#include <nuttx/config.h>
#include "sam_config.h"
/************************************************************************************
/****************************************************************************
* Pre-processor Definitions
************************************************************************************/
****************************************************************************/
/************************************************************************************
/****************************************************************************
* Public Types
************************************************************************************/
****************************************************************************/
/************************************************************************************
/****************************************************************************
* Public Data
************************************************************************************/
****************************************************************************/
/************************************************************************************
/****************************************************************************
* Inline Functions
************************************************************************************/
****************************************************************************/
/************************************************************************************
/****************************************************************************
* Public Functions
************************************************************************************/
****************************************************************************/
#endif /* __ARCH_ARM_SRC_SAMD_SAM_SERIAL_H */

View File

@ -279,6 +279,7 @@ int sam_spicmddata(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool cmd)
(void)sam_portwrite(PORT_OLED_DATA, !cmd);
}
#endif
return OK;
return OK;
}
#endif

View File

@ -128,11 +128,9 @@
# define PORT_SD_CD (PORT_INTERRUPT | PORT_INT_CHANGE | PORT_PULL_UP | \
PORTF | PORT_PIN5)
# define IRQ_SD_CD SAM_IRQ_PB5
# define PORT_SD_CS (PORT_OUTPUT | PORT_PULL_NONE | PORT_OUTPUT_SET | \
PORTA | PORT_PIN5)
# define SD_CSNO 0
# elif defined(CONFIG_SAMD20_XPLAINED_IOMODULE_EXT2)
@ -143,11 +141,9 @@
# define PORT_CD (PORT_INTERRUPT | PORT_INT_CHANGE | PORT_PULL_UP | \
PORTB | PORT_PIN15)
# define IRQ_CD SAM_IRQ_PB15
# define PORT_SD_CS (PORT_OUTPUT | PORT_PULL_NONE | PORT_OUTPUT_SET | \
PORTA | PORT_PIN17)
# define SD_CSNO 2
# else
# error Which connector is the I/O1 module installed in?
@ -200,7 +196,6 @@
PORTB | PORT_PIN5)
# define PORT_OLED_CS (PORT_OUTPUT | PORT_PULL_NONE | PORT_OUTPUT_SET | \
PORTA | PORT_PIN5)
# define OLED_CSNO 0
# elif defined(CONFIG_SAMD20_XPLAINED_OLED1MODULE_EXT2)
@ -215,7 +210,6 @@
PORTB | PORT_PIN15)
# define PORT_OLED_CS (PORT_OUTPUT | PORT_PULL_NONE | PORT_OUTPUT_SET | \
PORTA | PORT_PIN17)
# define OLED_CSNO 2
# else
# error Which connector is the OLED1 module installed in?

View File

@ -223,6 +223,6 @@ int rename(FAR const char *oldpath, FAR const char *newpath)
errout_with_oldinode:
inode_release(oldinode);
errout:
set_errno(ret);
set_errno(errcode);
return ERROR;
}