mirror of
https://github.com/apache/nuttx.git
synced 2026-06-07 01:05:54 +08:00
SAMA5: Hook in timer/counter logic so that it can driver periodic ADC sampling
This commit is contained in:
@@ -2070,6 +2070,7 @@ config SAMA5_ADC_ADTRG
|
||||
|
||||
config SAMA5_ADC_TIOATRIG
|
||||
bool "TC0 ouput A trigger"
|
||||
depends on SAMA5_TC0
|
||||
---help---
|
||||
A-to-D Conversion is initiated the A output from one of
|
||||
Timer/Counter 0 channels.
|
||||
@@ -2100,12 +2101,20 @@ endchoice # ADTRG edge
|
||||
|
||||
if SAMA5_ADC_TIOATRIG
|
||||
|
||||
config SAMA5_ADC_TIOAFREQ
|
||||
int "ADC sampling frequency"
|
||||
default 1
|
||||
---help---
|
||||
This setting provides the rate at which the timer will driver ADC
|
||||
sampling.
|
||||
|
||||
choice
|
||||
prompt "TC0 channel"
|
||||
default SAMA5_ADC_TIOA0TRIG
|
||||
|
||||
config SAMA5_ADC_TIOA0TRIG
|
||||
bool "TC0 Channel 0 Output A"
|
||||
select SAMA5_TC0_TIOA0
|
||||
---help---
|
||||
A-to-D conversion is triggered by the TC0 channel 0 output A signal.
|
||||
This output must be enabled independently in the Timer/Counter
|
||||
@@ -2113,6 +2122,7 @@ config SAMA5_ADC_TIOA0TRIG
|
||||
|
||||
config SAMA5_ADC_TIOA1TRIG
|
||||
bool "TC0 Channel 1 Output A"
|
||||
select SAMA5_TC0_TIOA1
|
||||
---help---
|
||||
A-to-D conversion is triggered by the TC0 channel 1 output A signal.
|
||||
This output must be enabled independently in the Timer/Counter
|
||||
@@ -2120,6 +2130,7 @@ config SAMA5_ADC_TIOA1TRIG
|
||||
|
||||
config SAMA5_ADC_TIOA2TRIG
|
||||
bool "TC0 Channel 2 Output A"
|
||||
select SAMA5_TC0_TIOA2
|
||||
---help---
|
||||
A-to-D conversion is triggered by the TC0 channel 2 output A signal.
|
||||
This output must be enabled independently in the Timer/Counter
|
||||
@@ -2161,6 +2172,92 @@ config SAMA5_ADC_REGDEBUG
|
||||
|
||||
endmenu # ADC Configuration
|
||||
|
||||
if SAMA5_TC0 || SAMA5_TC1
|
||||
menu "Timer/counter Configuration"
|
||||
|
||||
if SAMA5_TC0
|
||||
|
||||
config SAMA5_TC0_CLK0
|
||||
bool "Enable TC0 channel 0 clock input pin"
|
||||
default n
|
||||
|
||||
config SAMA5_TC0_TIOA0
|
||||
bool "Enable TC0 channel 0 ouput A"
|
||||
default n
|
||||
|
||||
config SAMA5_TC0_TIOB0
|
||||
bool "Enable TC0 channel 0 ouput B"
|
||||
default n
|
||||
|
||||
config SAMA5_TC0_CLK1
|
||||
bool "Enable TC0 channel 1 clock input pin"
|
||||
default n
|
||||
|
||||
config SAMA5_TC0_TIOA1
|
||||
bool "Enable TC0 channel 1 ouput A"
|
||||
default n
|
||||
|
||||
config SAMA5_TC0_TIOB1
|
||||
bool "Enable TC0 channel 1 ouput B"
|
||||
default n
|
||||
|
||||
config SAMA5_TC0_CLK2
|
||||
bool "Enable TC0 channel 2 clock input pin"
|
||||
default n
|
||||
|
||||
config SAMA5_TC0_TIOA2
|
||||
bool "Enable TC0 channel 2 ouput A"
|
||||
default n
|
||||
|
||||
config SAMA5_TC0_TIOB2
|
||||
bool "Enable TC0 channel 2 ouput B"
|
||||
default n
|
||||
|
||||
endif # SAMA5_TC0
|
||||
|
||||
if SAMA5_TC1
|
||||
|
||||
config SAMA5_TC1_CLK3
|
||||
bool "Enable TC1 channel 3 clock input pin"
|
||||
default n
|
||||
|
||||
config SAMA5_TC1_TIOA3
|
||||
bool "Enable TC1 channel 3 ouput A"
|
||||
default n
|
||||
|
||||
config SAMA5_TC1_TIOB3
|
||||
bool "Enable TC1 channel 3 ouput B"
|
||||
default n
|
||||
|
||||
config SAMA5_TC1_CLK4
|
||||
bool "Enable TC1 channel 4 clock input pin"
|
||||
default n
|
||||
|
||||
config SAMA5_TC1_TIOA4
|
||||
bool "Enable TC1 channel 4 ouput A"
|
||||
default n
|
||||
|
||||
config SAMA5_TC1_TIOB4
|
||||
bool "Enable TC1 channel 4 ouput B"
|
||||
default n
|
||||
|
||||
config SAMA5_TC1_CLK5
|
||||
bool "Enable TC1 channel 5 clock input pin"
|
||||
default n
|
||||
|
||||
config SAMA5_TC1_TIOA5
|
||||
bool "Enable TC1 channel 5 ouput A"
|
||||
default n
|
||||
|
||||
config SAMA5_TC1_TIOB5
|
||||
bool "Enable TC1 channel 5 ouput B"
|
||||
default n
|
||||
|
||||
endif # SAMA5_TC1
|
||||
|
||||
endmenu # Timer/counter Configuration
|
||||
endif # SAMA5_TC0 || SAMA5_TC1
|
||||
|
||||
menu "Touchscreen configuration"
|
||||
|
||||
config SAMA5_TSD
|
||||
|
||||
@@ -46,6 +46,10 @@
|
||||
/************************************************************************************
|
||||
* Pre-processor Definitions
|
||||
************************************************************************************/
|
||||
|
||||
#define SAM_TC_NCHANNELS 3 /* Number of channels per TC peripheral */
|
||||
#define SAM_TC_MAXPERCLK 66000000 /* Maximum peripheral input clock frequency */
|
||||
|
||||
/* TC Register Offsets **************************************************************/
|
||||
|
||||
#define SAM_TC_CHAN_OFFSET(n) ((n) << 6) /* Channel n offset */
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
#include "chip/sam_pmc.h"
|
||||
#include "sam_periphclks.h"
|
||||
#include "sam_dmac.h"
|
||||
#include "sam_tc.h"
|
||||
#include "sam_tsd.h"
|
||||
#include "sam_adc.h"
|
||||
|
||||
@@ -379,6 +380,9 @@ struct sam_adc_s
|
||||
#ifdef CONFIG_SAMA5_ADC_DMA
|
||||
DMA_HANDLE dma; /* Handle for DMA channel */
|
||||
#endif
|
||||
#ifdef CONFIG_SAMA5_ADC_TIOATRIG
|
||||
TC_HANDLE tc; /* Handle for the timer channel */
|
||||
#endif
|
||||
|
||||
/* DMA sample data buffer */
|
||||
|
||||
@@ -435,6 +439,10 @@ static int sam_adc_ioctl(struct adc_dev_s *dev, int cmd, unsigned long arg);
|
||||
|
||||
/* Initialization/Configuration */
|
||||
|
||||
#ifdef CONFIG_SAMA5_ADC_TIOATRIG
|
||||
static void sam_adc_settimer(struct sam_adc_s *priv, uint32_t frequency,
|
||||
int channel, boot tioa);
|
||||
#endif
|
||||
static void sam_adc_trigger(struct sam_adc_s *priv);
|
||||
static void sam_adc_autocalibrate(struct sam_adc_s *priv);
|
||||
static void sam_adc_offset(struct sam_adc_s *priv);
|
||||
@@ -878,6 +886,12 @@ static void sam_adc_reset(struct adc_dev_s *dev)
|
||||
|
||||
dma_stop(priv->dma);
|
||||
|
||||
/* Stop an release any timer */
|
||||
|
||||
#ifdef CONFIG_SAMA5_ADC_TIOATRIG
|
||||
sam_adc_freetimer(priv);
|
||||
#endif
|
||||
|
||||
/* Disable all EOC interrupts */
|
||||
|
||||
sam_adc_putreg(priv, SAM_ADC_IDR, ADC_INT_EOCALL);
|
||||
@@ -1067,6 +1081,85 @@ static int sam_adc_ioctl(struct adc_dev_s *dev, int cmd, unsigned long arg)
|
||||
* Initialization/Configuration
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam_adc_settimer
|
||||
*
|
||||
* Description:
|
||||
* Configure a timer to trigger the sampling periodically
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SAMA5_ADC_TIOATRIG
|
||||
static void sam_adc_settimer(struct sam_adc_s *priv, uint32_t frequency,
|
||||
int channel)
|
||||
{
|
||||
uint32_t div;
|
||||
uint32_t tcclks;
|
||||
|
||||
/* Configure TC for a 1Hz frequency and trigger on RC compare. */
|
||||
|
||||
ret = sam_tc_divisor(frequency, &div, &tcclks);
|
||||
if (ret < 0)
|
||||
{
|
||||
adbg("ERROR: sam_tc_divisor failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set the timer/counter waveform mode the the clock input slected by
|
||||
* sam_tc_divisor()
|
||||
*/
|
||||
|
||||
mode = ((tcclks << TC_CMR_TCCLKS_SHIFT) | /* Use selected TCCLKS value */
|
||||
TC_CMR_WAVSEL_UPRC | /* UP mode w/ trigger on RC Compare */
|
||||
TC_CMR_WAVE | /* Wave mode */
|
||||
TC_CMR_ACPA_CLEAR | /* RA Compare Effect on TIOA: Clear */
|
||||
TC_CMR_ACPC_SET); /* RC effect on TIOA: Set
|
||||
|
||||
/* Now allocate and configure the channel */
|
||||
|
||||
priv->tc = sam_tc_allocate(channel, mode);
|
||||
if (!priv->tc)
|
||||
{
|
||||
adbg("ERROR: Failed to allocate channel %d mode %08x\n", channel, mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Set up TC_RA and TC_RC */
|
||||
|
||||
sam_tc_setregister(priv->tc, TC_REGA, div / 2);
|
||||
sam_tc_setregister(priv->tc, TC_REGC, div);
|
||||
|
||||
/* And start the timer */
|
||||
|
||||
sam_tc_start(priv->tc);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam_adc_settimer
|
||||
*
|
||||
* Description:
|
||||
* Configure a timer to trigger the sampling periodically
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SAMA5_ADC_TIOATRIG
|
||||
static void sam_adc_settimer(struct sam_adc_s *priv, uint32_t frequency,
|
||||
int channel)
|
||||
{
|
||||
/* Is a timer allocated? */
|
||||
|
||||
if (priv->tc)
|
||||
{
|
||||
/* Yes.. stop it and free it */
|
||||
|
||||
sam_tc_stop(priv->tc);
|
||||
sam_tc_free(priv->tc);
|
||||
priv->tc = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam_adc_trigger
|
||||
*
|
||||
@@ -1119,6 +1212,18 @@ static void sam_adc_trigger(struct sam_adc_s *priv)
|
||||
sam_adc_putreg(priv, SAM_ADC_TRGR, regval);
|
||||
|
||||
#elif defined(CONFIG_SAMA5_ADC_TIOATRIG)
|
||||
/* Start the timer */
|
||||
|
||||
#if defined(CONFIG_SAMA5_ADC_TIOA0TRIG)
|
||||
sam_adc_settimer(priv, CONFIG_SAMA5_ADC_TIOAFREQ, TC_CHAN0);
|
||||
#elif defined(CONFIG_SAMA5_ADC_TIOA1TRIG)
|
||||
sam_adc_settimer(priv, CONFIG_SAMA5_ADC_TIOAFREQ, TC_CHAN1);
|
||||
#elif defined(CONFIG_SAMA5_ADC_TIOA2TRIG)
|
||||
sam_adc_settimer(priv, CONFIG_SAMA5_ADC_TIOAFREQ, TC_CHAN2);
|
||||
#else
|
||||
# error Timer/counter for trigger not defined
|
||||
#endif
|
||||
|
||||
/* Configure to trigger using Timer/counter 0, channel 1, 2, or 3.
|
||||
* NOTE: This trigger option depends on having properly configuer
|
||||
* timer/counter 0 to provide this output. That is done independently
|
||||
|
||||
@@ -116,7 +116,7 @@
|
||||
# define CAN_FREQUENCY (BOARD_MCK_FREQUENCY >> 3)
|
||||
# define CAN_PCR_DIV PMC_PCR_DIV8
|
||||
#else
|
||||
# error Cannot realize ADC input frequency
|
||||
# error Cannot realize CAN input frequency
|
||||
#endif
|
||||
|
||||
/* Debug ********************************************************************/
|
||||
|
||||
+339
-63
File diff suppressed because it is too large
Load Diff
+54
-12
@@ -62,11 +62,17 @@
|
||||
#define TC_CHAN4 4
|
||||
#define TC_CHAN5 5
|
||||
|
||||
/* Register identifier used with sam_tc_setregister */
|
||||
|
||||
#define TC_REGA 0
|
||||
#define TC_REGB 1
|
||||
#define TC_REGC 2
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
typedef void *TCHANDLE;
|
||||
typedef void *TC_HANDLE;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
@@ -104,7 +110,7 @@ extern "C"
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
TCHANDLE sam_tc_allocate(int channel, int mode);
|
||||
TC_HANDLE sam_tc_allocate(int channel, int mode);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam_tc_free
|
||||
@@ -120,7 +126,7 @@ TCHANDLE sam_tc_allocate(int channel, int mode);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void sam_tc_free(TCHANDLE handle);
|
||||
void sam_tc_free(TC_HANDLE handle);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam_tc_start
|
||||
@@ -136,7 +142,7 @@ void sam_tc_free(TCHANDLE handle);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void sam_tc_start(TCHANDLE handle);
|
||||
void sam_tc_start(TC_HANDLE handle);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam_tc_stop
|
||||
@@ -151,7 +157,44 @@ void sam_tc_start(TCHANDLE handle);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void sam_tc_stop(TCHANDLE handle);
|
||||
void sam_tc_stop(TC_HANDLE handle);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam_tc_setregister
|
||||
*
|
||||
* Description:
|
||||
* Set TC_RA, TC_RB, or TC_RB using the provided divisor. The actual
|
||||
* setting in the regsiter will be the TC input frequency divided by
|
||||
* the provided divider (which should derive from the divider returned
|
||||
* by sam_tc_divider).
|
||||
*
|
||||
*
|
||||
* Input Parameters:
|
||||
* handle Channel handle previously allocated by sam_tc_allocate()
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void sam_tc_setregister(TC_HANDLE handle, int reg, unsigned int div);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam_tc_frequency
|
||||
*
|
||||
* 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_frequency(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam_tc_divisor
|
||||
@@ -160,17 +203,17 @@ void sam_tc_stop(TCHANDLE handle);
|
||||
* Finds the best MCK divisor given the timer frequency and MCK. The
|
||||
* result is guaranteed to satisfy the following equation:
|
||||
*
|
||||
* (MCK / (DIV * 65536)) <= freq <= (MCK / DIV)
|
||||
* (Ftc / (div * 65536)) <= freq <= (Ftc / dev)
|
||||
*
|
||||
* with DIV being the highest possible value.
|
||||
* where:
|
||||
* freq - the desitred frequency
|
||||
* Ftc - The timer/counter input frequency
|
||||
* div - With DIV being the highest possible value.
|
||||
*
|
||||
* Input Parameters:
|
||||
*
|
||||
* frequency Desired timer frequency.
|
||||
* mck Master clock frequency.
|
||||
* div Divisor value.
|
||||
* tcclks TCCLKS field value for divisor.
|
||||
* boardmck Board clock frequency.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) if a proper divisor has been found, otherwise a negated errno
|
||||
@@ -178,8 +221,7 @@ void sam_tc_stop(TCHANDLE handle);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint32_t sam_tc_divisor(uint32_t frequency, uint32_t mck, uint32_t *div,
|
||||
uint32_t *tcclks, uint32_t boardmck);
|
||||
int sam_tc_divisor(uint32_t frequency, uint32_t *div, uint32_t *tcclks);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
|
||||
Reference in New Issue
Block a user