How to handle CCU timer wraparound in Capture mode?

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

cross mob
Not applicable
The use case:
I want to timestamp edges for 8 different input signals.
The timestamps should have 64 bit resolution.

The problem:
The CCU4/8 have 16 bit resolution, which is insufficient. Timer concatenation can't be used as some of the signals share CCU module (using different slices).
As far as I can tell, it is not possible to generate an interrupt when timer wraps around while in Capture mode.

The question:
How do I work around this problem?
0 Likes
2 Replies
jferreira
Employee
Employee
10 sign-ins 5 sign-ins First like received
Hi Frederik,

CCU4 and CCU8 both can generate a period interrupt in capture mode.
As an example see below.

#include
#include

#define INPUT_PIN P1_2

const XMC_GPIO_CONFIG_t gpio_config =
{
.mode = XMC_GPIO_MODE_INPUT_PULL_UP
};

const XMC_CCU4_SLICE_EVENT_CONFIG_t event_config =
{
.mapped_input = CCU40_IN1_P1_2,
.edge = XMC_CCU4_SLICE_EVENT_EDGE_SENSITIVITY_FALLING_EDGE,
};

const XMC_CCU4_SLICE_CAPTURE_CONFIG_t capture_config =
{
.prescaler_initval = XMC_CCU4_SLICE_PRESCALER_32768
};

volatile uint32_t capture_time = 0;
volatile uint16_t overflow = 0;

void CCU40_1_IRQHandler(void)
{
capture_time = (overflow << 16) | (XMC_CCU4_SLICE_GetCaptureRegisterValue(CCU40_CC41, 0) & 0xffffU);
overflow = 0;
}

void CCU40_0_IRQHandler(void)
{
overflow++;
}

int main(void)
{
XMC_GPIO_Init(INPUT_PIN, &gpio_config);

XMC_CCU4_Init(CCU40, XMC_CCU4_SLICE_MCMS_ACTION_TRANSFER_PR_CR);

XMC_CCU4_SLICE_CaptureInit(CCU40_CC41, &capture_config);
XMC_CCU4_SLICE_Capture0Config(CCU40_CC41, XMC_CCU4_SLICE_EVENT_0);
XMC_CCU4_SLICE_ConfigureEvent(CCU40_CC41, XMC_CCU4_SLICE_EVENT_0, &event_config);

XMC_CCU4_EnableClock(CCU40, 1);
XMC_CCU4_SLICE_SetTimerPeriodMatch(CCU40_CC41, 0xffff);
XMC_CCU4_EnableShadowTransfer(CCU40, XMC_CCU4_SHADOW_TRANSFER_SLICE_1);

XMC_CCU4_SLICE_EnableMultipleEvents(CCU40_CC41, XMC_CCU4_SLICE_MULTI_IRQ_ID_PERIOD_MATCH | XMC_CCU4_SLICE_MULTI_IRQ_ID_EVENT0);
XMC_CCU4_SLICE_SetInterruptNode(CCU40_CC41, XMC_CCU4_SLICE_IRQ_ID_PERIOD_MATCH, 0);
XMC_CCU4_SLICE_SetInterruptNode(CCU40_CC41, XMC_CCU4_SLICE_IRQ_ID_EVENT0, 1);

NVIC_SetPriority(CCU40_0_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 63, 0));
NVIC_EnableIRQ(CCU40_0_IRQn);

NVIC_SetPriority(CCU40_1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 62, 0));
NVIC_EnableIRQ(CCU40_1_IRQn);

XMC_CCU4_SLICE_StartTimer(CCU40_CC41);

/* Placeholder for user application code. The while loop below can be replaced with user application code. */
while(1U)
{

}
}


Please let us know if this solves your problem.

Regards,
Jesus
0 Likes
Not applicable
Hello Jesus,

Thanks for your reply.

That would probably not work for my use case, as I use both Capture Trigger 0 and 1. According to errata for XMC45 (CCU4_AI.001), "CCU4 period interrupt is not generated in capture mode" in that case. Both Capture Triggers are used because I want to get different interrupts for falling and rising edges.

I solved the problem using a software approach. In the ISR, a timestamp was retrieved by other means. The hardware timestamp was not used.

Thanks again for your reply, which should still be useful if only Capture 0 is used.

Best regards,
Fredrik
0 Likes