diff --git a/hex_parser.py b/hex_parser.py new file mode 100644 index 0000000..9974d4d --- /dev/null +++ b/hex_parser.py @@ -0,0 +1,108 @@ +from enum import Enum +import os +from typing import List, NamedTuple, Union + +from parsers import Record, RecordType, parse_line + + +class MemoryType(Enum): + BOOT = 0 + EEPROM = 1 + RAM = 2 + SPIFI = 3 + UNKNOWN = -1 + + +class MemorySection(NamedTuple): + type: MemoryType + offset: int + length: int # Memory section length in bytes + + +class Segment: + offset: int + memory: Union[MemorySection, None] = None + data: List[int] + + def __init__(self, offset: int, data: List[int], sections: List[MemorySection]): + self.offset = offset + self.data = data + + self._locate_memory_section(sections) + + def _locate_memory_section(self, sections: List[MemorySection]): + for section in sections: + if self._belongs_memory_section(section, self.offset): + self.memory = section + + if self.memory is None: + raise Exception( + f"ERROR: segment with offset {self.offset:#0x} doesn't belong to any section") + + if (self.offset + self.data.__len__()) > (self.memory.offset + self.memory.length): + raise Exception( + f"ERROR: segment with offset {self.offset:#0x} " + f"and length {self.data.__len__()} " + f"overflows section {self.memory.type.name}" + ) + + def _belongs_memory_section(self, memory_section: MemorySection, offset: int) -> bool: + if offset < memory_section.offset: + return False + if offset >= (memory_section.offset + memory_section.length): + return False + + return True + + +supported_text_formats = [".hex"] + + +class FirmwareFile: + file_name: str + file_extension: str + segments: List[Segment] = [] + + def __init__(self, path: str, sections: List[MemorySection]): + self.file_name, self.file_extension = os.path.splitext(path) + + if self.file_extension in supported_text_formats: + with open(path) as f: + lines = f.readlines() + self._parse_hex(lines, sections) + elif self.file_extension == ".bin": + with open(path, "rb") as f: + bin_content = list(f.read()) + self.segments.append(Segment(offset=0, data=bin_content, sections=sections)) + else: + raise Exception(f"Unsupported file format: {self.file_extension}") + + def _parse_hex(self, lines: List[str], sections: List[MemorySection]): + segments: List[Segment] = [] + + lba: int = 0 # Linear Base Address + expect_address = 0 # Address of the next byte + + for i, line in enumerate(lines): + record: Record = parse_line(line, i, self.file_extension) + if record.type == RecordType.DATA: + drlo: int = record.address # Data Record Load Offset + if (expect_address != lba+drlo) or (segments.__len__() == 0): + expect_address = lba+drlo + segments.append(Segment( + offset=expect_address, data=[], sections=sections)) + + for byte in record.data: + segments[-1].data.append(byte) + expect_address += 1 + elif record.type == RecordType.EXTADDR: + lba = record.address + elif record.type == RecordType.LINEARSTARTADDR: + print(f"Start Linear Address: {record.address:#10x}", ) + elif record.type == RecordType.EOF: + break + + self.segments.extend(segments) + + def get_segments(self) -> List[Segment]: + return self.segments diff --git a/mik32_check.py b/mik32_check.py new file mode 100644 index 0000000..3a170bd --- /dev/null +++ b/mik32_check.py @@ -0,0 +1,275 @@ +import argparse +import logging +import os +import subprocess +import sys +import time +from typing import List, Union + +from PyInstaller import DEFAULT_WORKPATH +from mik32_pm import pm_init +from mik32_upload import BootMode, Pages, form_pages, openocd_exec_path, openocd_scripts_path, openocd_interface_path, openocd_target_path, adapter_default_speed, run_openocd, default_post_action, default_log_path, default_openocd_host, mik32v0_sections, OpenOCDStartupException, adapter_speed_not_supported, memory_page_size +from mik32_gpio import MIK32_Version, gpio_init, gpio_deinit +import mik32_eeprom +import mik32_spifi +import mik32_ram +from hex_parser import FirmwareFile, MemoryType, Segment +from tclrpc import OpenOcdTclRpc, TclException + + +def upload_file( + filename: str, + host: str = '127.0.0.1', + port: int = OpenOcdTclRpc.DEFAULT_PORT, + is_run_openocd=False, + use_quad_spi=False, + openocd_exec=openocd_exec_path, + openocd_scripts=openocd_scripts_path, + openocd_interface=openocd_interface_path, + openocd_target=openocd_target_path, + adapter_speed=adapter_default_speed, + is_open_console=False, + boot_mode=BootMode.UNDEFINED, + log_path=DEFAULT_WORKPATH, + post_action=default_post_action, + mik_version=MIK32_Version.MIK32V2 +) -> int: + """ + Write ihex or binary file into MIK32 EEPROM or external flash memory + @filename: full path to the file with hex or bin file format + @return: return 0 if successful, 1 if failed + """ + + print(f"Using {mik_version.value}") + + result = 0 + + if not os.path.exists(filename): + print(f"ERROR: File {filename} does not exist") + exit(1) + + file = FirmwareFile(filename, mik32v0_sections) + + segments: List[Segment] = file.get_segments() + pages: Pages = form_pages(segments, boot_mode) + + proc: Union[subprocess.Popen, None] = None + if is_run_openocd: + try: + logging.debug("OpenOCD try start!") + + proc = run_openocd(openocd_exec, openocd_scripts, + openocd_interface, openocd_target, is_open_console) + + logging.debug("OpenOCD started!") + + except OSError as e: + raise OpenOCDStartupException(e) + try: + with OpenOcdTclRpc(host, port) as openocd: + if (all(openocd_interface.find(i) == -1 for i in adapter_speed_not_supported)): + openocd.run(f"adapter speed {adapter_speed}") + openocd.run(f"log_output \"{log_path}\"") + openocd.run(f"debug_level 1") + + logging.debug("OpenOCD configured!") + + pm_init(openocd) + + logging.debug("PM configured!") + + if (pages.pages_eeprom.__len__() > 0): + start_time = time.perf_counter() + + result |= mik32_eeprom.check_pages( + pages.pages_eeprom, openocd) + + write_time = time.perf_counter() - start_time + write_size = pages.pages_eeprom.__len__( + ) * memory_page_size[MemoryType.EEPROM] + print( + f"Check {write_size} bytes in {write_time:.2f} seconds (effective {(write_size/(write_time*1024)):.1f} kbyte/s)") + if (pages.pages_spifi.__len__() > 0): + gpio_init(openocd, mik_version) + start_time = time.perf_counter() + + result |= mik32_spifi.check_pages( + pages.pages_spifi, openocd, use_quad_spi=use_quad_spi) + + write_time = time.perf_counter() - start_time + write_size = pages.pages_spifi.__len__( + ) * memory_page_size[MemoryType.SPIFI] + print( + f"Check {write_size} bytes in {write_time:.2f} seconds (effective {(write_size/(write_time*1024)):.1f} kbyte/s)") + gpio_deinit(openocd, mik_version) + + segments_ram = list(filter( + lambda segment: (segment.memory is not None) and (segment.memory.type == MemoryType.RAM), segments)) + if (segments_ram.__len__() > 0): + mik32_ram.check_segments(segments_ram, openocd) + result |= 0 + + openocd.run(post_action) + except ConnectionRefusedError: + print("ERROR: The connection to OpenOCD is not established. Check the settings and connection of the debugger") + except TclException as e: + print(f"ERROR: TclException {e.code} \n {e.msg}") + finally: + if proc is not None: + proc.kill() + + return result + + +def createParser(): + parser = argparse.ArgumentParser( + prog='mik32_upload.py', + description='''Скрипт предназначен для записи программы в ОЗУ, EEPROM и внешнюю flash память, + подключенную по интерфейсу SPIFI''' + ) + parser.add_argument( + 'filepath', + nargs='?', + help='Путь к файлу прошивки' + ) + parser.add_argument( + '--run-openocd', + dest='run_openocd', + action='store_true', + default=False, + help='Запуск openocd при прошивке МК' + ) + parser.add_argument( + '--use-quad-spi', + dest='use_quad_spi', + action='store_true', + default=False, + help='Использование режима QuadSPI при программировании внешней флеш памяти' + ) + parser.add_argument( + '--openocd-host', + dest='openocd_host', + default=default_openocd_host, + help=f"Адрес для подключения к openocd. По умолчанию: {default_openocd_host}" + ) + parser.add_argument( + '--openocd-port', + dest='openocd_port', + default=OpenOcdTclRpc.DEFAULT_PORT, + help=f"Порт tcl сервера openocd. По умолчанию: {OpenOcdTclRpc.DEFAULT_PORT}" + ) + parser.add_argument( + '--adapter-speed', + dest='adapter_speed', + default=adapter_default_speed, + help=f"Скорость отладчика в кГц. По умолчанию: {adapter_default_speed}" + ) + parser.add_argument( + '--openocd-exec', + dest='openocd_exec', + default=openocd_exec_path, + help=f"Путь к исполняемому файлу openocd. По умолчанию: {openocd_exec_path}" + ) + parser.add_argument( + '--openocd-scripts', + dest='openocd_scripts', + default=openocd_scripts_path, + help=f"Путь к папке scripts. По умолчанию: {openocd_scripts_path}" + ) + parser.add_argument( + '--openocd-interface', + dest='openocd_interface', + default=openocd_interface_path, + help='Путь к файлу конфигурации отладчика относительно папки scripts или абсолютный путь. ' + f"По умолчанию: {openocd_interface_path}" + ) + parser.add_argument( + '--openocd-target', + dest='openocd_target', + default=openocd_target_path, + help='Путь к файлу конфигурации целевого контроллера относительно папки scripts. ' + f"По умолчанию: {openocd_target_path}" + ) + parser.add_argument( + '--open-console', + dest='open_console', + action='store_true', + default=False, + help='Открывать OpenOCD в отдельной консоли' + ) + parser.add_argument( + '-b', + '--boot-mode', + dest='boot_mode', + type=BootMode, + choices=list(BootMode), + default=BootMode.UNDEFINED, + help="Выбор типа памяти, который отображается на загрузочную область. " + "Если тип не выбран, данные, находящиеся в загрузочной области в hex файле отбрасываются. " + f"По умолчанию: {BootMode.UNDEFINED}" + ) + parser.add_argument( + '--log-path', + dest='log_path', + default=default_log_path, + help=f"Путь к файлу журнала. По умолчанию: {default_log_path}" + ) + # parser.add_argument( + # '--log-terminal', + # dest='log_termir', + # action='store_true', + # default=False, + # help='Вывод журнала в консоль' + # ) + parser.add_argument( + '--post-action', + dest='post_action', + default=default_post_action, + help=f"Команды OpenOCD, запускаемые после прошивки. По умолчанию: {default_post_action}" + ) + parser.add_argument( + '--no-color', + dest='no_color', + action='store_true', + default=False, + help='Вывод без последовательностей управления терминалом. Временно не используется' + ) + parser.add_argument( + '-t', + '--mcu-type', + dest='mcu_type', + type=MIK32_Version, + choices=list(MIK32_Version), + default=MIK32_Version.MIK32V2, + help="Выбор микроконтроллера. " + f"По умолчанию: {MIK32_Version.MIK32V2}" + ) + return parser + + +if __name__ == '__main__': + logging.basicConfig(stream=sys.stderr, level=logging.INFO) + + parser = createParser() + namespace = parser.parse_args() + + if namespace.filepath: + upload_file( + namespace.filepath, + host=namespace.openocd_host, + port=namespace.openocd_port, + is_run_openocd=namespace.run_openocd, + use_quad_spi=namespace.use_quad_spi, + openocd_exec=namespace.openocd_exec, + openocd_scripts=namespace.openocd_scripts, + openocd_interface=namespace.openocd_interface, + openocd_target=namespace.openocd_target, + adapter_speed=namespace.adapter_speed, + is_open_console=namespace.open_console, + boot_mode=namespace.boot_mode, + log_path=namespace.log_path, + post_action=namespace.post_action, + mik_version=namespace.mcu_type + ) + else: + print("Nothing to check") diff --git a/mik32_eeprom.py b/mik32_eeprom.py index 25d9db0..b330f4e 100644 --- a/mik32_eeprom.py +++ b/mik32_eeprom.py @@ -246,6 +246,30 @@ def write_words(words: List[int], openocd: OpenOcdTclRpc, write_by_word=False, r return result +def check_pages(pages: Dict[int, List[int]], openocd: OpenOcdTclRpc) -> int: + openocd.halt() + eeprom_sysinit(openocd) + # configure cycles duration + eeprom_configure_cycles(openocd, 1, 3, 1, 100000, 1000) + time.sleep(0.1) + print("EEPROM checking...", flush=True) + + pages_offsets = list(pages) + + for index, page_offset in enumerate(pages_offsets): + page_words = bytes2words(pages[page_offset]) + + print( + f"Check page {page_offset:#06x}... {(index*100)//pages_offsets.__len__()}%", flush=True) + + if eeprom_check_data(openocd, page_words, page_offset, False): + print("Page mismatch!", flush=True) + return 1 + + print("EEPROM page check completed", flush=True) + return 0 + + def write_pages(pages: Dict[int, List[int]], openocd: OpenOcdTclRpc) -> int: openocd.halt() eeprom_sysinit(openocd) diff --git a/mik32_gpio.py b/mik32_gpio.py index 2c146c1..1ec8f3b 100644 --- a/mik32_gpio.py +++ b/mik32_gpio.py @@ -5,7 +5,7 @@ from enum import Enum from tclrpc import OpenOcdTclRpc -class MIK_VERSION(Enum): +class MIK32_Version(Enum): MIK32V0 = "MIK32V0" MIK32V2 = "MIK32V2" @@ -41,12 +41,12 @@ class PAD_CONFIG_REGS_V2(Enum): port2_value = 0 -def gpio_init(openocd: OpenOcdTclRpc, version: MIK_VERSION): +def gpio_init(openocd: OpenOcdTclRpc, version: MIK32_Version): port2_addr = 0 - if version == MIK_VERSION.MIK32V0: + if version == MIK32_Version.MIK32V0: port2_addr = PAD_CONFIG_BASE_ADDRESS + PAD_CONFIG_REGS_V0.PORT_2_CFG.value - elif version == MIK_VERSION.MIK32V2: + elif version == MIK32_Version.MIK32V2: port2_addr = PAD_CONFIG_BASE_ADDRESS + PAD_CONFIG_REGS_V2.PORT_2_CFG.value else: return @@ -58,9 +58,9 @@ def gpio_init(openocd: OpenOcdTclRpc, version: MIK_VERSION): port2_value_updated &= 0xF000 - if version == MIK_VERSION.MIK32V0: + if version == MIK32_Version.MIK32V0: port2_value_updated |= 0x000 - elif version == MIK_VERSION.MIK32V2: + elif version == MIK32_Version.MIK32V2: port2_value_updated |= 0x555 else: return @@ -71,11 +71,11 @@ def gpio_init(openocd: OpenOcdTclRpc, version: MIK_VERSION): openocd.write_word(port2_addr + 8, 0x0500) -def gpio_deinit(openocd: OpenOcdTclRpc, version: MIK_VERSION): +def gpio_deinit(openocd: OpenOcdTclRpc, version: MIK32_Version): - if version == MIK_VERSION.MIK32V0: + if version == MIK32_Version.MIK32V0: port2_addr = PAD_CONFIG_BASE_ADDRESS + PAD_CONFIG_REGS_V0.PORT_2_CFG.value - elif version == MIK_VERSION.MIK32V2: + elif version == MIK32_Version.MIK32V2: port2_addr = PAD_CONFIG_BASE_ADDRESS + PAD_CONFIG_REGS_V2.PORT_2_CFG.value else: return diff --git a/mik32_ram.py b/mik32_ram.py index c7c4546..b98f5dd 100644 --- a/mik32_ram.py +++ b/mik32_ram.py @@ -20,3 +20,18 @@ def write_segments(segments: List[Segment], openocd: OpenOcdTclRpc): print("Writing segment %s with size %d..." % (hex(segment.offset), segment.data.__len__())) segment_words = bytes2words(segment.data) openocd.write_memory(segment.offset, 32, segment_words) + + +def check_segments(segments: List[Segment], openocd: OpenOcdTclRpc) -> int: + openocd.halt() + for segment in segments: + print("Checking segment %s with size %d..." % (hex(segment.offset), segment.data.__len__())) + segment_words = bytes2words(segment.data) + segment_memory_words = openocd.read_memory(segment.offset, 32, len(segment_words)) + + for i in range(len(segment_words)): + if segment_words[i] != segment_memory_words[i]: + print(f"Word [{i}] expect {segment_words[i]} != read {segment_memory_words[i]} in segment {segment.offset}") + return 1 + + return 0 diff --git a/mik32_spifi.py b/mik32_spifi.py index 8d09143..cc9d7e9 100644 --- a/mik32_spifi.py +++ b/mik32_spifi.py @@ -519,6 +519,82 @@ def get_segments_list(pages_offsets: List[int], segment_size: int) -> List[int]: return list(segments) +def check_pages(pages: Dict[int, List[int]], openocd: OpenOcdTclRpc, use_quad_spi=False, use_chip_erase=False): + result = 0 + + openocd.halt() + spifi_init(openocd) + + JEDEC_ID = spifi_send_command(openocd, 0x9F, SPIFI_Frameform.OPCODE_NOADDR, SPIFI_Fieldform.ALL_SERIAL, 3) + + print(f"JEDEC_ID {JEDEC_ID[0]:02x} {JEDEC_ID[1]:02x} {JEDEC_ID[2]:02x}") + + dma = DMA(openocd) + dma.init() + + dma.channels[0].write_buffer = 0 + + dma.channels[0].channel = ChannelIndex.CHANNEL_0 + dma.channels[0].priority = ChannelPriority.VERY_HIGH + + dma.channels[0].read_mode = ChannelMode.MEMORY + dma.channels[0].read_increment = ChannelIncrement.ENABLE + dma.channels[0].read_size = ChannelSize.WORD + dma.channels[0].read_burst_size = 2 + dma.channels[0].read_request = ChannelRequest.SPIFI_REQUEST + dma.channels[0].read_ack = ChannelAck.DISABLE + + dma.channels[0].write_mode = ChannelMode.PERIPHERY + dma.channels[0].write_increment = ChannelIncrement.DISABLE + dma.channels[0].write_size = ChannelSize.WORD + dma.channels[0].write_burst_size = 2 + dma.channels[0].write_request = ChannelRequest.SPIFI_REQUEST + dma.channels[0].write_ack = ChannelAck.DISABLE + + dma.channels[1].write_buffer = 0 + + dma.channels[1].channel = ChannelIndex.CHANNEL_1 + dma.channels[1].priority = ChannelPriority.VERY_HIGH + + dma.channels[1].write_mode = ChannelMode.MEMORY + dma.channels[1].write_increment = ChannelIncrement.ENABLE + dma.channels[1].write_size = ChannelSize.WORD + dma.channels[1].write_burst_size = 2 + dma.channels[1].write_request = ChannelRequest.SPIFI_REQUEST + dma.channels[1].write_ack = ChannelAck.DISABLE + + dma.channels[1].read_mode = ChannelMode.PERIPHERY + dma.channels[1].read_increment = ChannelIncrement.DISABLE + dma.channels[1].read_size = ChannelSize.WORD + dma.channels[1].read_burst_size = 2 + dma.channels[1].read_request = ChannelRequest.SPIFI_REQUEST + dma.channels[1].read_ack = ChannelAck.DISABLE + + if (use_quad_spi): + print("Quad Enable") + spifi_quad_enable(openocd) + else: + spifi_quad_disable(openocd) + + pages_offsets = list(pages) + + for index, page_offset in enumerate(pages_offsets): + print(f"Check page {page_offset:#010x}... {(index*100)//pages_offsets.__len__()}%", flush=True) + page_bytes = pages[page_offset] + + result = spifi_read_data(openocd, page_offset, 256, page_bytes, dma=dma) + + if result == 1: + print("Data error") + if (use_quad_spi): + spifi_quad_disable(openocd) + return result + + if result == 0: + print("SPIFI page checking completed", flush=True) + return 0 + + def write_pages(pages: Dict[int, List[int]], openocd: OpenOcdTclRpc, use_quad_spi=False, use_chip_erase=False): result = 0 diff --git a/mik32_upload.py b/mik32_upload.py index d3f84dc..cef76e9 100644 --- a/mik32_upload.py +++ b/mik32_upload.py @@ -6,14 +6,16 @@ import os import time from enum import Enum from typing import List, Dict, NamedTuple, Union +from hex_parser import FirmwareFile, MemorySection, MemoryType, Segment from tclrpc import OpenOcdTclRpc, TclException -from mik32_gpio import MIK_VERSION, gpio_init, gpio_deinit +from mik32_gpio import MIK32_Version, gpio_init, gpio_deinit import mik32_eeprom import mik32_spifi import mik32_ram import mik32_pm -from mik32_parsers import * -import logging, sys +from parsers import * +import logging +import sys # class bcolors(Enum): @@ -35,8 +37,6 @@ default_post_action = "reset run" adapter_default_speed = 500 -supported_text_formats = [".hex"] - def test_connection(): output = "" @@ -46,25 +46,17 @@ def test_connection(): except OSError: logging.debug("Test connection timed out, try again") output = openocd.run("capture \"reg\"") - if output == "": raise Exception("ERROR: no regs found, check MCU connection") -class MemoryType(Enum): - BOOT = 0 - EEPROM = 1 - RAM = 2 - SPIFI = 80 - UNKNOWN = -1 - - memory_page_size = { - MemoryType.EEPROM : 128, - MemoryType.SPIFI : 256 + MemoryType.EEPROM: 128, + MemoryType.SPIFI: 256 } + class BootMode(Enum): UNDEFINED = 'undefined' EEPROM = 'eeprom' @@ -85,12 +77,6 @@ class BootMode(Enum): return MemoryType.UNKNOWN -class MemorySection(NamedTuple): - type: MemoryType - offset: int - length: int # Memory section length in bytes - - mik32v0_sections: List[MemorySection] = [ MemorySection(MemoryType.BOOT, 0x0, 16 * 1024), MemorySection(MemoryType.EEPROM, 0x01000000, 8 * 1024), @@ -99,93 +85,6 @@ mik32v0_sections: List[MemorySection] = [ ] -class Segment: - offset: int - memory: Union[MemorySection, None] = None - data: List[int] - - def __init__(self, offset: int, data: List[int]): - self.offset = offset - self.data = data - - self._locate_memory_section() - - def _locate_memory_section(self): - for section in mik32v0_sections: - if self._belongs_memory_section(section, self.offset): - self.memory = section - - if self.memory is None: - raise Exception( - f"ERROR: segment with offset {self.offset:#0x} doesn't belong to any section") - - if (self.offset + self.data.__len__()) > (self.memory.offset + self.memory.length): - raise Exception( - f"ERROR: segment with offset {self.offset:#0x} " - f"and length {self.data.__len__()} " - f"overflows section {self.memory.type.name}" - ) - - def _belongs_memory_section(self, memory_section: MemorySection, offset: int) -> bool: - if offset < memory_section.offset: - return False - if offset >= (memory_section.offset + memory_section.length): - return False - - return True - - -class FirmwareFile: - file_name: str - file_extension: str - file_content: Union[List[str], List[int]] = [] - - def __init__(self, path: str): - self.file_name, self.file_extension = os.path.splitext(path) - - if self.file_extension in supported_text_formats: - with open(path) as f: - self.file_content = f.readlines() - elif self.file_extension == ".bin": - with open(path, "rb") as f: - self.file_content = list(f.read()) - else: - raise Exception(f"Unsupported file format: {self.file_extension}") - - def _parse_text(self) -> List[Segment]: - segments: List[Segment] = [] - - lba: int = 0 # Linear Base Address - expect_address = 0 # Address of the next byte - - for i, line in enumerate(self.file_content): - record: Record = parse_line(line, i, self.file_extension) - if record.type == RecordType.DATA: - drlo: int = record.address # Data Record Load Offset - if (expect_address != lba+drlo) or (segments.__len__() == 0): - expect_address = lba+drlo - segments.append(Segment( - offset=expect_address, data=[])) - - for byte in record.data: - segments[-1].data.append(byte) - expect_address += 1 - elif record.type == RecordType.EXTADDR: - lba = record.address - elif record.type == RecordType.LINEARSTARTADDR: - print(f"Start Linear Address: {record.address:#10x}", ) - elif record.type == RecordType.EOF: - break - - return segments - - def get_segments(self) -> List[Segment]: - if self.file_extension in supported_text_formats: - return self._parse_text() - elif self.file_extension == ".bin": - return [Segment(offset=0, data=self.file_content)] - - def fill_pages_from_segment(segment: Segment, page_size: int, pages: Dict[int, List[int]]): if segment.memory is None: return @@ -228,7 +127,7 @@ def run_openocd( is_open_console=False ) -> subprocess.Popen: cmd = [openocd_exec, "-s", openocd_scripts, - "-f", openocd_interface, "-f", openocd_target] + "-f", openocd_interface, "-f", openocd_target] creation_flags = subprocess.SW_HIDE if is_open_console: @@ -293,7 +192,7 @@ def upload_file( boot_mode=BootMode.UNDEFINED, log_path=default_log_path, post_action=default_post_action, - mik_version=MIK_VERSION.MIK32V2 + mik_version=MIK32_Version.MIK32V2 ) -> int: """ Write ihex or binary file into MIK32 EEPROM or external flash memory @@ -309,7 +208,7 @@ def upload_file( print(f"ERROR: File {filename} does not exist") exit(1) - file = FirmwareFile(filename) + file = FirmwareFile(filename, mik32v0_sections) segments: List[Segment] = file.get_segments() pages: Pages = form_pages(segments, boot_mode) @@ -323,7 +222,7 @@ def upload_file( openocd_interface, openocd_target, is_open_console) logging.debug("OpenOCD started!") - + except OSError as e: raise OpenOCDStartupException(e) try: @@ -344,20 +243,24 @@ def upload_file( result |= mik32_eeprom.write_pages( pages.pages_eeprom, openocd) - + write_time = time.perf_counter() - start_time - write_size = pages.pages_eeprom.__len__() * memory_page_size[MemoryType.EEPROM] - print(f"Wrote {write_size} bytes in {write_time:.2f} seconds (effective {(write_size/(write_time*1024)):.1f} kbyte/s)") + write_size = pages.pages_eeprom.__len__( + ) * memory_page_size[MemoryType.EEPROM] + print( + f"Wrote {write_size} bytes in {write_time:.2f} seconds (effective {(write_size/(write_time*1024)):.1f} kbyte/s)") if (pages.pages_spifi.__len__() > 0): gpio_init(openocd, mik_version) start_time = time.perf_counter() result |= mik32_spifi.write_pages( pages.pages_spifi, openocd, use_quad_spi=use_quad_spi) - + write_time = time.perf_counter() - start_time - write_size = pages.pages_spifi.__len__() * memory_page_size[MemoryType.SPIFI] - print(f"Wrote {write_size} bytes in {write_time:.2f} seconds (effective {(write_size/(write_time*1024)):.1f} kbyte/s)") + write_size = pages.pages_spifi.__len__( + ) * memory_page_size[MemoryType.SPIFI] + print( + f"Wrote {write_size} bytes in {write_time:.2f} seconds (effective {(write_size/(write_time*1024)):.1f} kbyte/s)") gpio_deinit(openocd, mik_version) segments_ram = list(filter( @@ -385,121 +288,121 @@ def createParser(): подключенную по интерфейсу SPIFI''' ) parser.add_argument( - 'filepath', - nargs='?', + 'filepath', + nargs='?', help='Путь к файлу прошивки' ) parser.add_argument( - '--run-openocd', + '--run-openocd', dest='run_openocd', - action='store_true', - default=False, + action='store_true', + default=False, help='Запуск openocd при прошивке МК' ) parser.add_argument( - '--use-quad-spi', + '--use-quad-spi', dest='use_quad_spi', action='store_true', - default=False, + default=False, help='Использование режима QuadSPI при программировании внешней флеш памяти' ) parser.add_argument( - '--openocd-host', - dest='openocd_host', - default=default_openocd_host, + '--openocd-host', + dest='openocd_host', + default=default_openocd_host, help=f"Адрес для подключения к openocd. По умолчанию: {default_openocd_host}" ) parser.add_argument( - '--openocd-port', + '--openocd-port', dest='openocd_port', - default=OpenOcdTclRpc.DEFAULT_PORT, + default=OpenOcdTclRpc.DEFAULT_PORT, help=f"Порт tcl сервера openocd. По умолчанию: {OpenOcdTclRpc.DEFAULT_PORT}" ) parser.add_argument( - '--adapter-speed', + '--adapter-speed', dest='adapter_speed', - default=adapter_default_speed, + default=adapter_default_speed, help=f"Скорость отладчика в кГц. По умолчанию: {adapter_default_speed}" ) parser.add_argument( - '--openocd-exec', - dest='openocd_exec', - default=openocd_exec_path, + '--openocd-exec', + dest='openocd_exec', + default=openocd_exec_path, help=f"Путь к исполняемому файлу openocd. По умолчанию: {openocd_exec_path}" ) parser.add_argument( - '--openocd-scripts', - dest='openocd_scripts', - default=openocd_scripts_path, + '--openocd-scripts', + dest='openocd_scripts', + default=openocd_scripts_path, help=f"Путь к папке scripts. По умолчанию: {openocd_scripts_path}" ) parser.add_argument( - '--openocd-interface', - dest='openocd_interface', - default=openocd_interface_path, + '--openocd-interface', + dest='openocd_interface', + default=openocd_interface_path, help='Путь к файлу конфигурации отладчика относительно папки scripts или абсолютный путь. ' f"По умолчанию: {openocd_interface_path}" ) parser.add_argument( - '--openocd-target', - dest='openocd_target', - default=openocd_target_path, + '--openocd-target', + dest='openocd_target', + default=openocd_target_path, help='Путь к файлу конфигурации целевого контроллера относительно папки scripts. ' f"По умолчанию: {openocd_target_path}" ) parser.add_argument( - '--open-console', + '--open-console', dest='open_console', - action='store_true', - default=False, + action='store_true', + default=False, help='Открывать OpenOCD в отдельной консоли' ) parser.add_argument( - '-b', - '--boot-mode', - dest='boot_mode', + '-b', + '--boot-mode', + dest='boot_mode', type=BootMode, - choices=list(BootMode), - default=BootMode.UNDEFINED, + choices=list(BootMode), + default=BootMode.UNDEFINED, help="Выбор типа памяти, который отображается на загрузочную область. " "Если тип не выбран, данные, находящиеся в загрузочной области в hex файле отбрасываются. " f"По умолчанию: {BootMode.UNDEFINED}" ) parser.add_argument( - '--log-path', + '--log-path', dest='log_path', default=default_log_path, help=f"Путь к файлу журнала. По умолчанию: {default_log_path}" ) # parser.add_argument( - # '--log-terminal', + # '--log-terminal', # dest='log_termir', - # action='store_true', + # action='store_true', # default=False, # help='Вывод журнала в консоль' # ) parser.add_argument( - '--post-action', + '--post-action', dest='post_action', default=default_post_action, help=f"Команды OpenOCD, запускаемые после прошивки. По умолчанию: {default_post_action}" ) parser.add_argument( - '--no-color', + '--no-color', dest='no_color', - action='store_true', + action='store_true', default=False, help='Вывод без последовательностей управления терминалом. Временно не используется' ) parser.add_argument( - '-t', - '--mcu-type', - dest='mcu_type', - type=MIK_VERSION, - choices=list(MIK_VERSION), - default=MIK_VERSION.MIK32V2, + '-t', + '--mcu-type', + dest='mcu_type', + type=MIK32_Version, + choices=list(MIK32_Version), + default=MIK32_Version.MIK32V2, help="Выбор микроконтроллера. " - f"По умолчанию: {MIK_VERSION.MIK32V2}" + f"По умолчанию: {MIK32_Version.MIK32V2}" ) return parser diff --git a/mik32_parsers.py b/parsers.py similarity index 100% rename from mik32_parsers.py rename to parsers.py