PRU Interrupt Bug

I have a project where I am trying to use both PRUs. PRU0 loops until the ARM_PRU0_INTERRUPT (bit 31 of PRU0 r31) is received, and PRU1 loops until the ARM_PRU1_INTERUPT (bit 31 of PRU1 r31) is received. Once the loops terminate, they send a PRU0_ARM_INTERRUPT or PRU1_ARM_INTERRUPT, respectively.

This works. However, if the PRU0 code to sends a PRU0_PRU1_INTERRUPT then the PRU0 loop terminates because bit 31 of PRU0 r31 is set… even though ARM_PRU0_INTERUPT has not been sent.

Can anyone see a bug in the code below or otherwise know how to fix this problem? The code runs indefinitely until ctrl-c is hit. With the problematic code commented out, “00002222” is printed out once a second indicating that PRU0 is looping. If the problematic line is executied, then “80000000” is printed out once a second indicating that PRU0 is no longer looping and bit 31 of PRU0 r31 is set.

Thanks!

PRU0 Code:

`

.origin 0
.entrypoint PRUCODE0

#include “prucode.hp”

PRUCODE0:
// Enable OCP master port
LBCO r0, CONST_PRUCFG, 4, 4
CLR r0, r0, 4 // Clear SYSCFG[STANDBY_INIT] to enable OCP master port
SBCO r0, CONST_PRUCFG, 4, 4

// Set C28 to shared ram
MOV r0, SHARED_RAM
MOV r1, PRU0_CTRL + CTPPR0
SBBO r0, r1, 0, 4

MOV r20, 0x1111
SBCO r20, CONST_PRUSHAREDRAM, 0, 4

MAIN_LOOP:
MOV r20, 0x2222
SBCO r20, CONST_PRUSHAREDRAM, 0, 4

// Send notification to PRU1
//MOV r31.b0, PRU0_PRU1_INTERRUPT+16 // CAUSES LOOP TO TERMINATE

// Loop unless bit 31 of r31 is set (ARM to PRU0 event)
QBBC MAIN_LOOP, r31, 31
END:
MOV r20, r31
SBCO r20, CONST_PRUSHAREDRAM, 0, 4

// Send notification to ARM
MOV r31.b0, PRU0_ARM_INTERRUPT+16

// Halt the processor
HALT

`

PRU1 Code:

`

.origin 0
.entrypoint PRUCODE1

#include “prucode.hp”

PRUCODE1:

// Enable OCP master port
LBCO r0, CONST_PRUCFG, 4, 4
CLR r0, r0, 4 // Clear SYSCFG[STANDBY_INIT] to enable OCP master port
SBCO r0, CONST_PRUCFG, 4, 4

// Set C28 to shared ram
MOV r0, SHARED_RAM
MOV r1, PRU1_CTRL + CTPPR0
SBBO r0, r1, 0, 4

MAIN_LOOP:

// Loop unless bit 31 of r31 is set (ARM to PRU1 event)
QBBC MAIN_LOOP, r31, 31
END:

// Send notification to ARM
MOV r31.b0, PRU1_ARM_INTERRUPT+16

// Halt the processor
HALT

`

Header:

`

#ifndef _PRUCODE_HP
#define _PRUCODE_HP

#define PRU0_PRU1_INTERRUPT 17
#define PRU1_PRU0_INTERRUPT 18
#define PRU0_ARM_INTERRUPT 19
#define PRU1_ARM_INTERRUPT 20
#define ARM_PRU0_INTERRUPT 21
#define ARM_PRU1_INTERRUPT 22

#define CONST_PRUSSINTC C0
#define CONST_PRUCFG C4
#define CONST_PRUDRAM C24
#define CONST_PRUDRAM_OTHER C25
#define CONST_PRUSHAREDRAM C28
#define CONST_DDR C31

#define PRU0_CTRL 0x22000
#define PRU1_CTRL 0x24000

#define CTBIR 0x20
#define CTPPR0 0x28
#define CTPPR1 0x2c

#define OWN_RAM 0x000
#define OTHER_RAM 0x020
#define SHARED_RAM 0x100

#define GER_OFFSET 0x10
#define HIESR_OFFSET 0x34
#define SICR_OFFSET 0x24
#define EISR_OFFSET 0x28

#define INTC_CHNMAP_REGS_OFFSET 0x0400
#define INTC_HOSTMAP_REGS_OFFSET 0x0800
#define INTC_HOSTINTPRIO_REGS_OFFSET 0x0900
#define INTC_HOSTNEST_REGS_OFFSET 0x1100

#endif //_PRUCODE_HP

`

ARM Code:

`

/******************************************************************************

  • Header Files *
    ******************************************************************************/
    #include <stdio.h>
    #include <sys/mman.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <unistd.h>
    #include <string.h>
    #include <signal.h>
    #include <prussdrv.h>
    #include <pruss_intc_mapping.h>

/******************************************************************************

  • Literal Constants *
    ******************************************************************************/
    #define PRU0_NUM 0
    #define PRU1_NUM 1

#define PRUSS0_SHARED_DATARAM 4

/******************************************************************************

  • Typedefs *
    ******************************************************************************/
    typedef char boolean;

/******************************************************************************

  • Local Variables *
    ******************************************************************************/
    static volatile boolean done;

/******************************************************************************

  • Function Definitions *
    ******************************************************************************/
    void sighandle(int signum)
    {
    done = 1;
    }

int main (void)
{
unsigned int *buf; // PRU shared buffer
unsigned int ret;
tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA;

done = 0;

signal(SIGINT, sighandle);

printf("\nStarting…\r\n");
/* Initialize the PRUs */
prussdrv_init();

/* Open PRU Interrupts */
ret = prussdrv_open(PRU_EVTOUT_1);
if (ret)
{
fprintf(stderr,“ERROR: PRU1 Interrupt Failure\n\n”);
return (ret);
}

ret = prussdrv_open(PRU_EVTOUT_0);
if (ret)
{
fprintf(stderr,“ERROR: PRU0 Interrupt Failure\n\n”);
return (ret);
}

/* Get the interrupt initialized */
prussdrv_pruintc_init(&pruss_intc_initdata);

/* Allocate Shared PRU memory. /
prussdrv_map_prumem(PRUSS0_SHARED_DATARAM, (void
)&buf);

/* Execute PRU code */
prussdrv_exec_program (PRU1_NUM, “./prucode1.bin”);
prussdrv_exec_program (PRU0_NUM, “./prucode0.bin”);

while(!done)
{
sleep(1);
printf("%08x \n", buf[0] );
}
sleep(1);

prussdrv_pru_send_event( ARM_PRU1_INTERRUPT );
prussdrv_pru_wait_event (PRU_EVTOUT_1);
prussdrv_pru_clear_event (PRU_EVTOUT_1, PRU1_ARM_INTERRUPT);

prussdrv_pru_send_event( ARM_PRU0_INTERRUPT );
prussdrv_pru_wait_event (PRU_EVTOUT_0);
prussdrv_pru_clear_event (PRU_EVTOUT_0, PRU0_ARM_INTERRUPT);

printf("%08x \n", buf[0] );

prussdrv_pru_disable(PRU1_NUM);
prussdrv_pru_disable(PRU0_NUM);
prussdrv_exit ();

printf("\nDone.\n");

return(0);
}

`