BBB PRU input test

I was trying a few days to enable PRU (BBB Ubuntu 12.04) and run a input testing code using the pin P9_24.

MUX = pin 97 (44e10984) 00000006 pinctrl-single (SET to MODE 6)

P9 24 pr1_pru0_pru_r31_16.GPIO0_15: | MODE6 | INPUT

Nothing happens when I put the pin to 1.8 or GND

The ASM code is:

.origin 0
.entrypoint START

#define PRU0_ARM_INTERRUPT 19
#define AM33XX

#define GPIO1 0x4804c000
#define GPIO_CLEARDATAOUT 0x190
#define GPIO_SETDATAOUT 0x194

START:
// clear that bit
LBCO r0, C4, 4, 4
CLR r0, r0, 4
SBCO r0, C4, 4, 4

MOV r0, 1000000000 //# cycles

INPUTTEST:

WBS r31.t15 //Wait til GPIO-15-in is high… P9_24
SUB r0, r0, 1 //Subtract from counter
QBNE INPUTTEST, r0, 0 //Loop if counter not at zero

// Send notification to Host for program completion
MOV R31.b0, PRU0_ARM_INTERRUPT+16

MOV r0, 0
HALT

I don’t know what I am doing wrong and in Internet are not examples for INPUT tests.

I was trying a few days to enable PRU (BBB Ubuntu 12.04) and run a input
testing code using the pin P9_24.

MUX = pin 97 (44e10984) 00000006 pinctrl-single (SET to MODE 6)

P9 24 pr1_pru0_pru_r31_16.GPIO0_15: | MODE6 | INPUT

Nothing happens when I put the pin to 1.8 or GND

You have to enable the pin's input buffer:

The ASM code is:

.origin 0
.entrypoint START

#define PRU0_ARM_INTERRUPT 19
#define AM33XX

#define GPIO1 0x4804c000
#define GPIO_CLEARDATAOUT 0x190
#define GPIO_SETDATAOUT 0x194

START:
// clear that bit
    LBCO r0, C4, 4, 4
    CLR r0, r0, 4
    SBCO r0, C4, 4, 4

    MOV r0, 1000000000 //# cycles

INPUTTEST:

WBS r31.t15 //Wait til GPIO-15-in is high... P9_24
SUB r0, r0, 1 //Subtract from counter
QBNE INPUTTEST, r0, 0 //Loop if counter not at zero
// Send notification to Host for program completion
MOV R31.b0, PRU0_ARM_INTERRUPT+16

MOV r0, 0
HALT

I don't know what I am doing wrong and in Internet are not examples for
INPUT tests.

Your code looks OK. Here's a known working example that uses the PRU
direct inputs to implement a PRU software based encoder interface:

...it's not the easiest code to use as a reference, since it relies on
my universal overlay (to setup proper pin multiplexing), and ARM code
(to setup and configure the look-up tables to do counting, see encoder.c
in the same directory), but perhaps it will be of some help.

Along with what the others have described, since you’re the arm processor gpio rather than a pru gpio, meaning you’re going all the way out to system memory, you have to connect the pru to system memory. Here’s an example of accessing system memory with the pru:

http://nomel.tumblr.com/post/30006622413/beaglebone-tutorial-accessing-main-memory-from-the-pru

To set the pin mux for arm gpio, you can use one of these gpio overlays. Just follow the instructions:

https://github.com/nomel/beaglebone/tree/master/gpio-header

Also, there are a few pru debuggers out there now so you can view/step pru execution.

-Brandon

I was finding what is wrong and finally I got it. The thing is that I don’t know how to fix it.
My BBB is Ubuntu last 12.04 version with 3.8 kernel by nelson.
The error is here:

706.650640] omap_hwmod: pruss: failed to hardreset
[ 706.682785] pinctrl-single 44e10800.pinmux: pin 44e10984 already requested by helper.12; cannot claim for 4a300000.pruss
[ 706.694442] pinctrl-single 44e10800.pinmux: pin-97 (4a300000.pruss) status -22
[ 706.702096] pinctrl-single 44e10800.pinmux: could not request pin 97 on device pinctrl-single
[ 706.738323] pruss_uio 4a300000.pruss: pins are not configured from the driver
[ 706.765286] bone-capemgr bone_capemgr.9: slot #7: Applied #3 overlays.

Provide the *.dts source for the overlay you are trying to load, and the
contents of /sys/devices/bone_capemgr.*/slots, and maybe we can figure
out what's going wrong. It looks like something has already grabbed the
pin you want to use.

Note the "pruss: failed to hardreset" always shows up and doesn't
indicate a problem (or at least not the problem you're having). Your
issue is presumably the pin overlay that fails to load.

My DTS is:

/dts-v1/;
/plugin/;

/ {
compatible = “ti,beaglebone”, “ti,beaglebone-black”;

/* identification */
part-number = “BB-BONE-W”;
version = “00A0”;
exclusive-use = “P9.24”;

fragment@0 {
target = <&am33xx_pinmux>;
overlay {
mygpio: pinmux_mygpio{
pinctrl-single,pins = <

0x184 0x16 /* P9 24 pr1_pru0_pru_r31_16.GPIO0_15: | PULLUP | MODE6 | INPUT */

;
};
};
};

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”;
pinctrl-names = “default”;
pinctrl-0 = <&mygpio>;
};
};

};

and the

cat /sys/devices/bone_capemgr.*/slots
0: 54:PF—
1: 55:PF—
2: 56:PF—
3: 57:PF—
4: ff:P-O-L Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G
5: ff:P-O-- Bone-Black-HDMI,00A0,Texas Instrument,BB-BONELT-HDMI
6: ff:P-O-- Bone-Black-HDMIN,00A0,Texas Instrument,BB-BONELT-HDMIN
8: ff:P-O-L Override Board Name,00A0,Override Manuf,BB-BONE-W

cat /sys/kernel/debug/pinctrl/44e10800.pinmux/pins | grep “pin 97”
pin 97 (44e10984) 00000037 pinctrl-single BEFORE

root@donkeytom-t001:/texka/pinmux# echo BB-BONE-W > /sys/devices/bone_capemgr.9/slots
root@donkeytom-t001:/texka/pinmux# cat /sys/kernel/debug/pinctrl/44e10800.pinmux/pins | grep “pin 97”
pin 97 (44e10984) 00000016 pinctrl-single AFTER

When I do an interruput up or down the ASM keeps waiting and nothing…

Thank you!

Manuel

When I do an interruput up or down the ASM keeps waiting and nothing…

Read my previous email. Your code will not work as is.

I read your last email with attention by still I can’t understad why my code is not working. I a few words:
The code works when properly when I comment the line " WBS r31.t15 //Wait til GPIO-15-in is high… P9_24"

PINMUX DTS:

/dts-v1/;
/plugin/;

/ {
compatible = “ti,beaglebone”, “ti,beaglebone-black”;

/* identification */
part-number = “BB-BONE-W”;
version = “00A0”;
exclusive-use = “P9.24”;

fragment@0 {
target = <&am33xx_pinmux>;
overlay {
mygpio: pinmux_mygpio{
pinctrl-single,pins = <
0x184 0x36 /* P9 24 pr1_pru0_pru_r31_16.GPIO0_15: | PULLUP | MODE6 | INPUT */

;
};
};
};

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”;
};
};
};

PIN MUX STATUS:

cat /sys/kernel/debug/pinctrl/44e10800.pinmux/pins | grep “pin 97”

pin 97 (44e10984) 00000036 pinctrl-single

UNAME +DIST:

uname -a

Linux don-t001 3.8.13-bone30 #1 SMP Thu Nov 14 11:19:20 UTC 2013 armv7l armv7l armv7l GNU/Linux

cat /etc/issue

Ubuntu 12.04.3 LTS \n \l

ASM CODE:

.origin 0
.entrypoint START

#define PRU0_ARM_INTERRUPT 19
#define AM33XX

#define GPIO1 0x4804c000
#define GPIO_CLEARDATAOUT 0x190
#define GPIO_SETDATAOUT 0x194

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

MOV r1, 1000 //# cycles

INPUTTEST:

WBS r31.t15 //Wait til GPIO-15-in is high… P9_24

SUB r1, r1, 1 //Subtract from counter
QBNE INPUTTEST, r1, 0 //Loop if counter not at zero

// Send notification to Host for program completion
MOV R31.b0, PRU0_ARM_INTERRUPT+16

MOV r1, 0
HALT

INIT PROGRAM USING PyPRUSS:

#!/usr/bin/python

‘’’ ddr_write.py - Finds the DDR address and size, passes that info to the PRU0
data memory, executes a program and reads back data from the first and last banks’‘’

import pypruss
import mmap
import struct

pypruss.modprobe()
ddr_addr = pypruss.ddr_addr()
ddr_size = pypruss.ddr_size()

print “DDR memory address is 0x%x and the size is 0x%x”%(ddr_addr, ddr_size)

ddr_offset = ddr_addr-0x10000000
ddr_filelen = ddr_size+0x10000000
ddr_start = 0x10000000
ddr_end = 0x10000000+ddr_size

pypruss.init() # Init the PRU
pypruss.open(0) # Open PRU event 0 which is PRU0_ARM_INTERRUPT
pypruss.pruintc_init() # Init the interrupt controller
pypruss.pru_write_memory(0, 0, [ddr_addr, ddr_addr+ddr_size-4]) # Put the ddr address in the first region
pypruss.exec_program(0, “./ddr_write.bin”) # Load firmware “ddr_write.bin” on PRU 0
pypruss.wait_for_event(0) # Wait for event 0 which is connected to PRU0_ARM_INTERRUPT
pypruss.clear_event(0) # Clear the event
pypruss.exit() # Exit PRU

with open(“/dev/mem”, “r+b”) as f: # Open the physical memory device
ddr_mem = mmap.mmap(f.fileno(), ddr_filelen, offset=ddr_offset) # mmap the right area

read_back = struct.unpack(“L”, ddr_mem[ddr_start:ddr_start+4])[0] # Parse the data

print "The first 4 bytes of DDR memory reads "+hex(read_back)

ddr_mem.close() # Close the memory
f.close() # Close the file

No way to read the P9_24 PIN From BBB using PRUSS

May be the WBS does no work as I think … a week working on that and still nothing.

I think I see the problem. You have the pin muxed for pru gpio in the device tree overlay, but you’re trying to read the arm gpio block. PRU gpio is accessed directly with register r30 for output and r31 for input (section 5.2.2.3 in the somewhat terrible pru reference guide).

This is what I don’t know how to do, "access to the r31 "

could you help me?

Thank you.

To read the PRU direct input pins, you simply read register r31. The
wait for bit set instruction you use ought to work. If the PRU is not
seeing any change when the I/O pin toggles, you either don't have the
pin mux configured correctly or your code is running on the wrong PRU
(there are two, after all). Dig through the sysfs pinmux debugging
information to make sure your overlay is being properly loaded, and
review your PRU loading code to make sure it's targeting the proper PRU.

I got it! Finally I understood that the "R31" capture a 16bit value corresponding with the states of all ports on this MuxMode (R31 = input).
Here the fragment of port reading code:

INPUTTEST:
         MOV r3, r31 //R31
         QBEQ QUIT, r3, 0xa8 // sensing if the bit of this pin is DOWN. 0xa8 represents the state when the pin p9_24 is down.

The only thing that I still don't understand is why I can't use the function WBS as follows: WBS r31.t15

Thank you all for your cooperation.

Regards.

Congrats!

There are a few pru debuggers out there now that support stepping through code, breakpoints, etc. Make sure you check them out!

Also, for the pru assembler, there are some command line options that will dump the program counters for all of the instructions to help with stepping.

-Brandon

you should be using r31.t16 not t15

After a long time I am back with the PRU :slight_smile:

I need to read the bit r31.t16 and capture the current state either 1 or 0 and set it to r3, I do that with this instruction:

SET r3, r31.t16 //set the bit r31.t16 to r3

When I read r3 the value is not 0 or 1, the returned value is 0x8

Any idea what is happening?

Thanks.

I'm pretty sure you don't understand the operation of the SET
instruction, which is used to *SET* a bit (ie: make it a one) rather
than copy it's value (the preceding value is lost). Add to that the
note in the PRU Reference Guide that when using R31 as the source for a
SET instruction, "the resulting bits will be NULL and not reflect the
current input event flags that are normally obtained by reading R31",
and it's not surprising your code isn't working as expected.

Perhaps the MOV or shift (LSL/LSR) instructions will behave more like
what you're wanting?

I think that the work arround to get the bit what i am looking for is to MOV into the register r3 the register r31 with all states then doing right and left shifting to get that bit.

Is it r32 a 32 bits?

I am in the right way?

Manuel

There is no r32, but all registers (including r31) are 32-bits. But r31
does not have all 32-bits hooked to direct I/O pins, so some bits may
always be zero.

If you want bit 16 of r31 to be place in r3.t0, with all other bits
cleared, you can do this with a couple instructions. I'd probably do
something like:

Shifts, taking advantage of the PRU's unsigned zero-extend

Try

AND r3, r31.b2, 0b1

Why 0b1?