Hi,
I'm trying to create a very simple 32-bit concatenated timer by using CCU4 (no DAVE app). It only needs to generate interrupts and call my ISR at my specified interval. I'm using the PERIOD_MATCH event.
I've posted the code below. It does in fact generate interrupts and call my ISR, but the interval times is incorrect. E.g. when I set the frequency to be 100 Hz, it generates interrupts in ~300 Hz. If I try another frequency, I get another actual frequency. It does not seem to follow any linear relationship.
If I remove the code for concatenation, it works perfectly (with only 16-bit timer). I've tried to write the code exactly like the example in "CCU4_SLICE_CONFIG_EXAMPLE_XMC47.zip", but that example uses the COMPARE_MATCH event so the code if a little bit different.
Can you please take a look at my code and tell me what is wrong?
I'm trying to create a very simple 32-bit concatenated timer by using CCU4 (no DAVE app). It only needs to generate interrupts and call my ISR at my specified interval. I'm using the PERIOD_MATCH event.
I've posted the code below. It does in fact generate interrupts and call my ISR, but the interval times is incorrect. E.g. when I set the frequency to be 100 Hz, it generates interrupts in ~300 Hz. If I try another frequency, I get another actual frequency. It does not seem to follow any linear relationship.
If I remove the code for concatenation, it works perfectly (with only 16-bit timer). I've tried to write the code exactly like the example in "CCU4_SLICE_CONFIG_EXAMPLE_XMC47.zip", but that example uses the COMPARE_MATCH event so the code if a little bit different.
Can you please take a look at my code and tell me what is wrong?
Code:
const XMC_CCU4_SLICE_COMPARE_CONFIG_t timer_config =
{
.timer_mode = XMC_CCU4_SLICE_TIMER_COUNT_MODE_EA,
.monoshot = XMC_CCU4_SLICE_TIMER_REPEAT_MODE_REPEAT,
.shadow_xfer_clear = 0U,
.dither_timer_period = 0U,
.dither_duty_cycle = 0U,
.prescaler_mode = (uint32_t)XMC_CCU4_SLICE_PRESCALER_MODE_NORMAL,
.mcm_enable = 0U,
.prescaler_initval = 0U,
.float_limit = 0U,
.dither_limit = 0U,
.passive_level = (uint32_t)XMC_CCU4_SLICE_OUTPUT_PASSIVE_LEVEL_LOW,
.timer_concatenation = 0U
};
const XMC_CCU4_SLICE_COMPARE_CONFIG_t timer_config2 =
{
.timer_mode = XMC_CCU4_SLICE_TIMER_COUNT_MODE_EA,
.monoshot = XMC_CCU4_SLICE_TIMER_REPEAT_MODE_REPEAT,
.shadow_xfer_clear = 0U,
.dither_timer_period = 0U,
.dither_duty_cycle = 0U,
.prescaler_mode = (uint32_t)XMC_CCU4_SLICE_PRESCALER_MODE_NORMAL,
.mcm_enable = 0U,
.prescaler_initval = 0U,
.float_limit = 0U,
.dither_limit = 0U,
.passive_level = (uint32_t)XMC_CCU4_SLICE_OUTPUT_PASSIVE_LEVEL_LOW,
.timer_concatenation = 1U
};
void CCU43_0_IRQHandler(void)
{
// This Interrupt Service Routine is called every time the timer times out
// Clear pending interrupt
XMC_CCU4_SLICE_ClearEvent(CCU43_CC40, XMC_CCU4_SLICE_IRQ_ID_PERIOD_MATCH);
XMC_CCU4_SLICE_ClearEvent(CCU43_CC41, XMC_CCU4_SLICE_IRQ_ID_PERIOD_MATCH);
events |= EventFlag;
}
void SetFrequency(uint32_t desiredFrequency)
{
uint32_t desiredSteps = 0;
uint16_t desiredStepsHigh = 0;
uint16_t desiredStepsLow = 0;
if (desiredFrequency == 0)
{
desiredSteps = 0xFFFFFFFF;
}
desiredSteps = SystemCoreClock / desiredFrequency;
desiredStepsHigh = desiredSteps >> 16;
desiredStepsLow = desiredSteps & 0xFFFF;
XMC_CCU4_SLICE_SetTimerPeriodMatch(CCU43_CC41, desiredStepsHigh);
XMC_CCU4_SLICE_SetTimerPeriodMatch(CCU43_CC40, desiredStepsLow);
XMC_CCU4_EnableShadowTransfer(CCU43, (uint32_t)XMC_CCU4_SHADOW_TRANSFER_SLICE_0);
XMC_CCU4_EnableShadowTransfer(CCU43, (uint32_t)XMC_CCU4_SHADOW_TRANSFER_SLICE_1);
}
void Initialize()
{
XMC_CCU4_Init(CCU43, XMC_CCU4_SLICE_MCMS_ACTION_TRANSFER_PR_CR);
XMC_CCU4_StartPrescaler(CCU43);
XMC_CCU4_SetModuleClock(CCU43, XMC_CCU4_CLOCK_SCU);
XMC_CCU4_SLICE_CompareInit(CCU43_CC40, &timer_config);
XMC_CCU4_SLICE_CompareInit(CCU43_CC41, &timer_config2);
XMC_CCU4_SLICE_SetTimerCompareMatch(CCU43_CC40, 0U);
XMC_CCU4_SLICE_SetTimerCompareMatch(CCU43_CC41, 0U);
XMC_CCU4_SLICE_SetTimerPeriodMatch(CCU43_CC40, 0xFFFF);
XMC_CCU4_SLICE_SetTimerPeriodMatch(CCU43_CC41, 0xFFFF);
XMC_CCU4_SLICE_SetPrescaler(CCU43_CC40, 0x00);
XMC_CCU4_SLICE_SetPrescaler(CCU43_CC41, 0x00);
XMC_CCU4_EnableShadowTransfer(CCU43, (uint32_t)(XMC_CCU4_SHADOW_TRANSFER_SLICE_0 | XMC_CCU4_SHADOW_TRANSFER_PRESCALER_SLICE_0 | XMC_CCU4_SHADOW_TRANSFER_DITHER_SLICE_0));
XMC_CCU4_EnableShadowTransfer(CCU43, (uint32_t)(XMC_CCU4_SHADOW_TRANSFER_SLICE_1 | XMC_CCU4_SHADOW_TRANSFER_PRESCALER_SLICE_1 | XMC_CCU4_SHADOW_TRANSFER_DITHER_SLICE_1));
/* Enable the event for CCU43_41 because it is AND-ed with the period match of CCU43_CC40 */
XMC_CCU4_SLICE_EnableEvent(CCU43_CC41, XMC_CCU4_SLICE_IRQ_ID_PERIOD_MATCH);
XMC_CCU4_SLICE_SetInterruptNode(CCU43_CC41, XMC_CCU4_SLICE_IRQ_ID_PERIOD_MATCH, XMC_CCU4_SLICE_SR_ID_0);
XMC_CCU4_EnableClock(CCU43, 0);
XMC_CCU4_EnableClock(CCU43, 1);
NVIC_SetPriority(CCU43_0_IRQn, 3U);
NVIC_EnableIRQ(CCU43_0_IRQn);
/* Set the frequency */
SetFrequency(100);
// TODO: Start simultaneously
XMC_CCU4_SLICE_StartTimer(CCU43_CC40);
XMC_CCU4_SLICE_StartTimer(CCU43_CC41);
}