Repostiory containing DAPLink source code with Reset Pin workaround for HANI_IOT board.

Upstream: https://github.com/ARMmbed/DAPLink

Committer:
Pawel Zarembski
Date:
Tue Apr 07 12:55:42 2020 +0200
Revision:
0:01f31e923fe2
hani: DAPLink with reset workaround

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Pawel Zarembski 0:01f31e923fe2 1 #
Pawel Zarembski 0:01f31e923fe2 2 # DAPLink Interface Firmware
Pawel Zarembski 0:01f31e923fe2 3 # Copyright (c) 2009-2016, ARM Limited, All Rights Reserved
Pawel Zarembski 0:01f31e923fe2 4 # SPDX-License-Identifier: Apache-2.0
Pawel Zarembski 0:01f31e923fe2 5 #
Pawel Zarembski 0:01f31e923fe2 6 # Licensed under the Apache License, Version 2.0 (the "License"); you may
Pawel Zarembski 0:01f31e923fe2 7 # not use this file except in compliance with the License.
Pawel Zarembski 0:01f31e923fe2 8 # You may obtain a copy of the License at
Pawel Zarembski 0:01f31e923fe2 9 #
Pawel Zarembski 0:01f31e923fe2 10 # http://www.apache.org/licenses/LICENSE-2.0
Pawel Zarembski 0:01f31e923fe2 11 #
Pawel Zarembski 0:01f31e923fe2 12 # Unless required by applicable law or agreed to in writing, software
Pawel Zarembski 0:01f31e923fe2 13 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
Pawel Zarembski 0:01f31e923fe2 14 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Pawel Zarembski 0:01f31e923fe2 15 # See the License for the specific language governing permissions and
Pawel Zarembski 0:01f31e923fe2 16 # limitations under the License.
Pawel Zarembski 0:01f31e923fe2 17 #
Pawel Zarembski 0:01f31e923fe2 18
Pawel Zarembski 0:01f31e923fe2 19 from __future__ import absolute_import
Pawel Zarembski 0:01f31e923fe2 20 from __future__ import division
Pawel Zarembski 0:01f31e923fe2 21 import queue
Pawel Zarembski 0:01f31e923fe2 22 import functools
Pawel Zarembski 0:01f31e923fe2 23 import serial
Pawel Zarembski 0:01f31e923fe2 24 import threading
Pawel Zarembski 0:01f31e923fe2 25 import time
Pawel Zarembski 0:01f31e923fe2 26
Pawel Zarembski 0:01f31e923fe2 27 ERROR_TIMEOUT_SECONDS = 10.0
Pawel Zarembski 0:01f31e923fe2 28
Pawel Zarembski 0:01f31e923fe2 29
Pawel Zarembski 0:01f31e923fe2 30 def _same(d1, d2):
Pawel Zarembski 0:01f31e923fe2 31 #Do a string or bytearray compare
Pawel Zarembski 0:01f31e923fe2 32 if d1 != d2:
Pawel Zarembski 0:01f31e923fe2 33 return False
Pawel Zarembski 0:01f31e923fe2 34 return True
Pawel Zarembski 0:01f31e923fe2 35
Pawel Zarembski 0:01f31e923fe2 36 # http://digital.ni.com/public.nsf/allkb/D37754FFA24F7C3F86256706005B9BE7
Pawel Zarembski 0:01f31e923fe2 37 standard_baud = [
Pawel Zarembski 0:01f31e923fe2 38 9600,
Pawel Zarembski 0:01f31e923fe2 39 14400,
Pawel Zarembski 0:01f31e923fe2 40 19200,
Pawel Zarembski 0:01f31e923fe2 41 28800,
Pawel Zarembski 0:01f31e923fe2 42 38400,
Pawel Zarembski 0:01f31e923fe2 43 #56000, #TODO - uncomment once daplink-validation supports 56000 on nrf5x
Pawel Zarembski 0:01f31e923fe2 44 57600,
Pawel Zarembski 0:01f31e923fe2 45 115200,
Pawel Zarembski 0:01f31e923fe2 46 ]
Pawel Zarembski 0:01f31e923fe2 47 timing_test_baud = standard_baud[3:]
Pawel Zarembski 0:01f31e923fe2 48
Pawel Zarembski 0:01f31e923fe2 49
Pawel Zarembski 0:01f31e923fe2 50 def calc_timeout(length, baud):
Pawel Zarembski 0:01f31e923fe2 51 """Calculate a timeout given the data and baudrate
Pawel Zarembski 0:01f31e923fe2 52
Pawel Zarembski 0:01f31e923fe2 53 Positional arguments:
Pawel Zarembski 0:01f31e923fe2 54 length - size of data to be sent
Pawel Zarembski 0:01f31e923fe2 55 baud - baud rate to send data
Pawel Zarembski 0:01f31e923fe2 56
Pawel Zarembski 0:01f31e923fe2 57 Calculate a reasonable timeout given the supplied parameters.
Pawel Zarembski 0:01f31e923fe2 58 This function adds slightly more time then is needed, to accont
Pawel Zarembski 0:01f31e923fe2 59 for latency and various configurations.
Pawel Zarembski 0:01f31e923fe2 60 """
Pawel Zarembski 0:01f31e923fe2 61 return 12 * float(length) / float(baud) + 0.2
Pawel Zarembski 0:01f31e923fe2 62
Pawel Zarembski 0:01f31e923fe2 63
Pawel Zarembski 0:01f31e923fe2 64 class SerialTester(object):
Pawel Zarembski 0:01f31e923fe2 65 """Helper object to buffer serial and setup baud"""
Pawel Zarembski 0:01f31e923fe2 66
Pawel Zarembski 0:01f31e923fe2 67 def __init__(self, port):
Pawel Zarembski 0:01f31e923fe2 68 self.raw_serial = serial.Serial(port=port,bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, timeout=None, xonxoff=False, rtscts=False, write_timeout=None, dsrdtr=False, inter_byte_timeout=None, exclusive=None)
Pawel Zarembski 0:01f31e923fe2 69 self.raw_serial.write_timeout = ERROR_TIMEOUT_SECONDS
Pawel Zarembski 0:01f31e923fe2 70 self._queue = queue.Queue()
Pawel Zarembski 0:01f31e923fe2 71 self._write_thread = threading.Thread(target=self._serial_main)
Pawel Zarembski 0:01f31e923fe2 72 self._write_thread.start()
Pawel Zarembski 0:01f31e923fe2 73
Pawel Zarembski 0:01f31e923fe2 74 def __enter__(self):
Pawel Zarembski 0:01f31e923fe2 75 return self
Pawel Zarembski 0:01f31e923fe2 76
Pawel Zarembski 0:01f31e923fe2 77 def __exit__(self, exception_type, value, traceback):
Pawel Zarembski 0:01f31e923fe2 78 self._queue.put(None)
Pawel Zarembski 0:01f31e923fe2 79 self._write_thread.join(ERROR_TIMEOUT_SECONDS)
Pawel Zarembski 0:01f31e923fe2 80 assert not self._write_thread.isAlive(), "Thread join failed"
Pawel Zarembski 0:01f31e923fe2 81 self.raw_serial.close()
Pawel Zarembski 0:01f31e923fe2 82 self.raw_serial = None
Pawel Zarembski 0:01f31e923fe2 83 return False
Pawel Zarembski 0:01f31e923fe2 84
Pawel Zarembski 0:01f31e923fe2 85 def new_session_with_baud(self, baud, parent_test):
Pawel Zarembski 0:01f31e923fe2 86 """Start a new session by restarting target and setting baud"""
Pawel Zarembski 0:01f31e923fe2 87 test_info = parent_test.create_subtest("Set Baud")
Pawel Zarembski 0:01f31e923fe2 88
Pawel Zarembski 0:01f31e923fe2 89 # Set baud to 115200
Pawel Zarembski 0:01f31e923fe2 90 self.raw_serial.baudrate = 115200
Pawel Zarembski 0:01f31e923fe2 91 self.raw_serial.timeout = 1.0
Pawel Zarembski 0:01f31e923fe2 92
Pawel Zarembski 0:01f31e923fe2 93 # Reset the target
Pawel Zarembski 0:01f31e923fe2 94 self.raw_serial.reset_output_buffer()
Pawel Zarembski 0:01f31e923fe2 95 self.raw_serial.reset_input_buffer()
Pawel Zarembski 0:01f31e923fe2 96 self.raw_serial.sendBreak()
Pawel Zarembski 0:01f31e923fe2 97
Pawel Zarembski 0:01f31e923fe2 98 # Wait until the target is initialized
Pawel Zarembski 0:01f31e923fe2 99 expected_resp = "{init}"
Pawel Zarembski 0:01f31e923fe2 100 resp = self.read(len(expected_resp))
Pawel Zarembski 0:01f31e923fe2 101 if not _same(resp.decode(), expected_resp):
Pawel Zarembski 0:01f31e923fe2 102 test_info.failure("Fail on init: %s" % resp)
Pawel Zarembski 0:01f31e923fe2 103 return False
Pawel Zarembski 0:01f31e923fe2 104
Pawel Zarembski 0:01f31e923fe2 105 # Change baudrate to that of the first test
Pawel Zarembski 0:01f31e923fe2 106 command = "{baud:%i}" % baud
Pawel Zarembski 0:01f31e923fe2 107 self.write(command.encode())
Pawel Zarembski 0:01f31e923fe2 108 resp = self.read(len(command))
Pawel Zarembski 0:01f31e923fe2 109 if not _same(resp.decode(), command):
Pawel Zarembski 0:01f31e923fe2 110 test_info.failure("Fail on baud command: %s" % resp)
Pawel Zarembski 0:01f31e923fe2 111 return False
Pawel Zarembski 0:01f31e923fe2 112
Pawel Zarembski 0:01f31e923fe2 113 # Update baud of local serial port
Pawel Zarembski 0:01f31e923fe2 114 self.raw_serial.baudrate = baud
Pawel Zarembski 0:01f31e923fe2 115
Pawel Zarembski 0:01f31e923fe2 116 # Read the response indicating that the baudrate
Pawel Zarembski 0:01f31e923fe2 117 # on the target has changed
Pawel Zarembski 0:01f31e923fe2 118 expected_resp = "{change}"
Pawel Zarembski 0:01f31e923fe2 119 resp = self.read(len(expected_resp))
Pawel Zarembski 0:01f31e923fe2 120 if not _same(resp.decode(), expected_resp):
Pawel Zarembski 0:01f31e923fe2 121 test_info.failure("Fail on baud change %s" % resp)
Pawel Zarembski 0:01f31e923fe2 122 return False
Pawel Zarembski 0:01f31e923fe2 123
Pawel Zarembski 0:01f31e923fe2 124 # Set default timeout
Pawel Zarembski 0:01f31e923fe2 125 self.raw_serial.timeout = ERROR_TIMEOUT_SECONDS
Pawel Zarembski 0:01f31e923fe2 126
Pawel Zarembski 0:01f31e923fe2 127 # Success
Pawel Zarembski 0:01f31e923fe2 128 return True
Pawel Zarembski 0:01f31e923fe2 129
Pawel Zarembski 0:01f31e923fe2 130 def read(self, length):
Pawel Zarembski 0:01f31e923fe2 131 """Read serial data"""
Pawel Zarembski 0:01f31e923fe2 132 return self.raw_serial.read(length)
Pawel Zarembski 0:01f31e923fe2 133
Pawel Zarembski 0:01f31e923fe2 134 def write(self, data):
Pawel Zarembski 0:01f31e923fe2 135 """Write serial port data in the background"""
Pawel Zarembski 0:01f31e923fe2 136 func = functools.partial(self.raw_serial.write, data)
Pawel Zarembski 0:01f31e923fe2 137 self._queue.put(func)
Pawel Zarembski 0:01f31e923fe2 138
Pawel Zarembski 0:01f31e923fe2 139 def set_read_timeout(self, timeout):
Pawel Zarembski 0:01f31e923fe2 140 """Set timeout for read operations"""
Pawel Zarembski 0:01f31e923fe2 141 assert self._queue.empty(), "Queue must be empty to change timeout"
Pawel Zarembski 0:01f31e923fe2 142 self.raw_serial.timeout = timeout
Pawel Zarembski 0:01f31e923fe2 143
Pawel Zarembski 0:01f31e923fe2 144 def flush(self):
Pawel Zarembski 0:01f31e923fe2 145 """Wait for all writes to complete"""
Pawel Zarembski 0:01f31e923fe2 146 self._queue.join()
Pawel Zarembski 0:01f31e923fe2 147 assert self._queue.empty()
Pawel Zarembski 0:01f31e923fe2 148
Pawel Zarembski 0:01f31e923fe2 149 def _serial_main(self):
Pawel Zarembski 0:01f31e923fe2 150 """Write helper thread"""
Pawel Zarembski 0:01f31e923fe2 151 while True:
Pawel Zarembski 0:01f31e923fe2 152 task = self._queue.get(True)
Pawel Zarembski 0:01f31e923fe2 153 if task is None:
Pawel Zarembski 0:01f31e923fe2 154 self._queue.task_done()
Pawel Zarembski 0:01f31e923fe2 155 # End of processing is an empty task
Pawel Zarembski 0:01f31e923fe2 156 break
Pawel Zarembski 0:01f31e923fe2 157 try:
Pawel Zarembski 0:01f31e923fe2 158 task()
Pawel Zarembski 0:01f31e923fe2 159 except serial.SerialTimeoutException:
Pawel Zarembski 0:01f31e923fe2 160 pass
Pawel Zarembski 0:01f31e923fe2 161 self._queue.task_done()
Pawel Zarembski 0:01f31e923fe2 162
Pawel Zarembski 0:01f31e923fe2 163
Pawel Zarembski 0:01f31e923fe2 164 def test_serial(workspace, parent_test):
Pawel Zarembski 0:01f31e923fe2 165 """Test the serial port endpoint
Pawel Zarembski 0:01f31e923fe2 166
Pawel Zarembski 0:01f31e923fe2 167 Requirements:
Pawel Zarembski 0:01f31e923fe2 168 -daplink-validation must be loaded for the target.
Pawel Zarembski 0:01f31e923fe2 169
Pawel Zarembski 0:01f31e923fe2 170 Positional arguments:
Pawel Zarembski 0:01f31e923fe2 171 port - the serial port to open as a string
Pawel Zarembski 0:01f31e923fe2 172
Pawel Zarembski 0:01f31e923fe2 173 Return:
Pawel Zarembski 0:01f31e923fe2 174 True if the test passed, False otherwise
Pawel Zarembski 0:01f31e923fe2 175 """
Pawel Zarembski 0:01f31e923fe2 176 test_info = parent_test.create_subtest("Serial test")
Pawel Zarembski 0:01f31e923fe2 177 board = workspace.board
Pawel Zarembski 0:01f31e923fe2 178 port = board.get_serial_port()
Pawel Zarembski 0:01f31e923fe2 179 test_info.info("Testing serial port %s" % port)
Pawel Zarembski 0:01f31e923fe2 180
Pawel Zarembski 0:01f31e923fe2 181 # Note: OSX sends a break command when a serial port is closed.
Pawel Zarembski 0:01f31e923fe2 182 # To avoid problems while testing keep the serial port open the
Pawel Zarembski 0:01f31e923fe2 183 # whole time. Use the property 'baudrate' to change the baud
Pawel Zarembski 0:01f31e923fe2 184 # instead of opening a new instance.
Pawel Zarembski 0:01f31e923fe2 185
Pawel Zarembski 0:01f31e923fe2 186 with SerialTester(port) as sp:
Pawel Zarembski 0:01f31e923fe2 187
Pawel Zarembski 0:01f31e923fe2 188 # Generate a 4KB block of dummy data
Pawel Zarembski 0:01f31e923fe2 189 # and test supported baud rates
Pawel Zarembski 0:01f31e923fe2 190 test_data = [i for i in range(0, 256)] * 4 * 4
Pawel Zarembski 0:01f31e923fe2 191 test_data = bytearray(test_data)
Pawel Zarembski 0:01f31e923fe2 192 for baud in standard_baud:
Pawel Zarembski 0:01f31e923fe2 193
Pawel Zarembski 0:01f31e923fe2 194 test_info.info("Testing baud %i" % baud)
Pawel Zarembski 0:01f31e923fe2 195 success = sp.new_session_with_baud(baud, test_info)
Pawel Zarembski 0:01f31e923fe2 196 if not success:
Pawel Zarembski 0:01f31e923fe2 197 test_info.failure("Unable to setup session")
Pawel Zarembski 0:01f31e923fe2 198 continue
Pawel Zarembski 0:01f31e923fe2 199
Pawel Zarembski 0:01f31e923fe2 200 # Perform test
Pawel Zarembski 0:01f31e923fe2 201 sp.write(test_data)
Pawel Zarembski 0:01f31e923fe2 202 resp = sp.read(len(test_data))
Pawel Zarembski 0:01f31e923fe2 203 if _same(test_data, resp):
Pawel Zarembski 0:01f31e923fe2 204 test_info.info("Pass")
Pawel Zarembski 0:01f31e923fe2 205 else:
Pawel Zarembski 0:01f31e923fe2 206 test_info.failure("Fail on baud %s" % baud)
Pawel Zarembski 0:01f31e923fe2 207
Pawel Zarembski 0:01f31e923fe2 208 # Timing stress test - send data at critical points
Pawel Zarembski 0:01f31e923fe2 209 # in time like right as the transmitter is turned off
Pawel Zarembski 0:01f31e923fe2 210 # ------------------
Pawel Zarembski 0:01f31e923fe2 211 # Test sequence
Pawel Zarembski 0:01f31e923fe2 212 # 1. Send a block of data (vary size for the test)
Pawel Zarembski 0:01f31e923fe2 213 # 2. Wait until 1 byte is read back
Pawel Zarembski 0:01f31e923fe2 214 # 3. Write 1 byte
Pawel Zarembski 0:01f31e923fe2 215 # 4. Read back all data
Pawel Zarembski 0:01f31e923fe2 216 test_data = [i for i in range(0, 256)] * 4 * 4
Pawel Zarembski 0:01f31e923fe2 217 test_data = bytearray(test_data)
Pawel Zarembski 0:01f31e923fe2 218 for baud in timing_test_baud:
Pawel Zarembski 0:01f31e923fe2 219
Pawel Zarembski 0:01f31e923fe2 220 test_info.info("Timing test baud %i" % baud)
Pawel Zarembski 0:01f31e923fe2 221 success = sp.new_session_with_baud(baud, test_info)
Pawel Zarembski 0:01f31e923fe2 222 if not success:
Pawel Zarembski 0:01f31e923fe2 223 test_info.failure("Unable to setup session")
Pawel Zarembski 0:01f31e923fe2 224 continue
Pawel Zarembski 0:01f31e923fe2 225
Pawel Zarembski 0:01f31e923fe2 226 test_pass = True
Pawel Zarembski 0:01f31e923fe2 227 for data_size in range(1, 10):
Pawel Zarembski 0:01f31e923fe2 228 data = test_data[0:data_size + 1]
Pawel Zarembski 0:01f31e923fe2 229 for _ in range(0, 1000):
Pawel Zarembski 0:01f31e923fe2 230 resp = bytearray()
Pawel Zarembski 0:01f31e923fe2 231
Pawel Zarembski 0:01f31e923fe2 232 sp.write(data[0:data_size])
Pawel Zarembski 0:01f31e923fe2 233 resp += sp.read(1)
Pawel Zarembski 0:01f31e923fe2 234 sp.write(data[-1:])
Pawel Zarembski 0:01f31e923fe2 235 resp += sp.read(data_size)
Pawel Zarembski 0:01f31e923fe2 236 sp.flush()
Pawel Zarembski 0:01f31e923fe2 237 if not _same(data, resp):
Pawel Zarembski 0:01f31e923fe2 238 test_pass = False
Pawel Zarembski 0:01f31e923fe2 239 test_info.info("fail size - %s" % data_size)
Pawel Zarembski 0:01f31e923fe2 240 break
Pawel Zarembski 0:01f31e923fe2 241
Pawel Zarembski 0:01f31e923fe2 242 if test_pass:
Pawel Zarembski 0:01f31e923fe2 243 test_info.info("Pass")
Pawel Zarembski 0:01f31e923fe2 244 else:
Pawel Zarembski 0:01f31e923fe2 245 test_info.failure("Fail on timing test with baud %s"
Pawel Zarembski 0:01f31e923fe2 246 % baud)
Pawel Zarembski 0:01f31e923fe2 247
Pawel Zarembski 0:01f31e923fe2 248 # Setting change smoke test - reconfigure settings while
Pawel Zarembski 0:01f31e923fe2 249 # in the middle of a transfer and verify nothing bad
Pawel Zarembski 0:01f31e923fe2 250 test_data = [i for i in range(0, 128)]
Pawel Zarembski 0:01f31e923fe2 251 test_data = bytearray(test_data)
Pawel Zarembski 0:01f31e923fe2 252 sp.new_session_with_baud(115200, test_info)
Pawel Zarembski 0:01f31e923fe2 253 sp.set_read_timeout(0)
Pawel Zarembski 0:01f31e923fe2 254 for baud in standard_baud:
Pawel Zarembski 0:01f31e923fe2 255 sp.raw_serial.baudrate = baud
Pawel Zarembski 0:01f31e923fe2 256 sp.write(test_data)
Pawel Zarembski 0:01f31e923fe2 257 xfer_time = float(len(test_data) * 10) / float(baud)
Pawel Zarembski 0:01f31e923fe2 258 time.sleep(xfer_time / 2)
Pawel Zarembski 0:01f31e923fe2 259 # Discard data
Pawel Zarembski 0:01f31e923fe2 260 sp.read(1024)
Pawel Zarembski 0:01f31e923fe2 261 # Read any leftover data
Pawel Zarembski 0:01f31e923fe2 262 sp.flush()
Pawel Zarembski 0:01f31e923fe2 263 sp.raw_serial.baudrate = 115200
Pawel Zarembski 0:01f31e923fe2 264 sp.set_read_timeout(1.0)
Pawel Zarembski 0:01f31e923fe2 265 sp.read(128 * len(standard_baud))
Pawel Zarembski 0:01f31e923fe2 266
Pawel Zarembski 0:01f31e923fe2 267 # Generate a 8 KB block of dummy data
Pawel Zarembski 0:01f31e923fe2 268 # and test a large block transfer
Pawel Zarembski 0:01f31e923fe2 269 test_data = [i for i in range(0, 256)] * 4 * 8
Pawel Zarembski 0:01f31e923fe2 270 test_data = bytearray(test_data)
Pawel Zarembski 0:01f31e923fe2 271 sp.new_session_with_baud(115200, test_info)
Pawel Zarembski 0:01f31e923fe2 272
Pawel Zarembski 0:01f31e923fe2 273 sp.write(test_data)
Pawel Zarembski 0:01f31e923fe2 274 resp = sp.read(len(test_data))
Pawel Zarembski 0:01f31e923fe2 275 if _same(resp, test_data):
Pawel Zarembski 0:01f31e923fe2 276 test_info.info("Block test passed")
Pawel Zarembski 0:01f31e923fe2 277 else:
Pawel Zarembski 0:01f31e923fe2 278 test_info.failure("Block test failed")
Pawel Zarembski 0:01f31e923fe2 279
Pawel Zarembski 0:01f31e923fe2 280 # Refresh to check for asserts
Pawel Zarembski 0:01f31e923fe2 281 board.refresh(test_info)