beagleboard / am335x_pru_package

332 stars 181 forks source link

PRU to ARM interrupts are fired twice (debian) #28

Closed gibbonsj closed 10 years ago

gibbonsj commented 10 years ago

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

luigif commented 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.

gibbonsj commented 10 years ago

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).

zittix commented 10 years ago

Using the 2014-05-14 image, I cannot reproduce this problem. Can you confirm it is fixed?

jadonk commented 10 years ago

@gibbonsj Can you confirm issue?

gibbonsj commented 10 years ago

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.

dgesswein commented 10 years ago

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;
}
dgesswein commented 10 years ago

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.

jadonk commented 10 years ago

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 .

gibbonsj commented 10 years ago

Since @dgesswein merged the fix under #30; I'll close this issue once the next BB image is released and tested.

gibbonsj commented 10 years ago

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)