I finally got my Beaglebone Black PRU C code project up and going. It took a lot of googling and posting, but I thought it would be nice to post a condensed version of the notes needed to get C code running on the BBB PRU. This is targeting Debian 3.8 kernel versions.
------------------------------------------------------------------------------ Possible PRU pin mappings + values for device tree building + BBB conflict pins ------------------------------------------------------------------------------ Bit pr1_pru0_pru_r30_? (out) 0 P9_31, gpio3[14], 0x190 , Mode 6 1 P9-29, gpio3[15], 0x194, Mode 6 2 P9-30, gpio3[16], 0x198, Mode 6 (HDMI, LCD) 3 P9-28, gpio3[17], 0x19c, Mode 6 4 P9-42, gpio3[14], 0x1a0, Mode 6 5 P9-27, gpio3[19], 0x1a4, Mode 6 (HDMI, LCD) 6 P9-41, gpio3[20], 0x1a8, Mode 6 7 P9-25, gpio3[21], 0x1ac, Mode 6 8 9 10 11 12 13 14 P8-12, gpio1[12], 0x030, Mode 6 15 P8-11, gpio1[13], 0x034, Mode 6 Bit pr1_pru0_pru_r31_? (in) 0 P9-31, gpio3[14], 0x190, Mode 5 1 P9-29, gpio3[15], 0x194, Mode 5 2 P9-30, gpio3[16], 0x198, Mode 5 (HDMI, LCD) 3 P9-28, gpio3[17], 0x19c, Mode 5 4 P9-42, gpio3[14], 0x1a0, Mode 5 5 P9-27, gpio3[19], 0x1a4, Mode 5 6 P9-41, gpio3[20], 0x1a8, Mode 5 7 P9-25, gpio3[21], 0x1ac, Mode 5 8 9 10 11 12 13 14 P8-16, gpio1[14], 0x038, Mode 6 15 P8-15, gpio1[15], 0x03c, Mode 6 16 P9-24, gpio0[15], 0x0184, Mode 6 (HDMI, LCD) 16 P9-41, gpio3[20], 0x164, Mode 5 Bit pr1_pru1_pru_r30_? (out) 0 P8-45, gpio2[6], 0x0a0, Mode 5 (HDMI, LCD) 1 P8-46, gpio2[7], 0x0a0, Mode 5 (HDMI, LCD) 2 P8-43, gpio2[8], 0x0a8, Mode 5 (HDMI, LCD) 3 P8-44, gpio2[9], 0x0ac, Mode 5 (HDMI, LCD) 4 P8-41, gpio2[10], 0x0b0, Mode 5 (HDMI, LCD) 5 P8-42, gpio2[11], 0x0b4, Mode 5 (HDMI, LCD) 6 P8-39, gpio2[12], 0x0b8, Mode 5 (HDMI, LCD) 7 P8-40, gpio2[13], 0x0bc, Mode 5 (HDMI, LCD) 8 P8-27, gpio2[22], 0x0e0, Mode 5 (HDMI, LCD) 9 P8-29, gpio2[23], 0x0e4, Mode 5 (HDMI, LCD) 10 P8-28, gpio2[24], 0x0e8, Mode 5 (HDMI, LCD) 11 12 P8-21, gpio1[30], 0x080, Mode 5 (HDMI, LCD) 13 P8-20, gpio1[31], 0x084, Mode 5 (HDMI, LCD) 14 15 16 Bit pr1_pru1_pru_r31_? (in) 0 P8-45, gpio2[6], 0x0a0, Mode 6 (HDMI, LCD) 1 P8-46, gpio2[7], 0x0a0, Mode 6 (HDMI, LCD) 2 P8-43, gpio2[8], 0x0a8, Mode 6 (HDMI, LCD) 3 P8-44, gpio2[9], 0x0ac, Mode 6 (HDMI, LCD) 4 P8-41, gpio2[10], 0x0b0, Mode 6 (HDMI, LCD) 5 P8-42, gpio2[11], 0x0b4, Mode 6 (HDMI, LCD) 6 P8-39, gpio2[12], 0x0b8, Mode 6 (HDMI, LCD) 7 P8-40, gpio2[13], 0x0bc, Mode 6 (HDMI, LCD) 8 P8-27, gpio2[22], 0x0e0, Mode 6 (HDMI, LCD) 9 P8-29, gpio2[23], 0x0e4, Mode 6 (HDMI, LCD) 10 P8-28, gpio2[24], 0x0e8, Mode 6 (HDMI, LCD) 11 12 P8-21, gpio1[30], 0x080, Mode 6 (HDMI, LCD) 13 P8-20, gpio1[31], 0x084, Mode 6 (HDMI, LCD) 14 15 16 P9-26, gpio1[29], 0x180, Mode 6 ------------------------------------------------------------------------------ Beaglebone Black Kernel 3.8 Device Tree Overlay - map GPIO pins directly to PRU R30 or R31 Create overlay file /lib/kernel/myoverlay-00A0.dts using contents below. Compile using device tree compiler (dtc): #sudo apt-get install device-tree-compiler #sudo dtc -O dtb -o /lib/firmware/myoverlay-00A0.dtbo -b 0 -@ /lib/firmware/myoverlay-00A0.dts Modify cape manager file in /etc/default/capemgr to load overlay during boot: #sudo nano /etc/default/capemgr CAPE=myoverlay Edit /etc/modules and append text #sudo nano /etc/modules uio_pruss ------------------------------------------------------------------------------ /dts-v1/; /plugin/; / { compatible = "ti,beaglebone", "ti,beaglebone-black"; /* identification */ part-number = "MYOVERLAY"; version = "00A0"; /* state the resources this cape uses */ exclusive-use = // PRU resources used "pruss", "pru0", // PRU Input pins "P8.16","pr1_pru0_pru_r31_14", // PIN Name and the PRU port it maps to (see table above) // PRU Output pins "P9.31","pr1_pru0_pru_r30_0"; // MUX Bit Maps: // 0x40 = slow slew (0 = fast slew) // 0x20 = input (0 = output) // 0x10 = pullup, 0x08 = disabled (0 = pulldown) // 0x01 to 0x07 = mode 1 to 7 fragment@8 { target = <&am33xx_pinmux>; __overlay__ { pruss_pins: pruss_pins { pinctrl-single,pins = < 0x038 0x36 // P8_16, gpio3[14] mode 6, input pull-up 0x190 0x15 // P9_31 gpio1[19] mode 5, output, pull-down >; }; }; }; fragment@10 { target = <&pruss>; __overlay__ { status = "okay"; // This enables the PRU pinctrl-names = "default"; pinctrl-0 = <&pruss_pins>; // This uses our custom mapping (see above definition) // This is for documentation only. You can see the pin mappings by: // sudo cat /sys/kernel/debug/gpio any_name1 { // Grouping of pins under this name pin-names = "Input pin description"; // one name per pin defined in gpios. Multiple entries are comma seperated; gpios = <&gpio4 14 1>; // &gpio? (One based: 1-4 instead of 0-3) bit(0-31) input(1)/output(0). Multiple entries seperated by a space }; any_name2 { pin-names = "Output pin description"; gpios = <&gpio2 19 0>; }; }; }; }; ------------------------------------------------------------------------------ PRU C Code – compile using clpru & hexpru ------------------------------------------------------------------------------ // C library Installed by: apt-get install am335x-pru-package ti-pru-cgt-installer #include <stdint.h> // PRU support libraries Installed from home directory with: git clone git://git.ti.com/pru-software-support-package/pru-software-support-package.git pru_support #include <pru_cfg.h> #define PRU0_ARM_INTERRUPT 19 // Interrupt used to signal to host we have halted volatile register uint32_t __R30; // Output pins volatile register uint32_t __R31; // Input pins // Mapping Constant table register to variable volatile pruCfg CT_CFG __attribute__((cregister("CFG", near), peripheral)); // PRU CFG register pointer loaded from constants table (see lnk.cmd) int main(void) { // Enable OCP master ports - this enables pinmux pins to R30 & R31 & host ram access (all the BBB GPIO ports & such) CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; // Do work - write your code here // Signal the process has completed (this will wake up the loader to tell it work is done) __R31 = (__R31 & ~0xff) | (PRU0_ARM_INTERRUPT+16); return 0; } ------------------------------------------------------------------------------ lnk.cmd – linker command file defines physical address mappings ------------------------------------------------------------------------------ -cr -stack 0x100 -heap 0x100 MEMORY { PAGE 0: PRUIMEM : org = 0x00000000 len = 0x00002000 /* 8kB PRU0 Instruction RAM */ PAGE 1: PRUDMEM : org = 0x00000000 len = 0x00002000 /* 8kB PRU Data RAM 0 */ SHAREDMEM : org = 0x00010000 len = 0x00003000 /* 12kB Shared RAM */ PRU0_CTRL : org = 0x00022000 len = 0x00000030 PRU1_CTRL : org = 0x00024000 len = 0x00000030 /* Constant Table Memory directives. */ INTC : org = 0x00020000 len = 0x00001504 CREGISTER=0 DMTIMER2 : org = 0x48040000 len = 0x00000100 CREGISTER=1 I2C1 : org = 0x4802A000 len = 0x00000100 CREGISTER=2 ECAP : org = 0x00030000 len = 0x00000100 CREGISTER=3 CFG : org = 0x00026000 len = 0x00000100 CREGISTER=4 MMCHS0 : org = 0x48060000 len = 0x00000100 CREGISTER=5 MCSPI0 : org = 0x48030000 len = 0x00000100 CREGISTER=6 UART0 : org = 0x00028000 len = 0x00000100 CREGISTER=7 MCASP0_DMA : org = 0x46000000 len = 0x00000100 CREGISTER=8 GEMAC : org = 0x4A100000 len = 0x00000100 CREGISTER=9 RSVD10 : org = 0x48318000 len = 0x00000100 CREGISTER=10 UART1 : org = 0x48022000 len = 0x00000100 CREGISTER=11 UART2 : org = 0x48024000 len = 0x00000100 CREGISTER=12 RSVD13 : org = 0x48310000 len = 0x00000100 CREGISTER=13 DCAN0 : org = 0x481CC000 len = 0x00000100 CREGISTER=14 DCAN1 : org = 0x481D0000 len = 0x00000100 CREGISTER=15 MCSPI1 : org = 0x481A0000 len = 0x00000100 CREGISTER=16 I2C2 : org = 0x4819C000 len = 0x00000100 CREGISTER=17 EHRPWM1 : org = 0x48300000 len = 0x00000100 CREGISTER=18 EHRPWM2 : org = 0x48302000 len = 0x00000100 CREGISTER=19 EHRPWM3 : org = 0x48304000 len = 0x00000100 CREGISTER=20 MDIO : org = 0x00032400 len = 0x00000100 CREGISTER=21 MBX0 : org = 0x480C8000 len = 0x00000100 CREGISTER=22 SPINLOCK : org = 0x480CA000 len = 0x00000100 CREGISTER=23 /* PRU0_1 : org = 0x00000000 len = 0x00000100 CREGISTER=24 PRU1_0 : org = 0x00000000 len = 0x00000100 CREGISTER=25 */ IEP : org = 0x0002E000 len = 0x0000031C CREGISTER=26 /* MII_RT : org = 0x00032000 len = 0x00000100 CREGISTER=27 SHARED_RAM : org = 0x00000000 len = 0x00000100 CREGISTER=28 */ TPCC : org = 0x49000000 len = 0x000010A0 CREGISTER=29 L3OCMC : org = 0x40000000 len = 0x00010000 CREGISTER=30 DDR : org = 0x80000000 len = 0x00000100 CREGISTER=31 } SECTIONS { /* Forces _c_int00 to the start of PRU IRAM. Not necessary when loading an ELF file, but useful when loading a binary */ .text:_c_int00* > 0x0, PAGE 0 .text > PRUIMEM, PAGE 0 .stack > PRUDMEM, PAGE 1 .bss > PRUDMEM, PAGE 1 .cio > PRUDMEM, PAGE 1 .data > PRUDMEM, PAGE 1 .switch > PRUDMEM, PAGE 1 .sysmem > PRUDMEM, PAGE 1 .cinit > PRUDMEM, PAGE 1 .rodata > PRUDMEM, PAGE 1 .rofardata > PRUDMEM, PAGE 1 .farbss > PRUDMEM, PAGE 1 .fardata > PRUDMEM, PAGE 1 .PRU0_CTRL > PRU0_CTRL, PAGE 1 .resource_table > PRUDMEM, PAGE 1 } ------------------------------------------------------------------------------ bin.cmd – used by hexpru to generate text.bin and data.bin ------------------------------------------------------------------------------ -b -image ROMS { PAGE 0: text: o = 0x0, l = 0x1000, files={text.bin} PAGE 1: data: o = 0x0, l = 0x1000, files={data.bin} } ------------------------------------------------------------------------------ Compile command: ------------------------------------------------------------------------------ clpru -i /usr/share/ti/cgt-pru/lib -i ~/pru_support/include -i . --endian=little --define am3359 --define pru0 --silicon_version=3 -o1 source.c -z lnk.cmd -o source.out -m source.map hexpru bin.cmd pru_cblink.out ------------------------------------------------------------------------------ pru_loader.c – host side code to load the text.bin image to pru 0. Compile with: gcc -o pru_loader pru_loader.c -lprussdrv Run from linux command prompt to deploy text.bin to PRU 0 and run it (text.bin must be in the current directory) ------------------------------------------------------------------------------ #include <stdio.h> #include <stdlib.h> #include <prussdrv.h> #include <pruss_intc_mapping.h> #define PRU_NUM 0 #define AM33XX int main (int argc, char **argv) { unsigned int ret; tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA; /* Initialize the PRU */ prussdrv_init (); /* Open PRU Interrupt */ ret = prussdrv_open(PRU_EVTOUT_0); if (ret) { printf("prussdrv_open open failed\n"); return (ret); } /* Get the interrupt initialized */ prussdrv_pruintc_init(&pruss_intc_initdata); /* Execute example on PRU */ prussdrv_exec_program (PRU_NUM, "./text.bin"); /* Wait until PRU0 has finished execution */ prussdrv_pru_wait_event (PRU_EVTOUT_0); prussdrv_pru_clear_event (PRU_EVTOUT_0, PRU0_ARM_INTERRUPT); /* Disable PRU and close memory mapping*/ prussdrv_pru_disable (PRU_NUM); prussdrv_exit (); return(0); } -- For more options, visit http://beagleboard.org/discuss --- You received this message because you are subscribed to the Google Groups "BeagleBoard" group. To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.