Merge pull request #11336 from benpicco/sam0-timer
sam0_common: make Timer implementation common across all sam0 MCUs
This commit is contained in:
commit
85d37bb94f
@ -33,7 +33,7 @@ extern "C" {
|
||||
* @name xtimer configuration
|
||||
* @{
|
||||
*/
|
||||
#define XTIMER TIMER_DEV(1)
|
||||
#define XTIMER_DEV TIMER_DEV(1)
|
||||
#define XTIMER_CHAN (0)
|
||||
/** @} */
|
||||
|
||||
|
||||
@ -83,22 +83,44 @@ extern "C" {
|
||||
* @name Timer peripheral configuration
|
||||
* @{
|
||||
*/
|
||||
#define TIMER_NUMOF (2U)
|
||||
#define TIMER_0_EN 1
|
||||
#define TIMER_1_EN 1
|
||||
static const tc32_conf_t timer_config[] = {
|
||||
{ /* Timer 0 - System Clock */
|
||||
.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_DEV TC3->COUNT16
|
||||
#define TIMER_0_CHANNELS 2
|
||||
#define TIMER_0_MAX_VALUE (0xffff)
|
||||
#define TIMER_0_MAX_VALUE 0xffff
|
||||
|
||||
/* interrupt function name mapping */
|
||||
#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_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
||||
@ -81,21 +81,44 @@ extern "C" {
|
||||
* @name Timer peripheral configuration
|
||||
* @{
|
||||
*/
|
||||
#define TIMER_NUMOF (2U)
|
||||
#define TIMER_0_EN 1
|
||||
#define TIMER_1_EN 1
|
||||
static const tc32_conf_t timer_config[] = {
|
||||
{ /* Timer 0 - System Clock */
|
||||
.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_DEV TC3->COUNT16
|
||||
#define TIMER_0_CHANNELS 2
|
||||
#define TIMER_0_MAX_VALUE (0xffff)
|
||||
#define TIMER_0_MAX_VALUE 0xffff
|
||||
|
||||
/* interrupt function name mapping */
|
||||
#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_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
||||
@ -35,14 +35,23 @@ extern "C" {
|
||||
* @name Timer peripheral configuration
|
||||
* @{
|
||||
*/
|
||||
#define TIMER_NUMOF (1U)
|
||||
#define TIMER_0_EN 1
|
||||
static const tc32_conf_t timer_config[] = {
|
||||
{ /* 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 */
|
||||
#define TIMER_0_DEV TC0->COUNT32
|
||||
#define TIMER_0_CHANNELS 1
|
||||
#define TIMER_0_MAX_VALUE (0xffffffff)
|
||||
#define TIMER_0_CHANNELS 2
|
||||
#define TIMER_0_ISR isr_tc0
|
||||
#define TIMER_NUMOF (sizeof(timer_config)/sizeof(timer_config[0]))
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
||||
@ -78,21 +78,44 @@ extern "C" {
|
||||
* @name Timer peripheral configuration
|
||||
* @{
|
||||
*/
|
||||
#define TIMER_NUMOF (2U)
|
||||
#define TIMER_0_EN 1
|
||||
#define TIMER_1_EN 1
|
||||
static const tc32_conf_t timer_config[] = {
|
||||
{ /* Timer 0 - System Clock */
|
||||
.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_DEV TC3->COUNT16
|
||||
#define TIMER_0_CHANNELS 2
|
||||
#define TIMER_0_MAX_VALUE (0xffff)
|
||||
#define TIMER_0_MAX_VALUE 0xffff
|
||||
|
||||
/* interrupt function name mapping */
|
||||
#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_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
||||
@ -113,21 +113,44 @@ extern "C" {
|
||||
* @name Timer peripheral configuration
|
||||
* @{
|
||||
*/
|
||||
#define TIMER_NUMOF (2U)
|
||||
#define TIMER_0_EN 1
|
||||
#define TIMER_1_EN 1
|
||||
static const tc32_conf_t timer_config[] = {
|
||||
{ /* Timer 0 - System Clock */
|
||||
.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_DEV TC3->COUNT16
|
||||
#define TIMER_0_CHANNELS 2
|
||||
#define TIMER_0_MAX_VALUE (0xffff)
|
||||
#define TIMER_0_MAX_VALUE 0xffff
|
||||
|
||||
/* interrupt function name mapping */
|
||||
#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_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
||||
@ -89,21 +89,44 @@ extern "C" {
|
||||
* @name Timer peripheral configuration
|
||||
* @{
|
||||
*/
|
||||
#define TIMER_NUMOF (2U)
|
||||
#define TIMER_0_EN 1
|
||||
#define TIMER_1_EN 1
|
||||
static const tc32_conf_t timer_config[] = {
|
||||
{ /* Timer 0 - System Clock */
|
||||
.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_DEV TC3->COUNT16
|
||||
#define TIMER_0_CHANNELS 2
|
||||
#define TIMER_0_MAX_VALUE (0xffff)
|
||||
#define TIMER_0_MAX_VALUE 0xffff
|
||||
|
||||
/* interrupt function name mapping */
|
||||
#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_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
||||
@ -38,14 +38,23 @@ extern "C" {
|
||||
* @name Timer peripheral configuration
|
||||
* @{
|
||||
*/
|
||||
#define TIMER_NUMOF (1U)
|
||||
#define TIMER_0_EN 1
|
||||
static const tc32_conf_t timer_config[] = {
|
||||
{ /* 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 */
|
||||
#define TIMER_0_DEV TC0->COUNT32
|
||||
#define TIMER_0_CHANNELS 1
|
||||
#define TIMER_0_MAX_VALUE (0xffffffff)
|
||||
#define TIMER_0_CHANNELS 2
|
||||
#define TIMER_0_ISR isr_tc0
|
||||
#define TIMER_NUMOF (sizeof(timer_config)/sizeof(timer_config[0]))
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
||||
@ -89,21 +89,44 @@ extern "C" {
|
||||
* @name Timer peripheral configuration
|
||||
* @{
|
||||
*/
|
||||
#define TIMER_NUMOF (2U)
|
||||
#define TIMER_0_EN 1
|
||||
#define TIMER_1_EN 1
|
||||
static const tc32_conf_t timer_config[] = {
|
||||
{ /* Timer 0 - System Clock */
|
||||
.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_DEV TC3->COUNT16
|
||||
#define TIMER_0_CHANNELS 2
|
||||
#define TIMER_0_MAX_VALUE (0xffff)
|
||||
#define TIMER_0_MAX_VALUE 0xffff
|
||||
|
||||
/* interrupt function name mapping */
|
||||
#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_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
||||
@ -34,14 +34,23 @@ extern "C" {
|
||||
* @name Timer peripheral configuration
|
||||
* @{
|
||||
*/
|
||||
#define TIMER_NUMOF (1U)
|
||||
#define TIMER_0_EN 1
|
||||
static const tc32_conf_t timer_config[] = {
|
||||
{ /* 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 */
|
||||
#define TIMER_0_DEV TC0->COUNT32
|
||||
#define TIMER_0_CHANNELS 1
|
||||
#define TIMER_0_MAX_VALUE (0xffffffff)
|
||||
#define TIMER_0_CHANNELS 2
|
||||
#define TIMER_0_ISR isr_tc0
|
||||
#define TIMER_NUMOF (sizeof(timer_config)/sizeof(timer_config[0]))
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
||||
@ -79,21 +79,44 @@ extern "C" {
|
||||
* @name Timer peripheral configuration
|
||||
* @{
|
||||
*/
|
||||
#define TIMER_NUMOF (2U)
|
||||
#define TIMER_0_EN 1
|
||||
#define TIMER_1_EN 1
|
||||
static const tc32_conf_t timer_config[] = {
|
||||
{ /* Timer 0 - System Clock */
|
||||
.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_DEV TC3->COUNT16
|
||||
#define TIMER_0_CHANNELS 2
|
||||
#define TIMER_0_MAX_VALUE (0xffff)
|
||||
#define TIMER_0_MAX_VALUE 0xffff
|
||||
|
||||
/* interrupt function name mapping */
|
||||
#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_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
||||
@ -79,21 +79,44 @@ extern "C" {
|
||||
* @name Timer peripheral configuration
|
||||
* @{
|
||||
*/
|
||||
#define TIMER_NUMOF (2U)
|
||||
#define TIMER_0_EN 1
|
||||
#define TIMER_1_EN 1
|
||||
static const tc32_conf_t timer_config[] = {
|
||||
{ /* Timer 0 - System Clock */
|
||||
.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_DEV TC3->COUNT16
|
||||
#define TIMER_0_CHANNELS 2
|
||||
#define TIMER_0_MAX_VALUE (0xffff)
|
||||
#define TIMER_0_MAX_VALUE 0xffff
|
||||
|
||||
/* interrupt function name mapping */
|
||||
#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_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
||||
@ -26,13 +26,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name xtimer configuration
|
||||
* @{
|
||||
*/
|
||||
#define XTIMER_WIDTH (16)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name LED pin definitions and handlers
|
||||
* @{
|
||||
|
||||
@ -76,21 +76,44 @@ extern "C" {
|
||||
* @name Timer peripheral configuration
|
||||
* @{
|
||||
*/
|
||||
#define TIMER_NUMOF (2U)
|
||||
#define TIMER_0_EN 1
|
||||
#define TIMER_1_EN 1
|
||||
static const tc32_conf_t timer_config[] = {
|
||||
{ /* Timer 0 - System Clock */
|
||||
.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_DEV TC3->COUNT16
|
||||
#define TIMER_0_CHANNELS 2
|
||||
#define TIMER_0_MAX_VALUE (0xffff)
|
||||
#define TIMER_0_MAX_VALUE 0xffff
|
||||
|
||||
/* interrupt function name mapping */
|
||||
#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_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
||||
@ -79,21 +79,44 @@ extern "C" {
|
||||
* @name Timer peripheral configuration
|
||||
* @{
|
||||
*/
|
||||
#define TIMER_NUMOF (2U)
|
||||
#define TIMER_0_EN 1
|
||||
#define TIMER_1_EN 1
|
||||
static const tc32_conf_t timer_config[] = {
|
||||
{ /* Timer 0 - System Clock */
|
||||
.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_DEV TC3->COUNT16
|
||||
#define TIMER_0_CHANNELS 2
|
||||
#define TIMER_0_MAX_VALUE (0xffff)
|
||||
#define TIMER_0_MAX_VALUE 0xffff
|
||||
|
||||
/* interrupt function name mapping */
|
||||
#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_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
||||
@ -81,21 +81,44 @@ extern "C" {
|
||||
* @name Timer peripheral configuration
|
||||
* @{
|
||||
*/
|
||||
#define TIMER_NUMOF (2U)
|
||||
#define TIMER_0_EN 1
|
||||
#define TIMER_1_EN 1
|
||||
static const tc32_conf_t timer_config[] = {
|
||||
{ /* Timer 0 - System Clock */
|
||||
.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_DEV TC3->COUNT16
|
||||
#define TIMER_0_CHANNELS 2
|
||||
#define TIMER_0_MAX_VALUE (0xffff)
|
||||
#define TIMER_0_MAX_VALUE 0xffff
|
||||
|
||||
/* interrupt function name mapping */
|
||||
#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_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
||||
@ -289,6 +289,25 @@ typedef struct {
|
||||
uint8_t flags; /**< allow SERCOM to run in standby mode */
|
||||
} 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
|
||||
*
|
||||
|
||||
269
cpu/sam0_common/periph/timer.c
Normal file
269
cpu/sam0_common/periph/timer.c
Normal 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
|
||||
@ -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 */
|
||||
@ -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 */
|
||||
@ -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 */
|
||||
Loading…
x
Reference in New Issue
Block a user