check firmware feature in mik32_check

This commit is contained in:
Sergey Shchelkanov 2023-12-20 15:14:22 +03:00
parent ef7297f203
commit b8bd3e876f
8 changed files with 576 additions and 175 deletions

108
hex_parser.py Normal file
View File

@ -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

275
mik32_check.py Normal file
View File

@ -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")

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 = ""
@ -47,24 +47,16 @@ def test_connection():
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
@ -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)
@ -346,8 +245,10 @@ def upload_file(
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()
@ -356,8 +257,10 @@ def upload_file(
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(
@ -495,11 +398,11 @@ def createParser():
'-t',
'--mcu-type',
dest='mcu_type',
type=MIK_VERSION,
choices=list(MIK_VERSION),
default=MIK_VERSION.MIK32V2,
type=MIK32_Version,
choices=list(MIK32_Version),
default=MIK32_Version.MIK32V2,
help="Выбор микроконтроллера. "
f"По умолчанию: {MIK_VERSION.MIK32V2}"
f"По умолчанию: {MIK32_Version.MIK32V2}"
)
return parser