arch: samd5e5 : Oneshot, freerun and tickless available support. All support runs on Timer/Counter (TC).

Some fixes in external interrupt controller (EIC) and clockconfig.

Testing:
- Build check only.

Signed-off-by: Leomar Mateus Radke  <leomar@falker.com.br>
This commit is contained in:
leomarradke 2020-08-14 15:23:40 -03:00 committed by Alan Carvalho de Assis
parent 171cc38ac2
commit f5912b5cba
18 changed files with 4185 additions and 253 deletions

View File

@ -258,6 +258,7 @@ config ARCH_CHIP_SAML2X
config ARCH_CHIP_SAMD5X
bool "Microchip SAMD5x"
select ARCH_CORTEXM4
select ARCH_HAVE_TICKLESS
---help---
Microchip SAMD5X (ARM Cortex-M4)

View File

@ -321,6 +321,10 @@ config SAMD5E5_HAVE_SERCOM7
bool
default n
config SAMD5E5_HAVE_TC
bool
default n
config SAMD5E5_HAVE_TC4
bool
default n
@ -341,6 +345,22 @@ config SAMD5E5_SERCOM
bool
default n
config SAMD5E5_TC
bool
default y
config SAMD5E5_HAVE_TC4
bool
default n
config SAMD5E5_HAVE_TC5
bool
default n
config SAMD5E5_HAVE_TC6
bool
default n
config SAMD5E5_AC
bool "Analog Comparator"
default n
@ -429,38 +449,90 @@ config SAMD5E5_SERCOM7
config SAMD5E5_TC0
bool "Timer/Counter 0"
default n
depends on SAMD5E5_TC
select SAMD5E5_HAVE_TC
config SAMD5E5_TC1
bool "Timer/Counter 1"
default n
depends on SAMD5E5_TC
select SAMD5E5_HAVE_TC
config SAMD5E5_TC2
bool "Timer/Counter 2"
default n
depends on SAMD5E5_TC
select SAMD5E5_HAVE_TC
config SAMD5E5_TC3
bool "Timer/Counter 3"
default n
depends on SAMD5E5_TC
select SAMD5E5_HAVE_TC
config SAMD5E5_TC4
bool "Timer/Counter 4"
default n
depends on SAMD5E5_HAVE_TC4
select SAMD5E5_HAVE_TC
config SAMD5E5_TC5
bool "Timer/Counter 5"
default n
depends on SAMD5E5_HAVE_TC5
select SAMD5E5_HAVE_TC
config SAMD5E5_TC6
bool "Timer/Counter 6"
default n
depends on SAMD5E5_HAVE_TC6
select SAMD5E5_HAVE_TC
config SAMD5E5_TC7
bool "Timer/Counter 7"
default n
depends on SAMD5E5_HAVE_TC7
select SAMD5E5_HAVE_TC
config SAMD5E5_ONESHOT
bool "TC one-shot wrapper"
default n if !SCHED_TICKLESS
default y if SCHED_TICKLESS
---help---
Enable a wrapper around the low level timer/counter functions to
support one-shot timer.
config SAMD5E5_FREERUN
bool "TC free-running wrapper"
default n if !SCHED_TICKLESS
default y if SCHED_TICKLESS
---help---
Enable a wrapper around the low level timer/counter functions to
support a free-running timer.
if SCHED_TICKLESS
config SAMD5E5_TICKLESS_ONESHOT
int "Tickless one-shot timer channel"
default 2
range 0 7
---help---
If the Tickless OS feature is enabled, the one clock must be
assigned to provided the one-shot timer needed by the OS.
NOTE: Use even timers (0, 2 or 4) because timers are program
in 32-bit mode (1, 3 and 5 are slaves).
config SAMD5E5_TICKLESS_FREERUN
int "Tickless free-running timer channel"
default 4
range 0 7
---help---
If the Tickless OS feature is enabled, the one clock must be
assigned to provided the free-running timer needed by the OS.
NOTE: Use even timers (0, 2 or 4) because timers are program
in 32-bit mode (1, 3 and 5 are slaves).
endif
config SAMD5E5_USB
bool "USB"

View File

@ -51,7 +51,7 @@
/* EIC register offsets *********************************************************************/
#define SAM_EIC_CTRLA_OFFSET 0x0000 /* Control A register */
#define SAM_EIC_NMITRCL_OFFSET 0x0001 /* Non-maskable interrupt control register */
#define SAM_EIC_NMICTRL_OFFSET 0x0001 /* Non-maskable interrupt control register */
#define SAM_EIC_NMIFLAG_OFFSET 0x0002 /* Non-maskable interrupt flasg status and clear register */
#define SAM_EIC_SYNCBUSY_OFFSET 0x0004 /* Synchronization busy register */
#define SAM_EIC_EVCTRL_OFFSET 0x0008 /* Event control register */
@ -68,7 +68,7 @@
/* EIC register addresses *******************************************************************/
#define SAM_EIC_CTRLA (SAM_EIC_BASE + SAM_EIC_CTRLA_OFFSET)
#define SAM_EIC_NMITRCL (SAM_EIC_BASE + SAM_EIC_NMITRCL_OFFSET)
#define SAM_EIC_NMICTRL (SAM_EIC_BASE + SAM_EIC_NMICTRL_OFFSET)
#define SAM_EIC_NMIFLAG (SAM_EIC_BASE + SAM_EIC_NMIFLAG_OFFSET)
#define SAM_EIC_SYNCBUSY (SAM_EIC_BASE + SAM_EIC_SYNCBUSY_OFFSET)
#define SAM_EIC_EVCTRL (SAM_EIC_BASE + SAM_EIC_EVCTRL_OFFSET)
@ -86,9 +86,9 @@
/* Control A register */
#define EIC_CTRLA_SWRST (1 << 0) /* Bit 0: Software reset */
#define EIC_CTRLA_ENABLE (1 << 1) /* Bit 1: Enable */
#define EIC_CTRLA_CKSEL (1 << 4) /* Bit 4: Clock selection */
#define EIC_CTRLA_SWRST (1 << 0) /* Bit 0: Software reset */
#define EIC_CTRLA_ENABLE (1 << 1) /* Bit 1: Enable */
#define EIC_CTRLA_CKSEL (1 << 4) /* Bit 4: Clock selection */
# define EIC_CTRLA_CKSEL_GCLK_EIC (0) /* 0=EIC clocked by GCLK_EIC */
# define EIC_CTRLA_CKSEL_CLK_ULP32K EIC_CTRLA_CKSEL /* 1=EIC clocked by CLK_ULP32K */
@ -102,8 +102,8 @@
# define EIC_NMITRCL_NMISENSE_BOTH (3 << EIC_NMITRCL_NMISENSE_SHIFT) /* Both edge detection */
# define EIC_NMITRCL_NMISENSE_HIGH (4 << EIC_NMITRCL_NMISENSE_SHIFT) /* High level detection */
# define EIC_NMITRCL_NMISENSE_LOW (5 << EIC_NMITRCL_NMISENSE_SHIFT) /* Low level detection */
#define EIC_NMITRCL_NMIFLTEN (1 << 3) /* Bit 3: Non-maskable interrupt filter enable */
#define EIC_NMITRCL_ASYNC (1 << 4) /* Bit 4: Asynchronous edge detection mode */
#define EIC_NMITRCL_NMIFLTEN (1 << 3) /* Bit 3: Non-maskable interrupt filter enable */
#define EIC_NMITRCL_ASYNC (1 << 4) /* Bit 4: Asynchronous edge detection mode */
/* Non-maskable interrupt flas status and clear register */
@ -142,7 +142,7 @@
/* Configuration 0 register */
#define EIC_CONFIG0_FILTEN(n) (3 + ((n) << 2)) /* Filter n enable, n=0-7 */
#define EIC_CONFIG0_FILTEN(n) (0x8 << ((n) << 2)) /* Filter n enable, n=0-7 */
#define EIC_CONFIG0_SENSE_SHIFT(n) ((n) << 2) /* Filter n input sense, n=0-7 */
#define EIC_CONFIG0_SENSE_MASK(n) (7 << EIC_CONFIG0_SENSE_SHIFT(n))
# define EIC_CONFIG0_SENSE_NONE(n) (0 << EIC_CONFIG0_SENSE_SHIFT(n)) /* No detection */
@ -154,7 +154,7 @@
/* Configuration 1 register */
#define EIC_CONFIG1_FILTEN(n) (3 + (((n) - 8) << 2)) /* Filter n enable, n=8-15 */
#define EIC_CONFIG1_FILTEN(n) (0x8 << (((n) - 8) << 2)) /* Filter n enable, n=8-15 */
#define EIC_CONFIG1_SENSE_SHIFT(n) (((n) - 8) << 2) /* Filter n input sense, n=8-17 */
#define EIC_CONFIG1_SENSE_MASK(n) (7 << EIC_CONFIG1_SENSE_SHIFT(n))
# define EIC_CONFIG1_SENSE_NONE(n) (0 << EIC_CONFIG1_SENSE_SHIFT(n)) /* No detection */
@ -198,10 +198,10 @@
# define EIC_DPRESCALER_PRESCALER0_DIV64 (5 << EIC_DPRESCALER_PRESCALER0_SHIFT) /* EIC clock divided by 64 */
# define EIC_DPRESCALER_PRESCALER0_DIV128 (6 << EIC_DPRESCALER_PRESCALER0_SHIFT) /* EIC clock divided by 128 */
# define EIC_DPRESCALER_PRESCALER0_DIV256 (7 << EIC_DPRESCALER_PRESCALER0_SHIFT) /* EIC clock divided by 256 */
#define EIC_DPRESCALER_STATES0 (1 << 3) /* Bit 3: Debouncer number of states. EXTINT 0-7 */
# define EIC_DPRESCALER_STATES0_3 (0) /* 3 low frequency samples */
# define EIC_DPRESCALER_STATES0_7 EIC_DPRESCALER_STATES0 /* 7 low frequency samples */
#define EIC_DPRESCALER_PRESCALER1_SHIFT (4) /* Bitx 4-6: Debouncer Prescaler. EXTINT 8-15 */
#define EIC_DPRESCALER_STATES0 (1 << 3) /* Bit 3: Debouncer number of states. EXTINT 0-7 */
# define EIC_DPRESCALER_STATES0_3 (0) /* 3 low frequency samples */
# define EIC_DPRESCALER_STATES0_7 EIC_DPRESCALER_STATES0 /* 7 low frequency samples */
#define EIC_DPRESCALER_PRESCALER1_SHIFT (4) /* Bitx 4-6: Debouncer Prescaler. EXTINT 8-15 */
#define EIC_DPRESCALER_PRESCALER1_MASK (7 << EIC_DPRESCALER_PRESCALER1_SHIFT)
# define EIC_DPRESCALER_PRESCALER1_DIV2 (0 << EIC_DPRESCALER_PRESCALER1_SHIFT) /* EIC clock divided by 2 */
# define EIC_DPRESCALER_PRESCALER1_DIV4 (1 << EIC_DPRESCALER_PRESCALER1_SHIFT) /* EIC clock divided by 4 */
@ -211,12 +211,12 @@
# define EIC_DPRESCALER_PRESCALER1_DIV64 (5 << EIC_DPRESCALER_PRESCALER1_SHIFT) /* EIC clock divided by 64 */
# define EIC_DPRESCALER_PRESCALER1_DIV128 (6 << EIC_DPRESCALER_PRESCALER1_SHIFT) /* EIC clock divided by 128 */
# define EIC_DPRESCALER_PRESCALER1_DIV256 (7 << EIC_DPRESCALER_PRESCALER1_SHIFT) /* EIC clock divided by 256 */
#define EIC_DPRESCALER_STATES1 (1 << 7) /* Bit 7: Debouncer number of states. EXTINT 8-15 */
# define EIC_DPRESCALER_STATES1_3 (0) /* 3 low frequency samples */
# define EIC_DPRESCALER_STATES1_7 EIC_DPRESCALER_STATES1 /* 7 low frequency samples */
#define EIC_DPRESCALER_TICKON (1 << 16) /* Bit 16: Pin Sampler frequency selection */
# define EIC_DPRESCALER_TICKON_GCLKEIC (0) /* Bounce sampler uses GCLK_EIC */
# define EIC_DPRESCALER_TICKON_LFCLK EIC_DPRESCALER_TICKON /* Bounce sampler uses low frequency clock */
#define EIC_DPRESCALER_STATES1 (1 << 7) /* Bit 7: Debouncer number of states. EXTINT 8-15 */
# define EIC_DPRESCALER_STATES1_3 (0) /* 3 low frequency samples */
# define EIC_DPRESCALER_STATES1_7 EIC_DPRESCALER_STATES1 /* 7 low frequency samples */
#define EIC_DPRESCALER_TICKON (1 << 16) /* Bit 16: Pin Sampler frequency selection */
# define EIC_DPRESCALER_TICKON_GCLKEIC (0) /* Bounce sampler uses GCLK_EIC */
# define EIC_DPRESCALER_TICKON_LFCLK EIC_DPRESCALER_TICKON /* Bounce sampler uses low frequency clock */
/* Pin state */
@ -249,7 +249,7 @@
********************************************************************************************/
/********************************************************************************************
* Public Functions
* Public Functions Prototypes
********************************************************************************************/
#endif /* __ARCH_ARM_SRC_SAMD5E5_HARDWARE_SAM_EIC_H */

View File

@ -0,0 +1,479 @@
/****************************************************************************
* arch/arm/src/samd5e5/hardware/sam_tc.h
*
* Copyright 2020 Falker Automacao Agricola LTDA.
* Author: Leomar Mateus Radke <leomar@falker.com.br>
* Author: Ricardo Wartchow <wartchow@gmail.com>
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __ARCH_ARM_SRC_SAMD5E5_CHIP_SAMD_TC_H
#define __ARCH_ARM_SRC_SAMD5E5_CHIP_SAMD_TC_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include "hardware/sam_memorymap.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* TC - COUNTx mode register offsets */
#define SAM_TC_CTRLA_OFFSET 0x0000 /* Control A register */
#define SAM_TC_CTRLBCLR_OFFSET 0x0004 /* Control B clear register */
#define SAM_TC_CTRLBSET_OFFSET 0x0005 /* Control B Set register */
#define SAM_TC_EVCTRL_OFFSET 0x0006 /* Event Control registerr */
#define SAM_TC_INTENCLR_OFFSET 0x0008 /* Interrupt Enable Clear register */
#define SAM_TC_INTENSET_OFFSET 0x0009 /* Interrupt Enable Set register */
#define SAM_TC_INTFLAG_OFFSET 0x000A /* Interrupt Flag Status and Clear register */
#define SAM_TC_STATUS_OFFSET 0x000B /* Status register */
#define SAM_TC_WAVE_OFFSET 0x000C /* Waveform Generation Control register */
#define SAM_TC_DRVCTRL_OFFSET 0x000D /* Driver Control register */
#define SAM_TC_DBGCTRL_OFFSET 0x000F /* Debug Control register */
#define SAM_TC_SYNCBUSY_OFFSET 0x0010 /* Synchronization Busy register*/
#define SAM_TC_COUNT_OFFSET 0x0014 /* Counter Value register */
/* TC-8bits mode register offsets */
#define SAM_TC_COUNT8_PER_OFFSET 0x001B /* Period Value, 8-bit Mode register */
#define SAM_TC_COUNT8_CC0_OFFSET 0x001C /* Channel 0 Compare/Capture Value, 8-bit Mode register */
#define SAM_TC_COUNT8_CC1_OFFSET 0x001D /* Channel 1 Compare/Capture Value, 8-bit Mode register */
#define SAM_TC_COUNT8_PERBUF_OFFSET 0x002F /* Period Buffer Value, 8-bit Mode register */
#define SAM_TC_COUNT8_CCBUF0_OFFSET 0x0030 /* Channel 0 Compare Buffer Value, 8-bit Mode register */
#define SAM_TC_COUNT8_CCBUF1_OFFSET 0x0031 /* Channel 1 Compare Buffer Value, 8-bit Mode register */
/* TC-16bits mode register offsets */
#define SAM_TC_COUNT16_CC0_OFFSET 0x001C /* Channel 0 Compare/Capture Value, 16-bit Mode register */
#define SAM_TC_COUNT16_CC1_OFFSET 0x001E /* Channel 1 Compare/Capture Value, 16-bit Mode register */
#define SAM_TC_COUNT16_CCBUF0_OFFSET 0x0030 /* Channel 0 Compare Buffer Value, 16-bit Mode register */
#define SAM_TC_COUNT16_CCBUF1_OFFSET 0x0032 /* Channel 1 Compare Buffer Value, 16-bit Mode register */
/* TC-32bits mode register offsets */
#define SAM_TC_COUNT32_CC0_OFFSET 0x001C /* Channel 0 Compare/Capture Value, 32-bit Mode register */
#define SAM_TC_COUNT32_CC1_OFFSET 0x0020 /* Channel 1 Compare/Capture Value, 32-bit Mode register */
#define SAM_TC_COUNT32_CCBUF0_OFFSET 0x0030 /* Channel 0 Compare Buffer Value, 32-bit Mode register */
#define SAM_TC_COUNT32_CCBUF1_OFFSET 0x0034 /* Channel 1 Compare Buffer Value, 32-bit Mode register */
/* TCx register addresses */
#define SAM_TC0_CTRLA (SAM_TC0_BASE+SAM_TC_CTRLA_OFFSET)
#define SAM_TC0_CTRLBCLR (SAM_TC0_BASE+SAM_TC_CTRLBCLR_OFFSET)
#define SAM_TC0_CTRLBSET (SAM_TC0_BASE+SAM_TC_CTRLBSET_OFFSET)
#define SAM_TC0_EVCTRL (SAM_TC0_BASE+SAM_TC_EVCTRL_OFFSET)
#define SAM_TC0_INTENCLR (SAM_TC0_BASE+SAM_TC_INTENCLR_OFFSET)
#define SAM_TC0_INTENSET (SAM_TC0_BASE+SAM_TC_INTENSET_OFFSET)
#define SAM_TC0_INTFLAG (SAM_TC0_BASE+SAM_TC_INTFLAG_OFFSET)
#define SAM_TC0_STATUS (SAM_TC0_BASE+SAM_TC_STATUS_OFFSET)
#define SAM_TC0_WAVE (SAM_TC0_BASE+SAM_TC_WAVE_OFFSET)
#define SAM_TC0_DRVCTRL (SAM_TC0_BASE+SAM_TC_DRVCTRL_OFFSET)
#define SAM_TC0_DBGCTRL (SAM_TC0_BASE+SAM_TC_DBGCTRL_OFFSET)
#define SAM_TC0_SYNCBUSY (SAM_TC0_BASE+SAM_TC_SYNCBUSY_OFFSET)
#define SAM_TC0_COUNT (SAM_TC0_BASE+SAM_TC_COUNT_OFFSET)
#define SAM_TC0_COUNT8_PER (SAM_TC0_BASE+SAM_TC_COUNT8_PER_OFFSET)
#define SAM_TC0_COUNT8_CC0 (SAM_TC0_BASE+SAM_TC_COUNT8_CC0_OFFSET)
#define SAM_TC0_COUNT8_CC1 (SAM_TC0_BASE+SAM_TC_COUNT8_CC1_OFFSET)
#define SAM_TC0_COUNT8_PERBUF (SAM_TC0_BASE+SAM_TC_COUNT8_PERBUF_OFFSET)
#define SAM_TC0_COUNT8_CCBUF0 (SAM_TC0_BASE+SAM_TC_COUNT8_CCBUF0_OFFSET)
#define SAM_TC0_COUNT8_CCBUF1 (SAM_TC0_BASE+SAM_TC_COUNT8_CCBUF1_OFFSET)
#define SAM_TC0_COUNT16_CC0 (SAM_TC0_BASE+SAM_TC_COUNT16_CC0_OFFSET)
#define SAM_TC0_COUNT16_CC1 (SAM_TC0_BASE+SAM_TC_COUNT16_CC1_OFFSET)
#define SAM_TC0_COUNT16_CCBUF0 (SAM_TC0_BASE+SAM_TC_COUNT16_CCBUF0_OFFSET)
#define SAM_TC0_COUNT16_CCBUF1 (SAM_TC0_BASE+SAM_TC_COUNT16_CCBUF1_OFFSET)
#define SAM_TC0_COUNT32_CC0 (SAM_TC0_BASE+SAM_TC_COUNT32_CC0_OFFSET)
#define SAM_TC0_COUNT32_CC1 (SAM_TC0_BASE+SAM_TC_COUNT32_CC1_OFFSET)
#define SAM_TC0_COUNT32_CCBUF0 (SAM_TC0_BASE+SAM_TC_COUNT32_CCBUF0_OFFSET)
#define SAM_TC0_COUNT32_CCBUF1 (SAM_TC0_BASE+SAM_TC_COUNT32_CCBUF1_OFFSET)
#define SAM_TC1_CTRLA (SAM_TC1_BASE+SAM_TC_CTRLA_OFFSET)
#define SAM_TC1_CTRLBCLR (SAM_TC1_BASE+SAM_TC_CTRLBCLR_OFFSET)
#define SAM_TC1_CTRLBSET (SAM_TC1_BASE+SAM_TC_CTRLBSET_OFFSET)
#define SAM_TC1_EVCTRL (SAM_TC1_BASE+SAM_TC_EVCTRL_OFFSET)
#define SAM_TC1_INTENCLR (SAM_TC1_BASE+SAM_TC_INTENCLR_OFFSET)
#define SAM_TC1_INTENSET (SAM_TC1_BASE+SAM_TC_INTENSET_OFFSET)
#define SAM_TC1_INTFLAG (SAM_TC1_BASE+SAM_TC_INTFLAG_OFFSET)
#define SAM_TC1_STATUS (SAM_TC1_BASE+SAM_TC_STATUS_OFFSET)
#define SAM_TC1_WAVE (SAM_TC1_BASE+SAM_TC_WAVE_OFFSET)
#define SAM_TC1_DRVCTRL (SAM_TC1_BASE+SAM_TC_DRVCTRL_OFFSET)
#define SAM_TC1_DBGCTRL (SAM_TC1_BASE+SAM_TC_DBGCTRL_OFFSET)
#define SAM_TC1_SYNCBUSY (SAM_TC1_BASE+SAM_TC_SYNCBUSY_OFFSET)
#define SAM_TC1_COUNT (SAM_TC1_BASE+SAM_TC_COUNT_OFFSET)
#define SAM_TC1_COUNT8_PER (SAM_TC1_BASE+SAM_TC_COUNT8_PER_OFFSET)
#define SAM_TC1_COUNT8_CC0 (SAM_TC1_BASE+SAM_TC_COUNT8_CC0_OFFSET)
#define SAM_TC1_COUNT8_CC1 (SAM_TC1_BASE+SAM_TC_COUNT8_CC1_OFFSET)
#define SAM_TC1_COUNT8_PERBUF (SAM_TC1_BASE+SAM_TC_COUNT8_PERBUF_OFFSET)
#define SAM_TC1_COUNT8_CCBUF0 (SAM_TC1_BASE+SAM_TC_COUNT8_CCBUF0_OFFSET)
#define SAM_TC1_COUNT8_CCBUF1 (SAM_TC1_BASE+SAM_TC_COUNT8_CCBUF1_OFFSET)
#define SAM_TC1_COUNT16_CC0 (SAM_TC1_BASE+SAM_TC_COUNT16_CC0_OFFSET)
#define SAM_TC1_COUNT16_CC1 (SAM_TC1_BASE+SAM_TC_COUNT16_CC1_OFFSET)
#define SAM_TC1_COUNT16_CCBUF0 (SAM_TC1_BASE+SAM_TC_COUNT16_CCBUF0_OFFSET)
#define SAM_TC1_COUNT16_CCBUF1 (SAM_TC1_BASE+SAM_TC_COUNT16_CCBUF1_OFFSET)
#define SAM_TC1_COUNT32_CC0 (SAM_TC1_BASE+SAM_TC_COUNT32_CC0_OFFSET)
#define SAM_TC1_COUNT32_CC1 (SAM_TC1_BASE+SAM_TC_COUNT32_CC1_OFFSET)
#define SAM_TC1_COUNT32_CCBUF0 (SAM_TC1_BASE+SAM_TC_COUNT32_CCBUF0_OFFSET)
#define SAM_TC1_COUNT32_CCBUF1 (SAM_TC1_BASE+SAM_TC_COUNT32_CCBUF1_OFFSET)
#define SAM_TC2_CTRLA (SAM_TC2_BASE+SAM_TC_CTRLA_OFFSET)
#define SAM_TC2_CTRLBCLR (SAM_TC2_BASE+SAM_TC_CTRLBCLR_OFFSET)
#define SAM_TC2_CTRLBSET (SAM_TC2_BASE+SAM_TC_CTRLBSET_OFFSET)
#define SAM_TC2_EVCTRL (SAM_TC2_BASE+SAM_TC_EVCTRL_OFFSET)
#define SAM_TC2_INTENCLR (SAM_TC2_BASE+SAM_TC_INTENCLR_OFFSET)
#define SAM_TC2_INTENSET (SAM_TC2_BASE+SAM_TC_INTENSET_OFFSET)
#define SAM_TC2_INTFLAG (SAM_TC2_BASE+SAM_TC_INTFLAG_OFFSET)
#define SAM_TC2_STATUS (SAM_TC2_BASE+SAM_TC_STATUS_OFFSET)
#define SAM_TC2_WAVE (SAM_TC2_BASE+SAM_TC_WAVE_OFFSET)
#define SAM_TC2_DRVCTRL (SAM_TC2_BASE+SAM_TC_DRVCTRL_OFFSET)
#define SAM_TC2_DBGCTRL (SAM_TC2_BASE+SAM_TC_DBGCTRL_OFFSET)
#define SAM_TC2_SYNCBUSY (SAM_TC2_BASE+SAM_TC_SYNCBUSY_OFFSET)
#define SAM_TC2_COUNT (SAM_TC2_BASE+SAM_TC_COUNT_OFFSET)
#define SAM_TC2_COUNT8_PER (SAM_TC2_BASE+SAM_TC_COUNT8_PER_OFFSET)
#define SAM_TC2_COUNT8_CC0 (SAM_TC2_BASE+SAM_TC_COUNT8_CC0_OFFSET)
#define SAM_TC2_COUNT8_CC1 (SAM_TC2_BASE+SAM_TC_COUNT8_CC1_OFFSET)
#define SAM_TC2_COUNT8_PERBUF (SAM_TC2_BASE+SAM_TC_COUNT8_PERBUF_OFFSET)
#define SAM_TC2_COUNT8_CCBUF0 (SAM_TC2_BASE+SAM_TC_COUNT8_CCBUF0_OFFSET)
#define SAM_TC2_COUNT8_CCBUF1 (SAM_TC2_BASE+SAM_TC_COUNT8_CCBUF1_OFFSET)
#define SAM_TC2_COUNT16_CC0 (SAM_TC2_BASE+SAM_TC_COUNT16_CC0_OFFSET)
#define SAM_TC2_COUNT16_CC1 (SAM_TC2_BASE+SAM_TC_COUNT16_CC1_OFFSET)
#define SAM_TC2_COUNT16_CCBUF0 (SAM_TC2_BASE+SAM_TC_COUNT16_CCBUF0_OFFSET)
#define SAM_TC2_COUNT16_CCBUF1 (SAM_TC2_BASE+SAM_TC_COUNT16_CCBUF1_OFFSET)
#define SAM_TC2_COUNT32_CC0 (SAM_TC2_BASE+SAM_TC_COUNT32_CC0_OFFSET)
#define SAM_TC2_COUNT32_CC1 (SAM_TC2_BASE+SAM_TC_COUNT32_CC1_OFFSET)
#define SAM_TC2_COUNT32_CCBUF0 (SAM_TC2_BASE+SAM_TC_COUNT32_CCBUF0_OFFSET)
#define SAM_TC2_COUNT32_CCBUF1 (SAM_TC2_BASE+SAM_TC_COUNT32_CCBUF1_OFFSET)
#define SAM_TC3_CTRLA (SAM_TC3_BASE+SAM_TC_CTRLA_OFFSET)
#define SAM_TC3_CTRLBCLR (SAM_TC3_BASE+SAM_TC_CTRLBCLR_OFFSET)
#define SAM_TC3_CTRLBSET (SAM_TC3_BASE+SAM_TC_CTRLBSET_OFFSET)
#define SAM_TC3_EVCTRL (SAM_TC3_BASE+SAM_TC_EVCTRL_OFFSET)
#define SAM_TC3_INTENCLR (SAM_TC3_BASE+SAM_TC_INTENCLR_OFFSET)
#define SAM_TC3_INTENSET (SAM_TC3_BASE+SAM_TC_INTENSET_OFFSET)
#define SAM_TC3_INTFLAG (SAM_TC3_BASE+SAM_TC_INTFLAG_OFFSET)
#define SAM_TC3_STATUS (SAM_TC3_BASE+SAM_TC_STATUS_OFFSET)
#define SAM_TC3_WAVE (SAM_TC3_BASE+SAM_TC_WAVE_OFFSET)
#define SAM_TC3_DRVCTRL (SAM_TC3_BASE+SAM_TC_DRVCTRL_OFFSET)
#define SAM_TC3_DBGCTRL (SAM_TC3_BASE+SAM_TC_DBGCTRL_OFFSET)
#define SAM_TC3_SYNCBUSY (SAM_TC3_BASE+SAM_TC_SYNCBUSY_OFFSET)
#define SAM_TC3_COUNT (SAM_TC3_BASE+SAM_TC_COUNT_OFFSET)
#define SAM_TC3_COUNT8_PER (SAM_TC3_BASE+SAM_TC_COUNT8_PER_OFFSET)
#define SAM_TC3_COUNT8_CC0 (SAM_TC3_BASE+SAM_TC_COUNT8_CC0_OFFSET)
#define SAM_TC3_COUNT8_CC1 (SAM_TC3_BASE+SAM_TC_COUNT8_CC1_OFFSET)
#define SAM_TC3_COUNT8_PERBUF (SAM_TC3_BASE+SAM_TC_COUNT8_PERBUF_OFFSET)
#define SAM_TC3_COUNT8_CCBUF0 (SAM_TC3_BASE+SAM_TC_COUNT8_CCBUF0_OFFSET)
#define SAM_TC3_COUNT8_CCBUF1 (SAM_TC3_BASE+SAM_TC_COUNT8_CCBUF1_OFFSET)
#define SAM_TC3_COUNT16_CC0 (SAM_TC3_BASE+SAM_TC_COUNT16_CC0_OFFSET)
#define SAM_TC3_COUNT16_CC1 (SAM_TC3_BASE+SAM_TC_COUNT16_CC1_OFFSET)
#define SAM_TC3_COUNT16_CCBUF0 (SAM_TC3_BASE+SAM_TC_COUNT16_CCBUF0_OFFSET)
#define SAM_TC3_COUNT16_CCBUF1 (SAM_TC3_BASE+SAM_TC_COUNT16_CCBUF1_OFFSET)
#define SAM_TC3_COUNT32_CC0 (SAM_TC3_BASE+SAM_TC_COUNT32_CC0_OFFSET)
#define SAM_TC3_COUNT32_CC1 (SAM_TC3_BASE+SAM_TC_COUNT32_CC1_OFFSET)
#define SAM_TC3_COUNT32_CCBUF0 (SAM_TC3_BASE+SAM_TC_COUNT32_CCBUF0_OFFSET)
#define SAM_TC3_COUNT32_CCBUF1 (SAM_TC3_BASE+SAM_TC_COUNT32_CCBUF1_OFFSET)
#define SAM_TC4_CTRLA (SAM_TC4_BASE+SAM_TC_CTRLA_OFFSET)
#define SAM_TC4_CTRLBCLR (SAM_TC4_BASE+SAM_TC_CTRLBCLR_OFFSET)
#define SAM_TC4_CTRLBSET (SAM_TC4_BASE+SAM_TC_CTRLBSET_OFFSET)
#define SAM_TC4_EVCTRL (SAM_TC4_BASE+SAM_TC_EVCTRL_OFFSET)
#define SAM_TC4_INTENCLR (SAM_TC4_BASE+SAM_TC_INTENCLR_OFFSET)
#define SAM_TC4_INTENSET (SAM_TC4_BASE+SAM_TC_INTENSET_OFFSET)
#define SAM_TC4_INTFLAG (SAM_TC4_BASE+SAM_TC_INTFLAG_OFFSET)
#define SAM_TC4_STATUS (SAM_TC4_BASE+SAM_TC_STATUS_OFFSET)
#define SAM_TC4_WAVE (SAM_TC4_BASE+SAM_TC_WAVE_OFFSET)
#define SAM_TC4_DRVCTRL (SAM_TC4_BASE+SAM_TC_DRVCTRL_OFFSET)
#define SAM_TC4_DBGCTRL (SAM_TC4_BASE+SAM_TC_DBGCTRL_OFFSET)
#define SAM_TC4_SYNCBUSY (SAM_TC4_BASE+SAM_TC_SYNCBUSY_OFFSET)
#define SAM_TC4_COUNT (SAM_TC4_BASE+SAM_TC_COUNT_OFFSET)
#define SAM_TC4_COUNT8_PER (SAM_TC4_BASE+SAM_TC_COUNT8_PER_OFFSET)
#define SAM_TC4_COUNT8_CC0 (SAM_TC4_BASE+SAM_TC_COUNT8_CC0_OFFSET)
#define SAM_TC4_COUNT8_CC1 (SAM_TC4_BASE+SAM_TC_COUNT8_CC1_OFFSET)
#define SAM_TC4_COUNT8_PERBUF (SAM_TC4_BASE+SAM_TC_COUNT8_PERBUF_OFFSET)
#define SAM_TC4_COUNT8_CCBUF0 (SAM_TC4_BASE+SAM_TC_COUNT8_CCBUF0_OFFSET)
#define SAM_TC4_COUNT8_CCBUF1 (SAM_TC4_BASE+SAM_TC_COUNT8_CCBUF1_OFFSET)
#define SAM_TC4_COUNT16_CC0 (SAM_TC4_BASE+SAM_TC_COUNT16_CC0_OFFSET)
#define SAM_TC4_COUNT16_CC1 (SAM_TC4_BASE+SAM_TC_COUNT16_CC1_OFFSET)
#define SAM_TC4_COUNT16_CCBUF0 (SAM_TC4_BASE+SAM_TC_COUNT16_CCBUF0_OFFSET)
#define SAM_TC4_COUNT16_CCBUF1 (SAM_TC4_BASE+SAM_TC_COUNT16_CCBUF1_OFFSET)
#define SAM_TC4_COUNT32_CC0 (SAM_TC4_BASE+SAM_TC_COUNT32_CC0_OFFSET)
#define SAM_TC4_COUNT32_CC1 (SAM_TC4_BASE+SAM_TC_COUNT32_CC1_OFFSET)
#define SAM_TC4_COUNT32_CCBUF0 (SAM_TC4_BASE+SAM_TC_COUNT32_CCBUF0_OFFSET)
#define SAM_TC4_COUNT32_CCBUF1 (SAM_TC4_BASE+SAM_TC_COUNT32_CCBUF1_OFFSET)
#define SAM_TC5_CTRLA (SAM_TC5_BASE+SAM_TC_CTRLA_OFFSET)
#define SAM_TC5_CTRLBCLR (SAM_TC5_BASE+SAM_TC_CTRLBCLR_OFFSET)
#define SAM_TC5_CTRLBSET (SAM_TC5_BASE+SAM_TC_CTRLBSET_OFFSET)
#define SAM_TC5_EVCTRL (SAM_TC5_BASE+SAM_TC_EVCTRL_OFFSET)
#define SAM_TC5_INTENCLR (SAM_TC5_BASE+SAM_TC_INTENCLR_OFFSET)
#define SAM_TC5_INTENSET (SAM_TC5_BASE+SAM_TC_INTENSET_OFFSET)
#define SAM_TC5_INTFLAG (SAM_TC5_BASE+SAM_TC_INTFLAG_OFFSET)
#define SAM_TC5_STATUS (SAM_TC5_BASE+SAM_TC_STATUS_OFFSET)
#define SAM_TC5_WAVE (SAM_TC5_BASE+SAM_TC_WAVE_OFFSET)
#define SAM_TC5_DRVCTRL (SAM_TC5_BASE+SAM_TC_DRVCTRL_OFFSET)
#define SAM_TC5_DBGCTRL (SAM_TC5_BASE+SAM_TC_DBGCTRL_OFFSET)
#define SAM_TC5_SYNCBUSY (SAM_TC5_BASE+SAM_TC_SYNCBUSY_OFFSET)
#define SAM_TC5_COUNT (SAM_TC5_BASE+SAM_TC_COUNT_OFFSET)
#define SAM_TC5_COUNT8_PER (SAM_TC5_BASE+SAM_TC_COUNT8_PER_OFFSET)
#define SAM_TC5_COUNT8_CC0 (SAM_TC5_BASE+SAM_TC_COUNT8_CC0_OFFSET)
#define SAM_TC5_COUNT8_CC1 (SAM_TC5_BASE+SAM_TC_COUNT8_CC1_OFFSET)
#define SAM_TC5_COUNT8_PERBUF (SAM_TC5_BASE+SAM_TC_COUNT8_PERBUF_OFFSET)
#define SAM_TC5_COUNT8_CCBUF0 (SAM_TC5_BASE+SAM_TC_COUNT8_CCBUF0_OFFSET)
#define SAM_TC5_COUNT8_CCBUF1 (SAM_TC5_BASE+SAM_TC_COUNT8_CCBUF1_OFFSET)
#define SAM_TC5_COUNT16_CC0 (SAM_TC5_BASE+SAM_TC_COUNT16_CC0_OFFSET)
#define SAM_TC5_COUNT16_CC1 (SAM_TC5_BASE+SAM_TC_COUNT16_CC1_OFFSET)
#define SAM_TC5_COUNT16_CCBUF0 (SAM_TC5_BASE+SAM_TC_COUNT16_CCBUF0_OFFSET)
#define SAM_TC5_COUNT16_CCBUF1 (SAM_TC5_BASE+SAM_TC_COUNT16_CCBUF1_OFFSET)
#define SAM_TC5_COUNT32_CC0 (SAM_TC5_BASE+SAM_TC_COUNT32_CC0_OFFSET)
#define SAM_TC5_COUNT32_CC1 (SAM_TC5_BASE+SAM_TC_COUNT32_CC1_OFFSET)
#define SAM_TC5_COUNT32_CCBUF0 (SAM_TC5_BASE+SAM_TC_COUNT32_CCBUF0_OFFSET)
#define SAM_TC5_COUNT32_CCBUF1 (SAM_TC5_BASE+SAM_TC_COUNT32_CCBUF1_OFFSET)
/****************************************************************************
* Not used
****************************************************************************/
/****************************************************************************
#define SAM_TC6_CTRLA (SAM_TC6_BASE+SAM_TC_CTRLA_OFFSET)
#define SAM_TC6_CTRLBCLR (SAM_TC6_BASE+SAM_TC_CTRLBCLR_OFFSET)
#define SAM_TC6_CTRLBSET (SAM_TC6_BASE+SAM_TC_CTRLBSET_OFFSET)
#define SAM_TC6_EVCTRL (SAM_TC6_BASE+SAM_TC_EVCTRL_OFFSET)
#define SAM_TC6_INTENCLR (SAM_TC6_BASE+SAM_TC_INTENCLR_OFFSET)
#define SAM_TC6_INTENSET (SAM_TC6_BASE+SAM_TC_INTENSET_OFFSET)
#define SAM_TC6_INTFLAG (SAM_TC6_BASE+SAM_TC_INTFLAG_OFFSET)
#define SAM_TC6_STATUS (SAM_TC6_BASE+SAM_TC_STATUS_OFFSET)
#define SAM_TC6_WAVE (SAM_TC6_BASE+SAM_TC_WAVE_OFFSET)
#define SAM_TC6_DRVCTRL (SAM_TC6_BASE+SAM_TC_DRVCTRL_OFFSET)
#define SAM_TC6_DBGCTRL (SAM_TC6_BASE+SAM_TC_DBGCTRL_OFFSET)
#define SAM_TC6_SYNCBUSY (SAM_TC6_BASE+SAM_TC_SYNCBUSY_OFFSET)
#define SAM_TC6_COUNT (SAM_TC6_BASE+SAM_TC_COUNT_OFFSET)
#define SAM_TC6_COUNT8_PER (SAM_TC6_BASE+SAM_TC_COUNT8_PER_OFFSET)
#define SAM_TC6_COUNT8_CC0 (SAM_TC6_BASE+SAM_TC_COUNT8_CC0_OFFSET)
#define SAM_TC6_COUNT8_CC1 (SAM_TC6_BASE+SAM_TC_COUNT8_CC1_OFFSET)
#define SAM_TC6_COUNT8_PERBUF (SAM_TC6_BASE+SAM_TC_COUNT8_PERBUF_OFFSET)
#define SAM_TC6_COUNT8_CCBUF0 (SAM_TC6_BASE+SAM_TC_COUNT8_CCBUF0_OFFSET)
#define SAM_TC6_COUNT8_CCBUF1 (SAM_TC6_BASE+SAM_TC_COUNT8_CCBUF1_OFFSET)
#define SAM_TC6_COUNT16_CC0 (SAM_TC6_BASE+SAM_TC_COUNT16_CC0_OFFSET)
#define SAM_TC6_COUNT16_CC1 (SAM_TC6_BASE+SAM_TC_COUNT16_CC1_OFFSET)
#define SAM_TC6_COUNT16_CCBUF0 (SAM_TC6_BASE+SAM_TC_COUNT16_CCBUF0_OFFSET)
#define SAM_TC6_COUNT16_CCBUF1 (SAM_TC6_BASE+SAM_TC_COUNT16_CCBUF1_OFFSET)
#define SAM_TC6_COUNT32_CC0 (SAM_TC6_BASE+SAM_TC_COUNT32_CC0_OFFSET)
#define SAM_TC6_COUNT32_CC1 (SAM_TC6_BASE+SAM_TC_COUNT32_CC1_OFFSET)
#define SAM_TC6_COUNT32_CCBUF0 (SAM_TC6_BASE+SAM_TC_COUNT32_CCBUF0_OFFSET)
#define SAM_TC6_COUNT32_CCBUF1 (SAM_TC6_BASE+SAM_TC_COUNT32_CCBUF1_OFFSET)
#define SAM_TC7_CTRLA (SAM_TC7_BASE+SAM_TC_CTRLA_OFFSET)
#define SAM_TC7_CTRLBCLR (SAM_TC7_BASE+SAM_TC_CTRLBCLR_OFFSET)
#define SAM_TC7_CTRLBSET (SAM_TC7_BASE+SAM_TC_CTRLBSET_OFFSET)
#define SAM_TC7_EVCTRL (SAM_TC7_BASE+SAM_TC_EVCTRL_OFFSET)
#define SAM_TC7_INTENCLR (SAM_TC7_BASE+SAM_TC_INTENCLR_OFFSET)
#define SAM_TC7_INTENSET (SAM_TC7_BASE+SAM_TC_INTENSET_OFFSET)
#define SAM_TC7_INTFLAG (SAM_TC7_BASE+SAM_TC_INTFLAG_OFFSET)
#define SAM_TC7_STATUS (SAM_TC7_BASE+SAM_TC_STATUS_OFFSET)
#define SAM_TC7_WAVE (SAM_TC7_BASE+SAM_TC_WAVE_OFFSET)
#define SAM_TC7_DRVCTRL (SAM_TC7_BASE+SAM_TC_DRVCTRL_OFFSET)
#define SAM_TC7_DBGCTRL (SAM_TC7_BASE+SAM_TC_DBGCTRL_OFFSET)
#define SAM_TC7_SYNCBUSY (SAM_TC7_BASE+SAM_TC_SYNCBUSY_OFFSET)
#define SAM_TC7_COUNT (SAM_TC7_BASE+SAM_TC_COUNT_OFFSET)
#define SAM_TC7_COUNT8_PER (SAM_TC7_BASE+SAM_TC_COUNT8_PER_OFFSET)
#define SAM_TC7_COUNT8_CC0 (SAM_TC7_BASE+SAM_TC_COUNT8_CC0_OFFSET)
#define SAM_TC7_COUNT8_CC1 (SAM_TC7_BASE+SAM_TC_COUNT8_CC1_OFFSET)
#define SAM_TC7_COUNT8_PERBUF (SAM_TC7_BASE+SAM_TC_COUNT8_PERBUF_OFFSET)
#define SAM_TC7_COUNT8_CCBUF0 (SAM_TC7_BASE+SAM_TC_COUNT8_CCBUF0_OFFSET)
#define SAM_TC7_COUNT8_CCBUF1 (SAM_TC7_BASE+SAM_TC_COUNT8_CCBUF1_OFFSET)
#define SAM_TC7_COUNT16_CC0 (SAM_TC7_BASE+SAM_TC_COUNT16_CC0_OFFSET)
#define SAM_TC7_COUNT16_CC1 (SAM_TC7_BASE+SAM_TC_COUNT16_CC1_OFFSET)
#define SAM_TC7_COUNT16_CCBUF0 (SAM_TC7_BASE+SAM_TC_COUNT16_CCBUF0_OFFSET)
#define SAM_TC7_COUNT16_CCBUF1 (SAM_TC7_BASE+SAM_TC_COUNT16_CCBUF1_OFFSET)
#define SAM_TC7_COUNT32_CC0 (SAM_TC7_BASE+SAM_TC_COUNT32_CC0_OFFSET)
#define SAM_TC7_COUNT32_CC1 (SAM_TC7_BASE+SAM_TC_COUNT32_CC1_OFFSET)
#define SAM_TC7_COUNT32_CCBUF0 (SAM_TC7_BASE+SAM_TC_COUNT32_CCBUF0_OFFSET)
#define SAM_TC7_COUNT32_CCBUF1 (SAM_TC7_BASE+SAM_TC_COUNT32_CCBUF1_OFFSET)
****************************************************************************/
/* TC register bit definitions */
/* Control A register */
#define TC_CTRLA_SWRST (1 << 0) /* Bit 0: Software reset */
#define TC_CTRLA_ENABLE (1 << 1) /* Bit 1: Enable */
#define TC_CTRLA_DISABLE (0 << 1) /* Bit 1: Disable */
#define TC_CTRLA_MODE_SHIFT (2)
#define TC_CTRLA_MODE_MASK (3 << TC_CTRLA_MODE_SHIFT)
#define TC_CTRLA_MODE_COUNT16 (0 << TC_CTRLA_MODE_SHIFT)
#define TC_CTRLA_MODE_COUNT8 (1 << TC_CTRLA_MODE_SHIFT)
#define TC_CTRLA_MODE_COUNT32 (2 << TC_CTRLA_MODE_SHIFT)
#define TC_CTRLA_PRESCSYNC_SHIFT (4)
#define TC_CTRLA_PRESCSYNC_MASK (3 << TC_CTRLA_PRESCSYNC_SHIFT)
#define TC_CTRLA_PRESCSYNC_GCLK (0 << TC_CTRLA_PRESCSYNC_SHIFT)
#define TC_CTRLA_PRESCSYNC_PRESC (1 << TC_CTRLA_PRESCSYNC_SHIFT)
#define TC_CTRLA_PRESCSYNC_RESYNC (2 << TC_CTRLA_PRESCSYNC_SHIFT)
#define TC_CTRLA_RUNSTDBY (1 << 6)
#define TC_CTRLA_ONDEMAND (1 << 7)
#define TC_CTRLA_PRESCALER_SHIFT (8)
#define TC_CTRLA_PRESCALER_MASK (7 << TC_CTRLA_PRESCALER_SHIFT)
#define TC_CTRLA_PRESCALER(n) ((uint32_t)(n) << TC_CTRLA_PRESCALER_SHIFT)
#define TC_CTRLA_PRESCALER_DIV1 (0 << TC_CTRLA_PRESCALER_SHIFT)
#define TC_CTRLA_PRESCALER_DIV2 (1 << TC_CTRLA_PRESCALER_SHIFT)
#define TC_CTRLA_PRESCALER_DIV4 (2 << TC_CTRLA_PRESCALER_SHIFT)
#define TC_CTRLA_PRESCALER_DIV8 (3 << TC_CTRLA_PRESCALER_SHIFT)
#define TC_CTRLA_PRESCALER_DIV16 (4 << TC_CTRLA_PRESCALER_SHIFT)
#define TC_CTRLA_PRESCALER_DIV64 (5 << TC_CTRLA_PRESCALER_SHIFT)
#define TC_CTRLA_PRESCALER_DIV256 (6 << TC_CTRLA_PRESCALER_SHIFT)
#define TC_CTRLA_PRESCALER_DIV1024 (7 << TC_CTRLA_PRESCALER_SHIFT)
#define TC_CTRLA_ALOCK (1 << 11)
#define TC_CTRLA_CAPTEN0_SHIFT (16) /* (TC_CTRLA) Capture Channel 0 Enable */
#define TC_CTRLA_CAPTEN0 (1 << TC_CTRLA_CAPTEN0_SHIFT)
#define TC_CTRLA_CAPTEN1_SHIFT (17) /* (TC_CTRLA) Capture Channel 1 Enable */
#define TC_CTRLA_CAPTEN1 (1 << TC_CTRLA_CAPTEN1_SHIFT)
#define TC_CTRLA_COPEN0_SHIFT (20) /* (TC_CTRLA) Capture On Pin 0 Enable */
#define TC_CTRLA_COPEN0 (1 << TC_CTRLA_COPEN1_SHIFT)
#define TC_CTRLA_COPEN1_SHIFT (21) /* (TC_CTRLA) Capture On Pin 1 Enable */
#define TC_CTRLA_COPEN1 (1 << TC_CTRLA_CAPTEN1_SHIFT)
#define TC_CTRLA_CAPTMODE0_SHIFT (24) /* (TC_CTRLA) Capture Mode Channel 0 */
#define TC_CTRLA_CAPTMODE0_MASK (3 << TC_CTRLA_CAPTMODE0_SHIFT)
#define TC_CTRLA_CAPTMODE0_CAPTD (0 << TC_CTRLA_CAPTMODE0_SHIFT) /* (TC_CTRLA) Default capture */
#define TC_CTRLA_CAPTMODE0_CAPTMIN (1 << TC_CTRLA_CAPTMODE0_SHIFT) /* (TC_CTRLA) Minimum capture */
#define TC_CTRLA_CAPTMODE0_CAPTMAX (2 << TC_CTRLA_CAPTMODE0_SHIFT) /* (TC_CTRLA) Maximum capture */
#define TC_CTRLA_CAPTMODE1_SHIFT (27) /* (TC_CTRLA) Capture Mode Channel 0 */
#define TC_CTRLA_CAPTMODE1_MASK (3 << TC_CTRLA_CAPTMODE1_SHIFT)
#define TC_CTRLA_CAPTMODE1_CAPTD (0 << TC_CTRLA_CAPTMODE1_SHIFT) /* (TC_CTRLA) Default capture */
#define TC_CTRLA_CAPTMODE1_CAPTMIN (1 << TC_CTRLA_CAPTMODE1_SHIFT) /* (TC_CTRLA) Minimum capture */
#define TC_CTRLA_CAPTMODE1_CAPTMAX (2 << TC_CTRLA_CAPTMODE1_SHIFT) /* (TC_CTRLA) Maximum capture */
/* Control B Clear register */
#define TC_CTRLBCLR_DIR (1 << 0)
#define TC_CTRLBCLR_LUPD (1 << 1)
#define TC_CTRLBCLR_ONESHOT (1 << 2)
#define TC_CTRLBCLR_CMD_SHIFT (5)
#define TC_CTRLBCLR_CMD_MASK (7 << TC_CTRLBCLR_CMD_SHIFT)
#define TC_CTRLBCLR_CMD_NONE (0 << TC_CTRLBCLR_CMD_SHIFT) /* (TC_CTRLBCLR) No action */
#define TC_CTRLBCLR_CMD_RETRIGGER (1 << TC_CTRLBCLR_CMD_SHIFT) /* (TC_CTRLBCLR) Force a start, restart or retrigger */
#define TC_CTRLBCLR_CMD_STOP (2 << TC_CTRLBCLR_CMD_SHIFT) /* (TC_CTRLBCLR) Force a stop */
#define TC_CTRLBCLR_CMD_UPDATE (3 << TC_CTRLBCLR_CMD_SHIFT) /* (TC_CTRLBCLR) Force update of double-buffered register */
#define TC_CTRLBCLR_CMD_READSYNC (4 << TC_CTRLBCLR_CMD_SHIFT) /* (TC_CTRLBCLR) Force a read synchronization of COUNT */
#define TC_CTRLBCLR_CMD_DMAOS (5 << TC_CTRLBCLR_CMD_SHIFT) /* (TC_CTRLBCLR) One-shot DMA trigger */
/* Control B Set register */
#define TC_CTRLBSET_DIR (1 << 0)
#define TC_CTRLBSET_LUPD (1 << 1)
#define TC_CTRLBSET_ONESHOT (1 << 2)
#define TC_CTRLBSET_CMD_SHIFT (5)
#define TC_CTRLBSET_CMD_MASK (7 << TC_CTRLBSET_CMD_SHIFT)
#define TC_CTRLBSET_CMD_NONE (0 << TC_CTRLBSET_CMD_SHIFT) /* (TC_CTRLBCLR) No action */
#define TC_CTRLBSET_CMD_RETRIGGER (1 << TC_CTRLBSET_CMD_SHIFT) /* (TC_CTRLBCLR) Force a start, restart or retrigger */
#define TC_CTRLBSET_CMD_STOP (2 << TC_CTRLBSET_CMD_SHIFT) /* (TC_CTRLBCLR) Force a stop */
#define TC_CTRLBSET_CMD_UPDATE (3 << TC_CTRLBSET_CMD_SHIFT) /* (TC_CTRLBCLR) Force update of double-buffered register */
#define TC_CTRLBSET_CMD_READSYNC (4 << TC_CTRLBSET_CMD_SHIFT) /* (TC_CTRLBCLR) Force a read synchronization of COUNT */
#define TC_CTRLBSET_CMD_DMAOS (5 << TC_CTRLBSET_CMD_SHIFT) /* (TC_CTRLBCLR) One-shot DMA trigger */
/* Event control register */
#define TC_EVCTRL_EVACT_SHIFT (0)
#define TC_EVCTRL_EVACT_MASK (7 << TC_EVCTRL_EVACT_SHIFT)
# define TC_EVCTRL_EVACT_OFF (0 << TC_EVCTRL_EVACT_SHIFT)
# define TC_EVCTRL_EVACT_RETRIGGER (1 << TC_EVCTRL_EVACT_SHIFT)
# define TC_EVCTRL_EVACT_COUNT (2 << TC_EVCTRL_EVACT_SHIFT)
# define TC_EVCTRL_EVACT_START (3 << TC_EVCTRL_EVACT_SHIFT)
# define TC_EVCTRL_EVACT_STAMP (4 << TC_EVCTRL_EVACT_SHIFT)
# define TC_EVCTRL_EVACT_PPW (5 << TC_EVCTRL_EVACT_SHIFT)
# define TC_EVCTRL_EVACT_PWP (6 << TC_EVCTRL_EVACT_SHIFT)
# define TC_EVCTRL_EVACT_PW (7 << TC_EVCTRL_EVACT_SHIFT)
#define TC_EVCTRL_TCINV (1 << 4)
#define TC_EVCTRL_TCEI (1 << 5)
#define TC_EVCTRL_OVFEO (1 << 8)
#define TC_EVCTRL_MCEO0 (1 << 12)
#define TC_EVCTRL_MCEO1 (1 << 13)
/* TC_INTENCLR : Interrupt Enable Clear */
#define TC_INTENCLR_OVF (1 << 0) /* (TC_INTENCLR) OVF Interrupt Disable */
#define TC_INTENCLR_ERR (1 << 1) /* (TC_INTENCLR) ERR Interrupt Disable */
#define TC_INTENCLR_MC0 (1 << 4) /* (TC_INTENCLR) MC Interrupt Disable 0 */
#define TC_INTENCLR_MC1 (1 << 5) /* (TC_INTENCLR) MC Interrupt Disable 1 */
/* TC_INTENSET : Interrupt Enable Set */
#define TC_INTENSET_OVF (1 << 0) /* (TC_INTENCLR) OVF Interrupt Disable */
#define TC_INTENSET_ERR (1 << 1) /* (TC_INTENCLR) ERR Interrupt Disable */
#define TC_INTENSET_MC0 (1 << 4) /* (TC_INTENCLR) MC Interrupt Disable 0 */
#define TC_INTENSET_MC1 (1 << 5) /* (TC_INTENCLR) MC Interrupt Disable 1 */
/* TC_INTFLAG : Interrupt Flag Status and Clear */
#define TC_INTFLAG_OVF (1 << 0) /* (TC_INTENCLR) OVF Interrupt Disable */
#define TC_INTFLAG_ERR (1 << 1) /* (TC_INTENCLR) ERR Interrupt Disable */
#define TC_INTFLAG_MC0 (1 << 4) /* (TC_INTENCLR) MC Interrupt Disable 0 */
#define TC_INTFLAG_MC1 (1 << 5) /* (TC_INTENCLR) MC Interrupt Disable 1 */
#define TC_INTFLAG_ALL (TC_INTFLAG_OVF | TC_INTFLAG_ERR | TC_INTFLAG_MC0 | TC_INTFLAG_MC1)
/* Status register */
#define TC_STATUS_STOP (1 << 0)
#define TC_STATUS_SLAVE (1 << 1)
#define TC_STATUS_PERBUFV (1 << 3)
#define TC_STATUS_CCBUFV0 (1 << 4)
#define TC_STATUS_CCBUFV1 (1 << 5)
/* TC_WAVE : Waveform Generation Control */
#define TC_WAVE_WAVEGEN_SHIFT (0) /* (TC_WAVE) Waveform Generation Mode */
#define TC_WAVE_WAVEGEN_Msk (3 << TC_WAVE_WAVEGEN_SHIFT)
#define TC_WAVE_WAVEGEN_NFRQ (0 << TC_WAVE_WAVEGEN_SHIFT) /* (TC_WAVE) Normal frequency */
#define TC_WAVE_WAVEGEN_MFRQ (1 << TC_WAVE_WAVEGEN_SHIFT) /* (TC_WAVE) Match frequency */
#define TC_WAVE_WAVEGEN_NPWM (2 << TC_WAVE_WAVEGEN_SHIFT) /* (TC_WAVE) Normal PWM */
#define TC_WAVE_WAVEGEN_MPWM (3 << TC_WAVE_WAVEGEN_SHIFT) /* (TC_WAVE) Match PWM */
/* TC_DRVCTRL : Control C */
#define TC_DRVCTRL_INVEN0 (1 << 0 /* (TC_DRVCTRL) Output Waveform Invert Enable 0 */
#define TC_DRVCTRL_INVEN1 (1 << 1) /* (TC_DRVCTRL) Output Waveform Invert Enable 1 */
/* TC_DBGCTRL : Debug Control */
#define TC_DBGCTRL_DBGRUN (1 << 0) /* (TC_DBGCTRL) Run During Debug */
/* TC_SYNCBUSY : Synchronization Status */
#define TC_SYNCBUSY_SWRST (1 << 0) /* (TC_SYNCBUSY) swrst */
#define TC_SYNCBUSY_ENABLE (1 << 1) /* (TC_SYNCBUSY) enable */
#define TC_SYNCBUSY_CTRLB (1 << 2) /* (TC_SYNCBUSY) CTRLB */
#define TC_SYNCBUSY_STATUS (1 << 3) /* (TC_SYNCBUSY) STATUS */
#define TC_SYNCBUSY_COUNT (1 << 4) /* (TC_SYNCBUSY) Counter */
#define TC_SYNCBUSY_CC0 (1 << 6) /* (TC_SYNCBUSY) Compare Channel 0 */
#define TC_SYNCBUSY_CC1 (1 << 7) /* (TC_SYNCBUSY) Compare Channel 1 */
/****************************************************************************
* Public Types
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Public Functions Prototypes
****************************************************************************/
#endif /* __ARCH_ARM_SRC_SAMD5E5_CHIP_SAMD_TC_H */

View File

@ -82,209 +82,209 @@ static const struct sam_clockconfig_s g_initial_clocking =
.gclkset2 = BOARD_GCLK_SET2,
.cpu_frequency = BOARD_CPU_FREQUENCY,
#if BOARD_HAVE_XOSC32K != 0
.xosc32k =
{
.enable = BOARD_XOSC32K_ENABLE,
.highspeed = BOARD_XOSC32K_HIGHSPEED,
.extalen = BOARD_XOSC32K_XTALEN,
.en32k = BOARD_XOSC32K_EN32K,
.en1k = BOARD_XOSC32K_EN1K,
.runstdby = BOARD_XOSC32K_RUNSTDBY,
.ondemand = BOARD_XOSC32K_ONDEMAND,
.cfden = BOARD_XOSC32K_CFDEN,
.cfdeo = BOARD_XOSC32K_CFDEO,
.caliben = BOARD_XOSC32K_CALIBEN,
.startup = BOARD_XOSC32K_STARTUP,
.calib = BOARD_XOSC32K_CALIB,
.rtcsel = BOARD_XOSC32K_RTCSEL,
},
.xosc32k =
{
.enable = BOARD_XOSC32K_ENABLE,
.highspeed = BOARD_XOSC32K_HIGHSPEED,
.extalen = BOARD_XOSC32K_XTALEN,
.en32k = BOARD_XOSC32K_EN32K,
.en1k = BOARD_XOSC32K_EN1K,
.runstdby = BOARD_XOSC32K_RUNSTDBY,
.ondemand = BOARD_XOSC32K_ONDEMAND,
.cfden = BOARD_XOSC32K_CFDEN,
.cfdeo = BOARD_XOSC32K_CFDEO,
.caliben = BOARD_XOSC32K_CALIBEN,
.startup = BOARD_XOSC32K_STARTUP,
.calib = BOARD_XOSC32K_CALIB,
.rtcsel = BOARD_XOSC32K_RTCSEL,
},
#endif
#if BOARD_HAVE_XOSC0 != 0
.xosc0 =
{
.enable = BOARD_XOSC0_ENABLE,
.extalen = BOARD_XOSC0_XTALEN,
.runstdby = BOARD_XOSC0_RUNSTDBY,
.ondemand = BOARD_XOSC0_ONDEMAND,
.lowgain = BOARD_XOSC0_LOWGAIN,
.enalc = BOARD_XOSC0_ENALC,
.cfden = BOARD_XOSC0_CFDEN,
.startup = BOARD_XOSC0_STARTUP,
.xosc_frequency = BOARD_XOSC0_FREQUENCY,
},
.xosc0 =
{
.enable = BOARD_XOSC0_ENABLE,
.extalen = BOARD_XOSC0_XTALEN,
.runstdby = BOARD_XOSC0_RUNSTDBY,
.ondemand = BOARD_XOSC0_ONDEMAND,
.lowgain = BOARD_XOSC0_LOWGAIN,
.enalc = BOARD_XOSC0_ENALC,
.cfden = BOARD_XOSC0_CFDEN,
.startup = BOARD_XOSC0_STARTUP,
.xosc_frequency = BOARD_XOSC0_FREQUENCY,
},
#endif
#if BOARD_HAVE_XOSC1 != 0
.xosc1 =
{
.enable = BOARD_XOSC1_ENABLE,
.extalen = BOARD_XOSC1_XTALEN,
.runstdby = BOARD_XOSC1_RUNSTDBY,
.ondemand = BOARD_XOSC1_ONDEMAND,
.lowgain = BOARD_XOSC1_LOWGAIN,
.enalc = BOARD_XOSC1_ENALC,
.cfden = BOARD_XOSC1_CFDEN,
.startup = BOARD_XOSC1_STARTUP,
.xosc_frequency = BOARD_XOSC1_FREQUENCY,
},
.xosc1 =
{
.enable = BOARD_XOSC1_ENABLE,
.extalen = BOARD_XOSC1_XTALEN,
.runstdby = BOARD_XOSC1_RUNSTDBY,
.ondemand = BOARD_XOSC1_ONDEMAND,
.lowgain = BOARD_XOSC1_LOWGAIN,
.enalc = BOARD_XOSC1_ENALC,
.cfden = BOARD_XOSC1_CFDEN,
.startup = BOARD_XOSC1_STARTUP,
.xosc_frequency = BOARD_XOSC1_FREQUENCY,
},
#endif
.dfll =
{
.enable = BOARD_DFLL_ENABLE,
.runstdby = BOARD_DFLL_RUNSTDBY,
.ondemand = BOARD_DFLL_ONDEMAND,
.mode = BOARD_DFLL_MODE,
.stable = BOARD_DFLL_STABLE,
.llaw = BOARD_DFLL_LLAW,
.usbcrm = BOARD_DFLL_USBCRM,
.ccdis = BOARD_DFLL_CCDIS,
.qldis = BOARD_DFLL_QLDIS,
.bplckc = BOARD_DFLL_BPLCKC,
.waitlock = BOARD_DFLL_WAITLOCK,
.caliben = BOARD_DFLL_CALIBEN,
.gclklock = BOARD_DFLL_GCLKLOCK,
.fcalib = BOARD_DFLL_FCALIB,
.ccalib = BOARD_DFLL_CCALIB,
.fstep = BOARD_DFLL_FSTEP,
.cstep = BOARD_DFLL_CSTEP,
.gclk = BOARD_DFLL_GCLK,
.mul = BOARD_DFLL_MUL
},
.dpll =
{
{
.enable = BOARD_DPLL0_ENABLE,
.dcoen = BOARD_DPLL0_DCOEN,
.lbypass = BOARD_DPLL0_LBYPASS,
.wuf = BOARD_DPLL0_WUF,
.runstdby = BOARD_DPLL0_RUNSTDBY,
.ondemand = BOARD_DPLL0_ONDEMAND,
.reflock = BOARD_DPLL0_REFLOCK,
.refclk = BOARD_DPLL0_REFCLK,
.ltime = BOARD_DPLL0_LTIME,
.filter = BOARD_DPLL0_FILTER,
.dcofilter = BOARD_DPLL0_DCOFILTER,
.gclk = BOARD_DPLL0_GCLK,
.ldrfrac = BOARD_DPLL0_LDRFRAC,
.ldrint = BOARD_DPLL0_LDRINT,
.div = BOARD_DPLL0_DIV
},
{
.enable = BOARD_DPLL1_ENABLE,
.dcoen = BOARD_DPLL1_DCOEN,
.lbypass = BOARD_DPLL1_LBYPASS,
.wuf = BOARD_DPLL1_WUF,
.runstdby = BOARD_DPLL1_RUNSTDBY,
.ondemand = BOARD_DPLL1_ONDEMAND,
.reflock = BOARD_DPLL1_REFLOCK,
.refclk = BOARD_DPLL1_REFCLK,
.ltime = BOARD_DPLL1_LTIME,
.filter = BOARD_DPLL1_FILTER,
.dcofilter = BOARD_DPLL1_DCOFILTER,
.gclk = BOARD_DPLL1_GCLK,
.ldrfrac = BOARD_DPLL1_LDRFRAC,
.ldrint = BOARD_DPLL1_LDRINT,
.div = BOARD_DPLL1_DIV
}
},
.gclk =
{
{
.enable = BOARD_GCLK0_ENABLE,
.oov = BOARD_GCLK0_OOV,
.oe = BOARD_GCLK0_OE,
.runstdby = BOARD_GCLK0_RUNSTDBY,
.source = BOARD_GCLK0_SOURCE,
.div = BOARD_GCLK0_DIV
},
{
.enable = BOARD_GCLK1_ENABLE,
.oov = BOARD_GCLK1_OOV,
.oe = BOARD_GCLK1_OE,
.runstdby = BOARD_GCLK1_RUNSTDBY,
.source = BOARD_GCLK1_SOURCE,
.div = BOARD_GCLK1_DIV
},
{
.enable = BOARD_GCLK2_ENABLE,
.oov = BOARD_GCLK2_OOV,
.oe = BOARD_GCLK2_OE,
.runstdby = BOARD_GCLK2_RUNSTDBY,
.source = BOARD_GCLK2_SOURCE,
.div = BOARD_GCLK2_DIV
},
{
.enable = BOARD_GCLK3_ENABLE,
.oov = BOARD_GCLK3_OOV,
.oe = BOARD_GCLK3_OE,
.runstdby = BOARD_GCLK3_RUNSTDBY,
.source = BOARD_GCLK3_SOURCE,
.div = BOARD_GCLK3_DIV
},
{
.enable = BOARD_GCLK4_ENABLE,
.oov = BOARD_GCLK4_OOV,
.oe = BOARD_GCLK4_OE,
.runstdby = BOARD_GCLK4_RUNSTDBY,
.source = BOARD_GCLK4_SOURCE,
.div = BOARD_GCLK4_DIV
},
{
.enable = BOARD_GCLK5_ENABLE,
.oov = BOARD_GCLK5_OOV,
.oe = BOARD_GCLK5_OE,
.runstdby = BOARD_GCLK5_RUNSTDBY,
.source = BOARD_GCLK5_SOURCE,
.div = BOARD_GCLK5_DIV
},
{
.enable = BOARD_GCLK6_ENABLE,
.oov = BOARD_GCLK6_OOV,
.oe = BOARD_GCLK6_OE,
.runstdby = BOARD_GCLK6_RUNSTDBY,
.source = BOARD_GCLK6_SOURCE,
.div = BOARD_GCLK6_DIV
},
{
.enable = BOARD_GCLK7_ENABLE,
.oov = BOARD_GCLK7_OOV,
.oe = BOARD_GCLK7_OE,
.runstdby = BOARD_GCLK7_RUNSTDBY,
.source = BOARD_GCLK7_SOURCE,
.div = BOARD_GCLK7_DIV
},
{
.enable = BOARD_GCLK8_ENABLE,
.oov = BOARD_GCLK8_OOV,
.oe = BOARD_GCLK8_OE,
.runstdby = BOARD_GCLK8_RUNSTDBY,
.source = BOARD_GCLK8_SOURCE,
.div = BOARD_GCLK8_DIV
},
{
.enable = BOARD_GCLK9_ENABLE,
.oov = BOARD_GCLK9_OOV,
.oe = BOARD_GCLK9_OE,
.runstdby = BOARD_GCLK9_RUNSTDBY,
.source = BOARD_GCLK9_SOURCE,
.div = BOARD_GCLK9_DIV
},
{
.enable = BOARD_GCLK10_ENABLE,
.oov = BOARD_GCLK10_OOV,
.oe = BOARD_GCLK10_OE,
.runstdby = BOARD_GCLK10_RUNSTDBY,
.source = BOARD_GCLK10_SOURCE,
.div = BOARD_GCLK10_DIV
},
{
.enable = BOARD_GCLK11_ENABLE,
.oov = BOARD_GCLK11_OOV,
.oe = BOARD_GCLK11_OE,
.runstdby = BOARD_GCLK11_RUNSTDBY,
.source = BOARD_GCLK11_SOURCE,
.div = BOARD_GCLK11_DIV
}
}
.dfll =
{
.enable = BOARD_DFLL_ENABLE,
.runstdby = BOARD_DFLL_RUNSTDBY,
.ondemand = BOARD_DFLL_ONDEMAND,
.mode = BOARD_DFLL_MODE,
.stable = BOARD_DFLL_STABLE,
.llaw = BOARD_DFLL_LLAW,
.usbcrm = BOARD_DFLL_USBCRM,
.ccdis = BOARD_DFLL_CCDIS,
.qldis = BOARD_DFLL_QLDIS,
.bplckc = BOARD_DFLL_BPLCKC,
.waitlock = BOARD_DFLL_WAITLOCK,
.caliben = BOARD_DFLL_CALIBEN,
.gclklock = BOARD_DFLL_GCLKLOCK,
.fcalib = BOARD_DFLL_FCALIB,
.ccalib = BOARD_DFLL_CCALIB,
.fstep = BOARD_DFLL_FSTEP,
.cstep = BOARD_DFLL_CSTEP,
.gclk = BOARD_DFLL_GCLK,
.mul = BOARD_DFLL_MUL
},
.dpll =
{
{
.enable = BOARD_DPLL0_ENABLE,
.dcoen = BOARD_DPLL0_DCOEN,
.lbypass = BOARD_DPLL0_LBYPASS,
.wuf = BOARD_DPLL0_WUF,
.runstdby = BOARD_DPLL0_RUNSTDBY,
.ondemand = BOARD_DPLL0_ONDEMAND,
.reflock = BOARD_DPLL0_REFLOCK,
.refclk = BOARD_DPLL0_REFCLK,
.ltime = BOARD_DPLL0_LTIME,
.filter = BOARD_DPLL0_FILTER,
.dcofilter = BOARD_DPLL0_DCOFILTER,
.gclk = BOARD_DPLL0_GCLK,
.ldrfrac = BOARD_DPLL0_LDRFRAC,
.ldrint = BOARD_DPLL0_LDRINT,
.div = BOARD_DPLL0_DIV
},
{
.enable = BOARD_DPLL1_ENABLE,
.dcoen = BOARD_DPLL1_DCOEN,
.lbypass = BOARD_DPLL1_LBYPASS,
.wuf = BOARD_DPLL1_WUF,
.runstdby = BOARD_DPLL1_RUNSTDBY,
.ondemand = BOARD_DPLL1_ONDEMAND,
.reflock = BOARD_DPLL1_REFLOCK,
.refclk = BOARD_DPLL1_REFCLK,
.ltime = BOARD_DPLL1_LTIME,
.filter = BOARD_DPLL1_FILTER,
.dcofilter = BOARD_DPLL1_DCOFILTER,
.gclk = BOARD_DPLL1_GCLK,
.ldrfrac = BOARD_DPLL1_LDRFRAC,
.ldrint = BOARD_DPLL1_LDRINT,
.div = BOARD_DPLL1_DIV
}
},
.gclk =
{
{
.enable = BOARD_GCLK0_ENABLE,
.oov = BOARD_GCLK0_OOV,
.oe = BOARD_GCLK0_OE,
.runstdby = BOARD_GCLK0_RUNSTDBY,
.source = BOARD_GCLK0_SOURCE,
.div = BOARD_GCLK0_DIV
},
{
.enable = BOARD_GCLK1_ENABLE,
.oov = BOARD_GCLK1_OOV,
.oe = BOARD_GCLK1_OE,
.runstdby = BOARD_GCLK1_RUNSTDBY,
.source = BOARD_GCLK1_SOURCE,
.div = BOARD_GCLK1_DIV
},
{
.enable = BOARD_GCLK2_ENABLE,
.oov = BOARD_GCLK2_OOV,
.oe = BOARD_GCLK2_OE,
.runstdby = BOARD_GCLK2_RUNSTDBY,
.source = BOARD_GCLK2_SOURCE,
.div = BOARD_GCLK2_DIV
},
{
.enable = BOARD_GCLK3_ENABLE,
.oov = BOARD_GCLK3_OOV,
.oe = BOARD_GCLK3_OE,
.runstdby = BOARD_GCLK3_RUNSTDBY,
.source = BOARD_GCLK3_SOURCE,
.div = BOARD_GCLK3_DIV
},
{
.enable = BOARD_GCLK4_ENABLE,
.oov = BOARD_GCLK4_OOV,
.oe = BOARD_GCLK4_OE,
.runstdby = BOARD_GCLK4_RUNSTDBY,
.source = BOARD_GCLK4_SOURCE,
.div = BOARD_GCLK4_DIV
},
{
.enable = BOARD_GCLK5_ENABLE,
.oov = BOARD_GCLK5_OOV,
.oe = BOARD_GCLK5_OE,
.runstdby = BOARD_GCLK5_RUNSTDBY,
.source = BOARD_GCLK5_SOURCE,
.div = BOARD_GCLK5_DIV
},
{
.enable = BOARD_GCLK6_ENABLE,
.oov = BOARD_GCLK6_OOV,
.oe = BOARD_GCLK6_OE,
.runstdby = BOARD_GCLK6_RUNSTDBY,
.source = BOARD_GCLK6_SOURCE,
.div = BOARD_GCLK6_DIV
},
{
.enable = BOARD_GCLK7_ENABLE,
.oov = BOARD_GCLK7_OOV,
.oe = BOARD_GCLK7_OE,
.runstdby = BOARD_GCLK7_RUNSTDBY,
.source = BOARD_GCLK7_SOURCE,
.div = BOARD_GCLK7_DIV
},
{
.enable = BOARD_GCLK8_ENABLE,
.oov = BOARD_GCLK8_OOV,
.oe = BOARD_GCLK8_OE,
.runstdby = BOARD_GCLK8_RUNSTDBY,
.source = BOARD_GCLK8_SOURCE,
.div = BOARD_GCLK8_DIV
},
{
.enable = BOARD_GCLK9_ENABLE,
.oov = BOARD_GCLK9_OOV,
.oe = BOARD_GCLK9_OE,
.runstdby = BOARD_GCLK9_RUNSTDBY,
.source = BOARD_GCLK9_SOURCE,
.div = BOARD_GCLK9_DIV
},
{
.enable = BOARD_GCLK10_ENABLE,
.oov = BOARD_GCLK10_OOV,
.oe = BOARD_GCLK10_OE,
.runstdby = BOARD_GCLK10_RUNSTDBY,
.source = BOARD_GCLK10_SOURCE,
.div = BOARD_GCLK10_DIV
},
{
.enable = BOARD_GCLK11_ENABLE,
.oov = BOARD_GCLK11_OOV,
.oe = BOARD_GCLK11_OE,
.runstdby = BOARD_GCLK11_RUNSTDBY,
.source = BOARD_GCLK11_SOURCE,
.div = BOARD_GCLK11_DIV
}
}
};
/****************************************************************************
@ -317,7 +317,7 @@ static void sam_set_waitstates(const struct sam_clockconfig_s *config)
{
DEBUGASSERT(config->waitstates < 16);
modifyreg16(SAM_NVMCTRL_CTRLA, NVMCTRL_CTRLA_RWS_MASK,
NVMCTRL_CTRLA_RWS(config->waitstates) );
NVMCTRL_CTRLA_RWS(config->waitstates));
}
/****************************************************************************
@ -422,9 +422,9 @@ static void sam_xosc32k_configure(const struct sam_xosc32_config_s *config)
static uint32_t sam_xoscctrl(const struct sam_xosc_config_s *config)
{
uint32_t regval;
uint8_t cfdpresc;
uint8_t imult;
uint8_t iptat;
uint32_t cfdpresc;
uint32_t imult;
uint8_t iptat = 3;
/* Some settings determined by the crystal frequency */
@ -446,7 +446,7 @@ static uint32_t sam_xoscctrl(const struct sam_xosc_config_s *config)
imult = 5;
iptat = 3;
}
else if (config->xosc_frequency > 8000000)
else
{
cfdpresc = 3;
imult = 4;
@ -455,7 +455,7 @@ static uint32_t sam_xoscctrl(const struct sam_xosc_config_s *config)
/* Get the XOSCTCTL register *configuration */
regval = OSCCTRL_XOSCCTRL_IPTAT(ipta) | OSCCTRL_XOSCCTRL_IMULT(imult) |
regval = OSCCTRL_XOSCCTRL_IPTAT(iptat) | OSCCTRL_XOSCCTRL_IMULT(imult) |
OSCCTRL_XOSCCTRL_STARTUP(config->startup) |
OSCCTRL_XOSCCTRL_CFDPRESC(cfdpresc);
@ -504,15 +504,15 @@ static uint32_t sam_xoscctrl(const struct sam_xosc_config_s *config)
#endif
/****************************************************************************
* Name: sam_xosc32k_configure
* Name: sam_xosc0_configure
*
* Description:
* Configure XOSC32K
* Configure XOSC0K
*
****************************************************************************/
#if BOARD_HAVE_XOSC0 != 0
static void sam_xosc0_configure(const struct sam_clockconfig_s *config)
static void sam_xosc0_configure(const struct sam_xosc_config_s *config)
{
uint32_t regval;
@ -521,11 +521,11 @@ static void sam_xosc0_configure(const struct sam_clockconfig_s *config)
regval = sam_xoscctrl(config);
putreg32(regval, SAM_OSCCTRL_XOSCCTRL0);
/* Wait for XOSC32 to become ready if it was enabled */
/* Wait for XOSC0 to become ready if it was enabled */
if (config->enable)
{
while (getreg32(SAM_OSCCTRL_STATUS) & OSCCTRL_INT_XOSCRDY0) == 0)
while ((getreg32(SAM_OSCCTRL_STATUS) & OSCCTRL_INT_XOSCRDY0) == 0)
{
}
}
@ -534,14 +534,14 @@ static void sam_xosc0_configure(const struct sam_clockconfig_s *config)
if (config->ondemand)
{
regval = getre32(SAM_OSCCTRL_XOSCCTRL0)
regval = getreg32(SAM_OSCCTRL_XOSCCTRL0);
regval |= OSCCTRL_XOSCCTRL_ONDEMAND;
putreg32(regval, SAM_OSCCTRL_XOSCCTRL0);
}
}
#endif
#if BOARD_HAVE_XOSC0 != 0
#if BOARD_HAVE_XOSC1 != 0
void sam_xosc1_configure(const struct sam_xosc_config_s *config)
{
uint32_t regval;
@ -551,11 +551,11 @@ void sam_xosc1_configure(const struct sam_xosc_config_s *config)
regval = sam_xoscctrl(config);
putreg32(regval, SAM_OSCCTRL_XOSCCTRL1);
/* Wait for XOSC32 to become ready if it was enabled */
/* Wait for XOSC1 to become ready if it was enabled */
if (config->enable)
{
while (getreg32(SAM_OSCCTRL_STATUS) & OSCCTRL_INT_XOSCRDY1) == 0)
while ((getreg32(SAM_OSCCTRL_STATUS) & OSCCTRL_INT_XOSCRDY1) == 0)
{
}
}
@ -564,7 +564,7 @@ void sam_xosc1_configure(const struct sam_xosc_config_s *config)
if (config->ondemand)
{
regval = getre32(SAM_OSCCTRL_XOSCCTRL1)
regval = getreg32(SAM_OSCCTRL_XOSCCTRL1);
regval |= OSCCTRL_XOSCCTRL_ONDEMAND;
putreg32(regval, SAM_OSCCTRL_XOSCCTRL1);
}
@ -782,8 +782,9 @@ static void sam_dfll_ready(const struct sam_dfll_config_s *config)
uint32_t regval32;
uint8_t regval8;
/* Check if the mode bit was set, i.e., we are in closed-loop mode. If so
* wait for the DFLL to be ready for and for the coarse lock to be obtained.
/* Check if the mode bit was set, i.e., we are in closed-loop mode. If so
* wait for the DFLL to be ready for and for the coarse lock to be
* obtained.
*/
regval8 = getreg8(SAM_OSCCTRL_DPLL0CTRLB);
@ -828,7 +829,7 @@ static void sam_dfll_gclkready(const struct sam_dfll_config_s *config)
{
}
/* Set the source of GCLK0 to the configured source. */
/* Set the source of GCLK0 to to the configured source. */
regval32 = getreg32(SAM_GCLK_GENCTRL(0));
regval32 &= ~GCLK_GENCTRL_SRC_MASK;
@ -854,7 +855,9 @@ static void sam_dpll_gclkchannel(uint8_t chan,
if (config->refclk == 0 && !sam_gclk_chan_locked(chan))
{
/* Yes.. configure the GCLK channel that will be used as refclk source */
/* Yes.. configure the GCLK channel that will be used as
* refclk source.
*/
sam_gclk_chan_enable(chan, config->gclk, (bool)config->reflock);
}

View File

@ -49,6 +49,7 @@
#include "sam_periphclks.h"
#include "sam_port.h"
#include "sam_eic.h"
#include "hardware/sam_pac.h"
#include <arch/board/board.h>
@ -135,7 +136,7 @@ int sam_eic_initialize(void)
/* Configure the EIC APB clock */
sam_apb_eic_enableperiph();
sam_apb_eic_enableperiph(); /* SAM_MCLK_APBAMASK(MCLK_APBAMASK_EIC) */
/* Use the selected GCLK_EIC. Some optional functions need a peripheral
* clock, which can either be a generic clock (GCLK_EIC, for wider
@ -144,13 +145,13 @@ int sam_eic_initialize(void)
* and enabled before using the peripheral.
*/
regaddr = SAM_GCLK_PCHCTRL(GCLK_CHAN_EIC);
regaddr = SAM_GCLK_PCHCTRL(GCLK_CHAN_EIC); /* (GCLK_CHAN_EIC) */
regval = GCLK_PCHCTRL_GEN(BOARD_GCLK_EIC) | GCLK_PCHCTRL_CHEN;
putreg32(regval, regaddr);
/* Enable the EIC, selecting clocking via the GCLK_EIC */
putreg8(EIC_CTRLA_ENABLE | EIC_CTRLA_ENABLE, SAM_EIC_CTRLA);
putreg8(EIC_CTRLA_ENABLE, SAM_EIC_CTRLA);
sam_eic_syncwait();
sam_eic_dumpregs();
@ -179,6 +180,11 @@ int sam_eic_configure(uint8_t eirq, port_pinset_t pinset)
uint32_t val;
uint32_t config;
/* Disable the EIC: 23.6.2.1 */
putreg8(0, SAM_EIC_CTRLA);
sam_eic_syncwait();
/* Determine which of the CONFIG[0:1] registers to write to */
if (eirq < 8)
@ -196,6 +202,11 @@ int sam_eic_configure(uint8_t eirq, port_pinset_t pinset)
val = EIC_CONFIG0_SENSE_FALL(eirq);
}
if ((pinset & PORT_INT_HIGH) != 0)
{
val = EIC_CONFIG0_SENSE_HIGH(eirq);
}
val |= EIC_CONFIG0_FILTEN(eirq);
}
else /* if (eirq < 16) */
@ -213,7 +224,14 @@ int sam_eic_configure(uint8_t eirq, port_pinset_t pinset)
val = EIC_CONFIG1_SENSE_FALL(eirq);
}
val |= EIC_CONFIG1_FILTEN(eirq);
if ((pinset & PORT_INT_HIGH) != 0)
{
val = EIC_CONFIG1_SENSE_HIGH(eirq);
}
config = getreg32(SAM_EIC_EVCTRL);
config |= EIC_EXTINT(eirq);
putreg32(config, SAM_EIC_EVCTRL);
}
/* Write the new config to the CONFIGn register */
@ -222,9 +240,10 @@ int sam_eic_configure(uint8_t eirq, port_pinset_t pinset)
config |= val;
putreg32(config, reg);
/* Enable interrupt generation for this pin */
/* Enable the EIC, selecting clocking via the GCLK_EIC */
putreg32(EIC_EXTINT(eirq), SAM_EIC_INTENSET);
putreg8(EIC_CTRLA_ENABLE, SAM_EIC_CTRLA);
sam_eic_syncwait();
sam_eic_dumpregs();
return OK;
@ -248,7 +267,9 @@ int sam_eic_irq_ack(int irq)
{
int eirq = irq - SAM_IRQ_EXTINT0;
putreg32(EIC_EXTINT(eirq), SAM_EIC_INTENCLR);
irqinfo("sam_eic_irq_ack: irq=%d eirq=%d EIC_EXTINT=0x%x\n", irq,
eirq, EIC_EXTINT(eirq));
putreg32(EIC_EXTINT(eirq), SAM_EIC_INTFLAG);
return OK;
}

View File

@ -114,6 +114,8 @@ int sam_eic_configure(uint8_t eirq, port_pinset_t pinset);
int sam_eic_irq_ack(int irq);
void sam_eic_dumpregs(void);
#undef EXTERN
#if defined(__cplusplus)
}

View File

@ -0,0 +1,259 @@
/****************************************************************************
* arch/arm/src/samd5e5/sam_freerun.c
*
* Copyright 2020 Falker Automacao Agricola LTDA.
* Author: Leomar Mateus Radke <leomar@falker.com.br>
* Author: Ricardo Wartchow <wartchow@gmail.com>
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/irq.h>
#include <nuttx/clock.h>
#include "sam_freerun.h"
#ifdef CONFIG_SAMD5E5_FREERUN
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: sam_freerun_handler
*
* Description:
* Timer interrupt callback. When the freerun timer counter overflows,
* this interrupt will occur. We will just increment an overflow count.
*
* Input Parameters:
* tch - The handle that represents the timer state
* arg - An opaque argument provided when the interrupt was registered
* sr - The value of the timer interrupt status register at the time
* that the interrupt occurred.
*
* Returned Value:
* None
*
****************************************************************************/
static void sam_freerun_handler(TC_HANDLE tch, void *arg, uint32_t sr)
{
struct sam_freerun_s *freerun = (struct sam_freerun_s *)arg;
DEBUGASSERT(freerun && freerun->overflow < UINT16_MAX);
freerun->overflow++;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: sam_freerun_initialize
*
* Description:
* Initialize the freerun timer wrapper
*
* Input Parameters:
* freerun Caller allocated instance of the freerun state structure
* chan Timer counter channel to be used. See the TC_CHAN*
* definitions in arch/arm/src/samd5e5/sam_tc.h.
* resolution The required resolution of the timer in units of
* microseconds. NOTE that the range is restricted to the
* range of uint16_t (excluding zero).
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
int sam_freerun_initialize(struct sam_freerun_s *freerun, int chan,
uint16_t resolution)
{
uint32_t frequency;
tmrinfo("chan=%d resolution=%d usec\n", chan, resolution);
DEBUGASSERT(freerun && resolution > 0);
/* Get the TC frequency the corresponds to the requested resolution */
frequency = USEC_PER_SEC / (uint32_t)resolution;
freerun->tch = sam_tc_allocate(chan, frequency);
if (!freerun->tch)
{
tmrerr("ERROR: Failed to allocate timer channel %d\n", chan);
return -EBUSY;
}
/* Initialize the remaining fields in the state structure and return
* success.
*/
freerun->chan = chan;
freerun->running = false;
freerun->overflow = 0;
/* Set up to receive the callback when the counter overflow occurs */
(void)sam_tc_attach(freerun->tch, sam_freerun_handler,
freerun, TC_INTFLAG_OVF);
/* Start the counter */
sam_tc_start(freerun->tch);
return OK;
}
/****************************************************************************
* Name: sam_freerun_counter
*
* Description:
* Read the counter register of the free-running timer.
*
* Input Parameters:
* freerun Caller allocated instance of the freerun state structure. This
* structure must have been previously initialized via a call to
* sam_freerun_initialize();
* ts The location in which to return the time from the free-running
* timer.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
int sam_freerun_counter(struct sam_freerun_s *freerun, struct timespec *ts)
{
uint64_t usec;
uint32_t counter;
uint32_t verify;
uint8_t sr;
uint32_t overflow;
uint32_t sec;
irqstate_t flags;
DEBUGASSERT(freerun && freerun->tch && ts);
/* Temporarily disable the overflow counter.
* NOTE that we have to be here because sam_tc_getpending()
* will reset the pending interrupt status.
* If we do not handle the overflow here then, it will be lost.
*/
flags = enter_critical_section();
overflow = freerun->overflow;
counter = sam_tc_getcounter(freerun->tch);
sr = sam_tc_getpending(freerun->tch);
verify = sam_tc_getcounter(freerun->tch);
/* If an interrupt was pending before we re-enabled interrupts,
* then the overflow needs to be incremented.
*/
if ((sr & TC_INTFLAG_OVF) != 0)
{
/* Increment the overflow count and use the value of the
* guaranteed to be AFTER the overflow occurred.
*/
overflow++;
counter = verify;
/* Update freerun overflow counter. */
freerun->overflow = overflow;
}
leave_critical_section(flags);
tmrinfo("counter=%u (%u) overflow=%u, sr=0x%x\n",
counter, verify, overflow, sr);
/* Convert the whole thing to units of microseconds.
*
* frequency = ticks / second
* seconds = ticks * frequency
* usecs = (ticks * USEC_PER_SEC) / frequency;
*/
usec = ((((uint64_t)overflow << 32) + (uint64_t)counter) * USEC_PER_SEC) /
sam_tc_divfreq(freerun->tch);
/* And return the value of the timer */
sec = (uint32_t)(usec / USEC_PER_SEC);
ts->tv_sec = sec;
ts->tv_nsec = (usec - (sec * USEC_PER_SEC)) * NSEC_PER_USEC;
tmrinfo("usec=%llu ts=(%lu, %lu)\n",
usec, (unsigned long)ts->tv_sec, (unsigned long)ts->tv_nsec);
return OK;
}
/****************************************************************************
* Name: sam_freerun_uninitialize
*
* Description:
* Stop the free-running timer and release all resources that it uses.
*
* Input Parameters:
* freerun Caller allocated instance of the freerun state structure. This
* structure must have been previously initialized via a call to
* sam_freerun_initialize();
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
int sam_freerun_uninitialize(struct sam_freerun_s *freerun)
{
DEBUGASSERT(freerun && freerun->tch);
/* Now we can disable the timer interrupt and disable the timer. */
sam_tc_attach(freerun->tch, NULL, NULL, 0);
sam_tc_stop(freerun->tch);
/* Free the timer */
sam_tc_free(freerun->tch);
freerun->tch = NULL;
return OK;
}
#endif /* CONFIG_SAMD5E5_FREERUN */

View File

@ -0,0 +1,151 @@
/****************************************************************************
* arch/arm/src/samd5e5/sam_freerun.h
*
* Copyright 2020 Falker Automacao Agricola LTDA.
* Author: Leomar Mateus Radke <leomar@falker.com.br>
* Author: Ricardo Wartchow <wartchow@gmail.com>
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __ARCH_ARM_SRC_SAMD5E5_SAM_FREERUN_H
#define __ARCH_ARM_SRC_SAMD5E5_SAM_FREERUN_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <time.h>
#include "sam_tc.h"
#ifdef CONFIG_SAMD5E5_FREERUN
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define FREERUN_INITIALIZED(s) (((s)->tch) != NULL)
/****************************************************************************
* Public Types
****************************************************************************/
/* The freerun client must allocate an instance of this structure and called
* sam_freerun_initialize() before using the freerun facilities. The client
* should not access the contents of this structure directly since the
* contents are subject to change.
*/
struct sam_freerun_s
{
uint8_t chan; /* The timer/counter in use */
bool running; /* True: the timer is running */
uint32_t overflow; /* Timer counter overflow */
TC_HANDLE tch; /* Handle returned by sam_tc_initialize() */
};
/****************************************************************************
* Public Data
****************************************************************************/
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: sam_freerun_initialize
*
* Description:
* Initialize the freerun timer wrapper
*
* Input Parameters:
* freerun Caller allocated instance of the freerun state structure
* chan Timer counter channel to be used. See the TC_CHAN*
* definitions in arch/arm/src/sama5/sam_tc.h.
* resolution The required resolution of the timer in units of
* microseconds. NOTE that the range is restricted to the
* range of uint16_t (excluding zero).
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
int sam_freerun_initialize(struct sam_freerun_s *freerun, int chan,
uint16_t resolution);
/****************************************************************************
* Name: sam_freerun_counter
*
* Description:
* Read the counter register of the free-running timer.
*
* Input Parameters:
* freerun Caller allocated instance of the freerun state structure. This
* structure must have been previously initialized via a call to
* sam_freerun_initialize();
* ts The location in which to return the time remaining on the
* oneshot timer.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
int sam_freerun_counter(struct sam_freerun_s *freerun, struct timespec *ts);
/****************************************************************************
* Name: sam_freerun_uninitialize
*
* Description:
* Stop the free-running timer and release all resources that it uses.
*
* Input Parameters:
* freerun Caller allocated instance of the freerun state structure. This
* structure must have been previously initialized via a call to
* sam_freerun_initialize();
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
int sam_freerun_uninitialize(struct sam_freerun_s *freerun);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* CONFIG_SAMD5E5_FREERUN */
#endif /* __ARCH_ARM_SRC_SAMD5E5_SAM_FREERUN_H */

View File

@ -0,0 +1,459 @@
/****************************************************************************
* arch/arm/src/samd5e5/sam_oneshot.c
*
* Copyright 2020 Falker Automacao Agricola LTDA.
* Author: Leomar Mateus Radke <leomar@falker.com.br>
* Author: Ricardo Wartchow <wartchow@gmail.com>
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/irq.h>
#include <nuttx/clock.h>
#include "sam_oneshot.h"
#include "sam_freerun.h"
#ifdef CONFIG_SAMD5E5_ONESHOT
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: sam_oneshot_handler
*
* Description:
* Timer interrupt callback. When the oneshot timer interrupt expires,
* this function will be called. It will forward the call to the next
* level up.
*
* Input Parameters:
* tch - The handle that represents the timer state
* arg - An opaque argument provided when the interrupt was registered
* sr - The value of the timer interrupt status register at the time
* that the interrupt occurred.
*
* Returned Value:
* None
*
****************************************************************************/
static void sam_oneshot_handler(TC_HANDLE tch, void *arg, uint32_t sr)
{
struct sam_oneshot_s *oneshot = (struct sam_oneshot_s *)arg;
oneshot_handler_t oneshot_handler;
void *oneshot_arg;
tmrinfo("Expired...\n");
DEBUGASSERT(oneshot && oneshot->handler);
/* The clock was stopped, but not disabled when the RC match occurred.
* Disable the TC now and disable any further interrupts.
*/
sam_tc_attach(oneshot->tch, NULL, NULL, 0);
sam_tc_stop(oneshot->tch);
/* The timer is no longer running */
oneshot->running = false;
/* Forward the event, clearing out any vestiges */
oneshot_handler = (oneshot_handler_t)oneshot->handler;
oneshot->handler = NULL;
oneshot_arg = (void *)oneshot->arg;
oneshot->arg = NULL;
#ifdef CONFIG_SAMD5E5_FREERUN
oneshot->start_count = 0;
#endif
oneshot_handler(oneshot_arg);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: sam_oneshot_initialize
*
* Description:
* Initialize the oneshot timer wrapper
*
* Input Parameters:
* oneshot Caller allocated instance of the oneshot state structure
* chan Timer counter channel to be used. See the TC_CHAN*
* definitions in arch/arm/src/samd5e5/sam_tc.h.
* resolution The required resolution of the timer in units of
* microseconds. NOTE that the range is restricted to the
* range of uint16_t (excluding zero).
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
int sam_oneshot_initialize(struct sam_oneshot_s *oneshot, int chan,
uint16_t resolution)
{
uint32_t frequency;
tmrinfo("chan=%d resolution=%d usec\n", chan, resolution);
DEBUGASSERT(oneshot && resolution > 0);
/* Get the TC frequency the corresponds to the requested resolution */
frequency = USEC_PER_SEC / (uint32_t)resolution;
oneshot->tch = sam_tc_allocate(chan, frequency);
if (!oneshot->tch)
{
tmrerr("ERROR: Failed to allocate timer channel %d\n", chan);
return -EBUSY;
}
/* Initialize the remaining fields in the state structure and return
* success.
*/
oneshot->chan = chan;
oneshot->running = false;
oneshot->handler = NULL;
oneshot->arg = NULL;
#ifdef CONFIG_SAMD5E5_FREERUN
oneshot->start_count = 0;
#endif
return OK;
}
/****************************************************************************
* Name: sam_oneshot_max_delay
*
* Description:
* Return the maximum delay supported by the one shot timer (in
* microseconds).
*
* Input Parameters:
* oneshot Caller allocated instance of the oneshot state structure. This
* structure must have been previously initialized via a call to
* sam_oneshot_initialize();
* usec The location in which to return the maximum delay.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
int sam_oneshot_max_delay(struct sam_oneshot_s *oneshot, uint64_t *usec)
{
DEBUGASSERT(oneshot != NULL && usec != NULL);
*usec = (0xffffull * USEC_PER_SEC) /
(uint64_t)sam_tc_divfreq(oneshot->tch);
return OK;
}
/****************************************************************************
* Name: sam_oneshot_start
*
* Description:
* Start the oneshot timer
*
* Input Parameters:
* oneshot Caller allocated instance of the oneshot state structure. This
* structure must have been previously initialized via a call to
* sam_oneshot_initialize();
* handler The function to call when when the oneshot timer expires.
* arg An opaque argument that will accompany the callback.
* ts Provides the duration of the one shot timer.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
int sam_oneshot_start(struct sam_oneshot_s *oneshot,
struct sam_freerun_s *freerun,
oneshot_handler_t handler, void *arg,
const struct timespec *ts)
{
uint64_t usec;
uint64_t regval;
irqstate_t flags;
tmrinfo("handler=%p arg=%p, ts=(%lu, %lu)\n",
handler, arg, (unsigned long)ts->tv_sec, (unsigned long)ts->tv_nsec);
DEBUGASSERT(oneshot && handler && ts);
/* Was the oneshot already running? */
flags = enter_critical_section();
if (oneshot->running)
{
/* Yes.. then cancel it */
tmrinfo("Already running... cancelling\n");
(void)sam_oneshot_cancel(oneshot, freerun, NULL);
}
/* Save the new handler and its argument */
oneshot->handler = handler;
oneshot->arg = arg;
/* Express the delay in microseconds */
usec = (uint64_t)ts->tv_sec * USEC_PER_SEC + (uint64_t)(ts->tv_nsec /
NSEC_PER_USEC);
/* Get the timer counter frequency and determine
* the number of counts need to achieve the requested delay.
*
* frequency = ticks / second
* ticks = seconds * frequency
* = (usecs * frequency) / USEC_PER_SEC;
*/
regval = (usec * (uint64_t)sam_tc_divfreq(oneshot->tch)) / USEC_PER_SEC;
tmrinfo("usec=%llu * %lu / %lu -> regval=0x%08llx\n", usec,
sam_tc_divfreq(oneshot->tch), USEC_PER_SEC, regval);
DEBUGASSERT(regval <= UINT32_MAX);
/* Set up to receive the callback when the interrupt occurs */
(void)sam_tc_attach(oneshot->tch, sam_oneshot_handler,
oneshot, TC_INTFLAG_MC0);
/* Set CC0 so that an event will be triggered when COUNT register
* counts up to CC0.
*/
sam_tc_setregister(oneshot->tch, TC_REGCC0, (uint32_t)regval);
sam_tc_setregister(oneshot->tch, TC_REGCC1, (uint32_t)0xffffffff);
/* Start the counter */
sam_tc_start(oneshot->tch);
#ifdef CONFIG_SAMD5E5_FREERUN
/* The function sam_tc_start() starts the timer/counter by setting the
* bits TC_CCR_CLKEN and TC_CCR_SWTRG in the channel control register.
* The first one enables the timer/counter the latter performs an
* software trigger, which starts the clock and sets the counter
* register to zero. This reset is performed with the next valid edge
* of the selected clock. Thus it can take up USEC_PER_TICK microseconds
* until the counter register becomes zero.
*
* If the timer is canceled within this period the counter register holds
* the counter value for the last timer/counter run. To circumvent this
* the counter value of the freerun timer/counter is stored at each start
* of the oneshot timer/counter.
*
* The function up_timer_gettime() could also be used for this but it takes
* too long. If up_timer_gettime() is called within this function the
* problem vanishes at least if compiled with no optimisation.
*/
if (freerun != NULL)
{
oneshot->start_count = sam_tc_getcounter(freerun->tch);
}
#endif
/* Enable interrupts. We should get the callback when the interrupt
* occurs.
*/
oneshot->running = true;
leave_critical_section(flags);
return OK;
}
/****************************************************************************
* Name: sam_oneshot_cancel
*
* Description:
* Cancel the oneshot timer and return the time remaining on the timer.
*
* NOTE: This function may execute at a high rate with no timer running (as
* when pre-emption is enabled and disabled).
*
* Input Parameters:
* oneshot Caller allocated instance of the oneshot state structure. This
* structure must have been previously initialized via a call to
* sam_oneshot_initialize();
* ts The location in which to return the time remaining on the
* oneshot timer. A time of zero is returned if the timer is
* not running. ts may be zero in which case the time remaining
* is not returned.
*
* Returned Value:
* Zero (OK) is returned on success. A call to up_timer_cancel() when
* the timer is not active should also return success; a negated errno
* value is returned on any failure.
*
****************************************************************************/
int sam_oneshot_cancel(struct sam_oneshot_s *oneshot,
struct sam_freerun_s *freerun, struct timespec *ts)
{
irqstate_t flags;
uint64_t usec;
uint64_t sec;
uint64_t nsec;
uint32_t count;
uint32_t rc;
/* Was the timer running? */
flags = enter_critical_section();
if (!oneshot->running)
{
/* No.. Just return zero timer remaining and successful cancellation.
* This function may execute at a high rate with no timer running
* (as when pre-emption is enabled and disabled).
*/
ts->tv_sec = 0;
ts->tv_nsec = 0;
leave_critical_section(flags);
return OK;
}
/* Yes.. Get the timer counter and rc registers and stop the counter. If
* the counter expires while we are doing this, the counter clock will be
* stopped, but the clock will not be disabled.
*
* The expected behavior is that the counter register will freezes at
* a value equal to the RC register when the timer expires. The counter
* should have values between 0 and RC in all other cased.
*
* REVISIT: This does not appear to be the case.
*/
tmrinfo("Cancelling...\n");
count = sam_tc_getcounter(oneshot->tch);
rc = sam_tc_getregister(oneshot->tch, TC_REGCC0);
#ifdef CONFIG_SAMD5E5_FREERUN
/* In the case the timer/counter was canceled very short after its start,
* the counter register can hold the wrong value (the value of the last
* run). To prevent this the counter value is set to zero if not at
* least on tick passed since the start of the timer/counter.
*/
if (count > 0 && freerun != NULL &&
sam_tc_getcounter(freerun->tch) == oneshot->start_count)
{
count = 0;
}
#endif
/* Now we can disable the interrupt and stop the timer. */
sam_tc_attach(oneshot->tch, NULL, NULL, 0);
sam_tc_stop(oneshot->tch);
oneshot->running = false;
oneshot->handler = NULL;
oneshot->arg = NULL;
leave_critical_section(flags);
/* Did the caller provide us with a location to return the time
* remaining?
*/
if (ts)
{
/* Yes.. then calculate and return the time remaining on the
* oneshot timer.
*/
tmrinfo("rc=%lu count=%lu usec=%lu\n",
(unsigned long)rc, (unsigned long)count, (unsigned long)usec);
/* REVISIT: I am not certain why the timer counter value sometimes
* exceeds RC. Might be a bug, or perhaps the counter does not stop
* in all cases.
*/
if (count >= rc)
{
/* No time remaining (?) */
ts->tv_sec = 0;
ts->tv_nsec = 0;
}
else
{
/* The total time remaining is the difference. Convert the that
* to units of microseconds.
*
* frequency = ticks / second
* seconds = ticks * frequency
* usecs = (ticks * USEC_PER_SEC) / frequency;
*/
usec = (((uint64_t)(rc - count)) * USEC_PER_SEC) /
sam_tc_divfreq(oneshot->tch);
/* Each time the timer/counter is canceled the time calculated from
* the two registers (counter and REGC) is accurate up to an error
* between 0 and USEC_PER_TICK microseconds. To correct this error
* one tick which means USEC_PER_TICK microseconds are subtracted.
*/
usec = usec > USEC_PER_TICK ? usec - USEC_PER_TICK : 0;
/* Return the time remaining in the correct form */
sec = usec / USEC_PER_SEC;
nsec = ((usec) - (sec * USEC_PER_SEC)) * NSEC_PER_USEC;
ts->tv_sec = (time_t)sec;
ts->tv_nsec = (unsigned long)nsec;
}
tmrinfo("remaining (%lu, %lu)\n",
(unsigned long)ts->tv_sec, (unsigned long)ts->tv_nsec);
}
return OK;
}
#endif /* CONFIG_SAMD5E5_ONESHOT */

View File

@ -0,0 +1,212 @@
/****************************************************************************
* arch/arm/src/samd5e5/sam_oneshot.c
*
* Copyright 2020 Falker Automacao Agricola LTDA.
* Author: Leomar Mateus Radke <leomar@falker.com.br>
* Author: Ricardo Wartchow <wartchow@gmail.com>
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __ARCH_ARM_SRC_SAMD5E5_SAM_ONESHOT_H
#define __ARCH_ARM_SRC_SAMD5E5_SAM_ONESHOT_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <time.h>
#include "sam_tc.h"
#ifdef CONFIG_SAMD5E5_ONESHOT
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define ONESHOT_INITIALIZED(s) (((s)->tch) != NULL)
/****************************************************************************
* Public Types
****************************************************************************/
/* This describes the callback function that will be invoked when the oneshot
* timer expires. The oneshot fires, the client will receive:
*
* arg - The opaque argument provided when the interrupt was registered
*/
typedef void (*oneshot_handler_t)(void *arg);
/* The oneshot client must allocate an instance of this structure and called
* sam_oneshot_initialize() before using the oneshot facilities. The client
* should not access the contents of this structure directly since the
* contents are subject to change.
*/
struct sam_oneshot_s
{
uint8_t chan; /* The timer/counter in use */
volatile bool running; /* True: the timer is running */
TC_HANDLE tch; /* Handle returned by
* sam_tc_initialize() */
volatile oneshot_handler_t handler; /* Oneshot expiration callback */
volatile void *arg; /* The argument that will accompany
* the callback */
#ifdef CONFIG_SAMD5E5_FREERUN
volatile uint32_t start_count; /* Stores the value of the freerun counter,
* at each start of the onshot timer. Is neccesary
* to find out if the onshot counter was updated
* correctly at the time of the call to
* sam_oneshot_cancel or not. */
#endif
};
/****************************************************************************
* Public Data
****************************************************************************/
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: sam_oneshot_initialize
*
* Description:
* Initialize the oneshot timer wrapper
*
* Input Parameters:
* oneshot Caller allocated instance of the oneshot state structure
* chan Timer counter channel to be used. See the TC_CHAN*
* definitions in arch/arm/src/samd5e5/sam_tc.h.
* resolution The required resolution of the timer in units of
* microseconds. NOTE that the range is restricted to the
* range of uint16_t (excluding zero).
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
int sam_oneshot_initialize(struct sam_oneshot_s *oneshot, int chan,
uint16_t resolution);
/****************************************************************************
* Name: sam_oneshot_max_delay
*
* Description:
* Return the maximum delay supported by the one shot timer (in
* microseconds).
*
* Input Parameters:
* oneshot Caller allocated instance of the oneshot state structure. This
* structure must have been previously initialized via a call to
* sam_oneshot_initialize();
* usec The location in which to return the maximum delay.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
int sam_oneshot_max_delay(struct sam_oneshot_s *oneshot, uint64_t *usec);
/****************************************************************************
* Name: sam_oneshot_start
*
* Description:
* Start the oneshot timer
*
* Input Parameters:
* oneshot Caller allocated instance of the oneshot state structure. This
* structure must have been previously initialized via a call to
* sam_oneshot_initialize();
* freerun Caller allocated instance of the freerun state structure. This
* structure must have been previously initialized via a call to
* sam_freerun_initialize(). May be NULL if there is no matching
* free-running timer.
* handler The function to call when when the oneshot timer expires.
* arg An opaque argument that will accompany the callback.
* ts Provides the duration of the one shot timer.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
struct sam_freerun_s;
int sam_oneshot_start(struct sam_oneshot_s *oneshot,
struct sam_freerun_s *freerun,
oneshot_handler_t handler, void *arg,
const struct timespec *ts);
/****************************************************************************
* Name: sam_oneshot_cancel
*
* Description:
* Cancel the oneshot timer and return the time remaining on the timer.
*
* NOTE: This function may execute at a high rate with no timer running (as
* when pre-emption is enabled and disabled).
*
* Input Parameters:
* oneshot Caller allocated instance of the oneshot state structure. This
* structure must have been previously initialized via a call to
* sam_oneshot_initialize();
* freerun Caller allocated instance of the freerun state structure. This
* structure must have been previously initialized via a call to
* sam_freerun_initialize(). May be NULL if there is no matching
* free-running timer.
* ts The location in which to return the time remaining on the
* oneshot timer. A time of zero is returned if the timer is
* not running.
*
* Returned Value:
* Zero (OK) is returned on success. A call to up_timer_cancel() when
* the timer is not active should also return success; a negated errno
* value is returned on any failure.
*
****************************************************************************/
struct sam_freerun_s;
int sam_oneshot_cancel(struct sam_oneshot_s *oneshot,
struct sam_freerun_s *freerun, struct timespec *ts);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* CONFIG_SAMD5E5_ONESHOT */
#endif /* __ARCH_ARM_SRC_SAMD5E5_SAM_ONESHOT_H */

View File

@ -0,0 +1,336 @@
/****************************************************************************
* arch/arm/src/samd5e5/sam_oneshot_lowerhalf.c
*
* Copyright 2020 Falker Automacao Agricola LTDA.
* Author: Leomar Mateus Radke <leomar@falker.com.br>
* Author: Ricardo Wartchow <wartchow@gmail.com>
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <time.h>
#include <limits.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/irq.h>
#include <nuttx/kmalloc.h>
#include <nuttx/timers/oneshot.h>
#include "sam_oneshot.h"
/****************************************************************************
* Private Types
****************************************************************************/
/* This structure describes the state of oneshot timer lower-half driver */
struct sam_oneshot_lowerhalf_s
{
/* This is the part of the lower half driver that is visible to the upper-
* half client of the driver. This must be the first thing in this
* structure so that pointers to struct oneshot_lowerhalf_s are cast
* compatible to struct sam_oneshot_lowerhalf_s and vice versa.
*/
struct oneshot_lowerhalf_s lh; /* Common lower-half driver fields */
/* Private lower half data follows */
struct sam_oneshot_s oneshot; /* SAM-specific oneshot state */
oneshot_callback_t callback; /* internal handler that receives callback */
FAR void *arg; /* Argument that is passed to the handler */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static void sam_oneshot_handler(void *arg);
static int sam_max_delay(FAR struct oneshot_lowerhalf_s *lower,
FAR struct timespec *ts);
static int sam_start(FAR struct oneshot_lowerhalf_s *lower,
oneshot_callback_t callback, FAR void *arg,
FAR const struct timespec *ts);
static int sam_cancel(FAR struct oneshot_lowerhalf_s *lower,
FAR struct timespec *ts);
/****************************************************************************
* Private Data
****************************************************************************/
/* Lower half operations */
static const struct oneshot_operations_s g_oneshot_ops =
{
.max_delay = sam_max_delay,
.start = sam_start,
.cancel = sam_cancel,
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: sam_oneshot_handler
*
* Description:
* Timer expiration handler
*
* Input Parameters:
* arg - Should be the same argument provided when sam_oneshot_start()
* was called.
*
* Returned Value:
* None
*
****************************************************************************/
static void sam_oneshot_handler(void *arg)
{
FAR struct sam_oneshot_lowerhalf_s *priv =
(FAR struct sam_oneshot_lowerhalf_s *)arg;
oneshot_callback_t callback;
FAR void *cbarg;
DEBUGASSERT(priv != NULL);
/* Perhaps the callback was nullified in a race condition with
* sam_cancel?
*/
if (priv->callback)
{
/* Sample and nullify BEFORE executing callback (in case the callback
* restarts the oneshot).
*/
callback = priv->callback;
cbarg = priv->arg;
priv->callback = NULL;
priv->arg = NULL;
/* Then perform the callback */
callback(&priv->lh, cbarg);
}
}
/****************************************************************************
* Name: sam_max_delay
*
* Description:
* Determine the maximum delay of the one-shot timer (in microseconds)
*
* Input Parameters:
* lower An instance of the lower-half oneshot state structure. This
* structure must have been previously initialized via a call to
* oneshot_initialize();
* ts The location in which to return the maxumum delay.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
static int sam_max_delay(FAR struct oneshot_lowerhalf_s *lower,
FAR struct timespec *ts)
{
FAR struct sam_oneshot_lowerhalf_s *priv =
(FAR struct sam_oneshot_lowerhalf_s *)lower;
uint64_t usecs;
int ret;
DEBUGASSERT(priv != NULL && ts != NULL);
ret = sam_oneshot_max_delay(&priv->oneshot, &usecs);
if (ret >= 0)
{
uint64_t sec = usecs / 1000000;
usecs -= 1000000 * sec;
ts->tv_sec = (time_t)sec;
ts->tv_nsec = (long)(usecs * 1000);
}
return ret;
}
/****************************************************************************
* Name: sam_start
*
* Description:
* Start the oneshot timer
*
* Input Parameters:
* lower An instance of the lower-half oneshot state structure. This
* structure must have been previously initialized via a call to
* oneshot_initialize();
* handler The function to call when when the oneshot timer expires.
* arg An opaque argument that will accompany the callback.
* ts Provides the duration of the one shot timer.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/
static int sam_start(FAR struct oneshot_lowerhalf_s *lower,
oneshot_callback_t callback, FAR void *arg,
FAR const struct timespec *ts)
{
FAR struct sam_oneshot_lowerhalf_s *priv =
(FAR struct sam_oneshot_lowerhalf_s *)lower;
irqstate_t flags;
int ret;
DEBUGASSERT(priv != NULL && callback != NULL && ts != NULL);
/* Save the callback information and start the timer */
flags = enter_critical_section();
priv->callback = callback;
priv->arg = arg;
ret = sam_oneshot_start(&priv->oneshot, NULL,
sam_oneshot_handler, priv, ts);
leave_critical_section(flags);
if (ret < 0)
{
tmrerr("ERROR: sam_oneshot_start failed: %d\n", flags);
}
return ret;
}
/****************************************************************************
* Name: sam_cancel
*
* Description:
* Cancel the oneshot timer and return the time remaining on the timer.
*
* NOTE: This function may execute at a high rate with no timer running (as
* when pre-emption is enabled and disabled).
*
* Input Parameters:
* lower Caller allocated instance of the oneshot state structure. This
* structure must have been previously initialized via a call to
* oneshot_initialize();
* ts The location in which to return the time remaining on the
* oneshot timer. A time of zero is returned if the timer is
* not running.
*
* Returned Value:
* Zero (OK) is returned on success. A call to up_timer_cancel() when
* the timer is not active should also return success; a negated errno
* value is returned on any failure.
*
****************************************************************************/
static int sam_cancel(FAR struct oneshot_lowerhalf_s *lower,
FAR struct timespec *ts)
{
FAR struct sam_oneshot_lowerhalf_s *priv =
(FAR struct sam_oneshot_lowerhalf_s *)lower;
irqstate_t flags;
int ret;
DEBUGASSERT(priv != NULL);
/* Cancel the timer */
flags = enter_critical_section();
ret = sam_oneshot_cancel(&priv->oneshot, NULL, ts);
priv->callback = NULL;
priv->arg = NULL;
leave_critical_section(flags);
if (ret < 0)
{
tmrerr("ERROR: sam_oneshot_cancel failed: %d\n", flags);
}
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: oneshot_initialize
*
* Description:
* Initialize the oneshot timer and return a oneshot lower half driver
* instance.
*
* Input Parameters:
* chan Timer counter channel to be used.
* resolution The required resolution of the timer in units of
* microseconds. NOTE that the range is restricted to the
* range of uint16_t (excluding zero).
*
* Returned Value:
* On success, a non-NULL instance of the oneshot lower-half driver is
* returned. NULL is return on any failure.
*
****************************************************************************/
FAR struct oneshot_lowerhalf_s *oneshot_initialize(int chan,
uint16_t resolution)
{
FAR struct sam_oneshot_lowerhalf_s *priv;
int ret;
/* Allocate an instance of the lower half driver */
priv = (FAR struct sam_oneshot_lowerhalf_s *)
kmm_zalloc(sizeof(struct sam_oneshot_lowerhalf_s));
if (priv == NULL)
{
tmrerr("ERROR: Failed to initialized state structure\n");
return NULL;
}
/* Initialize the lower-half driver structure */
priv->lh.ops = &g_oneshot_ops;
/* Initialize the contained SAM oneshot timer */
ret = sam_oneshot_initialize(&priv->oneshot, chan, resolution);
if (ret < 0)
{
tmrerr("ERROR: sam_oneshot_initialize failed: %d\n", ret);
kmm_free(priv);
return NULL;
}
return &priv->lh;
}

View File

@ -57,9 +57,9 @@
/* Bit-encoded input to sam_portconfig() */
/* 24-bit Encoding. This could be compacted into 16-bits by making the bit usage
* mode specific. However, by giving each bit field a unique position, we handle
* bad combinations of properties safely.
/* 24-bit Encoding. This could be compacted into 16-bits by making the bit
* usage mode specific. However, by giving each bit field a unique position,
* we handle bad combinations of properties safely.
*
* MODE BITFIELDS
* ------------ -----------------------------
@ -85,12 +85,13 @@
* Peripheral: MM.. .... .... .... .... ....
*/
#define PORT_MODE_SHIFT (22) /* Bits 22-23: PORT mode */
#define PORT_MODE_SHIFT (22) /* Bits 22-23: PORT mode */
#define PORT_MODE_MASK (3 << PORT_MODE_SHIFT)
# define PORT_INPUT (0 << PORT_MODE_SHIFT) /* PORT Input */
# define PORT_OUTPUT (1 << PORT_MODE_SHIFT) /* PORT Output */
# define PORT_PERIPHERAL (2 << PORT_MODE_SHIFT) /* Controlled by peripheral */
# define PORT_INTERRUPT (3 << PORT_MODE_SHIFT) /* Interrupting input */
#define PORT_MODE(n) ((uint8_t)(n) << PORT_MODE_SHIFT)
/* Pull-up/down resistor control for inputs
*
@ -217,8 +218,8 @@
# define PORT_OUTREADBACK_DISABLE (0 << PORT_OUTREADBACK_SHIFT)
# define PORT_OUTREADBACK_ENABLE (1 << PORT_OUTREADBACK_SHIFT)
/* If the pin is a PORT output, then this identifies the initial output value:
*
/* If the pin is a PORT output, then this
* identifies the initial output value:
* MODE BITFIELDS
* ------------ -----------------------------
* 2222 1111 1111 1100 0000 0000
@ -251,6 +252,8 @@
# define PORT_INT_CHANGE (0 << PORT_INT_SHIFT) /* Pin change */
# define PORT_INT_RISING (1 << PORT_INT_SHIFT) /* Rising edge */
# define PORT_INT_FALLING (2 << PORT_INT_SHIFT) /* Falling edge */
# define PORT_INT_BOTH (3 << PORT_INT_SHIFT) /* Both edge */
# define PORT_INT_HIGH (4 << PORT_INT_SHIFT) /* High edge */
/* This identifies the PORT port:
*

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,367 @@
/****************************************************************************
* arch/arm/src/samd5e5/sam_tc.h
*
* Copyright 2020 Falker Automacao Agricola LTDA.
* Author: Leomar Mateus Radke <leomar@falker.com.br>
* Author: Ricardo Wartchow <wartchow@gmail.com>
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __ARCH_ARM_SRC_SAMD5E5_SAM_TC_H
#define __ARCH_ARM_SRC_SAMD5E5_SAM_TC_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#include "sam_config.h"
#include "sam_port.h"
#include "sam_periphclks.h"
#include "hardware/sam_tc.h"
#include "hardware/sam_pinmap.h"
#include "semaphore.h"
#ifdef CONFIG_SAMD5E5_TC
/* Register identifier used with sam_tc_setregister */
#define TC_REGCC0 0
#define TC_REGCC1 1
/****************************************************************************
* Public Types
****************************************************************************/
/* An opaque handle used to represent a timer channel */
typedef void *TC_HANDLE;
/* Timer interrupt callback. When a timer interrupt expires, the client will
* receive:
*
* tch - The handle that represents the timer state
* arg - An opaque argument provided when the interrupt was registered
* sr - The value of the timer interrupt status register at the time
* that the interrupt occurred.
*/
typedef void (*tc_handler_t)(TC_HANDLE tch, void *arg, uint32_t sr);
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
struct tc_attr_s
{
uint8_t tc; /* Identifies the TC peripheral */
uint8_t irq; /* Tc IRQ number */
uint8_t coregen; /* Source GCLK generator */
port_pinset_t cc0; /* Pin configuration CC0 - Compare/Capture Channel */
port_pinset_t cc1; /* Pin configuration CC1 - Compare/Capture Channel */
uint32_t srcfreq; /* Source clock frequency */
uintptr_t base; /* Base address of Tc registers */
};
/* Setup TC -> Add the timer register settings here. */
struct sam_tc_dev_s
{
const struct tc_attr_s *attr; /* Invariant attributes of TC device */
uint32_t mode; /* TC mode */
uint32_t prescaler; /* TC prescaler */
uint32_t prescsync; /* TC prescsync */
uint8_t wave; /* TC wave mode */
uint16_t flags; /* Transfer flags */
uint32_t freq; /* TC freq */
uint32_t duty; /* TC duty cycle */
sem_t exclsem; /* Only one thread can access at a time */
sem_t waitsem; /* Wait for TC */
bool initialized; /* True: Timer data has been initialized */
bool inuse; /* True: channel is in use */
tc_handler_t handler; /* Attached interrupt handler */
void *arg; /* Interrupt handler argument */
};
/****************************************************************************
* Name: sam_tc_configure
*
* Description:
* Configure the interrupt edge sensitivity in CONFIGn register of the
* tc. The interrupt will be enabled at the tc (but not at the NVIC).
*
* Input Parameters:
* eirq - Pin to be configured (0..15)
* pinset - Configuration of the pin
*
* Returned Value:
* None
*
****************************************************************************/
int sam_tc_configure(uint8_t tcrq, port_pinset_t pinset);
/****************************************************************************
* Name: sam_tc_allocate
*
* Description:
* Configures a Timer Counter to operate in the given mode. The timer is
* stopped after configuration and must be restarted with sam_tc_start().
* All the interrupts of the timer are also disabled.
*
* Input Parameters:
* channel TC channel number (see TC_CHANx definitions)
* mode Operating mode (TC_CMR value).
*
* Returned Value:
* On success, a non-NULL handle value is returned. This handle may be
* used with subsequent timer/counter interfaces to manage the timer. A
* NULL handle value is returned on a failure.
*
****************************************************************************/
TC_HANDLE sam_tc_allocate(int channel, int frequency);
/****************************************************************************
* Name: sam_tc_free
*
* Description:
* Release the handle previously allocated by sam_tc_allocate().
*
* Input Parameters:
* handle Channel handle previously allocated by sam_tc_allocate()
*
* Returned Value:
* None
*
****************************************************************************/
void sam_tc_free(TC_HANDLE handle);
/****************************************************************************
* Name: sam_tc_start
*
* Description:
* Reset and Start the TC Channel. Enables the timer clock and performs a
* software reset to start the counting.
*
* Input Parameters:
* handle Channel handle previously allocated by sam_tc_allocate()
*
* Returned Value:
*
****************************************************************************/
void sam_tc_start(TC_HANDLE handle);
/****************************************************************************
* Name: sam_tc_stop
*
* Description:
* Stop TC Channel. Disables the timer clock, stopping the counting.
*
* Input Parameters:
* handle Channel handle previously allocated by sam_tc_allocate()
*
* Returned Value:
*
****************************************************************************/
void sam_tc_stop(TC_HANDLE handle);
/****************************************************************************
* Name: sam_tc_attach/sam_tc_detach
*
* Description:
* Attach or detach an interrupt handler to the timer interrupt. The
* interrupt is detached if the handler argument is NULL.
*
* Input Parameters:
* handle The handle that represents the timer state
* handler The interrupt handler that will be invoked when the interrupt
* condition occurs
* arg An opaque argument that will be provided when the interrupt
* handler callback is executed. Ignored if handler is NULL.
* mask The value of the timer interrupt mask register that defines
* which interrupts should be disabled. Ignored if handler is
* NULL.
*
* Returned Value:
* The address of the previous handler, if any.
*
****************************************************************************/
tc_handler_t sam_tc_attach(TC_HANDLE handle, tc_handler_t handler,
void *arg, uint32_t mask);
#define sam_tc_detach(h) sam_tc_attach(h, NULL, NULL, 0)
/****************************************************************************
* Name: sam_tc_getpending
*
* Description:
* Return the current contents of the interrutp status register, clearing
* all pending interrupts.
*
* Input Parameters:
* handle The handle that represents the timer state
*
* Returned Value:
* The value of the channel interrupt status register.
*
****************************************************************************/
uint8_t sam_tc_getpending(TC_HANDLE handle);
/****************************************************************************
* Name: sam_tc_setregister
*
* Description:
* Set TC_REGA, TC_REGB, or TC_REGC register.
*
* Input Parameters:
* handle Channel handle previously allocated by sam_tc_allocate()
* regid One of {TC_REGA, TC_REGB, or TC_REGC}
* regval Then value to set in the register
*
* Returned Value:
* None
*
****************************************************************************/
void sam_tc_setregister(TC_HANDLE handle, int regid, uint32_t regval);
/****************************************************************************
* Name: sam_tc_getregister
*
* Description:
* Get the current value of the TC_REGA, TC_REGB, or TC_REGC register.
*
* Input Parameters:
* handle Channel handle previously allocated by sam_tc_allocate()
* regid One of {TC_REGA, TC_REGB, or TC_REGC}
*
* Returned Value:
* The value of the specified register.
*
****************************************************************************/
uint32_t sam_tc_getregister(TC_HANDLE handle, int regid);
/****************************************************************************
* Name: sam_tc_getcounter
*
* Description:
* Return the current value of the timer counter register
*
* Input Parameters:
* handle Channel handle previously allocated by sam_tc_allocate()
*
* Returned Value:
* The current value of the timer counter register for this channel.
*
****************************************************************************/
uint32_t sam_tc_getcounter(TC_HANDLE handle);
/****************************************************************************
* Name: sam_tc_infreq
*
* Description:
* Return the timer input frequency, that is, the MCK frequency divided
* down so that the timer/counter is driven within its maximum frequency.
*
* Input Parameters:
* None
*
* Returned Value:
* The timer input frequency.
*
****************************************************************************/
uint32_t sam_tc_infreq(void);
/****************************************************************************
* Name: sam_tc_divfreq
*
* Description:
* Return the divided timer input frequency that is currently driving the
* the timer counter.
*
* Input Parameters:
* handle Channel handle previously allocated by sam_tc_allocate()
*
* Returned Value:
* The timer counter frequency.
*
****************************************************************************/
uint32_t sam_tc_divfreq(TC_HANDLE handle);
/****************************************************************************
* Name: sam_tc_divisor
*
* Description:
* Finds the best MCK divisor given the timer frequency and MCK. The
* result is guaranteed to satisfy the following equation:
*
* (Ftcin / (div * 65536)) <= freq <= (Ftcin / div)
*
* where:
* freq - the desired frequency
* Ftcin - The timer/counter input frequency
* div - With DIV being the highest possible value.
*
* Input Parameters:
* frequency Desired timer frequency.
* div Divisor value.
* tcclks TCCLKS field value for divisor.
*
* Returned Value:
* Zero (OK) if a proper divisor has been found, otherwise a negated errno
* value indicating the nature of the failure.
*
****************************************************************************/
int sam_tc_divisor(struct sam_tc_dev_s *tc, uint32_t frequency,
uint32_t *div, uint32_t *tcclks);
uint32_t sam_tc_getctrla(TC_HANDLE handle);
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif /* CONFIG_SAMD5E5_TC */
#endif /* __ARCH_ARM_SRC_SAMD5E5_SAM_TC_H */

View File

@ -0,0 +1,409 @@
/****************************************************************************
* arch/arm/src/samd5e5/sam_tickless.c
*
* Copyright 2020 Falker Automacao Agricola LTDA.
* Author: Leomar Mateus Radke <leomar@falker.com.br>
* Author: Ricardo Wartchow <wartchow@gmail.com>
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Tickless OS Support.
*
* When CONFIG_SCHED_TICKLESS is enabled, all support for timer interrupts
* is suppressed and the platform specific code is expected to provide the
* following custom functions.
*
* void arm_timer_initialize(void): Initializes the timer facilities.
* Calledearly in the initialization sequence (by up_intialize()).
* int up_timer_gettime(FAR struct timespec *ts): Returns the current
* time from the platform specific time source.
* int up_timer_cancel(void): Cancels the interval timer.
* int up_timer_start(FAR const struct timespec *ts): Start (or re-starts)
* the interval timer.
*
* The RTOS will provide the following interfaces for use by the platform-
* specific interval timer implementation:
*
* void nxsched_timer_expiration(void): Called by the platform-specific
* logic when the interval timer expires.
*
****************************************************************************/
/****************************************************************************
* SAMD5E5 Timer Usage
*
* This current implementation uses two timers: A one-shot timer to provide
* the timed events and a free running timer to provide the current time.
* Since timers are a limited resource, that could be an issue on some
* systems.
*
* We could do the job with a single timer if we were to keep the single
* timer in a free-running at all times. The SAMD5E5 timer/counters have
* 32-bit counters with the capability to generate a compare interrupt when
* the timer matches a compare value but also to continue counting without
* stopping (giving another, different interrupt when the timer rolls over
* from 0xffffffff to zero). So we could potentially just set the compare
* at the number of ticks you want PLUS the current value of timer. Then
* you could have both with a single timer: An interval timer and a free-
* running counter with the same timer!
*
* Patches are welcome!
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#include "arm_arch.h"
#include <nuttx/arch.h>
#include "sam_oneshot.h"
#include "sam_freerun.h"
#ifdef CONFIG_SCHED_TICKLESS
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifndef CONFIG_SAMD5E5_HAVE_TC
# error Timer/counters must be selected for the Tickless OS option
#endif
#ifndef CONFIG_SAMD5E5_ONESHOT
# error CONFIG_SAMD5E5_ONESHOT must be selected for the Tickless OS option
#endif
#ifndef CONFIG_SAMD5E5_FREERUN
# error CONFIG_SAMD5E5_FREERUN must be selected for the Tickless OS option
#endif
#ifndef CONFIG_SAMD5E5_TICKLESS_FREERUN
# error CONFIG_SAMD5E5_TICKLESS_FREERUN must be selected for the Tickless OS option
#endif
#ifndef CONFIG_SAMD5E5_TICKLESS_ONESHOT
# error CONFIG_SAMD5E5_TICKLESS_ONESHOT must be selected for the Tickless OS option
#endif
#if CONFIG_SAMD5E5_TICKLESS_ONESHOT == 0 && !defined(CONFIG_SAMD5E5_TC0)
# error CONFIG_SAMD5E5_TICKLESS_ONESHOT == 0 && CONFIG_SAMD5E5_TC0 not selected
#elif CONFIG_SAMD5E5_TICKLESS_ONESHOT == 1 && !defined(CONFIG_SAMD5E5_TC1)
# error CONFIG_SAMD5E5_TICKLESS_ONESHOT == 1 && CONFIG_SAMD5E5_TC1 not selected
#elif CONFIG_SAMD5E5_TICKLESS_ONESHOT == 2 && !defined(CONFIG_SAMD5E5_TC2)
# error CONFIG_SAMD5E5_TICKLESS_ONESHOT == 2 && CONFIG_SAMD5E5_TC2 not selected
#elif CONFIG_SAMD5E5_TICKLESS_ONESHOT == 3 && !defined(CONFIG_SAMD5E5_TC3)
# error CONFIG_SAMD5E5_TICKLESS_ONESHOT == 3 && CONFIG_SAMD5E5_TC3 not selected
#elif CONFIG_SAMD5E5_TICKLESS_ONESHOT == 4 && !defined(CONFIG_SAMD5E5_TC4)
# error CONFIG_SAMD5E5_TICKLESS_ONESHOT == 4 && CONFIG_SAMD5E5_TC4 not selected
#elif CONFIG_SAMD5E5_TICKLESS_ONESHOT == 5 && !defined(CONFIG_SAMD5E5_TC5)
# error CONFIG_SAMD5E5_TICKLESS_ONESHOT == 5 && CONFIG_SAMD5E5_TC5 not selected
#elif CONFIG_SAMD5E5_TICKLESS_ONESHOT == 6 && !defined(CONFIG_SAMD5E5_TC6)
# error CONFIG_SAMD5E5_TICKLESS_ONESHOT == 6 && CONFIG_SAMD5E5_TC6 not selected
#elif CONFIG_SAMD5E5_TICKLESS_ONESHOT == 7 && !defined(CONFIG_SAMD5E5_TC7)
# error CONFIG_SAMD5E5_TICKLESS_ONESHOT == 7 && CONFIG_SAMD5E5_TC7 not selected
#endif
#if CONFIG_SAMD5E5_TICKLESS_ONESHOT < 0 || CONFIG_SAMD5E5_TICKLESS_ONESHOT > 7
# error CONFIG_SAMD5E5_TICKLESS_ONESHOT is not valid
#endif
#if CONFIG_SAMD5E5_TICKLESS_FREERUN == 0 && !defined(CONFIG_SAMD5E5_TC0)
# error CONFIG_SAMD5E5_TICKLESS_FREERUN == 0 && CONFIG_SAMD5E5_TC0 not selected
#elif CONFIG_SAMD5E5_TICKLESS_FREERUN == 1 && !defined(CONFIG_SAMD5E5_TC1)
# error CONFIG_SAMD5E5_TICKLESS_FREERUN == 1 && CONFIG_SAMD5E5_TC1 not selected
#elif CONFIG_SAMD5E5_TICKLESS_FREERUN == 2 && !defined(CONFIG_SAMD5E5_TC2)
# error CONFIG_SAMD5E5_TICKLESS_FREERUN == 2 && CONFIG_SAMD5E5_TC2 not selected
#elif CONFIG_SAMD5E5_TICKLESS_FREERUN == 3 && !defined(CONFIG_SAMD5E5_TC3)
# error CONFIG_SAMD5E5_TICKLESS_FREERUN == 3 && CONFIG_SAMD5E5_TC3 not selected
#elif CONFIG_SAMD5E5_TICKLESS_FREERUN == 4 && !defined(CONFIG_SAMD5E5_TC4)
# error CONFIG_SAMD5E5_TICKLESS_FREERUN == 4 && CONFIG_SAMD5E5_TC4 not selected
#elif CONFIG_SAMD5E5_TICKLESS_FREERUN == 5 && !defined(CONFIG_SAMD5E5_TC5)
# error CONFIG_SAMD5E5_TICKLESS_FREERUN == 5 && CONFIG_SAMD5E5_TC5 not selected
#elif CONFIG_SAMD5E5_TICKLESS_FREERUN == 6 && !defined(CONFIG_SAMD5E5_TC6)
# error CONFIG_SAMD5E5_TICKLESS_FREERUN == 6 && CONFIG_SAMD5E5_TC6 not selected
#elif CONFIG_SAMD5E5_TICKLESS_FREERUN == 7 && !defined(CONFIG_SAMD5E5_TC7)
# error CONFIG_SAMD5E5_TICKLESS_FREERUN == 7 && CONFIG_SAMD5E5_TC7 not selected
#endif
#if CONFIG_SAMD5E5_TICKLESS_FREERUN < 0 || CONFIG_SAMD5E5_TICKLESS_FREERUN > 7
# error CONFIG_SAMD5E5_TICKLESS_FREERUN is not valid
#endif
#if CONFIG_SAMD5E5_TICKLESS_FREERUN == CONFIG_SAMD5E5_TICKLESS_ONESHOT
# error CONFIG_SAMD5E5_TICKLESS_FREERUN is the same as CONFIG_SAMD5E5_TICKLESS_ONESHOT
#endif
/****************************************************************************
* Private Types
****************************************************************************/
struct sam_tickless_s
{
struct sam_oneshot_s oneshot;
struct sam_freerun_s freerun;
};
/****************************************************************************
* Private Data
****************************************************************************/
static struct sam_tickless_s g_tickless;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: sam_oneshot_handler
*
* Description:
* Called when the one shot timer expires
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions:
* Called early in the initialization sequence before any special
* concurrency protections are required.
*
****************************************************************************/
static void sam_oneshot_handler(void *arg)
{
tmrinfo("Expired...\n");
nxsched_timer_expiration();
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_timer_initialize
*
* Description:
* Initializes all platform-specific timer facilities. This function is
* called early in the initialization sequence by up_intialize().
* On return, the current up-time should be available from
* up_timer_gettime() and the interval timer is ready for use (but not
* actively timing.
*
* Provided by platform-specific code and called from the architecture-
* specific logic.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions:
* Called early in the initialization sequence before any special
* concurrency protections are required.
*
****************************************************************************/
void up_timer_initialize(void)
{
#ifdef CONFIG_SCHED_TICKLESS_LIMIT_MAX_SLEEP
uint64_t max_delay;
#endif
int ret;
/* Initialize the one-shot timer */
ret = sam_oneshot_initialize(&g_tickless.oneshot,
CONFIG_SAMD5E5_TICKLESS_ONESHOT,
CONFIG_USEC_PER_TICK);
if (ret < 0)
{
tmrerr("ERROR: sam_oneshot_initialize failed\n");
DEBUGPANIC();
}
DEBUGASSERT(ONESHOT_INITIALIZED(&g_tickless.oneshot));
#ifdef CONFIG_SCHED_TICKLESS_LIMIT_MAX_SLEEP
/* Get the maximum delay of the one-shot timer in microseconds */
ret = sam_oneshot_max_delay(&g_tickless.oneshot, &max_delay);
if (ret < 0)
{
tmrerr("ERROR: sam_oneshot_max_delay failed\n");
DEBUGPANIC();
}
/* Convert this to configured clock ticks for use by the OS timer logic */
max_delay /= CONFIG_USEC_PER_TICK;
if (max_delay > (uint64_t)UINT32_MAX)
{
g_oneshot_maxticks = UINT32_MAX;
}
else
{
g_oneshot_maxticks = (uint32_t)max_delay;
}
#endif
/* Initialize the free-running timer */
ret = sam_freerun_initialize(&g_tickless.freerun,
CONFIG_SAMD5E5_TICKLESS_FREERUN,
CONFIG_USEC_PER_TICK);
if (ret < 0)
{
tmrerr("ERROR: sam_freerun_initialize failed\n");
DEBUGPANIC();
}
DEBUGASSERT(FREERUN_INITIALIZED(&g_tickless.freerun));
}
/****************************************************************************
* Name: up_timer_gettime
*
* Description:
* Return the elapsed time since power-up (or, more correctly, since
* arm_timer_initialize() was called). This function is functionally
* equivalent to:
*
* int clock_gettime(clockid_t clockid, FAR struct timespec *ts);
*
* when clockid is CLOCK_MONOTONIC.
*
* This function provides the basis for reporting the current time and
* also is used to eliminate error build-up from small errors in interval
* time calculations.
*
* Provided by platform-specific code and called from the RTOS base code.
*
* Input Parameters:
* ts - Provides the location in which to return the up-time.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned on
* any failure.
*
* Assumptions:
* Called from the normal tasking context. The implementation must
* provide whatever mutual exclusion is necessary for correct operation.
* This can include disabling interrupts in order to assure atomic register
* operations.
*
****************************************************************************/
int up_timer_gettime(FAR struct timespec *ts)
{
return FREERUN_INITIALIZED(&g_tickless.freerun) ?
sam_freerun_counter(&g_tickless.freerun, ts) :
-EAGAIN;
}
/****************************************************************************
* Name: up_timer_cancel
*
* Description:
* Cancel the interval timer and return the time remaining on the timer.
* These two steps need to be as nearly atomic as possible.
* nxsched_timer_expiration() will not be called unless the timer is
* restarted with up_timer_start().
*
* If, as a race condition, the timer has already expired when this
* function is called, then that pending interrupt must be cleared so
* that up_timer_start() and the remaining time of zero should be
* returned.
*
* NOTE: This function may execute at a high rate with no timer running (as
* when pre-emption is enabled and disabled).
*
* Provided by platform-specific code and called from the RTOS base code.
*
* Input Parameters:
* ts - Location to return the remaining time. Zero should be returned
* if the timer is not active. ts may be zero in which case the
* time remaining is not returned.
*
* Returned Value:
* Zero (OK) is returned on success. A call to up_timer_cancel() when
* the timer is not active should also return success; a negated errno
* value is returned on any failure.
*
* Assumptions:
* May be called from interrupt level handling or from the normal tasking
* level. Interrupts may need to be disabled internally to assure
* non-reentrancy.
*
****************************************************************************/
int up_timer_cancel(FAR struct timespec *ts)
{
return ONESHOT_INITIALIZED(&g_tickless.oneshot) &&
FREERUN_INITIALIZED(&g_tickless.freerun) ?
sam_oneshot_cancel(&g_tickless.oneshot, &g_tickless.freerun, ts) :
-EAGAIN;
}
/****************************************************************************
* Name: up_timer_start
*
* Description:
* Start the interval timer. nxsched_timer_expiration() will be
* called at the completion of the timeout (unless up_timer_cancel
* is called to stop the timing.
*
* Provided by platform-specific code and called from the RTOS base code.
*
* Input Parameters:
* ts - Provides the time interval until nxsched_timer_expiration() is
* called.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned on
* any failure.
*
* Assumptions:
* May be called from interrupt level handling or from the normal tasking
* level. Interrupts may need to be disabled internally to assure
* non-reentrancy.
*
****************************************************************************/
int up_timer_start(FAR const struct timespec *ts)
{
tmrinfo("ts=(%lu, %lu)\n", (unsigned long)ts->tv_sec,
(unsigned long)ts->tv_nsec);
return ONESHOT_INITIALIZED(&g_tickless.oneshot) ?
sam_oneshot_start(&g_tickless.oneshot, &g_tickless.freerun,
sam_oneshot_handler, NULL, ts) :
-EAGAIN;
}
#endif /* CONFIG_SCHED_TICKLESS */

View File

@ -103,7 +103,7 @@ static int sam_timerisr(int irq, uint32_t *regs, void *arg)
****************************************************************************/
/****************************************************************************
* Function: up_timer_initialize
* Function: arm_timer_initialize
*
* Description:
* This function is called during start-up to initialize the timer
@ -129,7 +129,7 @@ void up_timer_initialize(void)
/* Attach the timer interrupt vector */
irq_attach(SAM_IRQ_SYSTICK, (xcpt_t)sam_timerisr, NULL);
(void)irq_attach(SAM_IRQ_SYSTICK, (xcpt_t)sam_timerisr, NULL);
/* Enable SysTick interrupts using the processor clock source. */

View File

@ -480,6 +480,21 @@
#define BOARD_SERCOM5_SLOW_GCLKGEN 3
#define BOARD_SERCOM5_FREQUENCY BOARD_GCLK1_FREQUENCY
/* Tickless */
#define BOARD_TC0_PINMAP_CC0 0 /* CC0: (not used) */
#define BOARD_TC0_PINMAP_CC1 0 /* CC1: (not used) */
#define BOARD_TC0_GCLKGEN 3
#define BOARD_TC0_FREQUENCY BOARD_GCLK3_FREQUENCY
#define BOARD_TC2_PINMAP_CC0 0 /* CC0: (not used) */
#define BOARD_TC2_PINMAP_CC1 0 /* CC1: (not used) */
#define BOARD_TC2_GCLKGEN 3
#define BOARD_TC2_FREQUENCY BOARD_GCLK3_FREQUENCY
#define BOARD_TC4_PINMAP_CC0 0 /* CC0: (not used) */
#define BOARD_TC4_PINMAP_CC1 0 /* CC1: (not used) */
#define BOARD_TC4_GCLKGEN 3
#define BOARD_TC4_FREQUENCY BOARD_GCLK3_FREQUENCY
/* USB */
#define BOARD_USB_GCLKGEN 1 /* GCLK1, 48MHz */