XMC4500 32-bit concatenated timer

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Not applicable
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?

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);
}
0 Likes
3 Replies
User9640
Level 1
Level 1
Hello,

I was having similar problem with concatenated timers and the examples provided by infineon lack explanation of how formulas actually work out.
any way, a bit of search on the web I came across an example for the XMC1300 mcu, and the documentation is a bit better and I was able to make it work
for XMC4700.

The example I found in this thread: https://www.infineonforums.com/threads/3227-DAVE-4-PWM-App-Removed-timer-concatenation-support

Hope it helps.
0 Likes
Not applicable
moisesesc wrote:
Hello,

I was having similar problem with concatenated timers and the examples provided by infineon lack explanation of how formulas actually work out.
any way, a bit of search on the web I came across an example for the XMC1300 mcu, and the documentation is a bit better and I was able to make it work
for XMC4700.

The example I found in this thread: https://www.infineonforums.com/threads/3227-DAVE-4-PWM-App-Removed-timer-concatenation-support

Hope it helps.


Thanks moisesesc.
I looked at the code that is posted in your link. It is doing exactly what I want to do. However I also see that I configure the timers exactly like in that example and my code does not work as expected.

My code works if I only use one CCU4 unit (16 bit timer). Of course I modify it a little bit from the code I posted above. But when I add the second CCU4 unit in concatenated mode (by setting the concatenated bit in the register), the period that is generated is not correct according to the period I set.

Am I missing something? Are there any other settings that must be done to make concatenation work properly?

Rickard
0 Likes
Not applicable
Hi!

I found the problem thanks to your code moisesesc! I made an error in how I calculated the upper and lower registers 🙂

Instead of:

desiredStepsHigh = desiredSteps >> 16;
desiredStepsLow = desiredSteps & 0xFFFF;


it should be:


for (i = 1; i < 65535; i++)
{
desiredStepsLow = desiredSteps / i;
if(desiredStepsLow < 65535U)
{
desiredStepsHigh = i - 1;
break;
}
}


Rickard
0 Likes