Commits

Elias Bakken committed 4f8d3f0

A working example of pru0 getting data from DDR. However, the amount of memory available is limited to 0x4000 Bytes, not nearly enough to have continous operation for 10 cm or more... How can more memory be made available? It seems that cat /sys/class/uio/uio0/maps/map2/size has a large chunk..

Comments (0)

Files changed (5)

Binary file modified.

firmware/firmware_pru_0.p

 #define CONST_DDR 			0x80001000
 #define DDR_END				0x80002000
 #define CTPPR_1         	0x2202C 	
+#define DDR_MAGIC			0xbabe7175		// Magic number used to reset the DDR counter 
 
 START:
     LBCO r0, C4, 4, 4					// Load Bytes Constant Offset (?)
 
     SUB r1, r1, 1
     QBNE BLINK, r1, 0					// Still more pins to go, jump back
-
-	MOV  r3, DDR_END 		
-	QBEQ RESET_R4, r4, r3				// Check if the end of DDR is reached
-
 	ADD  r4, r4, 4			
+
     MOV R31.b0, PRU0_ARM_INTERRUPT+16   // Send notification to Host that the instructions are done
 
+	MOV  r3, DDR_MAGIC					// Load the fancy word into r3
+	LBBO r2, r4, 0, 4					// Load the next data into r2
+	QBEQ RESET_R4, r2, r3				// Check if the end of DDR is reached
+
+
 WAIT:
     LBBO r1, r4, 0, 4     				// Load values from external DDR Memory into R1
     QBNE BLINK, r1, 0
 	QBA WAIT							// Loop back to wait for new data
 
 	
+DEBUG:
+    MOV r2, (7<<22)						// Load pin data into r2
+    MOV r3, GPIO1 | GPIO_DATAOUT
+    SBBO r2, r3, 0, 4
+	QBA DEBUG

firmware/firmware_test.py

 import struct
 import numpy as np
 
-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. 
+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. 
+DDR_MAGIC           = 0xbabe7175
 
-with open("/dev/mem", "r+b") as f:					# Open the memory device
-	ddr_mem = mmap.mmap(f.fileno(), DDR_FILELEN, offset=DDR_BASEADDR) # 
+#with open("/dev/mem", "r+b") as f:					# Open the memory device
+#	ddr_mem = mmap.mmap(f.fileno(), DDR_FILELEN, offset=DDR_BASEADDR) # 
 
-steps = [(7<<22), 0]*10								# 10 blinks, this control the GPIO1 pins
-delays = [0xFFFFFF]*20								# number of delays. Each delay adds 2 instructions, so ~10ns
+ddr_mem = mmap.mmap(0, 0x40000, offset=0x8c080000) # 
+
+
+steps = [(3<<22), 0]*2								# 10 blinks, this control the GPIO1 pins
+delays = [0xFFFFFF]*4								# number of delays. Each delay adds 2 instructions, so ~10ns
 
 data = np.array([steps, delays])					# Make a 2D matrix combining the ticks and delays
 data = data.transpose().flatten()					# Braid the data so every other item is a 
-data = [20]+list(data)								# Make the data into a list and add the number of ticks total
+data = [4]+list(data)+[DDR_MAGIC]						# Make the data into a list and add the number of ticks total
 
 str_data = ""										# Data in string form
 for reg in data:									
 	str_data += struct.pack('L', reg) 				# Make the data, it needs to be a string
 
+print str_data.encode("hex")
 ddr_mem[DDR_OFFSET:DDR_OFFSET+len(str_data)] = str_data	# Write the data to the DDR memory, four bytes should suffice
 ddr_mem.close()										# Close the memory 
 f.close()											# Close the file

software/Gcode.py

         for i, token in enumerate(self.tokens):
             if len(token) == 0:
                 self.tokens.pop(i)
-        self.debug = 1
+        self.debug = 0
         self.answer = "ok"
 
         if self.debug > 1:           
 import mmap
 import struct 
 
-DDR_BASEADDR		= 0x70000000					# The actual baseaddr is 0x80000000, but due to a bug(?), 
+DDR_BASEADDR		= 0x70000000					# The actual baseaddr is 0x80001000, but due to a bug(?), 
 DDR_HACK			= 0x10001000					# Python accept unsigned int as offset argument.
-DDR_END			    = DDR_HACK+0x1000 				# The amount of memory to make available
+DDR_END			    = DDR_HACK+0x4000 				# The amount of memory to make available
 DDR_START			= DDR_HACK						# Add the hack to the offset as well. 
 DDR_LEN             = DDR_END-DDR_START
+DDR_MAGIC			= 0xbabe7175
 
 class Pru:
     def __init__(self):
         with open("/dev/mem", "r+b") as f:					# Open the memory device
             self.ddr_mem = mmap.mmap(f.fileno(), DDR_HACK+DDR_LEN, offset=DDR_BASEADDR) # 
             self.ddr_mem[DDR_START:DDR_START+4] = struct.pack('L', 0) 
+
         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
         else:
             self.pru_data[pru_num] = data
 
-    ''' Commit the data to thr DDR memory '''
+    ''' Commit the data to the DDR memory '''
     def commit_data(self):
         data = struct.pack('L', len(self.pru_data[0])/2)	    # Data in string form
         for reg in self.pru_data[0]:									
             data += struct.pack('L', reg) 				        # Make the data, it needs to be a string
         data += struct.pack('L', 0)                             # Add a terminating 0, this keeps it looping.
 
-        self.ddr_end = self.ddr_start+len(data)
-        print "ddr_start: "+str(self.ddr_start)
-        print "ddr_end: "+str(self.ddr_end)
-        print "data len: "+str(len(data))
-
+        self.ddr_end = self.ddr_start+len(data)       
         if self.ddr_end > DDR_END:                              # If the data is too long, wrap it around to the start
-            print "wrapping"
-            cut = DDR_END-self.ddr_start
-            first = struct.pack('L', cut/8)+data[4:cut]
-            self.ddr_mem[self.ddr_start:DDR_END] = first   # Write the first part of the data to the DDR memory.
-            print "Wrote first"
-            second = struct.pack('L', (len(data[cut:])/8))+data[cut:]
-            self.ddr_mem[DDR_START:DDR_START+len(second)] = second# Write the second half of data to the DDR memory.
-            print "Wrote second"
-            self.ddr_end = DDR_START+len(second)
+            multiple = (DDR_END-self.ddr_start)%8               # Find a multiple of 8
+            cut = DDR_END-self.ddr_start-multiple-4             # The cut must be done after a delay, so a multiple of 8 bytes +/-4
+            first = struct.pack('L', cut/8)+data[4:cut]         # Update the loop count
+            first += struct.pack('L', DDR_MAGIC)                # Add the magic number to force a reset of DDR memory counter
+            self.ddr_mem[self.ddr_start:self.ddr_start+len(first)] = first  # Write the first part of the data to the DDR memory.
+            second = struct.pack('L', (len(data[cut:-4])/8))+data[cut:]     # Add the number of steps in this iteration
+            self.ddr_end = DDR_START+len(second)                # Update the end counter
+            self.ddr_mem[DDR_START:self.ddr_end] = second       # Write the second half of data to the DDR memory.
+            self.wait_for_event()                               # Must wait for event here
         else:
             self.ddr_mem[self.ddr_start:self.ddr_end] = data    # Write the data to the DDR memory.
+            if DDR_END-self.ddr_end < 16:                       # There is no room for a complete  step, add the magic number to wrap
+                self.ddr_mem[self.ddr_end-4:self.ddr_end] = struct.pack('L', DDR_MAGIC)
+                self.ddr_mem[DDR_START:DDR_START+4] = struct.pack('L', 0) # Terminate the next instruction
+                self.ddr_end = DDR_START+4                
+                print "wrapped due to insufficient DDR"
 
         self.ddr_start = self.ddr_end-4                         # Update the start of ddr for next time 
         self.pru_data = [[],[]]                                 # Reset the pru_data list since it has been commited         
 
+
     ''' Wait for the PRU to finish '''                
     def wait_for_event(self):
         pypruss.wait_for_event(PRU_EVTOUT_0)				    # Wait a while for it to finish.
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.