Ok, I think I might have to go for the GPIO fall back option.
Here's the final setup I tried (which still did not get P1.35 to move at all).
- Kept the default device tree (BB-BELA-00A1.dtbo and BB-BELA-CTAG-SPI-00A0.dtbo, in that order)
- Configured P1.35 to be mode
pruout
- config-pin P1.35 pruout
- In my PRU code, in the main loop, call
SET r30.t10
and CLR r30.t10
in an attempt to generate a clock signal.
The full code is pasted below for reference (the commented GPIO code in it seems to work)
.origin 0
.entrypoint START
// -----------
// Definitions
// -----------
#define GPIO0 0x44E07000
#define GPIO1 0x4804C000
#define GPIO2 0x481ac000
#define GPIO_PIN_SCLOCK_BASE GPIO0
#define GPIO_PIN_SCLOCK_OFFSET 23
#define GPIO_PIN_WCLOCK_BASE GPIO0
#define GPIO_PIN_WCLOCK_OFFSET 27
#define GPIO_PIN_DATA_BASE GPIO2
#define GPIO_PIN_DATA_OFFSET 1
#define GPIO_OE 0x134
#define GPIO_DATAIN 0x138
#define GPIO_CLEARDATAOUT 0x190
#define GPIO_SETDATAOUT 0x194
#define PRU0_ARM_INTERRUPT 19 // Interrupt signalling we're done
#define PRU1_ARM_INTERRUPT 20 // Interrupt signalling a block is ready
#define CHANNELS 0x2
#define BITS 0x10
// ------------
// Register map
// ------------
// --- r1, r2, r3 are used for temporary storage ---
// r4 to r26 available
// --- r27, r28 used in macros ---
// r29 to r31 available
// -------------
// Useful macros
// -------------
// GPIO_DIRECTION: Set the direction of a GPIO pin
// Parameters:
// gpio_base: address of the particular GPIO peripheral (e.g. GPIO1)
// gpio_num_bit: which bit number to change (0 to 31)
// output zero for input, nonzero for output
// Uses registers: r27, r28
.macro GPIO_DIRECTION
.mparam gpio_base, gpio_num_bit, output
MOV r27, gpio_base
MOV r28, GPIO_OE
ADD r27, r27, r28
MOV r28, output
QBEQ SET_INPUT, r28, 0
SET_OUTPUT: // Pin should become an output
LBBO r28, r27, 0, 4 // Load current OE register to R28
CLR r28, gpio_num_bit
QBA DONE
SET_INPUT: // Pin should become an input
LBBO r28, r27, 0, 4 // Load current OE register to R28
SET r28, gpio_num_bit
DONE:
SBBO r28, r27, 0, 4
.endm
// GPIO_WRITE: Set the value of a GPIO output pin
// Parameters:
// gpio_base: address of the particular GPIO peripheral (e.g. GPIO1)
// gpio_num_bit: which bit number to change (0 to 31)
// value: whether pin should be high (nonzero) or low (zero)
// Uses registers: r27, r28
.macro GPIO_WRITE
.mparam gpio_base, gpio_num_bit, value
MOV r27, gpio_base
MOV r28, value
QBEQ SET_LOW, r28, 0
SET_HIGH:
LDI r28, GPIO_SETDATAOUT
ADD r27, r27, r28
QBA DONE
SET_LOW:
LDI r28, GPIO_CLEARDATAOUT
ADD r27, r27, r28
DONE:
LDI r28, 0
SET r28, gpio_num_bit
SBBO r28, r27, 0, 4
.endm
// DELAY: Wait (busy loop) for a specified time
// Parameters:
// count: how long to wait, in 10ns increments
// this macro also adds a constant 10ns at the beginning
// Uses registers: r27
.macro DELAY
.mparam count
MOV r27, count
DELAY_LOOP:
SUB r27, r27, 1
QBNE DELAY_LOOP, r27, 0
.endm
START:
//GPIO_DIRECTION GPIO_PIN_SCLOCK_BASE, GPIO_PIN_SCLOCK_OFFSET, 1
//GPIO_DIRECTION GPIO_PIN_WCLOCK_BASE, GPIO_PIN_WCLOCK_OFFSET, 1
//GPIO_DIRECTION GPIO_PIN_DATA_BASE, GPIO_PIN_DATA_OFFSET, 1
LDI r7, 0
LDI r6, 0
LDI r5, 0
LDI r4, 0
MAIN:
//GPIO_WRITE GPIO_PIN_SCLOCK_BASE, GPIO_PIN_SCLOCK_OFFSET, 1
//GPIO_WRITE GPIO_PIN_WCLOCK_BASE, GPIO_PIN_WCLOCK_OFFSET, r4
//GPIO_WRITE GPIO_PIN_DATA_BASE, GPIO_PIN_DATA_OFFSET, r7
SET r30.t10
LSR r4, r5, 0x4
ADD r6, r6, 1
AND r6.b1, r6.b1, 0x7
DELAY 0xff
//GPIO_WRITE GPIO_PIN_SCLOCK_BASE, GPIO_PIN_SCLOCK_OFFSET, 0
//GPIO_WRITE GPIO_PIN_WCLOCK_BASE, GPIO_PIN_WCLOCK_OFFSET, r4
//GPIO_WRITE GPIO_PIN_DATA_BASE, GPIO_PIN_DATA_OFFSET, r7
CLR r30.t10
LSR r7, r6, 0xa
ADD r5, r5, 1
AND r5, r5, 0x1f
DELAY 0xff
QBA MAIN
// Signal the ARM that we have finished
MOV R31.b0, PRU0_ARM_INTERRUPT + 16
HALT