swd_port.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. # Copyright 2024 Google LLC
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import struct
  15. import time
  16. class SerialWireDebugPort(object):
  17. # debug port registers
  18. DP_IDCODE_ADDR = 0x00
  19. DP_ABORT_ADDR = 0x00
  20. DP_CTRLSTAT_ADDR = 0x04
  21. DP_SELECT_ADDR = 0x08
  22. DP_RDBUFF_ADDR = 0x0c
  23. # MEM-AP register
  24. MEM_AP_CSW_ADDR = 0x0
  25. MEM_AP_CSW_MASTER_DEBUG = (1 << 29)
  26. MEM_AP_CSW_PRIVILEGED_MODE = (1 << 25)
  27. MEM_AP_CSW_ADDRINCWORD = (1 << 4)
  28. MEM_AP_CSW_SIZE8BITS = (0 << 1)
  29. MEM_AP_CSW_SIZE32BITS = (1 << 1)
  30. MEM_AP_TAR_ADDR = 0x4
  31. MEM_AP_DRW_ADDR = 0xc
  32. MEM_AP_IDR_VALUES = [0x24770011, 0x74770001]
  33. def __init__(self, driver, reset=True):
  34. self._driver = driver
  35. self._swd_connected = False
  36. self._reset = reset
  37. self._pending_acks = 0
  38. def close(self):
  39. if self._swd_connected:
  40. # power down the system and debug domains
  41. self._write(self.DP_CTRLSTAT_ADDR, 0x00000000, is_access_port=False)
  42. # send 1 byte worth of trailing bits since we're done communicating
  43. self._driver.write_bits_cmd(0x00, 8)
  44. # this makes the Saleae's SWD analyzer happy, and it's otherwise harmless
  45. self._driver.write_bits_cmd(0x3, 2)
  46. self._swd_connected = False
  47. self._driver.close()
  48. @staticmethod
  49. def _fatal(message):
  50. raise Exception('FATAL ERROR: {}'.format(message))
  51. def _get_request_header(self, addr, is_read, is_access_port):
  52. # the header consists of the following fields
  53. # bit 0: start (always 1)
  54. # bit 1: DebugPort (0) or AccessPort (1)
  55. # bit 2: write (0) or read (1)
  56. # bits 3-4: bits 2 and 3 of the address
  57. # bit 5: parity bit such that bits 1-5 contain an even number of 1's
  58. # bit 6: stop (always 0)
  59. # bit 7: park (always 1)
  60. header = 0x1
  61. header |= (1 << 1) if is_access_port else 0
  62. header |= (1 << 2) if is_read else 0
  63. header |= ((addr & 0xf) >> 2) << 3
  64. parity = 0
  65. for i in range(1, 5):
  66. parity += (header >> i) & 0x1
  67. header |= (parity & 0x1) << 5
  68. header |= 1 << 7
  69. return header
  70. def _send_request_header(self, addr, is_read, is_access_port):
  71. self._driver.write_bytes_cmd([self._get_request_header(addr, is_read, is_access_port)])
  72. def _check_write_acks(self):
  73. if not self._pending_acks:
  74. return
  75. self._driver.send_cmds()
  76. # the ACK is in the top 3 bits that we get from the FTDI read, so shift right by 5
  77. for ack in [x >> 5 for x in self._driver.get_read_bytes(self._pending_acks)]:
  78. if ack != 0x1:
  79. self._fatal('ACK=0x{:02x}'.format(ack))
  80. self._pending_acks = 0
  81. def _read(self, addr, is_access_port):
  82. # check any pending write ACKs before doing a read
  83. self._check_write_acks()
  84. # send the read request
  85. self._send_request_header(addr, is_read=True, is_access_port=is_access_port)
  86. # do all the reads at the same time as an optimization (and hope we get an ACK)
  87. self._driver.read_bits_cmd(4) # 4 bits for ACK + turnaround
  88. self._driver.read_bytes_cmd(4) # 4 data bytes
  89. self._driver.read_bits_cmd(2) # 2 bits for parity + turnaround
  90. self._driver.send_cmds()
  91. result = self._driver.get_read_bytes(6)
  92. # check the ACK
  93. ack = result[0] >> 5
  94. if ack != 0x1:
  95. self._fatal('ACK=0x{:02x}'.format(ack))
  96. # grab the response
  97. response = struct.unpack('<I', result[1:5])[0]
  98. # read two more bits: the parity and another for some reason I don't understand
  99. # check that the parity is correct
  100. parity = (result[5] >> 6) & 0x1
  101. if parity != sum((response >> i) & 0x1 for i in range(32)) & 0x1:
  102. self._fatal('Bad parity')
  103. return response
  104. def _write(self, addr, data, is_access_port, no_ack=False):
  105. if data > 0xffffffff:
  106. self._fatal('Bad data')
  107. # send the write request
  108. self._send_request_header(addr, is_read=False, is_access_port=is_access_port)
  109. # OPTIMIZATION: queue the ACK read now and keep going (hope we get an ACK)
  110. self._driver.read_bits_cmd(4)
  111. # calculate the parity and send the data
  112. parity = sum((data >> i) & 0x1 for i in range(32)) & 0x1
  113. # OPTIMIZATION: We need to send 1 turnaround bit, 4 data bytes, and 1 parity bit.
  114. # We can combine this into a single FTDI write by sending it as 5 bytes, so
  115. # let's shift everything such that the extra 6 bits are at the end where they
  116. # will be properly ignored as trailing bits.
  117. temp = ((data << 1) & 0xfffffffe)
  118. data_bytes = [(temp >> (i * 8)) & 0xff for i in range(4)]
  119. data_bytes += [(data >> 31) | (parity << 1)]
  120. self._driver.write_bytes_cmd(data_bytes)
  121. # check the ACK(s) if necessary
  122. self._pending_acks += 1
  123. if not no_ack or self._pending_acks >= self._driver.get_read_fifo_size():
  124. self._check_write_acks()
  125. def connect(self):
  126. if self._reset:
  127. # reset the target
  128. self._driver.reset_lo()
  129. # switch from JTAG to SWD mode (based on what openocd does)
  130. # - line reset
  131. # - magic number of 0xE79E
  132. # - line reset
  133. # - 2 low bits for unknown reasons (maybe padding to nibbles?)
  134. def line_reset():
  135. # a line reset is 50 high bits (6 bytes + 2 bits)
  136. self._driver.write_bytes_cmd([0xff] * 6)
  137. self._driver.write_bits_cmd(0x3, 2)
  138. line_reset()
  139. self._driver.write_bytes_cmd([0x9e, 0xe7])
  140. line_reset()
  141. self._driver.write_bits_cmd(0x0, 2)
  142. idcode = self._read(self.DP_IDCODE_ADDR, is_access_port=False)
  143. # clear the error flags
  144. self._write(self.DP_ABORT_ADDR, 0x0000001E, is_access_port=False)
  145. # power up the system and debug domains
  146. self._write(self.DP_CTRLSTAT_ADDR, 0xF0000001, is_access_port=False)
  147. # check the MEM-AP IDR
  148. # the IDR register is has the same address as the DRW register but on the 0xf bank
  149. self._write(self.DP_SELECT_ADDR, 0xf0, is_access_port=False) # select the 0xf bank
  150. self._read(self.MEM_AP_DRW_ADDR, is_access_port=True) # read the value register (twice)
  151. if self._read(self.DP_RDBUFF_ADDR, is_access_port=False) not in self.MEM_AP_IDR_VALUES:
  152. self._fatal('Invalid MEM-AP IDR')
  153. self._write(self.DP_SELECT_ADDR, 0x0, is_access_port=False) # return to the 0x0 bank
  154. # enable privileged access to the MEM-AP with 32 bit data accesses and auto-incrementing
  155. csw_value = self.MEM_AP_CSW_PRIVILEGED_MODE
  156. csw_value |= self.MEM_AP_CSW_MASTER_DEBUG
  157. csw_value |= self.MEM_AP_CSW_ADDRINCWORD
  158. csw_value |= self.MEM_AP_CSW_SIZE32BITS
  159. self._write(self.MEM_AP_CSW_ADDR, csw_value, is_access_port=True)
  160. self._swd_connected = True
  161. if self._reset:
  162. self._driver.reset_hi()
  163. return idcode
  164. def read_memory_address(self, addr):
  165. self._write(self.MEM_AP_TAR_ADDR, addr, is_access_port=True)
  166. self._read(self.MEM_AP_DRW_ADDR, is_access_port=True)
  167. return self._read(self.DP_RDBUFF_ADDR, is_access_port=False)
  168. def write_memory_address(self, addr, value):
  169. self._write(self.MEM_AP_TAR_ADDR, addr, is_access_port=True)
  170. self._write(self.MEM_AP_DRW_ADDR, value, is_access_port=True)
  171. def write_memory_bulk(self, base_addr, data):
  172. # TAR is configured as auto-incrementing, but it wraps every 4096 bytes, so that's how much
  173. # we can write before we need to explicitly set it again.
  174. WORD_SIZE = 4
  175. BURST_LENGTH = 4096 / WORD_SIZE
  176. assert(base_addr % BURST_LENGTH == 0 and len(data) % WORD_SIZE == 0)
  177. for i in range(0, len(data), WORD_SIZE):
  178. if i % BURST_LENGTH == 0:
  179. # set the target address
  180. self._write(self.MEM_AP_TAR_ADDR, base_addr + i, is_access_port=True, no_ack=True)
  181. # write the word
  182. word = sum(data[i+j] << (j * 8) for j in range(WORD_SIZE))
  183. self._write(self.MEM_AP_DRW_ADDR, word, is_access_port=True, no_ack=True)
  184. def continuous_read(self, addr, duration):
  185. # This is a highly-optimized function which is samples the specified memory address for the
  186. # specified duration. This is generally used for profiling by reading the PC sampling
  187. # register.
  188. NUM_READS = 510 # a magic number which gives us the best sample rate on Silk/Robert
  189. # don't auto-increment the address
  190. csw_value = self.MEM_AP_CSW_PRIVILEGED_MODE
  191. csw_value |= self.MEM_AP_CSW_SIZE32BITS
  192. self._write(self.MEM_AP_CSW_ADDR, csw_value, is_access_port=True)
  193. # set the address
  194. self._write(self.MEM_AP_TAR_ADDR, addr, is_access_port=True)
  195. # discard the previous value
  196. self._read(self.MEM_AP_DRW_ADDR, is_access_port=True)
  197. # flush everything
  198. self._check_write_acks()
  199. header = self._get_request_header(self.MEM_AP_DRW_ADDR, is_read=True, is_access_port=True)
  200. self._driver.start_sequence()
  201. for i in range(NUM_READS):
  202. self._driver.write_bits_cmd(header, 8)
  203. self._driver.read_bits_cmd(6)
  204. self._driver.read_bytes_cmd(4)
  205. raw_data = []
  206. end_time = time.time() + duration
  207. while time.time() < end_time:
  208. # send the read requests
  209. self._driver.send_cmds()
  210. # do all the reads at the same time as an optimization (and hope we get an ACK)
  211. raw_data.extend(self._driver.get_read_bytes(5 * NUM_READS))
  212. self._driver.end_sequence()
  213. def get_value_from_bits(b):
  214. result = 0
  215. for o in range(len(b)):
  216. result |= b[o] << o
  217. return result
  218. values = []
  219. for raw_result in [raw_data[i:i+5] for i in range(0, len(raw_data), 5)]:
  220. result = raw_result
  221. # The result is read as 5 bytes, with the first one containing 6 bits (shifted in from
  222. # the left as they are read). Let's convert this into an array of bits, and then
  223. # reconstruct the values we care about.
  224. bits = []
  225. bits.extend((result[0] >> (2 + j)) & 1 for j in range(6))
  226. for i in range(4):
  227. bits.extend((result[i + 1] >> j) & 1 for j in range(8))
  228. ack = get_value_from_bits(bits[1:4])
  229. response = get_value_from_bits(bits[4:36])
  230. parity = bits[36]
  231. # check the ACK
  232. if ack != 0x1:
  233. self._fatal('ACK=0x{:02x}'.format(ack))
  234. # read two more bits: the parity and another for some reason I don't understand
  235. # check that the parity is correct
  236. if parity != sum((response >> i) & 0x1 for i in range(32)) & 0x1:
  237. self._fatal('Bad parity')
  238. # store the response
  239. values.append(response)
  240. return values