Closed gibbonsj closed 10 years ago
I have the same problem. BBB with debian 4-23-14. Interrupts are fired twice. It looks like the event is cleared with some delay, but could not debug more.
I just verified the same behavior on the BBW with Debian image 4-23-2014.. so the images are consistent WRT the PRUSS C libraries. I'm using a working around that ignores every other received interrupt (yes, I know kludgy and scary).
Using the 2014-05-14 image, I cannot reproduce this problem. Can you confirm it is fixed?
@gibbonsj Can you confirm issue?
Unfortunately, I'm still seeing twice the interrupts, but I'll investigate more to ensure it isn't an issue with a clear delay that @luigif pointed out earlier.
UPDATE: Reconfirmed... it's twice the number of expected interrupts. To test I rebooted the board in order to ensure 0 (pruss_evt0) interrupts, I then ran the module and saw twice the number of interrupts that should have been generated (checked with $cat /proc/interrupts). Perhaps @luigif can also confirm if he's seeing the same with the 2014-05-14 image.
I have confirmed with Linux beaglebone 3.8.13-bone60
I fixed it by adding a memory barrier (DMB). Not sure this is the best solution. I have a simple test program to demonstrate the issue I can provide.
in prussdrv.c
static inline void __DMB(void) { asm volatile ("dmb"); }
int prussdrv_pru_clear_event(unsigned int host_interrupt, unsigned int sysevent)
{
unsigned int *pruintc_io = (unsigned int *) prussdrv.intc_base;
if (sysevent < 32)
pruintc_io[PRU_INTC_SECR1_REG >> 2] = 1 << sysevent;
else
pruintc_io[PRU_INTC_SECR2_REG >> 2] = 1 << (sysevent - 32);
__DMB();
// Re-enable the host interrupt. Note that we must do this _after_ the
// system event has been cleared so as to not re-tigger the interrupt line.
// See Section 6.4.9 of Reference manual about HIEISR register.
// The +2 is because the first two host interrupts are reserved for
// PRU0 and PRU1.
pruintc_io[PRU_INTC_HIEISR_REG >> 2] = host_interrupt+2;
return 0;
}
Its GCC optimization. The optimized assembly is writing PRU_INTC_HIEISR_REG first then writing to either of the SECR registers.
If you change the declaration above to volatile unsigned int pruintc_io = (unsigned int ) prussdrv.intc_base; the __DMB is not needed and it works. The registers are written in the correct order.
There are more similar declarations in other routines in prussdrv.c.
Can you submit a pull request?
On Tue, Jul 15, 2014 at 7:36 AM, dgesswein notifications@github.com wrote:
Its GCC optimization. The optimized assembly is writing PRU_INTC_HIEISR_REG first then writing to either of the SECR registers.
If you change the declaration above to volatile unsigned int pruintc_io = (unsigned int ) prussdrv.intc_base; the __DMB is not needed and it works. The registers are written in the correct order.
There are more similar declarations in other routines in prussdrv.c.
— Reply to this email directly or view it on GitHub https://github.com/beagleboard/am335x_pru_package/issues/28#issuecomment-49019980 .
Since @dgesswein merged the fix under #30; I'll close this issue once the next BB image is released and tested.
Pulled and built PRUSS code using 09-03-14 (console image) and confirmed the interrupts are no longer firing twice. (@dgesswein: TY for the fix)
I'm noticing the latest-image (Debian 4-23-14 on BBB) has not fixed issue #3 but the patch is applied.
From the PRU I signal the host application with the following:
MOV r31.b0, PRU0_ARM_INTERRUPT + 16
In C I have a pthread listening as follows:
int c = 0; int stop = 0; void *EVT_0() { do { prussdrv_pru_wait_event(PRU_EVTOUT_0); c++; prussdrv_pru_clear_event(PRU_EVTOUT_0, PRU0_ARM_INTERRUPT); } while (stop == 0); }
When printing 'c' the number of interrupts are doubled what they should be. Using 'cat /proc/interrupts' confirms the interrupts are doubled