IRC_SR register values in interrupts

In IRC interrupt routine I sometimes get values of IRC_A_MON and IRC_B_MON which are the same as in the interrupt that follows. So the status changes of IRC_{A,B}_MON are like this: [...] 0 2 2 3 3 1 1 0 2 2 3 3 1 1 0 0 2 2 3 3 1 1 0 0 2 3 1 1 0 0 2 2 [...] However, absolute position computed from such status changes seems to be correct. Spin in one direction for a given time then spin in the opposite direction at the same speed for the same time returns to roughly initial value. The difference from initial value is only about tens (one step in absolute position corresponds to one interrupt). Besides, in some cases (tens of hundred thousands interrupts) I read zero from IRC_IRQ_MON, but interrupt source is setup to rising edge, so I'd expect '1' every time. Have anyone encountered similar issue or do you have any explanation for this behavior? Thanks Jaroslav Beran

I discovered the cause is multiple generated interrupts from GPIO module. This condition in the beginning of ISR fixes the issue: #define GPIO_INT_STAT_2 (*(volatile uint32_t *) (ZYNQ7K_GPIO_BASE + 0x00000298)) [...] if (!(GPIO_INT_STAT_2 & 0x4)) { /* Not interrupt from IRC */ return; } However, I still wonder where are these others interrupts come from. To be sure, I disabled interrupts from all GPIO banks in irc_init() function, but there are still many of them. Had anyone else problems with it? Besides, the irc_init() on the web [1] sets interrupt polarity on falling instead of rising edge according to Zynq TRM, 14.2.4 [2], but it shouldn't matter. The problematic line of code is this: *(volatile uint32_t *) (ZYNQ7K_GPIO_BASE + 0x000002a0) = 0x0; /* rising edge (polarity), should be set to 0x4 */ [1] http://rtime.felk.cvut.cz/psr/cviceni/semestralka/#irc-sensor-irq-handling [2] https://rtime.felk.cvut.cz/hw/index.php/Zynq Cituji beranj25@fel.cvut.cz:
In IRC interrupt routine I sometimes get values of IRC_A_MON and IRC_B_MON which are the same as in the interrupt that follows. So the status changes of IRC_{A,B}_MON are like this:
[...] 0 2 2 3 3 1 1 0 2 2 3 3 1 1 0 0 2 2 3 3 1 1 0 0 2 3 1 1 0 0 2 2 [...]
However, absolute position computed from such status changes seems to be correct. Spin in one direction for a given time then spin in the opposite direction at the same speed for the same time returns to roughly initial value. The difference from initial value is only about tens (one step in absolute position corresponds to one interrupt).
Besides, in some cases (tens of hundred thousands interrupts) I read zero from IRC_IRQ_MON, but interrupt source is setup to rising edge, so I'd expect '1' every time.
Have anyone encountered similar issue or do you have any explanation for this behavior?
Thanks
Jaroslav Beran
_______________________________________________ PSR mailing list PSR@rtime.felk.cvut.cz You can unsubscribe from the list at https://rtime.felk.cvut.cz/mailman/listinfo/psr

On 01/15/2018 07:20 PM, beranj25@fel.cvut.cz wrote:
I discovered the cause is multiple generated interrupts from GPIO module.
This condition in the beginning of ISR fixes the issue:
#define GPIO_INT_STAT_2 (*(volatile uint32_t *) (ZYNQ7K_GPIO_BASE + 0x00000298)) [...] if (!(GPIO_INT_STAT_2 & 0x4)) { /* Not interrupt from IRC */ return; }
However, I still wonder where are these others interrupts come from.
Multiple HW components are connected to interrupt #52 [1]. If you would like to enable only one GPIO to generate interrupt it should be sufficient to disable all by writing 0xffffffff to INT_DIS bank control in irc_init(): *(volatile uint32_t *) (ZYNQ7K_GPIO_BASE + 0x00000294) = 0xffffffff; Maybe reset them too: *(volatile uint32_t *) (ZYNQ7K_GPIO_BASE + 0x00000298) = 0xffffffff; And then enable only the desired one: *(volatile uint32_t *) (ZYNQ7K_GPIO_BASE + 0x00000290) = 0x4;
To be sure, I disabled interrupts from all GPIO banks in irc_init() function, but there are still many of them.
What you mean? # References [1]: TRM, pg. 389 Have a nice day, Jiri Hubacek

Cituji Jiri Hubacek <hubacji1@fel.cvut.cz>:
On 01/15/2018 07:20 PM, beranj25@fel.cvut.cz wrote:
I discovered the cause is multiple generated interrupts from GPIO module.
This condition in the beginning of ISR fixes the issue:
#define GPIO_INT_STAT_2 (*(volatile uint32_t *) (ZYNQ7K_GPIO_BASE + 0x00000298)) [...] if (!(GPIO_INT_STAT_2 & 0x4)) { /* Not interrupt from IRC */ return; }
However, I still wonder where are these others interrupts come from.
Multiple HW components are connected to interrupt #52 [1]. If you would like to enable only one GPIO to generate interrupt it should be sufficient to disable all by writing 0xffffffff to INT_DIS bank control in irc_init():
*(volatile uint32_t *) (ZYNQ7K_GPIO_BASE + 0x00000294) = 0xffffffff;
Maybe reset them too:
*(volatile uint32_t *) (ZYNQ7K_GPIO_BASE + 0x00000298) = 0xffffffff;
And then enable only the desired one:
*(volatile uint32_t *) (ZYNQ7K_GPIO_BASE + 0x00000290) = 0x4;
Yeah, that's exactly what I've done.
To be sure, I disabled interrupts from all GPIO banks in irc_init() function, but there are still many of them.
What you mean?
I mean that disabling and resetting interrupts (in this order) wasn't enough to prevent triggering other interrupts on IRQ #52 (GPIO's).
# References [1]: TRM, pg. 389
Have a nice day, Jiri Hubacek
_______________________________________________ PSR mailing list PSR@rtime.felk.cvut.cz You can unsubscribe from the list at https://rtime.felk.cvut.cz/mailman/listinfo/psr

Dear students, On Tuesday 16 of January 2018 09:38:44 beranj25@fel.cvut.cz wrote:
Multiple HW components are connected to interrupt #52 [1]. If you would like to enable only one GPIO to generate interrupt it should be sufficient to disable all by writing 0xffffffff to INT_DIS bank control in irc_init():
*(volatile uint32_t *) (ZYNQ7K_GPIO_BASE + 0x00000294) = 0xffffffff;
Maybe reset them too:
*(volatile uint32_t *) (ZYNQ7K_GPIO_BASE + 0x00000298) = 0xffffffff;
And then enable only the desired one:
*(volatile uint32_t *) (ZYNQ7K_GPIO_BASE + 0x00000290) = 0x4;
Yeah, that's exactly what I've done.
To be sure, I disabled interrupts from all GPIO banks in irc_init() function, but there are still many of them.
What you mean?
I mean that disabling and resetting interrupts (in this order) wasn't enough to prevent triggering other interrupts on IRQ #52 (GPIO's).
The interrupts from all four GPIO banks are ORed and passed to the GIC. You can disable interrupts from all banks by writting 0xffffffff to all four INT_DIS registers. INT_DIS_0 0x00000214 INT_DIS_1 0x00000254 INT_DIS_2 0x00000294 INT_DIS_3 0x000002D4 But described behavior is strange anyway. Because your proposed solution is correct - respond only to your (IRC) interrupt and ignore all others if (!(GPIO_INT_STAT_2 & 0x4)) { /* Not interrupt from IRC */ return; } But the interrupts are level sensitive and if there is not processed and confirmed (write 1 to the corresponding INT_STATUS_x bit) interrupt from GPIO then the system should stuck, block in interrupt processing. At least one CPU core should be lost in infinite loop. If VxWorks uses both then another core can continue to work. But if you you ignore interrupt and system still works that means that there is registered another handler on given interrupt which clears corresponding status or spurious interrupts are caused by some problem in central interrupts processing code in VxWorks. Anyway, this behavior is waisting of CPU time but if your solution works then I suggest to ignore it. It is not your problem. It is possible that some other GPIO pin is used for USB device or other functionality. I see only SDcard detect signal SD_CD routed to PS_MIO46_501 as usesfull candidate for monitoring over GPIO interrupt. But it is strange that this signal would alternate and cause interrupts. Best wishes, Pavel Pisa

Cituji Pavel Pisa <pisa@cmp.felk.cvut.cz>:
Dear students,
On Tuesday 16 of January 2018 09:38:44 beranj25@fel.cvut.cz wrote:
Multiple HW components are connected to interrupt #52 [1]. If you would like to enable only one GPIO to generate interrupt it should be sufficient to disable all by writing 0xffffffff to INT_DIS bank control in irc_init():
*(volatile uint32_t *) (ZYNQ7K_GPIO_BASE + 0x00000294) = 0xffffffff;
Maybe reset them too:
*(volatile uint32_t *) (ZYNQ7K_GPIO_BASE + 0x00000298) = 0xffffffff;
And then enable only the desired one:
*(volatile uint32_t *) (ZYNQ7K_GPIO_BASE + 0x00000290) = 0x4;
Yeah, that's exactly what I've done.
To be sure, I disabled interrupts from all GPIO banks in irc_init() function, but there are still many of them.
What you mean?
I mean that disabling and resetting interrupts (in this order) wasn't enough to prevent triggering other interrupts on IRQ #52 (GPIO's).
The interrupts from all four GPIO banks are ORed and passed to the GIC. You can disable interrupts from all banks by writting 0xffffffff to all four INT_DIS registers.
INT_DIS_0 0x00000214 INT_DIS_1 0x00000254 INT_DIS_2 0x00000294 INT_DIS_3 0x000002D4
It doesn't work.
But described behavior is strange anyway. Because your proposed solution is correct - respond only to your (IRC) interrupt and ignore all others
if (!(GPIO_INT_STAT_2 & 0x4)) { /* Not interrupt from IRC */ return; }
But the interrupts are level sensitive and if there is not processed and confirmed (write 1 to the corresponding INT_STATUS_x bit) interrupt from GPIO then the system should stuck, block in interrupt processing. At least one CPU core should be lost in infinite loop. If VxWorks uses both then another core can continue to work.
But if you you ignore interrupt and system still works that means that there is registered another handler on given interrupt which clears corresponding status or spurious interrupts are caused by some problem in central interrupts processing code in VxWorks. Anyway, this behavior is waisting of CPU time but if your solution works then I suggest to ignore it. It is not your problem. It is possible that some other GPIO pin is used for USB device or other functionality.
I see only SDcard detect signal SD_CD routed to PS_MIO46_501 as usesfull candidate for monitoring over GPIO interrupt. But it is strange that this signal would alternate and cause interrupts.
Values of GPIO status registers at the time interrupt occur are: STS0:0x00000000 STS1:0x00000000 STS2:0xffffff8f STS3:0x00000000 Even resetting all bits of GPIO_INT_STS_2 reg at the end of IRC interrupt handler doesn't prevent firing those other interrupt: // GPIO_INT_STS_2 = 0x4; // reset only IRC int GPIO_INT_STS_2 = ~0U; // reset all GPIO2 ints - even this doesn't work!
Best wishes,
Pavel Pisa

On Fri, Jan 12 2018, beranj25@fel.cvut.cz wrote:
Besides, in some cases (tens of hundred thousands interrupts) I read zero from IRC_IRQ_MON, but interrupt source is setup to rising edge, so I'd expect '1' every time.
There could be several reasons for this. 1) The interrupt is set pending at the time of rising edge. However the handler invocation can be delayed (as we measured in Task 6) so when the handler is executed, the triggering condition may no longer be true. 2) As far as I know, there are two possible sources of IRC interrupts. One is generated directly in the motor electronics (this signal should be visible via IRC_IRQ_MON), the second is generated in the FPGA (which is a port of the Zynq chip) based on IRC_A and IRC_B signals. I think that the example code uses the second signal for interrupt generation. Although both IRQ signals should be quite similar, there are some changes. I think that the IRQ pulses generated by FPGA are shorter. Best regards, -Michal Sojka
participants (4)
-
beranj25@fel.cvut.cz
-
Jiri Hubacek
-
Michal Sojka
-
Pavel Pisa