PRU1 to ARM interrupt

759 views
Skip to first unread message

Frédéric

unread,
Jun 21, 2015, 10:47:12 AM6/21/15
to beagl...@googlegroups.com
Hi!

I would like to notify my host program that PRU1 has reached the end of its execution.

On PRU1, I have:

MOV     R31.b0, PRU1_ARM_INTERRUPT+16

where PRU1_ARM_INTERRUPT = 20.

On host side, I have (using python binding):

prussdrv.init()
prussdrv
.open(prussdrv.PRU_EVTOUT_1)

...

prussdrv
.pru_wait_event(prussdrv.PRU_EVTOUT_1)
prussdrv
.pru_clear_event(prussdrv.PRU_EVTOUT_1, prussdrv.PRU1_ARM_INTERRUPT)

but it does not work; my host never comes out from pru_wait_event()...

I have to admit that I don't understand yet very well how interrupts work!

Thanks,

Frédéric

Luiz Chamon

unread,
Jun 22, 2015, 1:10:20 PM6/22/15
to beagl...@googlegroups.com
I believe you might be missing a

prussdrv.pruintc_init()

after your prussdrv.open() call. This initializes the PRU interrupt controller and determine what EVENT_1 etc. will be.

Frédéric

unread,
Jun 22, 2015, 1:26:18 PM6/22/15
to beagl...@googlegroups.com
I'll try that. Thanks !

--
Frédéric

terra ÜÝÜ

unread,
Jun 25, 2015, 4:23:32 AM6/25/15
to beagl...@googlegroups.com
ur lucky day, just did it :)
****************
// This is a nearly-minimal PRU program. It delays for five seconds, then
// notifies the host that it has completed, then halts the PRU.
//
// The idea is to have a program that does something you can see from user
// space, without doing anything complicated like playing with IO pins,
// DDR or shared memory.
//
// Try adjusting the DELAYCOUNT value and re-running the test; you should
// be able to convince yourself that the program is actually doing something.

.origin 0 // offset of the start of the code in PRU memory
.entrypoint START // program entry point, used by debugger only

// To signal the host that we're done, we set bit 5 in our R31
// simultaneously with putting the number of the signal we want
// into R31 bits 0-3. See 5.2.2.2 in AM335x PRU-ICSS Reference Guide.

#define PRU0_R31_VEC_VALID  32;
#define PRU_EVTOUT_0        3
#define PRU_EVTOUT_1        4
#define PRU1_ARM_INTERRUPT   20

#define DELAY_SECONDS 5 // adjust this to experiment
#define CLOCK 200000000 // PRU is always clocked at 200MHz
#define CLOCKS_PER_LOOP 2 // loop contains two instructions, one clock each
#define DELAYCOUNT DELAY_SECONDS * CLOCK / CLOCKS_PER_LOOP

START:

        // initialize loop counter
        MOV     r1, DELAYCOUNT

        // wait for specified period of time
DELAY:
        SUB     r1, r1, 1     // decrement loop counter
        QBNE    DELAY, r1, 0  // repeat loop unless zero
        // tell host we're done
        mov r31.b0, PRU1_ARM_INTERRUPT+16

        // initialize loop counter
        MOV     r1, DELAYCOUNT
        // wait for specified period of time
DELAY1:
        SUB     r1, r1, 1     // decrement loop counter
        QBNE    DELAY1, r1, 0  // repeat loop unless zero

        // tell host we're done, then halt
        mov r31.b0, PRU1_ARM_INTERRUPT+15
        mov r31.b0, PRU1_ARM_INTERRUPT+16

HALT
******************
/* PRUSS program to drive a HC-SR04 sensor and display the sensor output
*  in Linux userspace by sending an interrupt.
*  written by Derek Molloy for the book Exploring BeagleBone
*/
#include <stdio.h>
#include <stdlib.h>
#include <prussdrv.h>
#include <pruss_intc_mapping.h>
#include <pthread.h>
#include <unistd.h>

#include<iostream>
using namespace std;

#define PRU_NUM 1

static void *PRU1DataMemory;
static unsigned int *PRU1DataMemory_int;

void *threadFunction(void *value){
   do {
      int notimes = prussdrv_pru_wait_event (PRU_EVTOUT_1);
      cout << "PRU event 1 " << notimes << endl << flush ;
      sleep(1);
      prussdrv_pru_clear_event (PRU_EVTOUT_1, PRU1_ARM_INTERRUPT);
   } while (1);
}

int  main (void)
{
   if(getuid()!=0){
      printf("You must run this program as root. Exiting.\n");
      exit(EXIT_FAILURE);
   }
   pthread_t thread;
   tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA;

   // Allocate and initialize memory
   prussdrv_init ();
   prussdrv_open (PRU_EVTOUT_0);
   prussdrv_open (PRU_EVTOUT_1);

   // Map PRU's INTC
   prussdrv_pruintc_init(&pruss_intc_initdata);

   // Copy data to PRU memory - different way
   prussdrv_map_prumem(PRUSS0_PRU1_DATARAM, &PRU1DataMemory);
   PRU1DataMemory_int = (unsigned int *) PRU1DataMemory;
   // Use the first 4 bytes for the number of samples
   *PRU1DataMemory_int = 500;
   // Use the second 4 bytes for the sample delay in ms
   *(PRU1DataMemory_int+1) = 100;   // 2 milli seconds between samples

   // Load and execute binary on PRU
   prussdrv_exec_program (PRU_NUM, "./ultra.bin");
   if(pthread_create(&thread, NULL, &threadFunction, NULL)){
       printf("Failed to create thread!");
   }
   int n = prussdrv_pru_wait_event (PRU_EVTOUT_0);
   printf("PRU program completed, event number %d.\n", n);

   // distance in inches = time (ms) / 148 according to datasheet
   /* Disable PRU and close memory mappings */
   prussdrv_pru_disable(PRU_NUM);
   prussdrv_exit ();
   return EXIT_SUCCESS;
}
******************
:)

Frédéric

unread,
Jun 25, 2015, 10:13:40 AM6/25/15
to beagl...@googlegroups.com
Le Thursday 25 June 2015, terra a écrit :

> ur lucky day, just did it :)

Thanks! There are a lot of things I still need to understand (mainly about
default interrupt mapping), But your example helps!

Thanks,

--
Frédéric
Reply all
Reply to author
Forward
0 new messages