Guest User

Untitled

a guest
Jun 19th, 2023
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.79 KB | None | 0 0
  1. #!/usr/bin/python3
  2.  
  3. from uio.utils import fix_ctypes_struct
  4. from uio.ti.icss import Icss
  5. import ctypes
  6. from ctypes import c_uint32 as u32, c_uint16 as u16, c_int32 as int32, c_bool as boolean
  7. from time import sleep
  8. from sys import exit
  9.  
  10. pruss = Icss( "/dev/uio/pruss/module" )
  11. pruss.initialize()
  12. ddr = pruss.ddr
  13. pruss.uart.initialize(baudrate = 460800)
  14.  
  15. core_0 = pruss.core0
  16. core_0.load( 'pulse_train.out' )
  17.  
  18. core_1 = pruss.core1
  19. core_1.load( 'stream_pulse.out' )
  20.  
  21. class Message( ctypes.Structure ):
  22.     _fields_ = [
  23.             ( 'id',     u32 ),
  24.             ('timestamp',u32),
  25.             ('position',   u32),
  26.             ('force', int32),
  27.         ]
  28.  
  29. # used to communicate ddr layout to C program
  30. class DDRLayout( ctypes.Structure ):
  31.     _fields_ = [
  32.             ( 'msgbuf',      u32 ),
  33.             ( 'num_msgs',    u16 ),
  34.             ( 'msg_size',    u16 ),
  35.         ]
  36.  
  37. # volatile variables in pruss shared memory
  38. class StepperVars( ctypes.Structure ):
  39.     _fields_ = [
  40.             ( 'target_pos',  u32 ),
  41.             ( 'current_pos', u32 ),
  42.             ( 'speed', u32 ),
  43.             ( 'hault_request', boolean ),
  44.             ( 'moving', boolean ),
  45.         ]
  46.  
  47. # volatile variables in pruss shared memory
  48. class SharedVars( ctypes.Structure ):
  49.     _fields_ = [
  50.             ( 'abort_file', u32 ),
  51.             ( 'abort_line', u32 ),
  52.             ( 'ridx',       u16 ),
  53.         ]
  54.        
  55. # map shared memory variables
  56. shmem = core_0.map( StepperVars, 0x00000 )
  57.  
  58. # ready, set, go!
  59. shmem.hault_request = False
  60. shmem.current_pos = 0
  61. core_0.run()
  62. print('starting PRU0')
  63.  
  64.        
  65. # if you don't want the ringbuffer at the start of the ddr region, specify offset here
  66. MSGBUF_OFFSET = 0
  67.  
  68. # you can use a fixed ringbuffer size:
  69. #NUM_MSGS = 1024
  70. # or you can scale the ringbuffer to fit the size of the ddr region:
  71. NUM_MSGS = ( ddr.size - MSGBUF_OFFSET - ctypes.sizeof( u16 ) ) // ctypes.sizeof( Message )
  72. NUM_MSGS = min( NUM_MSGS, 65535 )  # make sure number of messages fits in u16
  73.  
  74. # map shared memory variables
  75. ddr_layout = core_1.map( DDRLayout, 0x10000 )
  76. shmem = core_1.map( SharedVars, 0x10100 )
  77. msgbuf = ddr.map( Message * NUM_MSGS, MSGBUF_OFFSET )
  78. ddr_widx = ddr.map( u16, MSGBUF_OFFSET + ctypes.sizeof( msgbuf ) )
  79.  
  80. # inform pru about layout of shared ddr memory region
  81. ddr_layout.msgbuf       = ddr.address + MSGBUF_OFFSET
  82. ddr_layout.num_msgs     = NUM_MSGS
  83. ddr_layout.msg_size     = ctypes.sizeof( Message )
  84.  
  85. # local copies of read-pointer and write-pointer
  86. ridx = 0
  87. widx = 0
  88. id_value = 0
  89. timestamp_cycles = 0
  90. lastid = 0
  91.  
  92. # initialize pointers in shared memory
  93. shmem.ridx = ridx
  94. ddr_widx.value = widx
  95.  
  96. # ready, set, go!
  97. pruss.ecap.pwm.initialize( 2**32 )
  98. core_1.run()
  99.  
  100.  
  101. def check_core():
  102.     if not core_1.halted:
  103.                 return
  104.  
  105.     if core_1.state.crashed:
  106.             msg = f'core crashed at pc={core_1.pc}'
  107.     elif shmem.abort_file == 0:
  108.             msg = f'core halted at pc={core_1.pc}'
  109.     else:
  110.         # FIXME figure out better way to read C-string from PRU memory
  111.                 abort_file = core_1.read( ctypes.c_char * 32, shmem.abort_file ).value
  112.                 abort_file = abort_file.decode("ascii")
  113.                 msg = f'core aborted at pc={core_1.pc} ({abort_file}:{shmem.abort_line})'
  114.  
  115.         # dump some potentially interesting information:
  116.                 msg += f'\n   ridx       = {ridx}'
  117.                 msg += f'\n   shmem.ridx = {shmem.ridx}'
  118.                 msg += f'\n   ddr_widx   = {ddr_widx.value}'
  119.  
  120.                 exit( msg )
  121.  
  122.     lastid = 0
  123.  
  124. def recv_messages():
  125.         global ridx, widx, lastid, timestamp_cycles
  126.  
  127.     # read updated write-pointer
  128.         widx = ddr_widx.value
  129.         assert widx < NUM_MSGS  # sanity-check
  130.  
  131.         position = 0
  132.         force = 0
  133.         timestamp = 0
  134.         # process messages
  135.         while ridx != widx:
  136.         # note: it may be faster to copy a batch of messages from shared memory
  137.         # instead of directly accessing individual messages and their fields.
  138.                 msg = msgbuf[ ridx ]
  139.         # sanity-check that message id increments monotonically
  140.                 lastid = ( lastid + 1 ) & 0xffffffff
  141.                 assert msg.id == lastid
  142.         # get 32-bit timestamp (in cycles) from message and unwrap it:
  143.                 timestamp_cycles += ( msg.timestamp - timestamp_cycles ) & 0xffffffff
  144.                 timestamp_ms = timestamp_cycles // 200000
  145.                 timestamp_s = ( timestamp_ms % 60000 ) / 1000
  146.                 timestamp_m = timestamp_ms // 60000
  147.                 timestamp_h = timestamp_m // 60
  148.                 timestamp_m = timestamp_m % 60
  149.                 timestamp = f'{timestamp_h:02d}:{timestamp_m:02d}:{timestamp_s:06.3f}'
  150.         # convert to timestamp in seconds:
  151.        
  152.                 force = msg.force
  153.             # consume message and update read pointer
  154.                 del msg  # direct access to message forbidden beyond this point
  155.                 ridx += 1
  156.                 if ridx == NUM_MSGS:
  157.                     ridx = 0
  158.                 shmem.ridx = ridx
  159.  
  160.         # update user interface
  161.         #print(f'\ridx=0x{ridx:04x} id=0x{lastid:08x} time={timestamp} position={position:08d} force={force:08d}', end='', flush=True )
  162.         print(f'ridx=0x{ridx:04x} id=0x{lastid:08x} time={timestamp} position={position:08d} force={force:08d}')
  163.    
  164.    
  165. try:
  166.         shmem.hault_request = False
  167.         shmem.target_pos = 3000
  168.         shmem.speed = 2
  169.         while True:
  170.             recv_messages()
  171.             check_core()
  172.             sleep( 0.01 )
  173.  
  174. except KeyboardInterrupt:
  175.     pass
  176.  
  177. finally:
  178.     print( '', flush=True )
  179.     core_1.halt()
  180.     pruss.uart.io.write( b'FFV\r', discard=True, flush=True )  # interrupt continuous transmission
  181.     sleep( 0.01 )  # make sure that response has been received
  182.     pruss.uart.io.discard()  # discard response
  183.  
  184.  
  185.  
Advertisement
Add Comment
Please, Sign In to add comment