stm32flash.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. # Copyright (c) 2019 Thomas Kupper <thomas.kupper@gmail.com>
  2. #
  3. # SPDX-License-Identifier: Apache-2.0
  4. '''Runner for flashing with stm32flash.'''
  5. from os import path
  6. import platform
  7. from runners.core import ZephyrBinaryRunner, RunnerCaps
  8. DEFAULT_DEVICE = '/dev/ttyUSB0'
  9. if platform.system() == 'Darwin':
  10. DEFAULT_DEVICE = '/dev/tty.SLAB_USBtoUART'
  11. class Stm32flashBinaryRunner(ZephyrBinaryRunner):
  12. '''Runner front-end for stm32flash.'''
  13. def __init__(self, cfg, device, action='write', baud=57600,
  14. force_binary=False, start_addr=0, exec_addr=None,
  15. serial_mode='8e1', reset=False, verify=False):
  16. super().__init__(cfg)
  17. self.device = device
  18. self.action = action
  19. self.baud = baud
  20. self.force_binary = force_binary
  21. self.start_addr = start_addr
  22. self.exec_addr = exec_addr
  23. self.serial_mode = serial_mode
  24. self.reset = reset
  25. self.verify = verify
  26. @classmethod
  27. def name(cls):
  28. return 'stm32flash'
  29. @classmethod
  30. def capabilities(cls):
  31. return RunnerCaps(commands={'flash'})
  32. @classmethod
  33. def do_add_parser(cls, parser):
  34. # required argument(s)
  35. # none for now
  36. # optional argument(s)
  37. parser.add_argument('--device', default=DEFAULT_DEVICE, required=False,
  38. help='serial port to flash, default \'' + DEFAULT_DEVICE + '\'')
  39. parser.add_argument('--action', default='write', required=False,
  40. choices=['erase', 'info', 'start', 'write'],
  41. help='erase / get device info / start execution / write flash')
  42. parser.add_argument('--baud-rate', default='57600', required=False,
  43. choices=['1200', '1800', '2400', '4800', '9600', '19200',
  44. '38400', '57600', '115200', '230400', '256000', '460800',
  45. '500000', '576000', '921600', '1000000', '1500000', '2000000'],
  46. help='serial baud rate, default \'57600\'')
  47. parser.add_argument('--force-binary', required=False, action='store_true',
  48. help='force the binary parser')
  49. parser.add_argument('--start-addr', default=0, required=False,
  50. help='specify start address for write operation, default \'0\'')
  51. parser.add_argument('--execution-addr', default=None, required=False,
  52. help='start execution at specified address, default \'0\' \
  53. which means start of flash')
  54. parser.add_argument('--serial-mode', default='8e1', required=False,
  55. help='serial port mode, default \'8e1\'')
  56. parser.add_argument('--reset', default=False, required=False, action='store_true',
  57. help='reset device at exit, default False')
  58. parser.add_argument('--verify', default=False, required=False, action='store_true',
  59. help='verify writes, default False')
  60. @classmethod
  61. def do_create(cls, cfg, args):
  62. return Stm32flashBinaryRunner(cfg, device=args.device, action=args.action,
  63. baud=args.baud_rate, force_binary=args.force_binary,
  64. start_addr=args.start_addr, exec_addr=args.execution_addr,
  65. serial_mode=args.serial_mode, reset=args.reset, verify=args.verify)
  66. def do_run(self, command, **kwargs):
  67. self.require('stm32flash')
  68. self.ensure_output('bin')
  69. bin_name = self.cfg.bin_file
  70. bin_size = path.getsize(bin_name)
  71. cmd_flash = ['stm32flash', '-b', self.baud,
  72. '-m', self.serial_mode]
  73. action = self.action.lower()
  74. if action == 'info':
  75. # show device information and exit
  76. msg_text = "get device info from {}".format(self.device)
  77. elif action == 'erase':
  78. # erase flash
  79. #size_aligned = (int(bin_size) >> 12) + 1 << 12
  80. size_aligned = (int(bin_size) & 0xfffff000) + 4096
  81. msg_text = "erase {} bit starting at {}".format(size_aligned, self.start_addr)
  82. cmd_flash.extend([
  83. '-S', str(self.start_addr) + ":" + str(size_aligned), '-o'])
  84. elif action == 'start':
  85. # start execution
  86. msg_text = "start code execution at {}".format(self.exec_addr)
  87. if self.exec_addr:
  88. if self.exec_addr == 0 or self.exec_addr.lower() == '0x0':
  89. msg_text += " (flash start)"
  90. else:
  91. self.exec_addr = 0
  92. cmd_flash.extend([
  93. '-g', str(self.exec_addr)])
  94. elif action == 'write':
  95. # flash binary file
  96. msg_text = "write {} bytes starting at {}".format(bin_size, self.start_addr)
  97. cmd_flash.extend([
  98. '-S', str(self.start_addr) + ":" + str(bin_size),
  99. '-w', bin_name])
  100. if self.exec_addr:
  101. cmd_flash.extend(['-g', self.exec_addr])
  102. if self.force_binary:
  103. cmd_flash.extend(['-f'])
  104. if self.reset:
  105. cmd_flash.extend(['-R'])
  106. if self.verify:
  107. cmd_flash.extend(['-v'])
  108. else:
  109. msg_text = "invalid action \'{}\' passed!".format(action)
  110. self.logger.error('Invalid action \'{}\' passed!'.format(action))
  111. return -1
  112. cmd_flash.extend([self.device])
  113. self.logger.info("Board: " + msg_text)
  114. self.check_call(cmd_flash)
  115. self.logger.info('Board: finished \'{}\' .'.format(action))