PRU Subroutines

I am currently working on a project that requires many delays in my code to get the timing correct. I want to call a subroutine multiple times through my main code to execute a simple delay. Right now I just use.

CALL DELAY2

Which I then have the following code to create a delay before it returns back to my original code to keep moving along.

`
DELAY2:
MOV r8,20
DEC:
SUB r8, r8, 1
QBNE DEC, r8, 1
RET

`
This doesn’t seem to delay my code all the time and doesn’t always seemed to get called. It gets called approximately 25 times in my script.

Write now I have the subroutine placed after my end statement. I have tried it in my main code as well but seems to go out of its loop.

Is this the proper syntax to execute a subroutine on the PRU?

Thanks,
Tyler

This procedure should take about 80ns to run when ever called. The syntax looks good.
If called from a procedure running on a PRU subsystem, it should soak up the cycles.
If called from a script running on sysfs, all bets are off on timing. It might take 200ns or longer.
If you give more information, it would be easier to zero in on the problem.
Chad

I found a solution to the problem. The Call routine uses the r30 register to store the address at. I currently use that register for manipulating inputs and outputs. At the beginning of the program I added…

.setcallreg r14.w0

That has seemed to resolved the possible register conflict issue and everything is functioning as it should. This now add all of the delays necessary.

Although off topic, another issue I seem to be having is with the interrupts necessary to go between both PRU’s. I tried to setup a pin to toggle on header P8 but haven’t come up with anything coming off of that pin. I know that pin is already allocated to MCASP0. The only solution that seemed to work was that if you went into the boot directory you could open up the device tree and delete the two snippets of code that were apart of MCASP0. From the device tree though it appeared they had already been disabled, so I deleted them. I also had no problem loading a new device tree overlay for pin31. However, with my current code I am trying to access from one PRU to the other so that way I can have one strictly handling data while the other does overhead.

Working from PRU1 and wanting to send an interrupt notice to PRU0 I used the following snippet of code to do this. I am using the PRUSSDRV libraries supplied to me by TI.

LDI r31, PRU1_PRU0_INTERRUPT+16

Then on the PRU0 side I service the interrupt with the following. First I wait for interrupt to be set, then I clear the ready signal from PRU1.

`
WBS R30, 30
SBCO &r0, C0,0x24,4
SET r31.t0 //Toggle pin 31 on header 8
CLR r31.t0

`

Once again I get now output from pin 31, nor do I believe that the interrupt is entering correctly.

Thanks,
Tyler

Jon

Hi Jon,

Thank you for your reply. There were a few instructions between the SET and CLR operations which did allow for a longer pulse. I added a loop in there to delay it for 250ns which should be sufficient for my test equipment as it samples at 100Ms/s. To clarify further you can see that my device tree overlay is enabled without conflict, but still no output from the pin.

`
root@beaglebone:~/# cat /sys/devices/bone_capemgr.8/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
7: ff:P-O-L Override Board Name,00A0,Override Manuf,bspm_P8_27_d
8: ff:P-O-L Override Board Name,00A0,Override Manuf,BB-BONE-PRU-01
9: ff:P-O-L Override Board Name,00A0,Override Manuf,bspm_P8_28_d
10: ff:P-O-L Override Board Name,00A0,Override Manuf,bspm_P8_17_f
11: ff:P-O-L Override Board Name,00A0,Override Manuf,bspm_P8_29_2e
12: ff:P-O-L Override Board Name,00A0,Override Manuf,bspm_P8_30_d
13: ff:P-O-L Override Board Name,00A0,Override Manuf,bspm_P8_39_2e
14: ff:P-O-L Override Board Name,00A0,Override Manuf,bspm_P8_40_2e
15: ff:P-O-L Override Board Name,00A0,Override Manuf,bspm_P8_41_2e
16: ff:P-O-L Override Board Name,00A0,Override Manuf,bspm_P8_42_2e
17: ff:P-O-L Override Board Name,00A0,Override Manuf,bspm_P8_43_2e
18: ff:P-O-L Override Board Name,00A0,Override Manuf,bspm_P8_44_2e
19: ff:P-O-L Override Board Name,00A0,Override Manuf,bspm_P8_45_2e
20: ff:P-O-L Override Board Name,00A0,Override Manuf,bspm_P8_46_2e
21: ff:P-O-L Override Board Name,00A0,Override Manuf,bspm_P9_31_d

`

If the pins were already allocated I believe that upon loading the overlay I would have received an error message but received none.

I need to find a way to interrupt PRU0 correctly as to manipulate this data. I tried to follow the PRU0 to PRU1 interrupt example and believe that I have the syntax correct. I would just like to find a way to confirm that the program is cycling correctly by toggling that pin.

I am calling my interrupts from PRU1 with

SET r31.t31

and then receiving my interrupts with

WBS eventStatus, 31 //Wait for bit set for Interrupt
LDI regVal.w2, 0x0000 //Clear the status of Interrupt
LDI regVal.w0, SYS_EVT_PRU0
SBCO regVal, CONST_PRUSSINTC, SICR_OFFSET, 4

where eventstatus is r31 and regVal is r17.

During all of this I set r30.t0 (P9_31) and run a loop for 50 intervals and then clear r30.t0.

When running this code on PRU0 it never reaches its halt statement. I have the halt statement as I believe it would be necessary to keep PRU0 from getting stuck at the interrupt in the code and to interrupt the ARM. I am going to move forward with removing the HALT statement at the end as well as the ARM interrupt and just have it always branch and have PRU1 responsible for ARM interrupt and taking care of disabling both PRU’s. Then I will just QBA in the PRU0 code to take care of just waiting for the next interrupt.

I don’t believe I need to setup any enables for these system events as it is not shown in the PRUtoPRU example code or in the Reference Guide.