test_bossac.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. # Copyright (c) 2018 Foundries.io
  2. # Copyright (c) 2019 Nordic Semiconductor ASA.
  3. # Copyright (c) 2020-2021 Gerson Fernando Budke <nandojve@gmail.com>
  4. #
  5. # SPDX-License-Identifier: Apache-2.0
  6. import argparse
  7. import os
  8. import platform
  9. from unittest.mock import patch, call
  10. import pytest
  11. from runners.bossac import BossacBinaryRunner
  12. from conftest import RC_KERNEL_BIN
  13. if platform.system() != 'Linux':
  14. pytest.skip("skipping Linux-only bossac tests", allow_module_level=True)
  15. TEST_BOSSAC_PORT = 'test-bossac-serial'
  16. TEST_BOSSAC_SPEED = '1200'
  17. TEST_OFFSET = 1234
  18. TEST_FLASH_ADDRESS = 5678
  19. TEST_BOARD_NAME = "my_board"
  20. EXPECTED_COMMANDS = [
  21. ['stty', '-F', TEST_BOSSAC_PORT, 'raw', 'ispeed', '115200',
  22. 'ospeed', '115200', 'cs8', '-cstopb', 'ignpar', 'eol', '255',
  23. 'eof', '255'],
  24. ['bossac', '-p', TEST_BOSSAC_PORT, '-R', '-e', '-w', '-v',
  25. '-b', RC_KERNEL_BIN],
  26. ]
  27. EXPECTED_COMMANDS_WITH_SPEED = [
  28. ['stty', '-F', TEST_BOSSAC_PORT, 'raw', 'ispeed', TEST_BOSSAC_SPEED,
  29. 'ospeed', TEST_BOSSAC_SPEED, 'cs8', '-cstopb', 'ignpar', 'eol', '255',
  30. 'eof', '255'],
  31. ['bossac', '-p', TEST_BOSSAC_PORT, '-R', '-e', '-w', '-v',
  32. '-b', RC_KERNEL_BIN],
  33. ]
  34. EXPECTED_COMMANDS_WITH_OFFSET = [
  35. ['stty', '-F', TEST_BOSSAC_PORT, 'raw', 'ispeed', '115200',
  36. 'ospeed', '115200', 'cs8', '-cstopb', 'ignpar', 'eol', '255',
  37. 'eof', '255'],
  38. ['bossac', '-p', TEST_BOSSAC_PORT, '-R', '-e', '-w', '-v',
  39. '-b', RC_KERNEL_BIN, '-o', str(TEST_OFFSET)],
  40. ]
  41. EXPECTED_COMMANDS_WITH_FLASH_ADDRESS = [
  42. [
  43. 'stty', '-F', TEST_BOSSAC_PORT, 'raw', 'ispeed', '115200',
  44. 'ospeed', '115200', 'cs8', '-cstopb', 'ignpar', 'eol', '255',
  45. 'eof', '255'
  46. ],
  47. [
  48. 'bossac', '-p', TEST_BOSSAC_PORT, '-R', '-e', '-w', '-v',
  49. '-b', RC_KERNEL_BIN, '-o', str(TEST_FLASH_ADDRESS),
  50. ],
  51. ]
  52. EXPECTED_COMMANDS_WITH_EXTENDED = [
  53. [
  54. 'stty', '-F', TEST_BOSSAC_PORT, 'raw', 'ispeed', '1200',
  55. 'ospeed', '1200', 'cs8', '-cstopb', 'ignpar', 'eol', '255',
  56. 'eof', '255'
  57. ],
  58. [
  59. 'bossac', '-p', TEST_BOSSAC_PORT, '-R', '-e', '-w', '-v',
  60. '-b', RC_KERNEL_BIN, '-o', str(TEST_FLASH_ADDRESS),
  61. ],
  62. ]
  63. # SAM-BA ROM without offset
  64. # No code partition Kconfig
  65. # No zephyr,code-partition (defined on DT)
  66. DOTCONFIG_STD = f'''
  67. CONFIG_BOARD="{TEST_BOARD_NAME}"
  68. CONFIG_FLASH_LOAD_OFFSET=0x162e
  69. '''
  70. # SAM-BA ROM/FLASH with offset
  71. DOTCONFIG_COND1 = f'''
  72. CONFIG_BOARD="{TEST_BOARD_NAME}"
  73. CONFIG_USE_DT_CODE_PARTITION=y
  74. CONFIG_HAS_FLASH_LOAD_OFFSET=y
  75. CONFIG_FLASH_LOAD_OFFSET=0x162e
  76. '''
  77. # SAM-BA ROM/FLASH without offset
  78. # No code partition Kconfig
  79. DOTCONFIG_COND2 = f'''
  80. CONFIG_BOARD="{TEST_BOARD_NAME}"
  81. CONFIG_HAS_FLASH_LOAD_OFFSET=y
  82. CONFIG_FLASH_LOAD_OFFSET=0x162e
  83. '''
  84. # SAM-BA Extended Arduino with offset
  85. DOTCONFIG_COND3 = f'''
  86. CONFIG_BOARD="{TEST_BOARD_NAME}"
  87. CONFIG_USE_DT_CODE_PARTITION=y
  88. CONFIG_BOOTLOADER_BOSSA_ARDUINO=y
  89. CONFIG_HAS_FLASH_LOAD_OFFSET=y
  90. CONFIG_FLASH_LOAD_OFFSET=0x162e
  91. '''
  92. # SAM-BA Extended Adafruit with offset
  93. DOTCONFIG_COND4 = f'''
  94. CONFIG_BOARD="{TEST_BOARD_NAME}"
  95. CONFIG_USE_DT_CODE_PARTITION=y
  96. CONFIG_BOOTLOADER_BOSSA_ADAFRUIT_UF2=y
  97. CONFIG_HAS_FLASH_LOAD_OFFSET=y
  98. CONFIG_FLASH_LOAD_OFFSET=0x162e
  99. '''
  100. # SAM-BA omit offset
  101. DOTCONFIG_COND5 = f'''
  102. CONFIG_BOARD="{TEST_BOARD_NAME}"
  103. CONFIG_USE_DT_CODE_PARTITION=y
  104. CONFIG_HAS_FLASH_LOAD_OFFSET=y
  105. CONFIG_FLASH_LOAD_OFFSET=0x0
  106. '''
  107. # SAM-BA Legacy Mode
  108. DOTCONFIG_COND6 = f'''
  109. CONFIG_BOARD="{TEST_BOARD_NAME}"
  110. CONFIG_USE_DT_CODE_PARTITION=y
  111. CONFIG_BOOTLOADER_BOSSA_LEGACY=y
  112. CONFIG_HAS_FLASH_LOAD_OFFSET=y
  113. CONFIG_FLASH_LOAD_OFFSET=0x162e
  114. '''
  115. def adjust_runner_config(runner_config, tmpdir, dotconfig):
  116. # Adjust a RunnerConfig object, 'runner_config', by
  117. # replacing its build directory with 'tmpdir' after writing
  118. # the contents of 'dotconfig' to tmpdir/zephyr/.config.
  119. zephyr = tmpdir / 'zephyr'
  120. zephyr.mkdir()
  121. with open(zephyr / '.config', 'w') as f:
  122. f.write(dotconfig)
  123. return runner_config._replace(build_dir=os.fspath(tmpdir))
  124. def require_patch(program):
  125. assert program in ['bossac', 'stty']
  126. os_path_isfile = os.path.isfile
  127. def os_path_isfile_patch(filename):
  128. if filename == RC_KERNEL_BIN:
  129. return True
  130. return os_path_isfile(filename)
  131. @patch('runners.bossac.BossacBinaryRunner.supports',
  132. return_value=False)
  133. @patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
  134. return_value=None)
  135. @patch('runners.core.ZephyrBinaryRunner.require',
  136. side_effect=require_patch)
  137. @patch('runners.core.ZephyrBinaryRunner.check_call')
  138. def test_bossac_init(cc, req, get_cod_par, sup, runner_config, tmpdir):
  139. """
  140. Test commands using a runner created by constructor.
  141. Requirements:
  142. Any SDK
  143. Configuration:
  144. ROM bootloader
  145. CONFIG_USE_DT_CODE_PARTITION=n
  146. without zephyr,code-partition
  147. Input:
  148. none
  149. Output:
  150. no --offset
  151. """
  152. runner_config = adjust_runner_config(runner_config, tmpdir, DOTCONFIG_STD)
  153. runner = BossacBinaryRunner(runner_config, port=TEST_BOSSAC_PORT)
  154. with patch('os.path.isfile', side_effect=os_path_isfile_patch):
  155. runner.run('flash')
  156. assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS]
  157. @patch('runners.bossac.BossacBinaryRunner.supports',
  158. return_value=False)
  159. @patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
  160. return_value=None)
  161. @patch('runners.core.ZephyrBinaryRunner.require',
  162. side_effect=require_patch)
  163. @patch('runners.core.ZephyrBinaryRunner.check_call')
  164. def test_bossac_create(cc, req, get_cod_par, sup, runner_config, tmpdir):
  165. """
  166. Test commands using a runner created from command line parameters.
  167. Requirements:
  168. Any SDK
  169. Configuration:
  170. ROM bootloader
  171. CONFIG_USE_DT_CODE_PARTITION=n
  172. without zephyr,code-partition
  173. Input:
  174. --bossac-port
  175. Output:
  176. no --offset
  177. """
  178. args = ['--bossac-port', str(TEST_BOSSAC_PORT)]
  179. parser = argparse.ArgumentParser()
  180. BossacBinaryRunner.add_parser(parser)
  181. arg_namespace = parser.parse_args(args)
  182. runner_config = adjust_runner_config(runner_config, tmpdir, DOTCONFIG_STD)
  183. runner = BossacBinaryRunner.create(runner_config, arg_namespace)
  184. with patch('os.path.isfile', side_effect=os_path_isfile_patch):
  185. runner.run('flash')
  186. assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS]
  187. @patch('runners.bossac.BossacBinaryRunner.supports',
  188. return_value=False)
  189. @patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
  190. return_value=None)
  191. @patch('runners.core.ZephyrBinaryRunner.require',
  192. side_effect=require_patch)
  193. @patch('runners.core.ZephyrBinaryRunner.check_call')
  194. def test_bossac_create_with_speed(cc, req, get_cod_par, sup, runner_config, tmpdir):
  195. """
  196. Test commands using a runner created from command line parameters.
  197. Requirements:
  198. Any SDK
  199. Configuration:
  200. ROM bootloader
  201. CONFIG_USE_DT_CODE_PARTITION=n
  202. without zephyr,code-partition
  203. Input:
  204. --bossac-port
  205. --speed
  206. Output:
  207. no --offset
  208. """
  209. args = ['--bossac-port', str(TEST_BOSSAC_PORT),
  210. '--speed', str(TEST_BOSSAC_SPEED)]
  211. parser = argparse.ArgumentParser()
  212. BossacBinaryRunner.add_parser(parser)
  213. arg_namespace = parser.parse_args(args)
  214. runner_config = adjust_runner_config(runner_config, tmpdir, DOTCONFIG_STD)
  215. runner = BossacBinaryRunner.create(runner_config, arg_namespace)
  216. with patch('os.path.isfile', side_effect=os_path_isfile_patch):
  217. runner.run('flash')
  218. assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS_WITH_SPEED]
  219. @patch('runners.bossac.BossacBinaryRunner.supports',
  220. return_value=True)
  221. @patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
  222. return_value=True)
  223. @patch('runners.core.ZephyrBinaryRunner.require',
  224. side_effect=require_patch)
  225. @patch('runners.core.ZephyrBinaryRunner.check_call')
  226. def test_bossac_create_with_flash_address(cc, req, get_cod_par, sup,
  227. runner_config, tmpdir):
  228. """
  229. Test command with offset parameter
  230. Requirements:
  231. SDK >= 0.12.0
  232. Configuration:
  233. Any bootloader
  234. CONFIG_USE_DT_CODE_PARTITION=y
  235. with zephyr,code-partition
  236. Input:
  237. --bossac-port
  238. Output:
  239. --offset
  240. """
  241. args = [
  242. '--bossac-port',
  243. str(TEST_BOSSAC_PORT),
  244. ]
  245. parser = argparse.ArgumentParser()
  246. BossacBinaryRunner.add_parser(parser)
  247. arg_namespace = parser.parse_args(args)
  248. runner_config = adjust_runner_config(runner_config, tmpdir,
  249. DOTCONFIG_COND1)
  250. runner = BossacBinaryRunner.create(runner_config, arg_namespace)
  251. with patch('os.path.isfile', side_effect=os_path_isfile_patch):
  252. runner.run('flash')
  253. assert cc.call_args_list == [
  254. call(x) for x in EXPECTED_COMMANDS_WITH_FLASH_ADDRESS
  255. ]
  256. @patch('runners.bossac.BossacBinaryRunner.supports',
  257. return_value=False)
  258. @patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
  259. return_value=True)
  260. @patch('runners.core.ZephyrBinaryRunner.require',
  261. side_effect=require_patch)
  262. @patch('runners.core.ZephyrBinaryRunner.check_call')
  263. def test_bossac_create_with_omit_address(cc, req, bcfg_ini, sup,
  264. runner_config, tmpdir):
  265. """
  266. Test command that will omit offset because CONFIG_FLASH_LOAD_OFFSET is 0.
  267. This case is valid for ROM bootloaders that define image start at 0 and
  268. define flash partitions, to use the storage capabilities, for instance.
  269. Requirements:
  270. Any SDK
  271. Configuration:
  272. ROM bootloader
  273. CONFIG_USE_DT_CODE_PARTITION=y
  274. with zephyr,code-partition
  275. Input:
  276. --bossac-port
  277. Output:
  278. no --offset
  279. """
  280. runner_config = adjust_runner_config(runner_config, tmpdir,
  281. DOTCONFIG_COND5)
  282. runner = BossacBinaryRunner(runner_config, port=TEST_BOSSAC_PORT)
  283. with patch('os.path.isfile', side_effect=os_path_isfile_patch):
  284. runner.run('flash')
  285. assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS]
  286. @patch('runners.bossac.BossacBinaryRunner.supports',
  287. return_value=True)
  288. @patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
  289. return_value=True)
  290. @patch('runners.core.ZephyrBinaryRunner.require',
  291. side_effect=require_patch)
  292. @patch('runners.core.ZephyrBinaryRunner.check_call')
  293. def test_bossac_create_with_arduino(cc, req, get_cod_par, sup,
  294. runner_config, tmpdir):
  295. """
  296. Test SAM-BA extended protocol with Arduino variation
  297. Requirements:
  298. SDK >= 0.12.0
  299. Configuration:
  300. Extended bootloader
  301. CONFIG_USE_DT_CODE_PARTITION=y
  302. CONFIG_BOOTLOADER_BOSSA_ARDUINO=y
  303. with zephyr,code-partition
  304. Input:
  305. --bossac-port
  306. Output:
  307. --offset
  308. """
  309. runner_config = adjust_runner_config(runner_config, tmpdir,
  310. DOTCONFIG_COND3)
  311. runner = BossacBinaryRunner(runner_config, port=TEST_BOSSAC_PORT)
  312. with patch('os.path.isfile', side_effect=os_path_isfile_patch):
  313. runner.run('flash')
  314. assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS_WITH_EXTENDED]
  315. @patch('runners.bossac.BossacBinaryRunner.supports',
  316. return_value=True)
  317. @patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
  318. return_value=True)
  319. @patch('runners.core.ZephyrBinaryRunner.require',
  320. side_effect=require_patch)
  321. @patch('runners.core.ZephyrBinaryRunner.check_call')
  322. def test_bossac_create_with_adafruit(cc, req, get_cod_par, sup,
  323. runner_config, tmpdir):
  324. """
  325. Test SAM-BA extended protocol with Adafruit UF2 variation
  326. Requirements:
  327. SDK >= 0.12.0
  328. Configuration:
  329. Extended bootloader
  330. CONFIG_USE_DT_CODE_PARTITION=y
  331. CONFIG_BOOTLOADER_BOSSA_ADAFRUIT_UF2=y
  332. with zephyr,code-partition
  333. Input:
  334. --bossac-port
  335. Output:
  336. --offset
  337. """
  338. runner_config = adjust_runner_config(runner_config, tmpdir,
  339. DOTCONFIG_COND4)
  340. runner = BossacBinaryRunner(runner_config, port=TEST_BOSSAC_PORT)
  341. with patch('os.path.isfile', side_effect=os_path_isfile_patch):
  342. runner.run('flash')
  343. assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS_WITH_EXTENDED]
  344. @patch('runners.bossac.BossacBinaryRunner.supports',
  345. return_value=True)
  346. @patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
  347. return_value=True)
  348. @patch('runners.core.ZephyrBinaryRunner.require',
  349. side_effect=require_patch)
  350. @patch('runners.core.ZephyrBinaryRunner.check_call')
  351. def test_bossac_create_with_legacy(cc, req, get_cod_par, sup,
  352. runner_config, tmpdir):
  353. """
  354. Test SAM-BA legacy protocol
  355. Requirements:
  356. Any SDK
  357. Configuration:
  358. Extended bootloader
  359. CONFIG_USE_DT_CODE_PARTITION=y
  360. CONFIG_BOOTLOADER_BOSSA_LEGACY=y
  361. with zephyr,code-partition
  362. Input:
  363. --bossac-port
  364. Output:
  365. no --offset
  366. """
  367. runner_config = adjust_runner_config(runner_config, tmpdir,
  368. DOTCONFIG_COND6)
  369. runner = BossacBinaryRunner(runner_config, port=TEST_BOSSAC_PORT)
  370. with patch('os.path.isfile', side_effect=os_path_isfile_patch):
  371. runner.run('flash')
  372. assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS]
  373. @patch('runners.bossac.BossacBinaryRunner.supports',
  374. return_value=False)
  375. @patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
  376. return_value=True)
  377. @patch('runners.core.ZephyrBinaryRunner.require',
  378. side_effect=require_patch)
  379. @patch('runners.core.ZephyrBinaryRunner.check_call')
  380. def test_bossac_create_with_oldsdk(cc, req, get_cod_par, sup,
  381. runner_config, tmpdir):
  382. """
  383. Test old SDK and ask user to upgrade
  384. Requirements:
  385. SDK <= 0.12.0
  386. Configuration:
  387. Any bootloader
  388. CONFIG_USE_DT_CODE_PARTITION=y
  389. with zephyr,code-partition
  390. Input:
  391. Output:
  392. Abort
  393. """
  394. runner_config = adjust_runner_config(runner_config, tmpdir,
  395. DOTCONFIG_COND1)
  396. runner = BossacBinaryRunner(runner_config)
  397. with pytest.raises(RuntimeError) as rinfo:
  398. with patch('os.path.isfile', side_effect=os_path_isfile_patch):
  399. runner.run('flash')
  400. assert str(rinfo.value) == "This version of BOSSA does not support the" \
  401. " --offset flag. Please upgrade to a newer" \
  402. " Zephyr SDK version >= 0.12.0."
  403. @patch('runners.bossac.BossacBinaryRunner.supports',
  404. return_value=False)
  405. @patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
  406. return_value=None)
  407. @patch('runners.core.ZephyrBinaryRunner.require',
  408. side_effect=require_patch)
  409. @patch('runners.core.ZephyrBinaryRunner.check_call')
  410. def test_bossac_create_error_missing_dt_info(cc, req, get_cod_par, sup,
  411. runner_config, tmpdir):
  412. """
  413. Test SAM-BA offset wrong configuration. No chosen code partition.
  414. Requirements:
  415. Any SDK
  416. Configuration:
  417. Any bootloader
  418. CONFIG_USE_DT_CODE_PARTITION=y
  419. with zephyr,code-partition (missing)
  420. Input:
  421. Output:
  422. Abort
  423. """
  424. runner_config = adjust_runner_config(runner_config, tmpdir,
  425. DOTCONFIG_COND1)
  426. runner = BossacBinaryRunner(runner_config)
  427. with pytest.raises(RuntimeError) as rinfo:
  428. with patch('os.path.isfile', side_effect=os_path_isfile_patch):
  429. runner.run('flash')
  430. assert str(rinfo.value) == "The device tree zephyr,code-partition" \
  431. " chosen node must be defined."
  432. @patch('runners.bossac.BossacBinaryRunner.supports',
  433. return_value=False)
  434. @patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
  435. return_value=True)
  436. @patch('runners.core.ZephyrBinaryRunner.require',
  437. side_effect=require_patch)
  438. @patch('runners.core.ZephyrBinaryRunner.check_call')
  439. def test_bossac_create_error_missing_kconfig(cc, req, get_cod_par, sup,
  440. runner_config, tmpdir):
  441. """
  442. Test SAM-BA offset wrong configuration. No CONFIG_USE_DT_CODE_PARTITION
  443. Kconfig definition.
  444. Requirements:
  445. Any SDK
  446. Configuration:
  447. Any bootloader
  448. CONFIG_USE_DT_CODE_PARTITION=y (missing)
  449. with zephyr,code-partition
  450. Input:
  451. Output:
  452. Abort
  453. """
  454. runner_config = adjust_runner_config(runner_config, tmpdir,
  455. DOTCONFIG_COND2)
  456. runner = BossacBinaryRunner(runner_config)
  457. with pytest.raises(RuntimeError) as rinfo:
  458. with patch('os.path.isfile', side_effect=os_path_isfile_patch):
  459. runner.run('flash')
  460. assert str(rinfo.value) == \
  461. "There is no CONFIG_USE_DT_CODE_PARTITION Kconfig defined at " \
  462. + TEST_BOARD_NAME + "_defconfig file.\n This means that" \
  463. " zephyr,code-partition device tree node should not be defined." \
  464. " Check Zephyr SAM-BA documentation."