Pin Change Interrupt for two pins

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

cross mob
Not applicable
Hello everybody,

as I am not able to find a solution myself, maybe someone else knows how to do it: I am trying to make my XMC4500 jump to an interrupt routine whenever a falling edge on P0.7 (ERU0_2B1) or P0.8 (ERU0_2A1) occurs.

In my minmal example the pins P0_7 and P0_8 each are toggled after some amount of time and a spike on P0_4 is generated to signalize when the IRQ-Handler becomes active:

int main(void) {
uint32_t reloader1 = 250017, reloader2 = 200000;

XMC_GPIO_CONFIG_t outp = {
.mode = XMC_GPIO_MODE_OUTPUT_PUSH_PULL,
.output_level = 0
};

XMC_GPIO_Init(P0_7, &outp);
XMC_GPIO_Init(P0_8, &outp);
XMC_GPIO_Init(P0_4, &outp);

const XMC_ERU_ETL_CONFIG_t PCI_ETL_CONFIG = {
.input_a = XMC_ERU_ETL_INPUT_A1,
.input_b = XMC_ERU_ETL_INPUT_B1,
.source = XMC_ERU_ETL_SOURCE_A_AND_B,
.edge_detection = XMC_ERU_ETL_EDGE_DETECTION_FALLING,
.status_flag_mode = XMC_ERU_ETL_STATUS_FLAG_MODE_SWCTRL,
.enable_output_trigger = XMC_ERU_ETL_OUTPUT_TRIGGER_ENABLED,
.output_trigger_channel = XMC_ERU_ETL_OUTPUT_TRIGGER_CHANNEL0 /* OGU0 */
};

XMC_ERU_ETL_Init(ERU0_ETL2, &PCI_ETL_CONFIG);

const XMC_ERU_OGU_CONFIG_t PCI_EVENT_DETECTION_CONFIG = {
.service_request = XMC_ERU_OGU_SERVICE_REQUEST_ON_TRIGGER
};

XMC_ERU_OGU_Init(ERU0_OGU0, &PCI_EVENT_DETECTION_CONFIG);

NVIC_SetPriority(ERU0_0_IRQn, 0U);
NVIC_EnableIRQ(ERU0_0_IRQn);

/* Placeholder for user application code. The while loop below can be replaced with user application code. */
while(1U) {
if(reloader1) reloader1--;
else {
XMC_GPIO_PORT0->OMR = (1 << 7) | (1 << 23);
reloader1 = 250017;
}

if(reloader2) reloader2--;
else {
XMC_GPIO_PORT0->OMR = (1 << 😎 | (1 << 24);
reloader2 = 190000;
}
}
}

void ERU0_0_IRQHandler(void) {
XMC_ERU_ETL_ClearStatusFlag(XMC_ERU0, 2);
XMC_GPIO_PORT0->OMR = (1 << 4);
XMC_GPIO_PORT0->OMR = (1 << 20);
}


I watch the pins' behaviour with a logic analyzer.

My problem now is that if I set .source to "A_AND_B" interrupts are only generated when a falling edge of one pin occurs while the other is high, for "A_OR_B" interrupts are only generated when a falling edge of one pin occurs while the other is low.
What can I do to have interrupts generated for every falling edge regardless of the other line's state? I really appreciate any help!
0 Likes
1 Reply
User11041
Level 1
Level 1
I can't figure out a solution for one ETL as well... If P0.7 and P0.8 are not fixed, I would suggest routing one signal to another pin, using two ETLs which detect the falling edges and forward them to the same OGU.

If those pins are fixed, my "dirty" solution would be to use P0.7 as input to CCU80.IN1A and P0.8 as input to CCU80.IN1B. In the CCU80 unit, there are 4 single timers (0 to 3), so-called "slices". Each slice module has some inputs (numbered A to H), of which A to C are physical pins on the chip. For each slice, you can configure up to three events listening on whichever input for whichever edge or level.
You can for example use them for starting the slices' timers - but you don't have to, in your case. For each slice there are 4 "service request lines" on which the three events can generate interrupt pulses. Those service request lines are forwarded to the interrupt controller (NVIC).

You could use it as follows: configure one event of slice number 1 to listen for a falling edge on input A (as P0.7 -> CCU80.IN1A) and pulse on for example service request line number 0. Configure a second event of the same slice number 1 to listen for a falling edge on input B (as P0.8 -> CCU80.IN1B) and make it pulse on the very same service request line. Now you can make the NVIC sensitive to this service request line and you're done.

If you're interested in this solution, I maybe could provide you some code...
0 Likes