I’ve got to be missing something obvious, but I even after several rounds of RTFM, I can’t seem to figure out how to get the PRU to change the direction of a pin or, at the very least, to let it go to a tri-state value.
I would go out over the L3/L4 (although that kinda smashes the whole “real-time” thing), but won’t that bump into the fact that the processor needs to be in supervisor mode?
I see you got some other answers, but it might help you to qualify if you are using a chip-level GPIO or PRU-level GPIO.
As mentioned, you don’t need a supervisor mode to get to the L3 bus needed to configure the GPIO or pinmux. You do need to clear the STANDBY_INIT bit in SYSCFG. Then, the PRU can poke all the SoC registers that the ARM can. Below is an example that clears this bit, but doesn’t need to do so, because the PRU GPIO bits are INSIDE the PRUSS, so I’ll likely remove those lines from this example in the future.
https://github.com/beagleboard/cloud9-examples/blob/master/BeagleBone/Black/pru/blinkR30.pru0.c :
////////////////////////////////////////
// blinkR30.pru0.c
// Blinks LEDs wired to P9_29 (and others) by writing register R30 on the PRU
// Wiring: P9_29 connects to the plus lead of an LED. The negative lead of the
// LED goes to a 220 Ohm resistor. The other lead of the resistor goes
// to ground.
// Setup: config_pin P9_29 pruout
// See: prugpio.h to see which pins attach to R30
// PRU: pru0
////////////////////////////////////////
#include <stdint.h>
#include <pru_cfg.h>
#include “resource_table_empty.h”
#include “prugpio.h”
volatile register unsigned int __R30;
volatile register unsigned int __R31;
void main(void) {
// Select which pins to toggle. These are all on pru1_1
uint32_t gpio = P9_29;
/* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */
CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;
while(1) {
__R30 |= gpio; // Set the GPIO pin to 1
__delay_cycles(500000000/5); // Wait 1/2 second
__R30 &= ~gpio; // Clear the GPIO pin
__delay_cycles(500000000/5);
}
__halt();
}
// Sets pinmux
#pragma DATA_SECTION(init_pins, “.init_pins”)
#pragma RETAIN(init_pins)
const char init_pins =
“/sys/devices/platform/ocp/ocp:P9_29_pinmux/state\0pruout\0” \
“\0\0”;
What I am thinking about adding to this repo is an example for reading an ultrasonic sensor that kinda stupidly (IMHO) uses the same pin to trigger a sample as to read it back. I think using the PRU for that would be good, but it means changing the pin direction. The way to do that without external hardware is to alter the PADCONF (ie., pinmux) settings on the pin to go from pru_out mode to pru_in. Otherwise, the PRU itself doesn’t have any way to go into a high-Z or tristate mode.
I’d be happy if someone beat me to both updates to the repo and provided a pull-request.