Advertisement
Guest User

Untitled

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