Ip 408 interrupt support#4
Conversation
Add the interrupt support to IP-408
added all 8 channels for interrupt vector
MarkRivers
left a comment
There was a problem hiding this comment.
The intFunc probably needs some changes for the IP408. The logic to clear the interrupt looks like it should be OK, except you don't want to be accessing the High registers that are NULL. The logic near the end with invertMask does not apply to the IP408, because it can be told to interrupt on Change of State. The IPUnidig cannot, so the logic is more complicate to change the polarity register depending on the current state of the input.
| } | ||
|
|
||
| *regs_.intPolarityRegisterLow = (epicsUInt16)polarityMask_; | ||
| *regs_.intPolarityRegisterHigh = (epicsUInt16)(polarityMask_ >> 16); |
There was a problem hiding this comment.
This line will generate an access violation because you have defined regs_.intPolarityRegisterHigh =NULL.
You either need to change this line to test for !NULL or you need to put it inside a model_ dependent code.
| regs_.outputRegisterLow = base + 0x2; | ||
| regs_.outputRegisterHigh = base + 0x3; | ||
| regs_.intEnableRegisterLow = base + 0x4; | ||
| regs_.intEnableRegisterHigh = NULL; |
There was a problem hiding this comment.
You need to check that the register addresses that you set to NULL are never dereferenced.
…k for lower-channels
MarkRivers
left a comment
There was a problem hiding this comment.
Please make sure that you do not have any Tab characters in the file, only use the space character. It looks like perhaps there are tabs, but I can't tell for sure on Github.
Is the new version you just committed working with interrupts?
grasswang
left a comment
There was a problem hiding this comment.
After this commit, I was able to get the interrupt from the first channel.
This IP408 is getting a 10us TTL pulse at Ch0. There are no input to other channels.
The setting in st.cmd is
initIpUnidig("Unidig1", 0, 0, 100, 0xd0, 1,0)"
This setup rising edge interrupts for Ch0.
Setting with both edge also works
initIpUnidig("Unidig1", 0, 0, 100, 0xd0, 1,1)"
However, if I try to turn on more channels, or using falling edge, the Vxworks freeze or rebooting
initIpUnidig("Unidig1", 0, 0, 100, 0xd0, 0,1)" //falling edge
initIpUnidig("Unidig1", 0, 0, 100, 0xd0, 3,0)" // rising edge for Ch0 and Ch1
Thanks Mark! I committed a new version and untabify the file. |
I am not sure what you mean by that? Your code looks OK. I don't understand why it crashes if you only enable the falling edge, or if you enable Ch1. What happens if you only enable rising on Ch1, and move the pulse source to that channel? |
I suspect that falling edge problem is because the pulse is only 10us, so there is only 10 us TTL high before the falling edge happens. Due to Covid restriction, I actually don't have access to the hardware now. When my colleague is on-site next time, he could help me to plug it to another channel, or flip the pulse. Thanks Mark! |
|
I did some tests; it looks like this IOC crash because the pulse is short. If I flipped the pulse then the IOC crashs if I setup the rising edge for interrupt. Turn on the neighboring channels crashes the IOC when there is a short positive pulse, but seem to be ok when there is a short negative pulse (normally 5V, the 10 us pulse to 0V) ### input 10us positive pulse, in ch1
input 10us negative pulse (normally 5V, goes to 0V for 10 us), in ch1
|
|
I wonder if the IOC is crashing on a too-short input pulse because the board's interrupt is being cleared at the beginning of the interrupt routine instead of at the end. I usually put code that clears an interrupt state as the last thing the ISR does, since I don't want subsequent hardware events to trigger another interrupt until the routine has finished handling the first event, so that aspect of the code here looks a bit strange to me. I recommend moving the code that writes to the The thing you have to be careful about with modern CPUs when exiting an ISR is to make sure that the CPU has actually flushed all the register write operations out to the hardware before it returns from the interrupt. To do that the code must read back a value from the last register that it wrote to; for an example see the end of an ISR in my IPAC module although that may be a bit more complicated than should be needed here. |
|
This seems strange. These tests seem to show that the problem is not electrical cross-talk causing interrupts on other channels. This crash does not make sense to me. Even if what Andrew says is valid, there should not be a second interrupt because you are only triggering on the trailing (falling) edge of a short positive pulse , and the next pulse comes much later. Have you looked at the pulse on a scope right near the IP module? Could there be ringing that is causing the TTL threshold to be crossed a second time? What happens if you stretch the pulse width, to 100 us or 1 ms? Is the crash pattern the same? If not that could mean that it is indeed a second interrupt on the other edge happening before the first is complete. |
|
I modified the IntFunc() as below according to Andrew's comment. sorry I miss spelled Change Of Status (COS) before. =====Error after crash ====
============Updated intFunc()====== |
That error almost certainly does mean that it got a second interrupt before finishing the first, or it is getting interrupts too fast. I could understand that error happening with a very short pulse and interrupts on both leading and trailing edge. But if you only enable one edge or the other I don't understand that error. That is why I suggested looking for ringing on the signal, because that could cause multiple closely spaced interrupts. |
I realized that I forgot an important test while reading Mark's comment again.
That indicates we might have a cross-talk issue. |
|
What kind of connectors do you have on these signals? Are you using one of the BCDA Lemo breakout panels? I suggest putting shorting plugs or 50 ohm terminators on the unused channels. If you do that does it still crash with this test? |
No description provided.