Merge pull request #11336 from benpicco/sam0-timer

sam0_common: make Timer implementation common across all sam0 MCUs
This commit is contained in:
Dylan Laduranty 2019-05-21 12:13:39 +02:00 committed by GitHub
commit 85d37bb94f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 719 additions and 969 deletions

View File

@ -33,7 +33,7 @@ extern "C" {
* @name xtimer configuration * @name xtimer configuration
* @{ * @{
*/ */
#define XTIMER TIMER_DEV(1) #define XTIMER_DEV TIMER_DEV(1)
#define XTIMER_CHAN (0) #define XTIMER_CHAN (0)
/** @} */ /** @} */

View File

@ -83,22 +83,44 @@ extern "C" {
* @name Timer peripheral configuration * @name Timer peripheral configuration
* @{ * @{
*/ */
#define TIMER_NUMOF (2U) static const tc32_conf_t timer_config[] = {
#define TIMER_0_EN 1 { /* Timer 0 - System Clock */
#define TIMER_1_EN 1 .dev = TC3,
.irq = TC3_IRQn,
.pm_mask = PM_APBCMASK_TC3,
.gclk_ctrl = GCLK_CLKCTRL_ID_TCC2_TC3,
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
.gclk_src = GCLK_CLKCTRL_GEN(1),
.prescaler = TC_CTRLA_PRESCALER_DIV1,
#else
.gclk_src = GCLK_CLKCTRL_GEN(0),
.prescaler = TC_CTRLA_PRESCALER_DIV8,
#endif
.flags = TC_CTRLA_MODE_COUNT16,
},
{ /* Timer 1 */
.dev = TC4,
.irq = TC4_IRQn,
.pm_mask = PM_APBCMASK_TC4 | PM_APBCMASK_TC5,
.gclk_ctrl = GCLK_CLKCTRL_ID_TC4_TC5,
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
.gclk_src = GCLK_CLKCTRL_GEN(1),
.prescaler = TC_CTRLA_PRESCALER_DIV1,
#else
.gclk_src = GCLK_CLKCTRL_GEN(0),
.prescaler = TC_CTRLA_PRESCALER_DIV8,
#endif
.flags = TC_CTRLA_MODE_COUNT32,
}
};
/* Timer 0 configuration */ #define TIMER_0_MAX_VALUE 0xffff
#define TIMER_0_DEV TC3->COUNT16
#define TIMER_0_CHANNELS 2 /* interrupt function name mapping */
#define TIMER_0_MAX_VALUE (0xffff)
#define TIMER_0_ISR isr_tc3 #define TIMER_0_ISR isr_tc3
/* Timer 1 configuration */
#define TIMER_1_DEV TC4->COUNT32
#define TIMER_1_CHANNELS 2
#define TIMER_1_MAX_VALUE (0xffffffff)
#define TIMER_1_ISR isr_tc4 #define TIMER_1_ISR isr_tc4
#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
/** @} */ /** @} */
/** /**

View File

@ -81,21 +81,44 @@ extern "C" {
* @name Timer peripheral configuration * @name Timer peripheral configuration
* @{ * @{
*/ */
#define TIMER_NUMOF (2U) static const tc32_conf_t timer_config[] = {
#define TIMER_0_EN 1 { /* Timer 0 - System Clock */
#define TIMER_1_EN 1 .dev = TC3,
.irq = TC3_IRQn,
.pm_mask = PM_APBCMASK_TC3,
.gclk_ctrl = GCLK_CLKCTRL_ID_TCC2_TC3,
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
.gclk_src = GCLK_CLKCTRL_GEN(1),
.prescaler = TC_CTRLA_PRESCALER_DIV1,
#else
.gclk_src = GCLK_CLKCTRL_GEN(0),
.prescaler = TC_CTRLA_PRESCALER_DIV8,
#endif
.flags = TC_CTRLA_MODE_COUNT16,
},
{ /* Timer 1 */
.dev = TC4,
.irq = TC4_IRQn,
.pm_mask = PM_APBCMASK_TC4 | PM_APBCMASK_TC5,
.gclk_ctrl = GCLK_CLKCTRL_ID_TC4_TC5,
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
.gclk_src = GCLK_CLKCTRL_GEN(1),
.prescaler = TC_CTRLA_PRESCALER_DIV1,
#else
.gclk_src = GCLK_CLKCTRL_GEN(0),
.prescaler = TC_CTRLA_PRESCALER_DIV8,
#endif
.flags = TC_CTRLA_MODE_COUNT32,
}
};
/* Timer 0 configuration */ #define TIMER_0_MAX_VALUE 0xffff
#define TIMER_0_DEV TC3->COUNT16
#define TIMER_0_CHANNELS 2 /* interrupt function name mapping */
#define TIMER_0_MAX_VALUE (0xffff)
#define TIMER_0_ISR isr_tc3 #define TIMER_0_ISR isr_tc3
/* Timer 1 configuration */
#define TIMER_1_DEV TC4->COUNT32
#define TIMER_1_CHANNELS 2
#define TIMER_1_MAX_VALUE (0xffffffff)
#define TIMER_1_ISR isr_tc4 #define TIMER_1_ISR isr_tc4
#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
/** @} */ /** @} */
/** /**

View File

@ -35,14 +35,23 @@ extern "C" {
* @name Timer peripheral configuration * @name Timer peripheral configuration
* @{ * @{
*/ */
#define TIMER_NUMOF (1U) static const tc32_conf_t timer_config[] = {
#define TIMER_0_EN 1 { /* Timer 0 - System Clock */
.dev = TC0,
.irq = TC0_IRQn,
.mclk = &MCLK->APBCMASK.reg,
.mclk_mask = MCLK_APBCMASK_TC0 | MCLK_APBCMASK_TC1,
.gclk_id = TC0_GCLK_ID,
.gclk_src = GCLK_PCHCTRL_GEN(0),
.prescaler = TC_CTRLA_PRESCALER(4),
.flags = TC_CTRLA_MODE_COUNT32,
}
};
/* Timer 0 configuration */ /* Timer 0 configuration */
#define TIMER_0_DEV TC0->COUNT32 #define TIMER_0_CHANNELS 2
#define TIMER_0_CHANNELS 1 #define TIMER_0_ISR isr_tc0
#define TIMER_0_MAX_VALUE (0xffffffff) #define TIMER_NUMOF (sizeof(timer_config)/sizeof(timer_config[0]))
#define TIMER_0_ISR isr_tc0
/** @} */ /** @} */
/** /**

View File

@ -78,21 +78,44 @@ extern "C" {
* @name Timer peripheral configuration * @name Timer peripheral configuration
* @{ * @{
*/ */
#define TIMER_NUMOF (2U) static const tc32_conf_t timer_config[] = {
#define TIMER_0_EN 1 { /* Timer 0 - System Clock */
#define TIMER_1_EN 1 .dev = TC3,
.irq = TC3_IRQn,
.pm_mask = PM_APBCMASK_TC3,
.gclk_ctrl = GCLK_CLKCTRL_ID_TCC2_TC3,
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
.gclk_src = GCLK_CLKCTRL_GEN(1),
.prescaler = TC_CTRLA_PRESCALER_DIV1,
#else
.gclk_src = GCLK_CLKCTRL_GEN(0),
.prescaler = TC_CTRLA_PRESCALER_DIV8,
#endif
.flags = TC_CTRLA_MODE_COUNT16,
},
{ /* Timer 1 */
.dev = TC4,
.irq = TC4_IRQn,
.pm_mask = PM_APBCMASK_TC4 | PM_APBCMASK_TC5,
.gclk_ctrl = GCLK_CLKCTRL_ID_TC4_TC5,
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
.gclk_src = GCLK_CLKCTRL_GEN(1),
.prescaler = TC_CTRLA_PRESCALER_DIV1,
#else
.gclk_src = GCLK_CLKCTRL_GEN(0),
.prescaler = TC_CTRLA_PRESCALER_DIV8,
#endif
.flags = TC_CTRLA_MODE_COUNT32,
}
};
/* Timer 0 configuration */ #define TIMER_0_MAX_VALUE 0xffff
#define TIMER_0_DEV TC3->COUNT16
#define TIMER_0_CHANNELS 2 /* interrupt function name mapping */
#define TIMER_0_MAX_VALUE (0xffff)
#define TIMER_0_ISR isr_tc3 #define TIMER_0_ISR isr_tc3
/* Timer 1 configuration */
#define TIMER_1_DEV TC4->COUNT32
#define TIMER_1_CHANNELS 2
#define TIMER_1_MAX_VALUE (0xffffffff)
#define TIMER_1_ISR isr_tc4 #define TIMER_1_ISR isr_tc4
#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
/** @} */ /** @} */
/** /**

View File

@ -113,21 +113,44 @@ extern "C" {
* @name Timer peripheral configuration * @name Timer peripheral configuration
* @{ * @{
*/ */
#define TIMER_NUMOF (2U) static const tc32_conf_t timer_config[] = {
#define TIMER_0_EN 1 { /* Timer 0 - System Clock */
#define TIMER_1_EN 1 .dev = TC3,
.irq = TC3_IRQn,
.pm_mask = PM_APBCMASK_TC3,
.gclk_ctrl = GCLK_CLKCTRL_ID_TCC2_TC3,
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
.gclk_src = GCLK_CLKCTRL_GEN(1),
.prescaler = TC_CTRLA_PRESCALER_DIV1,
#else
.gclk_src = GCLK_CLKCTRL_GEN(0),
.prescaler = TC_CTRLA_PRESCALER_DIV8,
#endif
.flags = TC_CTRLA_MODE_COUNT16,
},
{ /* Timer 1 */
.dev = TC4,
.irq = TC4_IRQn,
.pm_mask = PM_APBCMASK_TC4 | PM_APBCMASK_TC5,
.gclk_ctrl = GCLK_CLKCTRL_ID_TC4_TC5,
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
.gclk_src = GCLK_CLKCTRL_GEN(1),
.prescaler = TC_CTRLA_PRESCALER_DIV1,
#else
.gclk_src = GCLK_CLKCTRL_GEN(0),
.prescaler = TC_CTRLA_PRESCALER_DIV8,
#endif
.flags = TC_CTRLA_MODE_COUNT32,
}
};
/* Timer 0 configuration */ #define TIMER_0_MAX_VALUE 0xffff
#define TIMER_0_DEV TC3->COUNT16
#define TIMER_0_CHANNELS 2 /* interrupt function name mapping */
#define TIMER_0_MAX_VALUE (0xffff)
#define TIMER_0_ISR isr_tc3 #define TIMER_0_ISR isr_tc3
/* Timer 1 configuration */
#define TIMER_1_DEV TC4->COUNT32
#define TIMER_1_CHANNELS 2
#define TIMER_1_MAX_VALUE (0xffffffff)
#define TIMER_1_ISR isr_tc4 #define TIMER_1_ISR isr_tc4
#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
/** @} */ /** @} */
/** /**

View File

@ -32,7 +32,7 @@ extern "C" {
#endif #endif
/** /**
* @name xtimer configuration * @name xtimer configuration
* @{ * @{
*/ */
#define XTIMER_DEV TIMER_DEV(1) #define XTIMER_DEV TIMER_DEV(1)

View File

@ -89,21 +89,44 @@ extern "C" {
* @name Timer peripheral configuration * @name Timer peripheral configuration
* @{ * @{
*/ */
#define TIMER_NUMOF (2U) static const tc32_conf_t timer_config[] = {
#define TIMER_0_EN 1 { /* Timer 0 - System Clock */
#define TIMER_1_EN 1 .dev = TC3,
.irq = TC3_IRQn,
.pm_mask = PM_APBCMASK_TC3,
.gclk_ctrl = GCLK_CLKCTRL_ID_TCC2_TC3,
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
.gclk_src = GCLK_CLKCTRL_GEN(1),
.prescaler = TC_CTRLA_PRESCALER_DIV1,
#else
.gclk_src = GCLK_CLKCTRL_GEN(0),
.prescaler = TC_CTRLA_PRESCALER_DIV8,
#endif
.flags = TC_CTRLA_MODE_COUNT16,
},
{ /* Timer 1 */
.dev = TC4,
.irq = TC4_IRQn,
.pm_mask = PM_APBCMASK_TC4 | PM_APBCMASK_TC5,
.gclk_ctrl = GCLK_CLKCTRL_ID_TC4_TC5,
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
.gclk_src = GCLK_CLKCTRL_GEN(1),
.prescaler = TC_CTRLA_PRESCALER_DIV1,
#else
.gclk_src = GCLK_CLKCTRL_GEN(0),
.prescaler = TC_CTRLA_PRESCALER_DIV8,
#endif
.flags = TC_CTRLA_MODE_COUNT32,
}
};
/* Timer 0 configuration */ #define TIMER_0_MAX_VALUE 0xffff
#define TIMER_0_DEV TC3->COUNT16
#define TIMER_0_CHANNELS 2 /* interrupt function name mapping */
#define TIMER_0_MAX_VALUE (0xffff)
#define TIMER_0_ISR isr_tc3 #define TIMER_0_ISR isr_tc3
/* Timer 1 configuration */
#define TIMER_1_DEV TC4->COUNT32
#define TIMER_1_CHANNELS 2
#define TIMER_1_MAX_VALUE (0xffffffff)
#define TIMER_1_ISR isr_tc4 #define TIMER_1_ISR isr_tc4
#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
/** @} */ /** @} */
/** /**

View File

@ -38,14 +38,23 @@ extern "C" {
* @name Timer peripheral configuration * @name Timer peripheral configuration
* @{ * @{
*/ */
#define TIMER_NUMOF (1U) static const tc32_conf_t timer_config[] = {
#define TIMER_0_EN 1 { /* Timer 0 - System Clock */
.dev = TC0,
.irq = TC0_IRQn,
.mclk = &MCLK->APBCMASK.reg,
.mclk_mask = MCLK_APBCMASK_TC0 | MCLK_APBCMASK_TC1,
.gclk_id = TC0_GCLK_ID,
.gclk_src = GCLK_PCHCTRL_GEN(0),
.prescaler = TC_CTRLA_PRESCALER(4),
.flags = TC_CTRLA_MODE_COUNT32,
}
};
/* Timer 0 configuration */ /* Timer 0 configuration */
#define TIMER_0_DEV TC0->COUNT32 #define TIMER_0_CHANNELS 2
#define TIMER_0_CHANNELS 1 #define TIMER_0_ISR isr_tc0
#define TIMER_0_MAX_VALUE (0xffffffff) #define TIMER_NUMOF (sizeof(timer_config)/sizeof(timer_config[0]))
#define TIMER_0_ISR isr_tc0
/** @} */ /** @} */
/** /**

View File

@ -89,21 +89,44 @@ extern "C" {
* @name Timer peripheral configuration * @name Timer peripheral configuration
* @{ * @{
*/ */
#define TIMER_NUMOF (2U) static const tc32_conf_t timer_config[] = {
#define TIMER_0_EN 1 { /* Timer 0 - System Clock */
#define TIMER_1_EN 1 .dev = TC3,
.irq = TC3_IRQn,
.pm_mask = PM_APBCMASK_TC3,
.gclk_ctrl = GCLK_CLKCTRL_ID_TCC2_TC3,
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
.gclk_src = GCLK_CLKCTRL_GEN(1),
.prescaler = TC_CTRLA_PRESCALER_DIV1,
#else
.gclk_src = GCLK_CLKCTRL_GEN(0),
.prescaler = TC_CTRLA_PRESCALER_DIV8,
#endif
.flags = TC_CTRLA_MODE_COUNT16,
},
{ /* Timer 1 */
.dev = TC4,
.irq = TC4_IRQn,
.pm_mask = PM_APBCMASK_TC4 | PM_APBCMASK_TC5,
.gclk_ctrl = GCLK_CLKCTRL_ID_TC4_TC5,
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
.gclk_src = GCLK_CLKCTRL_GEN(1),
.prescaler = TC_CTRLA_PRESCALER_DIV1,
#else
.gclk_src = GCLK_CLKCTRL_GEN(0),
.prescaler = TC_CTRLA_PRESCALER_DIV8,
#endif
.flags = TC_CTRLA_MODE_COUNT32,
}
};
/* Timer 0 configuration */ #define TIMER_0_MAX_VALUE 0xffff
#define TIMER_0_DEV TC3->COUNT16
#define TIMER_0_CHANNELS 2 /* interrupt function name mapping */
#define TIMER_0_MAX_VALUE (0xffff)
#define TIMER_0_ISR isr_tc3 #define TIMER_0_ISR isr_tc3
/* Timer 1 configuration */
#define TIMER_1_DEV TC4->COUNT32
#define TIMER_1_CHANNELS 2
#define TIMER_1_MAX_VALUE (0xffffffff)
#define TIMER_1_ISR isr_tc4 #define TIMER_1_ISR isr_tc4
#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
/** @} */ /** @} */
/** /**

View File

@ -34,14 +34,23 @@ extern "C" {
* @name Timer peripheral configuration * @name Timer peripheral configuration
* @{ * @{
*/ */
#define TIMER_NUMOF (1U) static const tc32_conf_t timer_config[] = {
#define TIMER_0_EN 1 { /* Timer 0 - System Clock */
.dev = TC0,
.irq = TC0_IRQn,
.mclk = &MCLK->APBCMASK.reg,
.mclk_mask = MCLK_APBCMASK_TC0 | MCLK_APBCMASK_TC1,
.gclk_id = TC0_GCLK_ID,
.gclk_src = GCLK_PCHCTRL_GEN(0),
.prescaler = TC_CTRLA_PRESCALER(4),
.flags = TC_CTRLA_MODE_COUNT32,
}
};
/* Timer 0 configuration */ /* Timer 0 configuration */
#define TIMER_0_DEV TC0->COUNT32 #define TIMER_0_CHANNELS 2
#define TIMER_0_CHANNELS 1 #define TIMER_0_ISR isr_tc0
#define TIMER_0_MAX_VALUE (0xffffffff) #define TIMER_NUMOF (sizeof(timer_config)/sizeof(timer_config[0]))
#define TIMER_0_ISR isr_tc0
/** @} */ /** @} */
/** /**

View File

@ -79,21 +79,44 @@ extern "C" {
* @name Timer peripheral configuration * @name Timer peripheral configuration
* @{ * @{
*/ */
#define TIMER_NUMOF (2U) static const tc32_conf_t timer_config[] = {
#define TIMER_0_EN 1 { /* Timer 0 - System Clock */
#define TIMER_1_EN 1 .dev = TC3,
.irq = TC3_IRQn,
.pm_mask = PM_APBCMASK_TC3,
.gclk_ctrl = GCLK_CLKCTRL_ID_TCC2_TC3,
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
.gclk_src = GCLK_CLKCTRL_GEN(1),
.prescaler = TC_CTRLA_PRESCALER_DIV1,
#else
.gclk_src = GCLK_CLKCTRL_GEN(0),
.prescaler = TC_CTRLA_PRESCALER_DIV8,
#endif
.flags = TC_CTRLA_MODE_COUNT16,
},
{ /* Timer 1 */
.dev = TC4,
.irq = TC4_IRQn,
.pm_mask = PM_APBCMASK_TC4 | PM_APBCMASK_TC5,
.gclk_ctrl = GCLK_CLKCTRL_ID_TC4_TC5,
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
.gclk_src = GCLK_CLKCTRL_GEN(1),
.prescaler = TC_CTRLA_PRESCALER_DIV1,
#else
.gclk_src = GCLK_CLKCTRL_GEN(0),
.prescaler = TC_CTRLA_PRESCALER_DIV8,
#endif
.flags = TC_CTRLA_MODE_COUNT32,
}
};
/* Timer 0 configuration */ #define TIMER_0_MAX_VALUE 0xffff
#define TIMER_0_DEV TC3->COUNT16
#define TIMER_0_CHANNELS 2 /* interrupt function name mapping */
#define TIMER_0_MAX_VALUE (0xffff)
#define TIMER_0_ISR isr_tc3 #define TIMER_0_ISR isr_tc3
/* Timer 1 configuration */
#define TIMER_1_DEV TC4->COUNT32
#define TIMER_1_CHANNELS 2
#define TIMER_1_MAX_VALUE (0xffffffff)
#define TIMER_1_ISR isr_tc4 #define TIMER_1_ISR isr_tc4
#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
/** @} */ /** @} */
/** /**

View File

@ -79,21 +79,44 @@ extern "C" {
* @name Timer peripheral configuration * @name Timer peripheral configuration
* @{ * @{
*/ */
#define TIMER_NUMOF (2U) static const tc32_conf_t timer_config[] = {
#define TIMER_0_EN 1 { /* Timer 0 - System Clock */
#define TIMER_1_EN 1 .dev = TC3,
.irq = TC3_IRQn,
.pm_mask = PM_APBCMASK_TC3,
.gclk_ctrl = GCLK_CLKCTRL_ID_TCC2_TC3,
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
.gclk_src = GCLK_CLKCTRL_GEN(1),
.prescaler = TC_CTRLA_PRESCALER_DIV1,
#else
.gclk_src = GCLK_CLKCTRL_GEN(0),
.prescaler = TC_CTRLA_PRESCALER_DIV8,
#endif
.flags = TC_CTRLA_MODE_COUNT16,
},
{ /* Timer 1 */
.dev = TC4,
.irq = TC4_IRQn,
.pm_mask = PM_APBCMASK_TC4 | PM_APBCMASK_TC5,
.gclk_ctrl = GCLK_CLKCTRL_ID_TC4_TC5,
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
.gclk_src = GCLK_CLKCTRL_GEN(1),
.prescaler = TC_CTRLA_PRESCALER_DIV1,
#else
.gclk_src = GCLK_CLKCTRL_GEN(0),
.prescaler = TC_CTRLA_PRESCALER_DIV8,
#endif
.flags = TC_CTRLA_MODE_COUNT32,
}
};
/* Timer 0 configuration */ #define TIMER_0_MAX_VALUE 0xffff
#define TIMER_0_DEV TC3->COUNT16
#define TIMER_0_CHANNELS 2 /* interrupt function name mapping */
#define TIMER_0_MAX_VALUE (0xffff)
#define TIMER_0_ISR isr_tc3 #define TIMER_0_ISR isr_tc3
/* Timer 1 configuration */
#define TIMER_1_DEV TC4->COUNT32
#define TIMER_1_CHANNELS 2
#define TIMER_1_MAX_VALUE (0xffffffff)
#define TIMER_1_ISR isr_tc4 #define TIMER_1_ISR isr_tc4
#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
/** @} */ /** @} */
/** /**

View File

@ -26,13 +26,6 @@
extern "C" { extern "C" {
#endif #endif
/**
* @name xtimer configuration
* @{
*/
#define XTIMER_WIDTH (16)
/** @} */
/** /**
* @name LED pin definitions and handlers * @name LED pin definitions and handlers
* @{ * @{

View File

@ -76,21 +76,44 @@ extern "C" {
* @name Timer peripheral configuration * @name Timer peripheral configuration
* @{ * @{
*/ */
#define TIMER_NUMOF (2U) static const tc32_conf_t timer_config[] = {
#define TIMER_0_EN 1 { /* Timer 0 - System Clock */
#define TIMER_1_EN 1 .dev = TC3,
.irq = TC3_IRQn,
.pm_mask = PM_APBCMASK_TC3,
.gclk_ctrl = GCLK_CLKCTRL_ID_TCC2_TC3,
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
.gclk_src = GCLK_CLKCTRL_GEN(1),
.prescaler = TC_CTRLA_PRESCALER_DIV1,
#else
.gclk_src = GCLK_CLKCTRL_GEN(0),
.prescaler = TC_CTRLA_PRESCALER_DIV8,
#endif
.flags = TC_CTRLA_MODE_COUNT16,
},
{ /* Timer 1 */
.dev = TC4,
.irq = TC4_IRQn,
.pm_mask = PM_APBCMASK_TC4 | PM_APBCMASK_TC5,
.gclk_ctrl = GCLK_CLKCTRL_ID_TC4_TC5,
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
.gclk_src = GCLK_CLKCTRL_GEN(1),
.prescaler = TC_CTRLA_PRESCALER_DIV1,
#else
.gclk_src = GCLK_CLKCTRL_GEN(0),
.prescaler = TC_CTRLA_PRESCALER_DIV8,
#endif
.flags = TC_CTRLA_MODE_COUNT32,
}
};
/* Timer 0 configuration */ #define TIMER_0_MAX_VALUE 0xffff
#define TIMER_0_DEV TC3->COUNT16
#define TIMER_0_CHANNELS 2 /* interrupt function name mapping */
#define TIMER_0_MAX_VALUE (0xffff)
#define TIMER_0_ISR isr_tc3 #define TIMER_0_ISR isr_tc3
/* Timer 1 configuration */
#define TIMER_1_DEV TC4->COUNT32
#define TIMER_1_CHANNELS 2
#define TIMER_1_MAX_VALUE (0xffffffff)
#define TIMER_1_ISR isr_tc4 #define TIMER_1_ISR isr_tc4
#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
/** @} */ /** @} */
/** /**

View File

@ -79,21 +79,44 @@ extern "C" {
* @name Timer peripheral configuration * @name Timer peripheral configuration
* @{ * @{
*/ */
#define TIMER_NUMOF (2U) static const tc32_conf_t timer_config[] = {
#define TIMER_0_EN 1 { /* Timer 0 - System Clock */
#define TIMER_1_EN 1 .dev = TC3,
.irq = TC3_IRQn,
.pm_mask = PM_APBCMASK_TC3,
.gclk_ctrl = GCLK_CLKCTRL_ID_TCC2_TC3,
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
.gclk_src = GCLK_CLKCTRL_GEN(1),
.prescaler = TC_CTRLA_PRESCALER_DIV1,
#else
.gclk_src = GCLK_CLKCTRL_GEN(0),
.prescaler = TC_CTRLA_PRESCALER_DIV8,
#endif
.flags = TC_CTRLA_MODE_COUNT16,
},
{ /* Timer 1 */
.dev = TC4,
.irq = TC4_IRQn,
.pm_mask = PM_APBCMASK_TC4 | PM_APBCMASK_TC5,
.gclk_ctrl = GCLK_CLKCTRL_ID_TC4_TC5,
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
.gclk_src = GCLK_CLKCTRL_GEN(1),
.prescaler = TC_CTRLA_PRESCALER_DIV1,
#else
.gclk_src = GCLK_CLKCTRL_GEN(0),
.prescaler = TC_CTRLA_PRESCALER_DIV8,
#endif
.flags = TC_CTRLA_MODE_COUNT32,
}
};
/* Timer 0 configuration */ #define TIMER_0_MAX_VALUE 0xffff
#define TIMER_0_DEV TC3->COUNT16
#define TIMER_0_CHANNELS 2 /* interrupt function name mapping */
#define TIMER_0_MAX_VALUE (0xffff)
#define TIMER_0_ISR isr_tc3 #define TIMER_0_ISR isr_tc3
/* Timer 1 configuration */
#define TIMER_1_DEV TC4->COUNT32
#define TIMER_1_CHANNELS 2
#define TIMER_1_MAX_VALUE (0xffffffff)
#define TIMER_1_ISR isr_tc4 #define TIMER_1_ISR isr_tc4
#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
/** @} */ /** @} */
/** /**

View File

@ -81,21 +81,44 @@ extern "C" {
* @name Timer peripheral configuration * @name Timer peripheral configuration
* @{ * @{
*/ */
#define TIMER_NUMOF (2U) static const tc32_conf_t timer_config[] = {
#define TIMER_0_EN 1 { /* Timer 0 - System Clock */
#define TIMER_1_EN 1 .dev = TC3,
.irq = TC3_IRQn,
.pm_mask = PM_APBCMASK_TC3,
.gclk_ctrl = GCLK_CLKCTRL_ID_TCC2_TC3,
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
.gclk_src = GCLK_CLKCTRL_GEN(1),
.prescaler = TC_CTRLA_PRESCALER_DIV1,
#else
.gclk_src = GCLK_CLKCTRL_GEN(0),
.prescaler = TC_CTRLA_PRESCALER_DIV8,
#endif
.flags = TC_CTRLA_MODE_COUNT16,
},
{ /* Timer 1 */
.dev = TC4,
.irq = TC4_IRQn,
.pm_mask = PM_APBCMASK_TC4 | PM_APBCMASK_TC5,
.gclk_ctrl = GCLK_CLKCTRL_ID_TC4_TC5,
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
.gclk_src = GCLK_CLKCTRL_GEN(1),
.prescaler = TC_CTRLA_PRESCALER_DIV1,
#else
.gclk_src = GCLK_CLKCTRL_GEN(0),
.prescaler = TC_CTRLA_PRESCALER_DIV8,
#endif
.flags = TC_CTRLA_MODE_COUNT32,
}
};
/* Timer 0 configuration */ #define TIMER_0_MAX_VALUE 0xffff
#define TIMER_0_DEV TC3->COUNT16
#define TIMER_0_CHANNELS 2 /* interrupt function name mapping */
#define TIMER_0_MAX_VALUE (0xffff)
#define TIMER_0_ISR isr_tc3 #define TIMER_0_ISR isr_tc3
/* Timer 1 configuration */
#define TIMER_1_DEV TC4->COUNT32
#define TIMER_1_CHANNELS 2
#define TIMER_1_MAX_VALUE (0xffffffff)
#define TIMER_1_ISR isr_tc4 #define TIMER_1_ISR isr_tc4
#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
/** @} */ /** @} */
/** /**

View File

@ -289,6 +289,25 @@ typedef struct {
uint8_t flags; /**< allow SERCOM to run in standby mode */ uint8_t flags; /**< allow SERCOM to run in standby mode */
} i2c_conf_t; } i2c_conf_t;
/**
* @brief Timer device configuration
*/
typedef struct {
Tc *dev; /**< pointer to the used Timer device */
IRQn_Type irq; /**< IRQ# of Timer Interrupt */
#ifdef MCLK
volatile uint32_t *mclk;/**< Pointer to MCLK->APBxMASK.reg */
uint32_t mclk_mask; /**< MCLK_APBxMASK bits to enable Timer */
uint16_t gclk_id; /**< TCn_GCLK_ID */
#else
uint32_t pm_mask; /**< PM_APBCMASK bits to enable Timer */
uint16_t gclk_ctrl; /**< GCLK_CLKCTRL_ID for the Timer */
#endif
uint16_t gclk_src; /**< GCLK source which supplys Timer */
uint16_t prescaler; /**< prescaler used by the Timer */
uint16_t flags; /**< flags for CTRA, e.g. TC_CTRLA_MODE_COUNT32 */
} tc32_conf_t;
/** /**
* @brief Set up alternate function (PMUX setting) for a PORT pin * @brief Set up alternate function (PMUX setting) for a PORT pin
* *

View File

@ -0,0 +1,269 @@
/*
* Copyright (C) 2019 ML!PA Consulting GmbH
*
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_sam0_common
* @ingroup drivers_periph_timer
* @{
*
* @file timer.c
* @brief Low-level timer driver implementation
*
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
*
* @}
*/
#include <stdlib.h>
#include <stdio.h>
#include "board.h"
#include "cpu.h"
#include "periph/timer.h"
#include "periph_conf.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
/**
* @brief Timer state memory
*/
static timer_isr_ctx_t config[TIMER_NUMOF];
static inline TcCount32 *dev(tim_t tim)
{
return &timer_config[tim].dev->COUNT32;
}
static inline TcCount16 *dev16(tim_t tim)
{
return &timer_config[tim].dev->COUNT16;
}
static inline TcCount8 *dev8(tim_t tim)
{
return &timer_config[tim].dev->COUNT8;
}
static inline void wait_synchronization(tim_t tim)
{
#if defined(TC_SYNCBUSY_MASK)
/* SYNCBUSY is a register */
while ((dev(tim)->SYNCBUSY.reg & TC_SYNCBUSY_MASK) != 0) {}
#elif defined(TC_STATUS_SYNCBUSY)
/* SYNCBUSY is a bit */
while ((dev(tim)->STATUS.reg & TC_STATUS_SYNCBUSY) != 0) {}
#else
#error Unsupported device
#endif
}
/* enable timer interrupts */
static inline void _irq_enable(tim_t tim)
{
NVIC_EnableIRQ(timer_config[tim].irq);
}
/**
* @brief Setup the given timer
*/
int timer_init(tim_t tim, unsigned long freq, timer_cb_t cb, void *arg)
{
const tc32_conf_t *cfg = &timer_config[tim];
/* make sure given device is valid */
if (tim >= TIMER_NUMOF) {
return -1;
}
/* at the moment, the timer can only run at 1MHz */
if (freq != 1000000ul) {
return -1;
}
/* make sure the timer is not running */
timer_stop(tim);
#ifdef MCLK
GCLK->PCHCTRL[cfg->gclk_id].reg = cfg->gclk_src | GCLK_PCHCTRL_CHEN;
*cfg->mclk |= cfg->mclk_mask;
#else
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | cfg->gclk_src | cfg->gclk_ctrl;
PM->APBCMASK.reg |= cfg->pm_mask;
#endif
/* reset the timer */
dev(tim)->CTRLA.bit.SWRST = 1;
while (dev(tim)->CTRLA.bit.SWRST) {}
dev(tim)->CTRLA.reg = cfg->flags
#ifdef TC_CTRLA_WAVEGEN_NFRQ
| TC_CTRLA_WAVEGEN_NFRQ
#endif
| cfg->prescaler
| TC_CTRLA_PRESCSYNC_RESYNC;
#ifdef TC_WAVE_WAVEGEN_NFRQ
dev(tim)->WAVE.reg = TC_WAVE_WAVEGEN_NFRQ;
#endif
wait_synchronization(tim);
dev(tim)->INTENCLR.reg = TC_INTENCLR_MASK;
/* save callback */
config[tim].cb = cb;
config[tim].arg = arg;
timer_start(tim);
/* enable interrupts for given timer */
_irq_enable(tim);
return 0;
}
static void _set_cc(tim_t tim, int cc, unsigned int value)
{
const uint16_t flags = timer_config[tim].flags;
if (flags & TC_CTRLA_MODE_COUNT32) {
dev(tim)->CC[cc].reg = value;
return;
}
if (flags & TC_CTRLA_MODE_COUNT8) {
dev8(tim)->CC[cc].reg = value;
return;
}
/* 16 bit is the default */
dev16(tim)->CC[cc].reg = value;
}
int timer_set_absolute(tim_t tim, int channel, unsigned int value)
{
DEBUG("Setting timer %i channel %i to %i\n", tim, channel, value);
/* set timeout value */
switch (channel) {
case 0:
dev(tim)->INTFLAG.reg = TC_INTFLAG_MC0;
_set_cc(tim, 0, value);
dev(tim)->INTENSET.bit.MC0 = 1;
break;
case 1:
dev(tim)->INTFLAG.reg = TC_INTFLAG_MC1;
_set_cc(tim, 1, value);
dev(tim)->INTENSET.bit.MC1 = 1;
break;
default:
return -1;
}
return 1;
}
int timer_clear(tim_t tim, int channel)
{
switch (channel) {
case 0:
dev(tim)->INTFLAG.reg = TC_INTFLAG_MC0;
dev(tim)->INTENCLR.bit.MC0 = 1;
break;
case 1:
dev(tim)->INTFLAG.reg = TC_INTFLAG_MC1;
dev(tim)->INTENCLR.bit.MC1 = 1;
break;
default:
return -1;
}
return 1;
}
unsigned int timer_read(tim_t tim)
{
/* WORKAROUND to prevent being stuck there if timer not init */
if (!dev(tim)->CTRLA.bit.ENABLE) {
return 0;
}
/* request syncronisation */
#ifdef TC_CTRLBSET_CMD_READSYNC_Val
dev(tim)->CTRLBSET.bit.CMD = TC_CTRLBSET_CMD_READSYNC_Val;
#else
dev(tim)->READREQ.reg = TC_READREQ_RREQ | TC_READREQ_ADDR(0x10);
#endif
wait_synchronization(tim);
return dev(tim)->COUNT.reg;
}
void timer_stop(tim_t tim)
{
dev(tim)->CTRLA.bit.ENABLE = 0;
}
void timer_start(tim_t tim)
{
dev(tim)->CTRLA.bit.ENABLE = 1;
}
static inline void timer_isr(tim_t tim)
{
TcCount32 *tc = dev(tim);
uint8_t status = tc->INTFLAG.reg;
/* Acknowledge all interrupts */
tc->INTFLAG.reg = status;
if ((status & TC_INTFLAG_MC0) && tc->INTENSET.bit.MC0) {
tc->INTENCLR.reg = TC_INTENCLR_MC0;
if (config[tim].cb) {
config[tim].cb(config[tim].arg, 0);
}
}
if ((status & TC_INTFLAG_MC1) && tc->INTENSET.bit.MC1) {
tc->INTENCLR.reg = TC_INTENCLR_MC1;
if (config[tim].cb) {
config[tim].cb(config[tim].arg, 1);
}
}
}
#ifdef TIMER_0_ISR
void TIMER_0_ISR(void)
{
timer_isr(0);
cortexm_isr_end();
}
#endif
#ifdef TIMER_1_ISR
void TIMER_1_ISR(void)
{
timer_isr(1);
cortexm_isr_end();
}
#endif
#ifdef TIMER_2_ISR
void TIMER_2_ISR(void)
{
timer_isr(2);
cortexm_isr_end();
}
#endif
#ifdef TIMER_3_ISR
void TIMER_3_ISR(void)
{
timer_isr(3);
cortexm_isr_end();
}
#endif

View File

@ -1,351 +0,0 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_samd21
* @ingroup drivers_periph_timer
* @{
*
* @file
* @brief Low-level timer driver implementation
*
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de>
*
* @}
*/
#include <stdlib.h>
#include <stdio.h>
#include "board.h"
#include "cpu.h"
#include "periph/timer.h"
#include "periph_conf.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
/**
* @brief Timer state memory
*/
static timer_isr_ctx_t config[TIMER_NUMOF];
/* enable timer interrupts */
static inline void _irq_enable(tim_t dev);
/**
* @brief Setup the given timer
*/
int timer_init(tim_t dev, unsigned long freq, timer_cb_t cb, void *arg)
{
/* at the moment, the timer can only run at 1MHz */
if (freq != 1000000ul) {
return -1;
}
/* select the clock generator depending on the main clock source:
* GCLK0 (1MHz) if we use the internal 8MHz oscillator
* GCLK1 (8MHz) if we use the PLL */
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
/* configure GCLK1 (configured to 1MHz) to feed TC3, TC4 and TC5 */;
/* configure GCLK1 to feed TC3, TC4 and TC5 */;
GCLK->CLKCTRL.reg = (uint16_t)((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK1 | (TC3_GCLK_ID << GCLK_CLKCTRL_ID_Pos)));
while (GCLK->STATUS.bit.SYNCBUSY) {}
/* TC4 and TC5 share the same channel */
GCLK->CLKCTRL.reg = (uint16_t)((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK1 | (TC4_GCLK_ID << GCLK_CLKCTRL_ID_Pos)));
#else
/* configure GCLK0 to feed TC3, TC4 and TC5 */;
GCLK->CLKCTRL.reg = (uint16_t)((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | (TC3_GCLK_ID << GCLK_CLKCTRL_ID_Pos)));
/* TC4 and TC5 share the same channel */
GCLK->CLKCTRL.reg = (uint16_t)((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | (TC4_GCLK_ID << GCLK_CLKCTRL_ID_Pos)));
#endif
while (GCLK->STATUS.bit.SYNCBUSY) {}
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
if (TIMER_0_DEV.CTRLA.bit.ENABLE) {
return 0;
}
PM->APBCMASK.reg |= PM_APBCMASK_TC3;
/* reset timer */
TIMER_0_DEV.CTRLA.bit.SWRST = 1;
while (TIMER_0_DEV.CTRLA.bit.SWRST) {}
/* choosing 16 bit mode */
TIMER_0_DEV.CTRLA.bit.MODE = TC_CTRLA_MODE_COUNT16_Val;
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
/* PLL/DFLL: sourced by 1MHz and prescaler 1 to reach 1MHz */
TIMER_0_DEV.CTRLA.bit.PRESCALER = TC_CTRLA_PRESCALER_DIV1_Val;
#else
/* sourced by 8MHz with Presc 8 results in 1MHz clk */
TIMER_0_DEV.CTRLA.bit.PRESCALER = TC_CTRLA_PRESCALER_DIV8_Val;
#endif
/* choose normal frequency operation */
TIMER_0_DEV.CTRLA.bit.WAVEGEN = TC_CTRLA_WAVEGEN_NFRQ_Val;
break;
#endif
#if TIMER_1_EN
case TIMER_1:
if (TIMER_1_DEV.CTRLA.bit.ENABLE) {
return 0;
}
PM->APBCMASK.reg |= PM_APBCMASK_TC4;
/* reset timer */
TIMER_1_DEV.CTRLA.bit.SWRST = 1;
while (TIMER_1_DEV.CTRLA.bit.SWRST) {}
TIMER_1_DEV.CTRLA.bit.MODE = TC_CTRLA_MODE_COUNT32_Val;
#if CLOCK_USE_PLL || CLOCK_USE_XOSC32_DFLL
/* PLL/DFLL: sourced by 1MHz and prescaler 1 to reach 1MHz */
TIMER_1_DEV.CTRLA.bit.PRESCALER = TC_CTRLA_PRESCALER_DIV1_Val;
#else
/* sourced by 8MHz with Presc 8 results in 1Mhz clk */
TIMER_1_DEV.CTRLA.bit.PRESCALER = TC_CTRLA_PRESCALER_DIV8_Val;
#endif
/* choose normal frequency operation */
TIMER_1_DEV.CTRLA.bit.WAVEGEN = TC_CTRLA_WAVEGEN_NFRQ_Val;
break;
#endif
case TIMER_UNDEFINED:
default:
return -1;
}
/* save callback */
config[dev].cb = cb;
config[dev].arg = arg;
/* enable interrupts for given timer */
_irq_enable(dev);
timer_start(dev);
return 0;
}
int timer_set_absolute(tim_t dev, int channel, unsigned int value)
{
DEBUG("Setting timer %i channel %i to %i\n", dev, channel, value);
/* get timer base register address */
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
/* set timeout value */
switch (channel) {
case 0:
TIMER_0_DEV.INTFLAG.reg = TC_INTFLAG_MC0;
TIMER_0_DEV.CC[0].reg = value;
TIMER_0_DEV.INTENSET.reg = TC_INTENSET_MC0;
break;
case 1:
TIMER_0_DEV.INTFLAG.reg = TC_INTFLAG_MC1;
TIMER_0_DEV.CC[1].reg = value;
TIMER_0_DEV.INTENSET.reg = TC_INTENSET_MC1;
break;
default:
return -1;
}
break;
#endif
#if TIMER_1_EN
case TIMER_1:
/* set timeout value */
switch (channel) {
case 0:
TIMER_1_DEV.INTFLAG.reg = TC_INTFLAG_MC0;
TIMER_1_DEV.CC[0].reg = value;
TIMER_1_DEV.INTENSET.reg = TC_INTENSET_MC0;
break;
case 1:
TIMER_1_DEV.INTFLAG.reg = TC_INTFLAG_MC1;
TIMER_1_DEV.CC[1].reg = value;
TIMER_1_DEV.INTENSET.reg = TC_INTENSET_MC1;
break;
default:
return -1;
}
break;
#endif
case TIMER_UNDEFINED:
default:
return -1;
}
return 1;
}
int timer_clear(tim_t dev, int channel)
{
/* get timer base register address */
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
switch (channel) {
case 0:
TIMER_0_DEV.INTFLAG.reg = TC_INTFLAG_MC0;
TIMER_0_DEV.INTENCLR.reg = TC_INTENCLR_MC0;
break;
case 1:
TIMER_0_DEV.INTFLAG.reg = TC_INTFLAG_MC1;
TIMER_0_DEV.INTENCLR.reg = TC_INTENCLR_MC1;
break;
default:
return -1;
}
break;
#endif
#if TIMER_1_EN
case TIMER_1:
switch (channel) {
case 0:
TIMER_1_DEV.INTFLAG.reg = TC_INTFLAG_MC0;
TIMER_1_DEV.INTENCLR.reg = TC_INTENCLR_MC0;
break;
case 1:
TIMER_1_DEV.INTFLAG.reg = TC_INTFLAG_MC1;
TIMER_1_DEV.INTENCLR.reg = TC_INTENCLR_MC1;
break;
default:
return -1;
}
break;
#endif
case TIMER_UNDEFINED:
default:
return -1;
}
return 1;
}
unsigned int timer_read(tim_t dev)
{
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
/* request syncronisation */
TIMER_0_DEV.READREQ.reg = TC_READREQ_RREQ | TC_READREQ_ADDR(0x10);
while (TIMER_0_DEV.STATUS.bit.SYNCBUSY) {}
return TIMER_0_DEV.COUNT.reg;
#endif
#if TIMER_1_EN
case TIMER_1:
/* request syncronisation */
TIMER_1_DEV.READREQ.reg = TC_READREQ_RREQ | TC_READREQ_ADDR(0x10);
while (TIMER_1_DEV.STATUS.bit.SYNCBUSY) {}
return TIMER_1_DEV.COUNT.reg;
#endif
default:
return 0;
}
}
void timer_stop(tim_t dev)
{
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
TIMER_0_DEV.CTRLA.bit.ENABLE = 0;
break;
#endif
#if TIMER_1_EN
case TIMER_1:
TIMER_1_DEV.CTRLA.bit.ENABLE = 0;
break;
#endif
case TIMER_UNDEFINED:
break;
}
}
void timer_start(tim_t dev)
{
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
TIMER_0_DEV.CTRLA.bit.ENABLE = 1;
break;
#endif
#if TIMER_1_EN
case TIMER_1:
TIMER_1_DEV.CTRLA.bit.ENABLE = 1;
break;
#endif
case TIMER_UNDEFINED:
break;
}
}
static inline void _irq_enable(tim_t dev)
{
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
NVIC_EnableIRQ(TC3_IRQn);
break;
#endif
#if TIMER_1_EN
case TIMER_1:
NVIC_EnableIRQ(TC4_IRQn);
break;
#endif
case TIMER_UNDEFINED:
break;
}
}
#if TIMER_0_EN
void TIMER_0_ISR(void)
{
if (TIMER_0_DEV.INTFLAG.bit.MC0 && TIMER_0_DEV.INTENSET.bit.MC0) {
TIMER_0_DEV.INTFLAG.reg = TC_INTFLAG_MC0;
TIMER_0_DEV.INTENCLR.reg = TC_INTENCLR_MC0;
if(config[TIMER_0].cb) {
config[TIMER_0].cb(config[TIMER_0].arg, 0);
}
}
if (TIMER_0_DEV.INTFLAG.bit.MC1 && TIMER_0_DEV.INTENSET.bit.MC1) {
TIMER_0_DEV.INTFLAG.reg = TC_INTFLAG_MC1;
TIMER_0_DEV.INTENCLR.reg = TC_INTENCLR_MC1;
if(config[TIMER_0].cb) {
config[TIMER_0].cb(config[TIMER_0].arg, 1);
}
}
cortexm_isr_end();
}
#endif /* TIMER_0_EN */
#if TIMER_1_EN
void TIMER_1_ISR(void)
{
if (TIMER_1_DEV.INTFLAG.bit.MC0 && TIMER_1_DEV.INTENSET.bit.MC0) {
TIMER_1_DEV.INTFLAG.reg = TC_INTFLAG_MC0;
TIMER_1_DEV.INTENCLR.reg = TC_INTENCLR_MC0;
if (config[TIMER_1].cb) {
config[TIMER_1].cb(config[TIMER_1].arg, 0);
}
}
if (TIMER_1_DEV.INTFLAG.bit.MC1 && TIMER_1_DEV.INTENSET.bit.MC1) {
TIMER_1_DEV.INTFLAG.reg = TC_INTFLAG_MC1;
TIMER_1_DEV.INTENCLR.reg = TC_INTENCLR_MC1;
if(config[TIMER_1].cb) {
config[TIMER_1].cb(config[TIMER_1].arg, 1);
}
}
cortexm_isr_end();
}
#endif /* TIMER_1_EN */

View File

@ -1,231 +0,0 @@
/*
* Copyright (C) 2018 Mesotic SAS
*
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_saml1x
* @ingroup drivers_periph_timer
* @{
*
* @file timer.c
* @brief Low-level timer driver implementation
*
* @author Dylan Laduranty <dylan.laduranty@mesotic.com>
*
* @}
*/
#include <stdlib.h>
#include <stdio.h>
#include "board.h"
#include "cpu.h"
#include "periph/timer.h"
#include "periph_conf.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
/**
* @brief Timer state memory
*/
static timer_isr_ctx_t config[TIMER_NUMOF];
/* enable timer interrupts */
static inline void _irq_enable(tim_t dev);
/**
* @brief Setup the given timer
*/
int timer_init(tim_t dev, unsigned long freq, timer_cb_t cb, void *arg)
{
/* at the moment, the timer can only run at 1MHz */
if (freq != 1000000ul) {
return -1;
}
/* configure GCLK0 to feed TC0 & TC1*/
GCLK->PCHCTRL[TC0_GCLK_ID].reg |= GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK0;
while (!(GCLK->PCHCTRL[TC0_GCLK_ID].reg & GCLK_PCHCTRL_CHEN)) {}
/* select the timer and enable the timer specific peripheral clocks */
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
if (TIMER_0_DEV.CTRLA.bit.ENABLE) {
return 0;
}
MCLK->APBCMASK.reg |= MCLK_APBCMASK_TC0;
/* reset timer */
TIMER_0_DEV.CTRLA.bit.SWRST = 1;
while (TIMER_0_DEV.SYNCBUSY.bit.SWRST) {}
TIMER_0_DEV.CTRLA.reg |= TC_CTRLA_MODE_COUNT32 | /* choosing 32 bit mode */
TC_CTRLA_PRESCALER(4) | /* sourced by 4MHz with Presc 4 results in 1MHz*/
TC_CTRLA_PRESCSYNC_RESYNC; /* initial prescaler resync */
break;
#endif
case TIMER_UNDEFINED:
default:
return -1;
}
/* save callback */
config[dev].cb = cb;
config[dev].arg = arg;
/* enable interrupts for given timer */
_irq_enable(dev);
timer_start(dev);
return 0;
}
int timer_set_absolute(tim_t dev, int channel, unsigned int value)
{
DEBUG("Setting timer %i channel %i to %i\n", dev, channel, value);
/* get timer base register address */
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
/* set timeout value */
switch (channel) {
case 0:
TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC0;
TIMER_0_DEV.CC[0].reg = value;
TIMER_0_DEV.INTENSET.bit.MC0 = 1;
break;
case 1:
TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC1;
TIMER_0_DEV.CC[1].reg = value;
TIMER_0_DEV.INTENSET.bit.MC1 = 1;
break;
default:
return -1;
}
break;
#endif
case TIMER_UNDEFINED:
default:
return -1;
}
return 1;
}
int timer_clear(tim_t dev, int channel)
{
/* get timer base register address */
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
switch (channel) {
case 0:
TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC0;
TIMER_0_DEV.INTENCLR.bit.MC0 = 1;
break;
case 1:
TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC1;
TIMER_0_DEV.INTENCLR.bit.MC1 = 1;
break;
default:
return -1;
}
break;
#endif
case TIMER_UNDEFINED:
default:
return -1;
}
return 1;
}
unsigned int timer_read(tim_t dev)
{
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
/* request syncronisation */
TIMER_0_DEV.CTRLBSET.bit.CMD = TC_CTRLBSET_CMD_READSYNC_Val;
while (TIMER_0_DEV.SYNCBUSY.bit.CTRLB) {
/* WORKAROUND to prevent being stuck there if timer not init */
if(!TIMER_0_DEV.CTRLA.bit.ENABLE) {
return 0;
}
}
return TIMER_0_DEV.COUNT.reg;
#endif
default:
return 0;
}
}
void timer_stop(tim_t dev)
{
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
TIMER_0_DEV.CTRLA.bit.ENABLE = 0;
break;
#endif
case TIMER_UNDEFINED:
break;
}
}
void timer_start(tim_t dev)
{
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
TIMER_0_DEV.CTRLA.bit.ENABLE = 1;
break;
#endif
case TIMER_UNDEFINED:
break;
}
}
static inline void _irq_enable(tim_t dev)
{
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
NVIC_EnableIRQ(TC0_IRQn);
break;
#endif
case TIMER_UNDEFINED:
break;
}
}
#if TIMER_0_EN
void TIMER_0_ISR(void)
{
if (TIMER_0_DEV.INTFLAG.bit.MC0 && TIMER_0_DEV.INTENSET.bit.MC0) {
if(config[TIMER_0].cb) {
TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC0;
TIMER_0_DEV.INTENCLR.reg = TC_INTENCLR_MC0;
config[TIMER_0].cb(config[TIMER_0].arg, 0);
}
}
else if (TIMER_0_DEV.INTFLAG.bit.MC1 && TIMER_0_DEV.INTENSET.bit.MC1) {
if(config[TIMER_0].cb) {
TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC1;
TIMER_0_DEV.INTENCLR.reg = TC_INTENCLR_MC1;
config[TIMER_0].cb(config[TIMER_0].arg, 1);
}
}
cortexm_isr_end();
}
#endif /* TIMER_0_EN */

View File

@ -1,228 +0,0 @@
/*
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
* 2015 FreshTemp, LLC.
* 2014 Freie Universität Berlin
*
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_saml21
* @ingroup drivers_periph_timer
* @{
*
* @file timer.c
* @brief Low-level timer driver implementation
*
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de>
* @author Kaspar Schleiser <kaspar@schleiser.de>
*
* @}
*/
#include <stdlib.h>
#include <stdio.h>
#include "board.h"
#include "cpu.h"
#include "periph/timer.h"
#include "periph_conf.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
/**
* @brief Timer state memory
*/
static timer_isr_ctx_t config[TIMER_NUMOF];
/* enable timer interrupts */
static inline void _irq_enable(tim_t dev);
/**
* @brief Setup the given timer
*/
int timer_init(tim_t dev, unsigned long freq, timer_cb_t cb, void *arg)
{
/* at the moment, the timer can only run at 1MHz */
if (freq != 1000000ul) {
return -1;
}
/* configure GCLK0 to feed TC0 & TC1*/;
GCLK->PCHCTRL[TC0_GCLK_ID].reg |= GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK0;
while (!(GCLK->PCHCTRL[TC0_GCLK_ID].reg & GCLK_PCHCTRL_CHEN)) {}
/* select the timer and enable the timer specific peripheral clocks */
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
if (TIMER_0_DEV.CTRLA.bit.ENABLE) {
return 0;
}
MCLK->APBCMASK.reg |= MCLK_APBCMASK_TC0;
/* reset timer */
TIMER_0_DEV.CTRLA.bit.SWRST = 1;
while (TIMER_0_DEV.SYNCBUSY.bit.SWRST) {}
TIMER_0_DEV.CTRLA.reg |= TC_CTRLA_MODE_COUNT32 | /* choosing 32 bit mode */
TC_CTRLA_PRESCALER(4) | /* sourced by 4MHz with Presc 4 results in 1MHz*/
TC_CTRLA_PRESCSYNC_RESYNC; /* initial prescaler resync */
break;
#endif
case TIMER_UNDEFINED:
default:
return -1;
}
/* save callback */
config[dev].cb = cb;
config[dev].arg = arg;
/* enable interrupts for given timer */
_irq_enable(dev);
timer_start(dev);
return 0;
}
int timer_set_absolute(tim_t dev, int channel, unsigned int value)
{
DEBUG("Setting timer %i channel %i to %i\n", dev, channel, value);
/* get timer base register address */
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
/* set timeout value */
switch (channel) {
case 0:
TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC0;
TIMER_0_DEV.CC[0].reg = value;
TIMER_0_DEV.INTENSET.bit.MC0 = 1;
break;
case 1:
TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC1;
TIMER_0_DEV.CC[1].reg = value;
TIMER_0_DEV.INTENSET.bit.MC1 = 1;
break;
default:
return -1;
}
break;
#endif
case TIMER_UNDEFINED:
default:
return -1;
}
return 1;
}
int timer_clear(tim_t dev, int channel)
{
/* get timer base register address */
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
switch (channel) {
case 0:
TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC0;
TIMER_0_DEV.INTENCLR.bit.MC0 = 1;
break;
case 1:
TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC1;
TIMER_0_DEV.INTENCLR.bit.MC1 = 1;
break;
default:
return -1;
}
break;
#endif
case TIMER_UNDEFINED:
default:
return -1;
}
return 1;
}
unsigned int timer_read(tim_t dev)
{
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
/* request syncronisation */
TIMER_0_DEV.CTRLBSET.bit.CMD = TC_CTRLBSET_CMD_READSYNC_Val;
while (TIMER_0_DEV.SYNCBUSY.bit.STATUS) {}
return TIMER_0_DEV.COUNT.reg;
#endif
default:
return 0;
}
}
void timer_stop(tim_t dev)
{
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
TIMER_0_DEV.CTRLA.bit.ENABLE = 0;
break;
#endif
case TIMER_UNDEFINED:
break;
}
}
void timer_start(tim_t dev)
{
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
TIMER_0_DEV.CTRLA.bit.ENABLE = 1;
break;
#endif
case TIMER_UNDEFINED:
break;
}
}
static inline void _irq_enable(tim_t dev)
{
switch (dev) {
#if TIMER_0_EN
case TIMER_0:
NVIC_EnableIRQ(TC0_IRQn);
break;
#endif
case TIMER_UNDEFINED:
break;
}
}
#if TIMER_0_EN
void TIMER_0_ISR(void)
{
if (TIMER_0_DEV.INTFLAG.bit.MC0 && TIMER_0_DEV.INTENSET.bit.MC0) {
if(config[TIMER_0].cb) {
TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC0;
TIMER_0_DEV.INTENCLR.reg = TC_INTENCLR_MC0;
config[TIMER_0].cb(config[TIMER_0].arg, 0);
}
}
else if (TIMER_0_DEV.INTFLAG.bit.MC1 && TIMER_0_DEV.INTENSET.bit.MC1) {
if(config[TIMER_0].cb) {
TIMER_0_DEV.INTFLAG.reg |= TC_INTFLAG_MC1;
TIMER_0_DEV.INTENCLR.reg = TC_INTENCLR_MC1;
config[TIMER_0].cb(config[TIMER_0].arg, 1);
}
}
cortexm_isr_end();
}
#endif /* TIMER_0_EN */