You are on page 1of 5

Nathan Barrett 9/30/14

Page 1 of 5

Beaglebone Black SPI Through PRU

You must set SPI up to run by using the previously described BB-SPIDEV9 overlay and
disabling HDMI. Again, P9.31 is SPI Clock, P9.30 is the stream being sent out (this
could also be P9.29 depending on settings). This is McSPI 1 channel 1 in the AM335X
manual.

This program will pass a word, number of words, and frequency to one of the PRU units.
The PRU will then repeatedly send the selected word out of the SPI channel for the
number of words at the specified frequency.

Note: The DTBO frequency is now superseded by the PRU’s settings. It doesn’t matter
what it’s set to in the BB-SPIDEV9 overlay.

Program Usage:

./SPI [word] [num words] [frequency (0-15)]

# ./SPI 808464432 1 0

INFO: Initializing.
INFO: Transmitting 808464432 (1 times) at 48000000 Hz
INFO: Sending...PRU program completed (4), in 0 seconds

This sends 0x30303030 down 1 time at 48 Hz. The resulting analyzer shot looks
something like this:

A B Interval: 20 ns

Doing multiples:

A B Cycles: 160 A B Interval: 3.584 µS

How does this compare to the expected 48 MHz?

3584 ns / 160 cycles = 22.4 ns / cycle


So 1 / (22.4 * (10^-9)) = 44.64 MHz
Nathan Barrett 9/30/14
Page 2 of 5

How far can we push it? Let’s send 128 MB at 48 MHz and watch the CPU usage.

# ./SPI 808464432 33554432 0 &

INFO: Initializing.
INFO: Transmitting 808464432 (33554432 times) at 48000000 Hz
INFO: Sending...PRU program completed (6), in 24 seconds

While sending, the main CPU is sitting around 99% idle

128 MB @ 24 seconds = 5.33 megabytes / sec

How about 24 MHz? This previously took about 60 seconds through the main processor.

./SPI 808464432 33554432 1


INFO: Initializing.
INFO: Transmitting 808464432 (33554432 times) at 24000000 Hz
INFO: Sending...PRU program completed (9), in 47 seconds

Cycles AB: 512 Interval A B: 22.27 µS

22.27 µS for 512 cycles = 43.49 ns per cycle


1/(43.49 * (10^-9)) = 22.99 MHz over 64 bytes

This is a few MHz faster.


Nathan Barrett 9/30/14
Page 3 of 5

Bulk DMA could also be set up to offload PRU usage as well. Currently, the PRU is
jamming 0x30303030 into the SPI FIFO repeatedly.

Multichannel Serial Port Interface (McSPI)

Clock Signal Max Freq Reference / Source Comments


CLK 100 MHz CORE_CLKOUTM4 / 2 pd_per_l4ls_gclk
Interface clock
From PRCM
CLKSPIREF 48 MHz PER_CLKOUTM2 / 4 pd_per_spi_gclk
Functional clock
From PRCM
Table 24-3. McSPI Clock Signals

Pin Type Description


SPIx_SCLK I/O SPI serial clock (output when master,
input when slave)
SPIx_D0 I/0 Can be configured as either input or
output (MOSI or MISO)
SPIx_D1 I/0 Can be configured as either input or
output (MOSI or MISO)
SPIx_CS0 I/0 SPI chip select 0 output when master,
input when slave (active low)
SPIx_CS1 O SPI chip select 1 output when master,
input when slave (active low)
Table 24-4. McSPI Pin List

Relevant Registers:

CM_PER_SPI1_CLKCTRL @ 0x44E00050
 Enable the Clock

MCSPI_SYSCONFIG @ 0x481A0110
 Reset the SPI

MCSPI_SYSSTATUS @ 0x481a0114
 Check Reset Completed

MCSPI_MODULCTRL @ 0x481A0128
 Turn DMA off (for now)

MCSPI_SYSCONFIG @ 0x481A0110
 Automatic OCP clock gating strategy is applied, based on the
OCP interface activity.
Nathan Barrett 9/30/14
Page 4 of 5

 Smart-idle mode: local target's idle state eventually follows


(acknowledges) the system's idle requests, depending on the IP
module's internal requirements.

 Clocks activity during wake-up mode period.


3h = OCP and Functional clocks are maintained.

MCSPI_IRQSTATUS @ 0x481A0118
 Disable Interrupts

MCSPI_CH1CTRL @ 0x481A0148
 Turn on/off SPI CH1

MCSPI_CH1CTRL @ 0x481A0140
 Set polarity, phases, frequencies, word length, tx/rx registers, etc

MCSPI_CH1STAT @ 0x481A0144
 Check buffer empty/full

MCSPI_TX1 @ 0x481A014C
 Load in data to transfer

MCSPI_XFERLEVEL @ 0x481A017C
 Could set this up to take advantage of larger FIFO sizes. Currently not being used
Nathan Barrett 9/30/14
Page 5 of 5

PRU Initialization for SPI


1) Load Device Tree Overlay to Enable PRU
echo "BB-BONE-PRU-01" > /sys/devices/bone_capemgr.*/slots
2) Load Device Tree Overlay to Enable SPI
echo "BB-SPIDEV9" > /sys/devices/bone_capemgr.*/slots

(./init script will do both of these)

// Enable OCP master port


LBCO r0, CONST_PRUCFG, 4, 4 //Config SYSCONFIG
CLR r0, r0, 4 MOV r1, 0x481A0110
SBCO r0, CONST_PRUCFG, 4, 4 MOV r2, 0x00000311
SBBO r2, r1, 0, 4
//C28 will point to 0x00012000
//(PRU shared RAM) //Reset interrupt status bits
MOV r0, 0x00000120 MOV r1, 0x481A0118
MOV r1, CTPPR_0 MOV r2, 0xFFFFFFFF
ST32 r0, r1 SBBO r2, r1, 0, 4

// Enable CLKSPIREF and CLK //Disable interupts


MOV r1, 0x44E00050 MOV r1, 0x481A011C
MOV r2, 0x00000002 MOV r2, 0x00000000
SBBO r2, r1, 0, 4 SBBO r2, r1, 0, 4

// Reset SPI // Disable channel 1


MOV r1, 0x481A0110 MOV r1, 0x481A0148
LBBO r2, r1, 0, 4 MOV r2, 0x00000000
SET r2.t1 SBBO r2, r1, 0, 4
SBBO r2, r1, 0, 4
// Configure channel 1 of MCSPI1
//Wait for RESET MOV r1, 0x481A0140
RESET: MOV r2, 0x000192FC0
MOV r1, 0x481a0114 LBCO r4, CONST_PRUSHAREDRAM,
LBBO r2, r1, 0, 4 8, 4 //frequency
QBBC RESET, r2.t0 OR r2, r2,r4
SBBO r2, r1, 0, 4
//Config MODULCTRL
MOV r1, 0x481A0128 …
MOV r2, 0x00000000
SBBO r2, r1 , 0, 4

You might also like