hi,
I’ll place this info here just for reference. The code is “rough” and based off the examples. I was a newbie to this stuff to, and I still am, but I made some progress.
I used the PRU to quickly scan p8_16 for input coming from an IR Sensor (IRM-3438). The PRU will read the p8_16 at close to 10ns. After comparing the input to a PWM output, I would say either the PWM has precision issues or the GPIO/PRU can’t read at 10ns, but it’s still significantly less than 1microsecond, iirc.
IR wiring:
BBB IR Sensor
3.3V_sys → 100 ohm → vcc
gnd → gnd
p8_16 → 4.7 kOhm → ir output
Typical output for IRM-3438 with a yk-001 remote:
`
`
Values close to 60000±10000 are 0’s, where values close to 160000±10000 are 1’s. Start value is 909000 ±10000 is a code start value. Code size is 64, however all codes for the yk-001 can be used by just looking at the “on” times: 60000 for 0, 160000 for 1, 10000 tolerance.
Regards,
Rene Robichaud
BB-BONE-PRU-00A0.dts:
`
/*
- pru dts file BB-BONE-PRU-00A0.dts
*/
/dts-v1/;
/plugin/;
/ {
compatible = “ti,beaglebone”, “ti,beaglebone-black”;
/* identification */
part-number = “BB-BONE-PRU”;
version = “00A0”;
exclusive-use =
“pru0”,
“P8.16”;
fragment@0 {
target = <&am33xx_pinmux>;
overlay {
mygpio: pinmux_mygpio{
pinctrl-single,pins =
<
0x038 0x2e /* p8_16 input gpio1_14 mode, no pullup/down */
;
};
};
};
fragment@1 {
target = <&ocp>;
overlay {
test_helper: helper {
compatible = “bone-pinmux-helper”;
pinctrl-names = “default”;
pinctrl-0 = <&mygpio>;
status = “okay”;
};
};
};
fragment@2{
target = <&pruss>;
overlay {
status = “okay”;
};
};
};
`
pru_p8_16.p:
`
.origin 0
.entrypoint start
#define GPIO1 0x4804c000
#define GPIO2 0x481ac000
#define GPIO_OE 0x134
#define GPIO_DATAIN 0x138
// Refer to this mapping in the file - \prussdrv\include\pruss_intc_mapping.h
#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_PRUCFG C4
#define CONST_PRUDRAM C24
#define CONST_PRUSHAREDRAM C28
#define CONST_DDR C31
// Address for the Constant table Block Index Register (CTBIR)
#define CTBIR 0x22020
// Address for the Constant table Programmable Pointer Register 0(CTPPR_0)
#define CTPPR_0 0x22028
// Address for the Constant table Programmable Pointer Register 1(CTPPR_1)
#define CTPPR_1 0x2202C
///////////////////////////////////////////////////////////////////////////////
// start
///////////////////////////////////////////////////////////////////////////////
start:
// 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
// Configure the programmable pointer register for PRU0 by setting c28_pointer[15:0]
// field to 0x0120. This will make C28 point to 0x00012000 (PRU shared RAM).
mov r0, 0x00000120
mov r1, CTPPR_0
sbbo r0, r1, 0, 4
// Configure the programmable pointer register for PRU0 by setting c31_pointer[15:0]
// field to 0x0010. This will make C31 point to 0x80001000 (DDR memory).
mov r0, 0x00100000
mov r1, CTPPR_1
sbbo r0, r1, 0, 4
//Load values from external DDR Memory into Registers R0/R1/R2
//lbco r0, CONST_DDR, 0, 16
reset:
mov r1, 0 // off counter
mov r2, 0 // on counter
mov r3, 0 // period counter
// off loop
loop_off:
add r1, r1, 1 // increment off counter
qbbc loop_off, r31, 14 // while ( r31.t14 == 0 )
// check to see if arm processor signals exit
qbbs exit, r31, 30 // r31.t30
// on loop
loop_on:
add r2, r2, 1 // inc on counter
qbbs loop_on, r31, 14 // while ( r31.t14 == 1 )
send_data:
// store values of registers r0, r1, r2 and r3 into PRU shared RAM
sbco r0, CONST_PRUSHAREDRAM, 0, 32
// notify program
mov r31.b0, PRU0_ARM_INTERRUPT+16
jmp reset
exit:
// notify program
mov r31.b0, PRU0_ARM_INTERRUPT+16
halt
`
pru_p8_16.c
`
// modified pru example to read p8_16 at close to 10ns
// Rene Robichaud
#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
// Driver header file
#include <prussdrv.h>
#include <pruss_intc_mapping.h>
#define PRU_NUM 0
#define DDR_BASEADDR 0x80000000
#define OFFSET_DDR 0x00001000
#define OFFSET_SHAREDRAM 2048 // 0x00002000
#define ADDEND1 0x98765400u
#define ADDEND2 0x12345678u
#define ADDEND3 0x00000001u
#define ADDEND4 0x87654321u
#define PRUSS0_SHARED_DATARAM 4
static int mem_fd;
static void *ddrMem, *sharedMem;
static unsigned int *sharedMem_uint;
int g_interrupted = 0;
//=============================================================================
static int user_pru_init( unsigned short pru_num )
{
void *DDR_regaddr1, *DDR_regaddr2, *DDR_regaddr3, *DDR_regaddr4;
/* open the device */
mem_fd = open( “/dev/mem”, O_RDWR );
if (mem_fd < 0)
{
printf( “Failed to open /dev/mem (%s)\n”, strerror( errno ) );
return -1;
}
/* map the DDR memory */
ddrMem = mmap( 0, 0x0FFFFFFF, PROT_WRITE | PROT_READ, MAP_SHARED, mem_fd, DDR_BASEADDR );
if ( ddrMem == NULL )
{
printf(“Failed to map the device (%s)\n”, strerror(errno));
close(mem_fd);
return -1;
}
/* Store Addends in DDR memory location */
DDR_regaddr1 = ddrMem + OFFSET_DDR;
DDR_regaddr2 = ddrMem + OFFSET_DDR + 0x00000004;
DDR_regaddr3 = ddrMem + OFFSET_DDR + 0x00000008;
DDR_regaddr4 = ddrMem + OFFSET_DDR + 0x0000000c;
(unsigned int) DDR_regaddr1 = ADDEND1;
(unsigned int) DDR_regaddr2 = ADDEND2;
(unsigned int) DDR_regaddr3 = ADDEND3;
(unsigned int) DDR_regaddr4 = ADDEND4;
return(0);
}
//=============================================================================
static unsigned short user_pru_recv_data( unsigned short pru_num )
{
/* Allocate Shared PRU memory. /
prussdrv_map_prumem( PRUSS0_SHARED_DATARAM, &sharedMem );
sharedMem_uint = (unsigned int) sharedMem;
return 1;
}
//=============================================================================
int main( int argc, char* argv )
{
unsigned int ret;
tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA;
int i;
int update = 0;
printf(“\nINFO: Starting %s example.\r\n”, “PRU_p8_12”);
/* Initialize the PRU */
prussdrv_init ();
/* Open PRU Interrupt */
ret = prussdrv_open( PRU_EVTOUT_0 );
if (ret)
{
printf(“prussdrv_open open failed\n”);
return (ret);
}
/* Get the interrupt initialized */
prussdrv_pruintc_init(&pruss_intc_initdata);
/* Initialize example */
printf(“\tINFO: Initializing example.\r\n”);
user_pru_init( PRU_NUM );
/* Execute example on PRU */
printf(“\tINFO: Executing example.\r\n”);
// EXECUTE
prussdrv_exec_program (PRU_NUM, “./pru_p8_16.bin”);
/* Wait until PRU0 has finished execution */
printf(“\tINFO: Waiting for HALT command.\r\n”);
while ( !g_interrupted )
{
// wait for interrupt
prussdrv_pru_wait_event ( PRU_EVTOUT_0 );
prussdrv_pru_clear_event ( PRU_EVTOUT_0, PRU0_ARM_INTERRUPT );
// process pru shared memory
user_pru_recv_data( PRU_NUM );
update = !update;
printf( "%c ", update ? ‘+’ : ‘-’ );
for ( i = 1; i < 3; i++ )
{
printf( "%10u ", sharedMem_uint[ OFFSET_SHAREDRAM + i ] );
}
printf( “\n” );
}
prussdrv_pru_wait_event ( PRU_EVTOUT_0 );
prussdrv_pru_clear_event ( PRU_EVTOUT_0, PRU0_ARM_INTERRUPT );
/* Disable PRU and close memory mapping*/
prussdrv_pru_disable( PRU_NUM );
prussdrv_exit ();
munmap( ddrMem, 0x0FFFFFFF );
close( mem_fd );
return 0;
}
`