Commits

Elias Bakken  committed 9c9aa35

Finally the PRU is working for all steppers. I did a dry run before committing this and it seems promising. Need to change all stepper pins to Bank 1 for pcb rev 1 in order to speed up the toggle operations. Also, must start adding some queuing to the path planner to keep from stopping for every move and also calculate speed through corners

  • Participants
  • Parent commits 0d394af

Comments (0)

Files changed (4)

File firmware/firmware_pru_0.p

 .entrypoint START
 
 #define PRU0_ARM_INTERRUPT 	19
-#define GPIO1 				0x4804c000		// The adress of the GPIO1 
-#define GPIO_DATAOUT 		0x13c			// This is the register for setting data
-#define CONST_DDR 			0x80001000
-#define DDR_END				0x80002000
-#define CTPPR_1         	0x2202C 	
-#define DDR_MAGIC			0xbabe7175		// Magic number used to reset the DDR counter 
+#define GPIO_DATAOUT 		0x13c				// This is the register for setting data
+#define DDR_MAGIC			0xbabe7175			// Magic number used to reset the DDR counter 
+#define GPIO1 				0x4804C000			// The adress of the GPIO1 bank
+#define GPIO2 				0x481AC000	 		// The adress of the GPIO2 bank
+#define GPIO3 				0x481AE000 			// The adress of the GPIO3 bank 
+#define GPIO1_MASK			(1<<13)|(1<<12)|(1<<30)|(1<<31)|(1<<1)	// Only these two pins are togglable
+#define GPIO2_MASK			(1<<2)
+#define GPIO3_MASK			(1<<19)|(1<<21)		// Only these two pins are togglable
 
 START:
-    LBCO r0, C4, 4, 4					// Load Bytes Constant Offset (?)
-    CLR  r0, r0, 4						// Clear bit 4 in reg 0
-    SBCO r0, C4, 4, 4					// Store Bytes Constant Offset
+    LBCO r0, C4, 4, 4							// Load Bytes Constant Offset (?)
+    CLR  r0, r0, 4								// Clear bit 4 in reg 0
+    SBCO r0, C4, 4, 4							// Store Bytes Constant Offset
 
-    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
+	MOV  r10, GPIO1_MASK						// Make the mask
+    MOV  r11, GPIO1 | GPIO_DATAOUT				// Load address
+    MOV  r12, 0xFFFFFFFF ^ (GPIO1_MASK)			// Invert the mask
+	MOV  r13, GPIO2_MASK						// Make the mask
+    MOV  r14, GPIO2 | GPIO_DATAOUT				// Load address 
+    MOV  r15, 0xFFFFFFFF ^ (GPIO2_MASK)			// Invert mask
+	MOV  r16, GPIO3_MASK						// Make the mask
+    MOV  r17, GPIO3 | GPIO_DATAOUT				// Load address
+    MOV  r18, 0xFFFFFFFF ^ (GPIO3_MASK)			// Invert mask
 
 RESET_R4:
-	MOV  r4, CONST_DDR
-	QBA WAIT
+	MOV  r0, 0
+	LBBO r4, r0, 0, 4							// Load the ddr_addr from the first adress in the PRU0 DRAM
+	QBA WAIT									// Check if the end of DDR is reached
 
 BLINK:
-	ADD  r4, r4, 4						// Increment r4
-    LBBO r2, r4, 0, 4					// Load pin data into r2
-    MOV r3, GPIO1 | GPIO_DATAOUT
-    SBBO r2, r3, 0, 4
+	ADD  r4, r4, 4								// Increment r4
+    LBBO r2, r4, 0, 4							// Load pin data into r2
+	AND  r2, r2, r10							// Mask the pins to PRU0, GPIO1
+	LBBO r3, r11, 0, 4							// Load the data currently in addr r3
+	AND	 r3, r3, r12							// Mask the data so only the necessary pins can change
+	OR   r3, r3, r2 							// Add the GPIO1-mask to hinder toggling PRU1's pins
+    SBBO r3, r11, 0, 4							// Ok, set the pins
+
+    LBBO r2, r4, 0, 4							// Load pin data into r2
+	AND  r2, r2, r13							// Mask the pins to PRU0, GPIO1
+	LBBO r3, r14, 0, 4							// Load the data currently in addr r3
+	AND	 r3, r3, r15							// Mask the data so only the necessary pins can change
+	OR   r3, r3, r2 							// Add the GPIO1-mask to hinder toggling PRU1's pins
+    SBBO r3, r14, 0, 4							// Ok, set the pins
+
+    LBBO r2, r4, 0, 4							// Load pin data into r2
+	AND  r2, r2, r16							// Mask the pins to PRU0, GPIO1
+	LBBO r3, r17, 0, 4							// Load the data currently in addr r3
+	AND	 r3, r3, r18							// Mask the data so only the necessary pins can change
+	OR   r3, r3, r2 							// Add the GPIO1-mask to hinder toggling PRU1's pins
+    SBBO r3, r17, 0, 4							// Ok, set the pins
 
 	ADD  r4, r4, 4
-    LBBO r0, r4, 0, 4					// Load delay data into r0
+    LBBO r0, r4, 0, 4							// Load delay data into r0
 DELAY:
     SUB r0, r0, 1
     QBNE DELAY, r0, 0
 
     SUB r1, r1, 1
-    QBNE BLINK, r1, 0					// Still more pins to go, jump back
+    QBNE BLINK, r1, 0							// Still more pins to go, jump back
 	ADD  r4, r4, 4			
 
-    MOV R31.b0, PRU0_ARM_INTERRUPT+16   // Send notification to Host that the instructions are done
+    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
+	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
+    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
+	QBA WAIT									// Loop back to wait for new data
+

File firmware/firmware_test.py

-''' ddr_write.py - test script for writing to DDR memory using the PyPRUSS library'''
-
-import pypruss
-import mmap
-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_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) # 
-
-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 = [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
-
-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, "./firmware_pru_0.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. 
-
-
-

File software/Path_planner.py

                         continue
                     stepper = self.steppers[axis]                   # Get a handle of  the stepper
                     data = self._make_data(path, axis)              # Generate the timing and pin data                         
-                    if stepper.has_pru():                           # If this stepper has a PRU associated with it
-                        pru_num = stepper.get_pru()
-                        self.pru.add_data(data, pru_num) 
-                    else:               
-                        stepper.add_data(data)                      # If not, let the stepper fix this.     
+                    #if stepper.has_pru():                           # If this stepper has a PRU associated with it
+                    pru_num = stepper.get_pru()
+                    self.pru.add_data(data, 0)#pru_num) 
+                    #else:               
+                    #    stepper.add_data(data)                      # If not, let the stepper fix this.     
 
                 for axis in path.get_axes():                        
                     self.steppers[axis].prepare_move()              # Make them start performing

File software/Pru.py

 import mmap
 import struct 
 
-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+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:
         self.inst_pr_loop 	= 16				            # This is the minimum number of instructions needed to step. 
         self.inst_pr_delay 	= 2					            # Every loop adds two instructions: i-- and i != 0            
         self.pru_data       = [[], []]                      
-        self.ddr_start      = DDR_START
-        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) 
+        with open("/sys/class/uio/uio0/maps/map2/addr", "r") as f:
+            ddr_addr = int(f.readline(), 16)
+
+        with open("/sys/class/uio/uio0/maps/map2/size", "r") as f:
+            ddr_size = int(f.readline(), 16)
+
+        ddr_offset     = ddr_addr-0x10000000
+        ddr_filelen    = ddr_size+0x10000000
+        self.DDR_START      = 0x10000000
+        self.DDR_END        = 0x10000000+ddr_size
+        self.ddr_start      = self.DDR_START
+
+        with open("/dev/mem", "r+b") as f:	                # Open the memory device
+            self.ddr_mem = mmap.mmap(f.fileno(), ddr_filelen, offset=ddr_offset) # mmap the right area            
+            self.ddr_mem[self.ddr_start:self.ddr_start+4] = struct.pack('L', 0)  # Add a zero to the first reg to make it wait
 
         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, "../firmware/firmware_pru_0.bin")			# Load firmware "ddr_write.bin" on PRU 0
+        pypruss.pru_write_memory(0, 0, [ddr_addr])			# Put the ddr address in the first region 
+        pypruss.exec_program(0, "../firmware/firmware_pru_0.bin")	# Load firmware "ddr_write.bin" on PRU 0
         print "PRU initialized"
 
-
-
     ''' Add some data to one of the PRUs '''
     def add_data(self, data, pru_num):
         (pins, delays) = data                       	    # Get the data
         data += struct.pack('L', 0)                             # Add a terminating 0, this keeps it looping.
 
         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
-            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
+        if self.ddr_end > self.DDR_END:                         # If the data is too long, wrap it around to the start
+            multiple = (self.DDR_END-self.ddr_start)%8          # Find a multiple of 8
+            cut = self.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
+            self.ddr_end = self.DDR_START+len(second)           # Update the end counter
+            self.ddr_mem[self.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  
+            print "Wrapped"
         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
+            if self.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                
+                self.ddr_mem[self.DDR_START:self.DDR_START+4] = struct.pack('L', 0) # Terminate the next instruction
+                self.ddr_end = self.DDR_START+4                
                 print "wrapped due to insufficient DDR"
 
         self.ddr_start = self.ddr_end-4                         # Update the start of ddr for next time