Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
test_daplink.py
00001 # 00002 # DAPLink Interface Firmware 00003 # Copyright (c) 2009-2016, ARM Limited, All Rights Reserved 00004 # SPDX-License-Identifier: Apache-2.0 00005 # 00006 # Licensed under the Apache License, Version 2.0 (the "License"); you may 00007 # not use this file except in compliance with the License. 00008 # You may obtain a copy of the License at 00009 # 00010 # http://www.apache.org/licenses/LICENSE-2.0 00011 # 00012 # Unless required by applicable law or agreed to in writing, software 00013 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00014 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 # See the License for the specific language governing permissions and 00016 # limitations under the License. 00017 # 00018 00019 from __future__ import absolute_import 00020 import future 00021 import os 00022 import binascii 00023 import intelhex 00024 import sys 00025 00026 try: 00027 from cStringIO import StringIO 00028 except ImportError: 00029 from io import StringIO 00030 00031 from msd_test import (MassStorageTester, MOCK_DIR_LIST, MOCK_FILE_LIST, 00032 MOCK_DIR_LIST_AFTER, MOCK_FILE_LIST_AFTER) 00033 00034 TRIGGER_ASSERT_FILE_NAME = "ASSERT.ACT" 00035 ASSERT_FILE_NAME = "ASSERT.TXT" 00036 NEED_BL_FILE_NAME = "NEED_BL.TXT" 00037 DAPLINK_VECTOR_TABLE_OFFSET = 0x00 00038 DAPLINK_BUILD_KEY_OFFSET = 0x20 00039 DAPLINK_HIC_ID_OFFSET = 0x24 00040 00041 00042 def intel_hex_get_sections(intel_hex): 00043 """Return list of address, size tuples""" 00044 addresses = intel_hex.addresses() 00045 addresses.sort() 00046 section_list = [] 00047 section_start = None 00048 last_addr = None 00049 for addr in addresses: 00050 if section_start is None: 00051 section_start = addr 00052 last_addr = addr 00053 if addr == last_addr or addr == last_addr + 1: 00054 last_addr = addr 00055 else: 00056 section_size = last_addr - section_start + 1 00057 section_list.append((section_start, section_size)) 00058 section_start = addr 00059 last_addr = addr 00060 if section_start is not None: 00061 section_size = last_addr - section_start + 1 00062 section_list.append((section_start, section_size)) 00063 return section_list 00064 00065 00066 def bin_data_to_hex_data(addr, data): 00067 """Covert binary data to a string in intel hex format""" 00068 intel_hex = intelhex.IntelHex() 00069 if sys.version_info >= (3,0): 00070 data = data.decode('latin1') 00071 intel_hex.puts(addr, data) 00072 sio = StringIO() 00073 intel_hex.tofile(sio, format='hex') 00074 hex_data = sio.getvalue() 00075 return bytearray(hex_data.encode('latin1')) 00076 00077 00078 class DLMassStorageTester (MassStorageTester): 00079 """DAPLink mass storage tester""" 00080 00081 def __init__(self, board, parent_test, test_name, test_mode): 00082 super(DLMassStorageTester, self).__init__(board, parent_test, 00083 test_name) 00084 self._expected_mode = None 00085 self._actual_mode = None 00086 self._test_mode = test_mode 00087 if self._test_mode == board.MODE_IF: 00088 self._crc_tag = board.KEY_BL_CRC 00089 elif self._test_mode == board.MODE_BL: 00090 self._crc_tag = board.KEY_IF_CRC 00091 else: 00092 assert False 00093 00094 def _run(self, test_info): 00095 assert self._expected_mode is not None 00096 # Set board to the correct mode before running test 00097 self.board.set_mode(self._test_mode ) 00098 self._actual_mode = None 00099 00100 super(DLMassStorageTester, self)._run(test_info) 00101 00102 if self._actual_mode is None: 00103 # Set expected mode if it hasn't been set in _check_data_correct 00104 self._actual_mode = self.board.get_mode() 00105 if self._expected_mode is not self._actual_mode : 00106 test_info.failure("Wrong mode after test - Expected " 00107 " %s got %s" % (self._expected_mode , 00108 self._actual_mode )) 00109 00110 def set_expected_mode(self, mode): 00111 self._expected_mode = mode 00112 00113 def _check_data_correct(self, expected_data, test_info): 00114 board = self.board 00115 self._actual_mode = self.board.get_mode() 00116 board.set_mode(self._test_mode ) 00117 if self._crc_tag not in board.details_txt: 00118 test_info.info("CRC not in details.txt") 00119 return False 00120 actual_crc32 = int(self.board.details_txt[self._crc_tag ], 16) 00121 expected_crc32 = binascii.crc32(expected_data[0:-4]) & 0xFFFFFFFF 00122 test_info.info("Expected CRC: 0x%08x, actual crc: 0x%08x" % 00123 (expected_crc32, actual_crc32)) 00124 return actual_crc32 == expected_crc32 00125 00126 00127 def daplink_test(workspace, parent_test): 00128 board = workspace.board 00129 interface = workspace.if_firmware 00130 test_info = parent_test.create_subtest('daplink_test') 00131 00132 intel_hex = intelhex.IntelHex(interface.hex_path) 00133 section_list = intel_hex_get_sections(intel_hex) 00134 assert len(section_list) == 1, ("Only 1 section supported, found %s" % 00135 len(section_list)) 00136 start, length = section_list[0] 00137 00138 bin_data = bytearray(intel_hex.tobinarray(start=start, size=length)) 00139 sio = StringIO() 00140 intel_hex.tofile(sio, format='hex') 00141 hex_data = sio.getvalue() 00142 hex_data = bytearray(hex_data.encode('latin1')) 00143 00144 # Make sure asserts work as expected 00145 test_assert(workspace, test_info) 00146 00147 # Test loading a binary file with shutils 00148 test = DLMassStorageTester(board, test_info, "Shutil binary file load " 00149 "interface", board.MODE_BL) 00150 test.set_shutils_copy(interface.bin_path) 00151 test.set_expected_data(bin_data, start) 00152 test.set_expected_mode(board.MODE_IF) 00153 test.run() 00154 00155 # Test loading a hex file with shutils 00156 test = DLMassStorageTester(board, test_info, "Shutil hex file load " 00157 "interface", board.MODE_BL) 00158 test.set_shutils_copy(interface.hex_path) 00159 test.set_expected_data(bin_data, start) 00160 test.set_expected_mode(board.MODE_IF) 00161 test.run() 00162 00163 test_file_type('bin', board.MODE_BL, board, test_info, start, bin_data) 00164 test_file_type('hex', board.MODE_BL, board, test_info, start, bin_data) 00165 00166 # Test bootloader updates 00167 firmware = workspace.bl_firmware 00168 intel_hex = intelhex.IntelHex(firmware.hex_path) 00169 section_list = intel_hex_get_sections(intel_hex) 00170 assert len(section_list) == 1, ("Only 1 section supported, found %s" % 00171 len(section_list)) 00172 start, length = section_list[0] 00173 00174 bin_data = bytearray(intel_hex.tobinarray(start=start, size=length)) 00175 sio = StringIO() 00176 intel_hex.tofile(sio, format='hex') 00177 hex_data = sio.getvalue() 00178 hex_data = bytearray(hex_data.encode('latin1')) 00179 00180 # Test loading a binary file with shutils 00181 test = DLMassStorageTester(board, test_info, "Shutil binary file load " 00182 "bootloader", board.MODE_IF) 00183 test.set_shutils_copy(firmware.bin_path) 00184 test.set_expected_data(bin_data, start) 00185 test.set_expected_mode(board.MODE_IF) 00186 test.run() 00187 00188 # Test loading a hex file with shutils 00189 test = DLMassStorageTester(board, test_info, "Shutil hex file load " 00190 "bootloader", board.MODE_IF) 00191 test.set_shutils_copy(firmware.hex_path) 00192 test.set_expected_data(bin_data, start) 00193 test.set_expected_mode(board.MODE_IF) 00194 test.run() 00195 00196 test_file_type('bin', board.MODE_IF, board, test_info, start, bin_data) 00197 test_file_type('hex', board.MODE_IF, board, test_info, start, bin_data) 00198 00199 00200 def test_assert(workspace, parent_test): 00201 """Test that asserts work and persist across modes""" 00202 board = workspace.board 00203 test_info = parent_test.create_subtest('Assert Test') 00204 00205 board.set_assert_auto_manage(False) 00206 00207 board.set_mode(board.MODE_IF) 00208 00209 # Create a test assert file 00210 test_info.info('Triggering assert by creating %s' % 00211 TRIGGER_ASSERT_FILE_NAME) 00212 trigger_assert_path = board.get_file_path(TRIGGER_ASSERT_FILE_NAME) 00213 with open(trigger_assert_path, 'wb') as _: 00214 pass 00215 board.wait_for_remount(test_info) 00216 00217 test_info.info('Checking that assert file was created') 00218 board.set_mode(board.MODE_IF) 00219 assert_path = board.get_file_path(ASSERT_FILE_NAME) 00220 if not os.path.exists(assert_path): 00221 test_info.failure('Assert file not created') 00222 00223 test_info.info('Checking that assert file persists if->bl') 00224 board.set_mode(board.MODE_BL) 00225 assert_path = board.get_file_path(ASSERT_FILE_NAME) 00226 if not os.path.exists(assert_path): 00227 test_info.failure('Assert file not created') 00228 00229 test_info.info('Checking that assert file persists bl->if') 00230 board.set_mode(board.MODE_IF) 00231 assert_path = board.get_file_path(ASSERT_FILE_NAME) 00232 if not os.path.exists(assert_path): 00233 test_info.failure('Assert file not created') 00234 00235 board.clear_assert() 00236 00237 board.set_mode(board.MODE_IF) 00238 assert_path = board.get_file_path(ASSERT_FILE_NAME) 00239 if os.path.exists(assert_path): 00240 test_info.failure('Assert file not cleared correctly') 00241 00242 board.set_mode(board.MODE_BL) 00243 assert_path = board.get_file_path(ASSERT_FILE_NAME) 00244 if os.path.exists(assert_path): 00245 test_info.failure('Assert file not cleared correctly') 00246 00247 board.set_mode(board.MODE_IF) 00248 assert_path = board.get_file_path(ASSERT_FILE_NAME) 00249 if os.path.exists(assert_path): 00250 test_info.failure('Assert file not cleared correctly') 00251 00252 board.set_assert_auto_manage(True) 00253 00254 00255 def test_file_type(file_type, board_mode, board, parent_test, 00256 data_start, raw_data): 00257 """Test updates of a given file type using the given mode""" 00258 assert file_type in ('hex', 'bin'), 'Unsupported file type %s' % file_type 00259 00260 if board_mode == board.MODE_IF: 00261 data_type = board.MODE_BL 00262 elif board_mode == board.MODE_BL: 00263 data_type = board.MODE_IF 00264 else: 00265 assert False 00266 00267 test_info = parent_test.create_subtest('%s %s filetype test' % 00268 (file_type, data_type)) 00269 00270 def get_file_name(base='image'): 00271 """Get the file name to be used for loading""" 00272 return base + '.' + file_type 00273 00274 def get_file_content(addr, bin_data): 00275 """Get the file contents to be used for loading""" 00276 if file_type == 'bin': 00277 return bytearray(bin_data) # Make a copy 00278 elif file_type == 'hex': 00279 return bin_data_to_hex_data(addr, bin_data) 00280 00281 # Test partial update 00282 file_name = get_file_name() 00283 local_data = get_file_content(data_start, raw_data[0:len(raw_data) // 2]) 00284 test = DLMassStorageTester(board, test_info, "Load partial", 00285 board_mode) 00286 test.set_programming_data(local_data, file_name) 00287 test.set_expected_data(None) 00288 test.set_expected_failure_msg("In application programming failed because " 00289 "the update sent was incomplete.", "interface") 00290 test.set_expected_mode(board_mode) 00291 test.run() 00292 # If bootloader is missing then this should be indicated by a file 00293 if board_mode == board.MODE_IF: 00294 if not os.path.isfile(board.get_file_path(NEED_BL_FILE_NAME)): 00295 test_info.failure("Bootloader missing but file %s not present" % 00296 NEED_BL_FILE_NAME) 00297 test_info.info("Testing switch to bootloader") 00298 try: 00299 board.set_mode(board.MODE_BL) 00300 test_info.failure("Board switched to bootloader mode") 00301 except Exception: 00302 pass 00303 finally: 00304 if board.get_mode() == board.MODE_IF: 00305 test_info.info("Device able to recover from bad BL") 00306 else: 00307 test_info.failure("Device in wrong mode") 00308 00309 # Test loading a normal image 00310 file_name = get_file_name() 00311 local_data = get_file_content(data_start, raw_data) 00312 test = DLMassStorageTester(board, test_info, "Normal Load", 00313 board_mode) 00314 test.set_programming_data(local_data, file_name) 00315 test.set_expected_data(raw_data) 00316 test.set_expected_mode(board.MODE_IF) 00317 test.run() 00318 00319 # Wrong starting address 00320 if file_type != 'bin': 00321 mode_to_error = { 00322 board.MODE_IF: ('The starting address for the bootloader ' 00323 'update is wrong.'), 00324 board.MODE_BL: ('The starting address for the interface ' 00325 'update is wrong.') 00326 } 00327 file_name = get_file_name() 00328 local_data = get_file_content(data_start + 0x400, raw_data) 00329 test = DLMassStorageTester(board, test_info, "Wrong Address", 00330 board_mode) 00331 test.set_expected_failure_msg(mode_to_error[board_mode], 'user') 00332 test.set_programming_data(local_data, file_name) 00333 test.set_expected_data(raw_data) 00334 test.set_expected_mode(board_mode) 00335 test.run() 00336 00337 # Test flushes during update 00338 file_name = get_file_name() 00339 local_data = get_file_content(data_start, raw_data) 00340 test = DLMassStorageTester(board, test_info, "Load with flushes", 00341 board_mode) 00342 test.set_programming_data(local_data, file_name) 00343 test.set_expected_data(raw_data) 00344 test.set_flush_size(0x1000) 00345 test.set_expected_mode(board.MODE_IF) 00346 test.run() 00347 00348 # Test bad crc 00349 file_name = get_file_name() 00350 local_raw_data = bytearray(raw_data) 00351 local_raw_data[-1] = (local_raw_data[-1] + 1) % 0x100 # Corrupt CRC 00352 local_data = get_file_content(data_start, local_raw_data) 00353 test = DLMassStorageTester(board, test_info, 'Wrong CRC', 00354 board_mode) 00355 test.set_programming_data(local_data, file_name) 00356 if board_mode == board.MODE_IF: 00357 test.set_expected_failure_msg('The bootloader CRC did not pass.', 'interface') 00358 test.set_expected_data(None) 00359 elif board_mode == board.MODE_BL: 00360 # Interface images can be from other vendors and be missing 00361 # the crc, so don't treat this as an error 00362 test.set_expected_data(local_raw_data) 00363 test.set_expected_mode(board.MODE_IF) 00364 test.run() 00365 # If bootloader is missing then this should be indicated by a file 00366 if (board_mode == board.MODE_IF and 00367 not os.path.isfile(board.get_file_path(NEED_BL_FILE_NAME))): 00368 test_info.failure("Bootloader missing but file %s not present" % 00369 NEED_BL_FILE_NAME) 00370 00371 # Test load with extra padding 00372 file_name = get_file_name() 00373 local_data = get_file_content(data_start, raw_data) 00374 local_data.extend(b'\xFF' * 0x1000) 00375 test = DLMassStorageTester(board, test_info, "Padded load", board_mode) 00376 test.set_programming_data(local_data, file_name) 00377 test.set_expected_data(raw_data) 00378 test.set_expected_mode(board.MODE_IF) 00379 test.run() 00380 00381 # Test bad crc in file data 00382 # Note - crc is only a requirment for loading bootloades 00383 if board_mode == board.MODE_IF: 00384 file_name = get_file_name() 00385 local_raw_data = bytearray(raw_data) 00386 local_raw_data[0x100] = (local_raw_data[0x100] + 1) % 0x100 # Corrupt CRC 00387 local_data = get_file_content(data_start, local_raw_data) 00388 test = DLMassStorageTester(board, test_info, 'Wrong data CRC', 00389 board_mode) 00390 test.set_programming_data(local_data, file_name) 00391 test.set_expected_failure_msg('The bootloader CRC did not pass.', 'interface') 00392 test.set_expected_data(None) 00393 test.set_expected_mode(board.MODE_IF) 00394 test.run() 00395 # If bootloader is missing then this should be indicated by a file 00396 if not os.path.isfile(board.get_file_path(NEED_BL_FILE_NAME)): 00397 test_info.failure("Bootloader missing but file %s not present" % 00398 NEED_BL_FILE_NAME) 00399 00400 # Restore a good image 00401 file_name = get_file_name() 00402 local_data = get_file_content(data_start, raw_data) 00403 test = DLMassStorageTester(board, test_info, "Normal Load", 00404 board_mode) 00405 test.set_programming_data(local_data, file_name) 00406 test.set_expected_data(raw_data) 00407 test.set_expected_mode(board.MODE_IF) 00408 test.run() 00409 00410 # Test wrong HIC ID 00411 # Bootloader should perform interface update regardless of key 00412 if data_type == board.MODE_IF: 00413 local_raw_data = bytearray(raw_data) 00414 local_raw_data[DAPLINK_HIC_ID_OFFSET] = \ 00415 (local_raw_data[DAPLINK_HIC_ID_OFFSET] + 1) % 0x100 00416 file_name = get_file_name() 00417 local_data = get_file_content(data_start, local_raw_data) 00418 test = DLMassStorageTester(board, test_info, "Wrong HIC ID", 00419 board_mode) 00420 test.set_programming_data(local_data, file_name) 00421 test.set_expected_data(local_raw_data) 00422 test.set_expected_mode(board.MODE_IF) 00423 test.run() 00424 00425 # TODO future - Wrong type 00426 00427 # Test a normal load with dummy files created beforehand 00428 file_name = get_file_name() 00429 local_data = get_file_content(data_start, raw_data) 00430 test = DLMassStorageTester(board, test_info, "Extra Files", board_mode) 00431 test.set_programming_data(local_data, file_name) 00432 test.add_mock_dirs(MOCK_DIR_LIST) 00433 test.add_mock_files(MOCK_FILE_LIST) 00434 test.add_mock_dirs_after_load(MOCK_DIR_LIST_AFTER) 00435 test.add_mock_files_after_load(MOCK_FILE_LIST_AFTER) 00436 test.set_expected_data(raw_data) 00437 test.set_expected_mode(board.MODE_IF) 00438 test.run() 00439 00440 # Restore good image 00441 file_name = get_file_name() 00442 local_data = get_file_content(data_start, raw_data) 00443 test = DLMassStorageTester(board, test_info, "Restore image", 00444 board_mode) 00445 test.set_programming_data(local_data, file_name) 00446 test.set_expected_data(raw_data) 00447 test.set_expected_mode(board.MODE_IF) 00448 test.run() 00449
Generated on Tue Jul 12 2022 15:37:25 by
1.7.2