MC9S08QE128 KBI interrupt issues - sometimes second interrupt does not fire after the first one

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MC9S08QE128 KBI interrupt issues - sometimes second interrupt does not fire after the first one

1,964 Views
petrascerniausk
Contributor II

Hello! We have a product based on Freescale MC9S08QE128 MCU that uses 2 KBI interrupt pins to determine time difference between certain related external events that are a few (2-20) milliseconds apart. As KBI interrupt fires our KBI ISR loops while KBF == 1 disabling any asserted KBI pins and setting KBACK = 1 effectively making sure that when we leave KBI ISR we are ready to receive new KBI interrupt. The problem is that sometimes after the first interrupt fires the second interrupt does not. I studied KBI block diagram and I understand that any enabled asserted KBI pin will prevent generation of new KBI interrupt. But it seems to me there is a potential MCU bug where even if asserted pin is disabled it prevents generation of new interrupt. This same behavior was mentioend by Javier Rodriguez in "MC13213 : Problem using KBI interrupt" thread. Assuming this is MCU bug is there a workaround besides polling of second KBI line after the first interrupt? Thanks!

Labels (1)
19 Replies

1,620 Views
petrascerniausk
Contributor II

Guys, thanks for all your help. Once I switched to edges and levels KBI detection mode the interrupts started working reliably. I am pretty sure the problem is with the signal that is supposed to generate an interrupt and not with MCU KBI implementation which seems to work just as described by above mentioned diagram. Thanks again!

- Petras

0 Kudos

1,620 Views
Leojunin
Contributor III

Hi. In my view, if the events are from two different sources and not from the same source, one after another, you should use two interruptions that maybe comes an interruption of the second source while you attend the first, and there have failed. If you use two interrupts, the second will be pending to run after the first. If you use two channels of the timer as IC, the hardware itself is responsible for capturing the time of the event, and you just have to do the math.

If you want to use the KBI, I propose that also use another, for example IRQ.

Regards.

0 Kudos

1,620 Views
petrascerniausk
Contributor II

The interrupt sources are independent. There is plenty of time between them (on average 7ms) that there should not be a case where KBI1 interrupt arrives while KBI0 is being handled. I can poll the lines after the first interrupt fires and I can see that KBI1 line is not asserted when KBI0 is already deactivated (I perform this check in main() ). Then some time later it gets asserted but I don't get an interrupt (which eventually arrives but about 20 ms later).

Maybe more clarification would help. My interrupt sources come from sort of window comparators. Once certain measured value goes outside of predefined window they pull the output low otherwise they stay high. During my measuring cycle the value can go back and forth but I am interested in the first "out of window" occurrence on each channel and the time difference between those two events. I think this problem is somehow related to KBI0 line going through asserted/deasserted states although being disabled during the first KBI ISR call.

I considered moving KBI1 to IRQ but unfortunately IRQ pin is being used as RESET.

0 Kudos

1,620 Views
Leojunin
Contributor III

If you look at the diagram, as you said, the first interruption of the KBI should return to its inactive state because all KBI inputs converge in an OR gate, therefore, can not activate a new interruption before releasing the previous one. If the first remains active while the second arrives, it will not detect the latter. The mode of operation of the KBI (edge or level) is after the OR gate. Again, you should use two interruptions.

KBI.JPG

0 Kudos

1,620 Views
Leojunin
Contributor III

This is what I see may be happening. In the first case, the interruptions do not overlap or also may be that your comparator outputs generate an edge. In the second case would be superimposed interruptions or your comparators maintain the state more than 20mS until the comparison is reversed.

KBI2.JPG

If you have at the entrance of KBI are comparators ... Why not use internal ACMP, which software can connect to a timer each?

0 Kudos

1,620 Views
petrascerniausk
Contributor II

Thanks guys! I know I can do a lot of things and the simplest one would be to start polling the inputs after the first interrupt fires. The reason I asked the question is that I wanted to see whether somebody else ran into this before and confirm I am not doing something wrong here. It really does seem to me that this is MCU bug where if you use multiple KBI lines it's not sufficient to disable the asserted line. The asserted one has to be in deasserted state (even if disabled) in order for other KBI lines to generate interrupts. Which is actually different from what KBI diagram is telling...

0 Kudos

1,620 Views
Leojunin
Contributor III

Well, it's a way out, but if you look at the scheme before entering the OR gate goes through an AND to enable / disable the corresponding pin, this works well, I used the KBI. Normally, when you have more of an interruption in the KBI, you must verify software, which of all the entries that have enabled is the one that generated the interrupt. Perhaps the flanks are not as expected at some point.

0 Kudos

1,620 Views
petrascerniausk
Contributor II

Ok, so maybe this will clarify the problem I am having with the KBI and it will show that sometimes it does NOT work the way it's documented. I am sorry if I sound grumpy but this caused a lot of grey hair for me and a substantial number of customer calls (we have thousands of these devices out in the field)! So here is the log generated from main(). The pairs of numbers are KBI0 Enable status - KBI0 line status and then KBI1 Enable Status - KBI1 Line status. The 2=> is printed once the KBI ISR detects KBI0 interrupt and sets corresponding global to TRUE. The 4=> is printed once KBI ISR detects KBI1 interrupt and sets corresponding global to TRUE.

This log shows when everything works fine:

...

1-1  1-1

1-1  1-1

1-1  1-1

1-1  1-1

1-1  1-1

1-1  1-1

2 =>

0-0  1-1

4 =>

0-0  0-0

0-0  0-0

0-0  0-0

0-1  0-0

0-0  0-1

0-0  0-0

0-1  0-0

0-0  0-1

0-1  0-0

0-0  0-0

0-0  0-1

0-0  0-0

0-1  0-0

0-0  0-1

0-1  0-0

...

And here is where it does NOT work:

...

1-1  1-1

1-1  1-1

1-1  1-1

1-1  1-1

1-1  1-1

1-1  1-1

2 =>

0-0  1-1

0-0  1-0         <- Where is the interrupt?

0-0  1-0

0-0  1-0

0-1  1-0

4 =>

0-0  0-1

0-1  0-0

0-0  0-0

0-0  0-0

0-1  0-0

0-0  0-1

0-0  0-0

0-1  0-0

0-0  0-0

0-0  0-0

0-1  0-0

0-0  0-1

0-0  0-0

0-1  0-0

0-0  0-1

...

Note that KBI0 is disabled (although it's in asserted state) but KBI1 does not cause an interrupt for a very long time (I suspect until the status change on the KBI0 pin). Now, I tried to keep my examples simple. But to complicate matters we are using STOP mode and we have an alarm clock chip hooked up yet to one more KBI line. The real problem is when this same situation occurs with the KBI line that has alarm clock connected to it and after handling that interrupt we go to sleep. The MCU never wakes up...

0 Kudos

1,620 Views
Leojunin
Contributor III

I have two things to say:

The first is that used the KBI in the QE32, I guess it's the same, also the QE32 has two KBI groups on the same interrupt vector.

Second, do not really understand the data you offer to see the fault, maybe someone else will understand better.

0 Kudos

1,620 Views
petrascerniausk
Contributor II

Sorry, my references to KBI0 and KBI1 should be read as KBI1P0 and KBI1P1. And the pairs of values printed are KBI1PE for pin 0 - KBI1P0 and KBI1PE for pin 1 - KBI1P1. In other words Pin Enable status - Pin value. The edge detection is setup up to detect falling edge. The log clearly shows that when pin 0 goes from deasserted to asserted state (change from 1 to 0) the ISR is called but when pin 1 goes from deasserted to asserted state the ISR is not called for quite some time. Actually I am yet to figure out what causes it to call the ISR...

0 Kudos

1,620 Views
Leojunin
Contributor III

Hello, my last entry for today.

It has nothing to do with the pin be enabled, that there is an interrupt. If the pin is enabled may be taking an edge of a spurious close, it happened to me. If the frequency entering pin is as low as you say, put a filter (RC) before entering the uP.

Also check clearing sequence from the pending interrupt.

As soon as you enter the interrupt routine that is checked by 1 KBI1SC_KBF then write KBI1SC_KBACK to 1.

Leaving the INT verifies that KBI1SC_KBF this to 0 if you do this is you had a interrupt in the middle.

Regards.

0 Kudos

1,620 Views
Leojunin
Contributor III

Hi. Personally I would use 2-channel timer as IC, QE has many, and include counter and latch to measure the time. The KBI not measure time, therefore you overload routines.

Luck.

1,620 Views
Stano
NXP Employee
NXP Employee

Hello all,

for better understanding - the time is used as free-running counter, the KBI interrupt is used to catch the counter value when the edge interrupt arrives. Then you can calculate the time interval between two samples. The KBI_isr routine is very simply:

- disable KBI interrupt on pin1/pin2

- read timer counter

- clear interrupt flag

- enable interrupt on pin2/pin1

Then the pins will be sensitive concurrently.

Best Regards,

Stano.

0 Kudos

1,620 Views
petrascerniausk
Contributor II

Stano,

  That's exactly right. I do have a TPM timer to measure time difference between KBI0 and KBI1 interrupts. The KBI pins are configured to detect edges only. And I do exactly that - as first interrupt fires I disable it, start the timer, ack the interrupt and leave the ISR. Then when second interrupt arrives I disable it, grab the free running counter value and ack the interrupt. Both interrupts get re-enabled much later (probably in about 1 sec). The problem is that sometimes (about 10% of the time) second interrupt does not fire. I even made sure that I leave KBI ISR with KBF set to 0 and KBI interrupts disabled for asserted lines.

I do not do any debouncing though because I am measuring time between two events. What I noticed though that KBI ISR is activated about 7-8 times during each measuring cycle. Which means I get an interrupt but when I check the pins they are not in asserted state. So in that case I have no clue which pin caused an interrupt. All I do is ACK an interrupt make sure KBF == 0 and leave the ISR. That's probably what is causing a problem.

0 Kudos

1,620 Views
Stano
NXP Employee
NXP Employee

OK, now it is more clear.

Please check if you have enabled the KBI interrupts only on those two used pins. Then use these pins concurrently for the generating interrupts. It is possible to avoid false interrupt calls. Please try to use free-running timer instead of "enable timer" or "reset timer" on the first edge event. If the false interrupt arrives, check to source (which bit) of this interrupt.

I think it could help you.

Best Regards,

Stano.

0 Kudos

1,620 Views
tonyp
Senior Contributor II

I don't know if this is considered a bug.  It's certainly annoying behavior -- or, rather, not what one would expect.  But given there is only a single ISR for all KBI pins, I guess the KBI design was meant to work like an OR to a single output but without the actual wiring externally.

In any case, I think you should go this way:

In the ISR read all pins at once and mask out the unused ones.  Do whatever debouncing, and put the recognized key code into some queue (or something) for later use by the main code loop.

As you know, keyboards are by nature slow peripherals.  Now, if you wanted to use the KBI for grabbing much faster (non-human) events, I think you're a bit out of luck, and you need to reassign your inputs to some other interrupts.

Hope this helps.

0 Kudos

1,620 Views
Stano
NXP Employee
NXP Employee

Hello Petras,

you need select the edge only sensitivity on both KBI pins. Then in the KBI_isr code as first disable KBI interrupt, check which pin was asserted, make required action (e.g. read timer counter value for the first edge) and back enable the KBI interrupt. Then when the second pin will be asserted, in the KBI_isr disable interrupt, make required action (e.g. read timer counter value for second egde) and back enable interrupt. Then you can simply calculate the delay between those two edges. It is possible to measure also very short time delays this way.

Best Regards,

Stano.

0 Kudos

1,620 Views
tonyp
Senior Contributor II

And it would be even simpler (programmatically) to just use the IRQ pin, and when inside the ISR check the status of the two pins.

However, both your proposed approach and my (non-proposed) IRQ example have no way of getting accurate timing for fast events.  For example, if the code happens to be in a blocked (interrupts disabled) section when the edges come the times will be skewed.

The O.P. says the events are 2 to 20 msec apart, which is relatively long.  But we know nothing about the timing accuracy required between the two (the timing resolution).  So, as a general approach only the Input Capture can really work correctly either for fast events or when accurate timing resolution is required.

0 Kudos

1,620 Views
petrascerniausk
Contributor II

Using IRQ pin is not an option since we are already using it as a RESET.

0 Kudos