Replicape was announced as the winner of the BeagleBone cape contest! In honor of that, here is a very special blog post for you: A long expected library!
Update 31/01-2014: PyPRUSS is now available as a package for easy installation:
The Programmable Real-time Units (PRU) in the BeagleBone are perfect for controlling steppers motor movements. With the 200MHz system clocks on these bad boys you get some 5ns resolution,
more than enough for some good old fashion acceleration.
I could not find any Python bindings for controlling the PRUs, so I decided to start one myself.
The library is called PyPRUSS and is meant to be a wrapper for the C-library that already exists for controlling the PRUs.
So far, the library is experimental at best, but it does implement the basic functionality for initializing, loading a binary file into the program memory of the PRUs, catching events and exiting.
The functions that are mapped are the functions described on the Texas Instruments wiki:
Some of the functions are missing, especially for mapping as DDR memory shared between the ARM and PRUs. Instead, it is possible to map the memory directly from Python by using mmap:
import pypruss import mmap DDR_BASEADDR = 0x70000000 # The actual baseaddr is 0x80000000, but due to a bug(?), DDR_HACK = 0x10001000 # Python accept unsigned int as offset argument. DDR_FILELEN = DDR_HACK+0x1000 # The amount of memory to make available DDR_OFFSET = DDR_HACK # Add the hack to the offset as well. with open("/dev/mem", "r+b") as f: # Open the memory device ddr_mem = mmap.mmap(f.fileno(), DDR_FILELEN, offset=DDR_BASEADDR) # data = "".join(map(chr, [5, 0, 0, 0])) # Make the data, it needs to be a string ddr_mem[DDR_OFFSET:DDR_OFFSET+4] = data # Write the data to the DDR memory, four bytes should suffice ddr_mem.close() # Close the memory f.close() # Close the file pypruss.modprobe() # This only has to be called once pr boot pypruss.init() # Init the PRU pypruss.open(0) # Open PRU event 0 which is PRU0_ARM_INTERRUPT pypruss.pruintc_init() # Init the interrupt controller pypruss.exec_program(0, "./ddr_write.bin") # Load firmware "ddr_write.bin" on PRU 0 pypruss.wait_for_event(0) # Wait for event 0 which is connected to PRU0_ARM_INTERRUPT pypruss.clear_event(0) # Clear the event pypruss.pru_disable(0) # Disable PRU 0, this is already done by the firmware pypruss.exit() # Exit, don't know what this does.
The firmware to accompany this is:
.origin 0 .entrypoint START #define PRU0_ARM_INTERRUPT 19 #define GPIO1 0x4804c000 // The adress of the GPIO1 #define GPIO_CLEARDATAOUT 0x190 #define GPIO_SETDATAOUT 0x194 #define CONST_DDR C31 #define CTPPR_1 0x2202C START: MOV r0, 0x00100000 // Configure the programmable pointer register for PRU0 by setting c31_pointer[15:0] MOV r1, CTPPR_1 // field to 0x0010. This will make C31 point to 0x80001000 (DDR memory). SBBO r0, r1, 0, 4 LBCO r1, CONST_DDR, 0, 4 //Load values from external DDR Memory into R1 BLINK: MOV r2, 7<<22 MOV r3, GPIO1 | GPIO_SETDATAOUT SBBO r2, r3, 0, 4 MOV r0, 0x00a00000 DELAY: SUB r0, r0, 1 QBNE DELAY, r0, 0 MOV r2, 7<<22 MOV r3, GPIO1 | GPIO_CLEARDATAOUT SBBO r2, r3, 0, 4 MOV r0, 0x00a00000 DELAY2: SUB r0, r0, 1 QBNE DELAY2, r0, 0 SUB r1, r1, 1 QBNE BLINK, r1, 0 MOV R31.b0, PRU0_ARM_INTERRUPT+16 // Send notification to Host for program completion HALT
I have given the library it’s own repository: It is here.
If you are having trouble with this, please write a comment. If you get the message:
ImportError: libprussdrv.so: cannot open shared object file: No such file or directory
That means the .so file is not found. Either your LD_LIBARY_PATH is wrong or the file is not in the /usr/local/lib as it should.
If you are getting a segmentation fault, make sure the .bin file is in the same directory as your .py-file and that you have modprobed uio_pruss.
Also, if you have any idea how to extend the available DDR memory beyond 0×4000 bytes, I am VERY interested in hearing about it.. (That seems to be the amount of available DDR memory now. Coincides with /sys/class/uio/uio0/maps/map1/size, so maybe that has something to do with it. )