I've been working through Derek Molloys book, http://exploringbeaglebone.com/, for a student project. It's been an excellent resource, but I've finally hit a snag.
For anyone else fusing the book, I'm in Chapter 13, in the section on Utilizing Regular Linux GPIOs.
I've deviated from the examples he provides by using PRU1 instead of PRU0. I've successfully used the PRUs to flash LEDs through the enhanced IO pins that tie directly to the PRU. Now I am trying to flash LEDs using the GPIO, and I'm not succeeding. I am hoping that someone here will take a look at my code and be able to spot something I've missed. I've thoroughly tested the circuit, and I am certain the the off-board electronics are working correctly. I'm confident that its either something I've missed on the dtbo or in the assembler code. But (I think) I've carefully checked my code against the examples, and I cannot spot my error.
After loading the dtbo, all the relevant GPIO pins are in mode 0x07.
I've set one enhanced IO pin to light as well, and it blinks when it is supposed to, so I know the program is running with the correct timing. None of the GPIO fins will flash, however.
// PRUSS program to trigger 10 output pins in sequence for a calculated time
// then waits for input pins to go high and starts counter
// Written by Alwyn Smith for Firefighting Drone Challenge
.setcallreg r29.w0 // set a register for CALL/RET
.origin 0 // offset of start of program in PRU memory
.entrypoint SETUP // program entry point used by the debugger
#define PRU0_R31_VEC_VALID 32;
#define PRU_EVTOUT_0 3
#define PRU_EVTOUT_1 4
#define DELAY 100000000 //#instructions for .5 second
#define GPIO0 0x44e07000 //GPIO Bank 0, see AM335x TRM tab 2.2 Peripheral Map
#define GPIO1 0x4804c000 //GPIO Bank 1
#define GPIO2 0x481ac000 //GPIO Bank 2
#define GPIO3 0x481ae000 //GPIO Bank 3
#define GPIO_CLEARDATAOUT 0x190 //for clearing GPIO registers
#define GPIO_SETDATAOUT 0x194 //for setting GPIO registers
#define GPIO_DATAOUT 0x138 //for reading GPIO registers
#define GPIO0_8 1<<8 //P8_35 gpio0[8] Output - bit 8
#define GPIO0_9 1<<9 //P8_33 gpio0[9] Output - bit 9
#define GPIO0_10 1<<10 //P8_31 gpio0[10] Output - bit 10
#define GPIO0_11 1<<11 //P8_32 gpio0[11] Output - bit 11
#define GPIO2_14 1<<14 //P8_37 gpio2[14] Output - bit 14
#define GPIO2_15 1<<15 //P8_38 gpio2[15] Output - bit 15
#define GPIO2_16 1<<16 //P8_36 gpio2[16] Output - bit 16
#define GPIO2_17 1<<17 //P8_34 gpio2[17] Output - bit 17
#define GPIO2_25 1<<25 //P8_30 gpio2[25] Output - bit 25
SETUP:
LBCO r0, c4, 4, 4 //load SYSCFG register to r0 (use c4 const address)
CLR r0, r0, 4 //clear bit 4 (STANDBY_INIT)
SBCO r0, c4, 4, 4 //store the modified r0 back at the the load addr
LDI r7, 30 //set the number of blink cycles
START:
MOV r8, DELAY //reset clock counter
TRIGGER:
//set each output pin high to start trigger pulse
SET r30.t8 //set P8_27 high
CALL DELAYON
TRIGGER_P8_30:
MOV r1, GPIO0 | GPIO_SETDATAOUT //load address for GPIO Set Data to r1
MOV r2, GPIO0_8 //write GPIO_8 to r2
SBBO r2, r1, 0, 4 //write r2 to the r1 address -LED ON
MOV r8, DELAY //reset clock counter
CALL DELAYON
TRIGGER_P8_31:
MOV r1, GPIO0 | GPIO_SETDATAOUT //load address for GPIO Set Data to r1
MOV r2, GPIO0_9 //write GPIO_9 to r2
SBBO r2, r1, 0, 4 //write r2 to the r1 address -LED ON
MOV r8, DELAY //reset clock counter
CALL DELAYON
//set each output pin low to finish trigger pulse
CLR r30.t8 //set P8_27 low
KILL_P8_30:
MOV r1, GPIO0 | GPIO_CLEARDATAOUT //load address for GPIO Clear Data to r1
MOV r2, GPIO0_8 //write GPIO_8 to r2
SBBO r2, r1, 0, 4 //write r2 to the r1 address -LED OFF
MOV r8, DELAY //reset clock counter
CALL DELAYON
KILL_P8_31:
MOV r1, GPIO0 | GPIO_CLEARDATAOUT //load address for GPIO Clear Data to r1
MOV r2, GPIO0_9 //write GPIO_9 to r2
SBBO r2, r1, 0, 4 //write r2 to the r1 address -LED OFF
MOV r8, DELAY //reset clock counter
CALL DELAYON
CHECK: //check to see if loop should continue
SUB r7, r7, 1 //reduce the cycle count by 1
QBNE START, r7, 0 //if cycle count != 0, then start new cycle
QBEQ END, r7, 0 //if r1 == 0, then end the program
DELAYON: //start a 1 second counter
SUB r8, r8, 1 //decrement the counter by 1
QBNE DELAYON, r8 , 0 //while count !=0, continue counting
RET //return to calling procedure
END:
MOV R31.b0, PRU0_R31_VEC_VALID | PRU_EVTOUT_0
HALT