This commit is contained in:
Sergey Shchelkanov 2023-05-30 16:07:15 +03:00
commit a37f8fc93c
2 changed files with 115 additions and 34 deletions

View File

@ -3,6 +3,7 @@ from typing import Dict, List
import time import time
from tclrpc import TclException from tclrpc import TclException
from tclrpc import OpenOcdTclRpc from tclrpc import OpenOcdTclRpc
import config
# -------------------------- # --------------------------
# PM register offset # PM register offset
@ -306,11 +307,13 @@ def spifi_sector_erase(openocd: OpenOcdTclRpc, address: int):
spifi_wait_intrq_timeout(openocd, "Timeout executing chip erase command") spifi_wait_intrq_timeout(openocd, "Timeout executing chip erase command")
def spifi_read_data(openocd: OpenOcdTclRpc, address: int, byte_count: int, bin_data: List[int]) -> int: def spifi_read_data(openocd: OpenOcdTclRpc, address: int, byte_count: int) -> List[int]:
read_data: List[int] = [] read_data: List[int] = []
openocd.write_word(SPIFI_CONFIG_ADDR, address) openocd.write_word(SPIFI_CONFIG_ADDR, address)
spifi_intrq_clear(openocd) # spifi_intrq_clear(openocd)
openocd.write_word(SPIFI_CONFIG_STAT, openocd.read_word(
SPIFI_CONFIG_STAT) | SPIFI_CONFIG_STAT_INTRQ_M)
openocd.write_word(SPIFI_CONFIG_CMD, (READ_DATA_COMMAND << SPIFI_CONFIG_CMD_OPCODE_S) | openocd.write_word(SPIFI_CONFIG_CMD, (READ_DATA_COMMAND << SPIFI_CONFIG_CMD_OPCODE_S) |
(SPIFI_CONFIG_CMD_FRAMEFORM_OPCODE_3ADDR << SPIFI_CONFIG_CMD_FRAMEFORM_S) | (SPIFI_CONFIG_CMD_FRAMEFORM_OPCODE_3ADDR << SPIFI_CONFIG_CMD_FRAMEFORM_S) |
(SPIFI_CONFIG_CMD_FIELDFORM_ALL_SERIAL << SPIFI_CONFIG_CMD_FIELDFORM_S) | (SPIFI_CONFIG_CMD_FIELDFORM_ALL_SERIAL << SPIFI_CONFIG_CMD_FIELDFORM_S) |
@ -319,11 +322,33 @@ def spifi_read_data(openocd: OpenOcdTclRpc, address: int, byte_count: int, bin_d
for i in range(byte_count): for i in range(byte_count):
data8 = openocd.read_memory(SPIFI_CONFIG_DATA32, 8, 1)[0] data8 = openocd.read_memory(SPIFI_CONFIG_DATA32, 8, 1)[0]
read_data.append(data8) read_data.append(data8)
# print(f"DATA[{i+address}] = {read_data[i]:#0x}") if config.is_verbose:
print(f"DATA[{i+address}] = {read_data[i]:#0x}")
return read_data
def spifi_check_erase(openocd: OpenOcdTclRpc, address: int, byte_count: int):
print(f"Checking erase from {address:#0x} to {(byte_count-1):#0x}")
read_data: List[int] = spifi_read_data(openocd, address, byte_count)
for i in range(byte_count):
if read_data[i] != 0:
print(f"DATA[{(i+address):#0x}] = {read_data[i]:#0x}, expected {0:#0x}")
return 1
return 0
def spifi_check_program(openocd: OpenOcdTclRpc, address: int, byte_count: int, bin_data: List[int]) -> int:
read_data: List[int] = spifi_read_data(openocd, address, byte_count)
if read_data.__len__ != byte_count:
return 1
for i in range(byte_count): for i in range(byte_count):
if read_data[i] != bin_data[i]: if read_data[i] != bin_data[i]:
print(f"DATA[{i+address}] = {read_data[i]:#0x} - ошибка") print(f"DATA[{(i+address):#0x}] = {read_data[i]:#0x}, expected {bin_data[i]:#0x}")
return 1 return 1
return 0 return 0
@ -333,9 +358,8 @@ def spifi_page_program(openocd: OpenOcdTclRpc, ByteAddress: int, data: List[int]
if byte_count > 256: if byte_count > 256:
raise Exception("Byte count more than 256") raise Exception("Byte count more than 256")
# spifi_intrq_clear(openocd) print("Writing page %s..." % hex(ByteAddress))
openocd.write_word(SPIFI_CONFIG_STAT, openocd.read_word( spifi_intrq_clear(openocd)
SPIFI_CONFIG_STAT) | SPIFI_CONFIG_STAT_INTRQ_M)
openocd.write_word(SPIFI_CONFIG_ADDR, ByteAddress) openocd.write_word(SPIFI_CONFIG_ADDR, ByteAddress)
openocd.write_word(SPIFI_CONFIG_IDATA, 0x00) openocd.write_word(SPIFI_CONFIG_IDATA, 0x00)
openocd.write_word(SPIFI_CONFIG_CLIMIT, 0x00000000) openocd.write_word(SPIFI_CONFIG_CLIMIT, 0x00000000)
@ -360,15 +384,20 @@ class EraseType(Enum):
def spifi_erase(openocd, erase_type: EraseType = EraseType.CHIP_ERASE, sectors: List[int] = []): def spifi_erase(openocd, erase_type: EraseType = EraseType.CHIP_ERASE, sectors: List[int] = []):
result = 0
if erase_type == EraseType.CHIP_ERASE: if erase_type == EraseType.CHIP_ERASE:
spifi_write_enable(openocd) spifi_write_enable(openocd)
spifi_chip_erase(openocd) spifi_chip_erase(openocd)
spifi_wait_busy(openocd) spifi_wait_busy(openocd)
result |= spifi_check_erase(openocd, 0, 4096)
elif erase_type == EraseType.SECTOR_ERASE: elif erase_type == EraseType.SECTOR_ERASE:
for sector in sectors: for sector in sectors:
spifi_write_enable(openocd) spifi_write_enable(openocd)
spifi_sector_erase(openocd, sector) spifi_sector_erase(openocd, sector)
spifi_wait_busy(openocd) spifi_wait_busy(openocd)
result |= spifi_check_erase(openocd, sector, sector + 0x800)
return result
def spifi_write(openocd: OpenOcdTclRpc, address: int, data: List[int], data_len: int): def spifi_write(openocd: OpenOcdTclRpc, address: int, data: List[int], data_len: int):
@ -397,14 +426,14 @@ def spifi_write_file(bytes: List[int], openocd: OpenOcdTclRpc, is_resume=True):
break break
print("address = ", address) print("address = ", address)
spifi_write(openocd, address, bytes, 256) spifi_write(openocd, address, bytes, 256)
if spifi_read_data(openocd, address, 256, bytes) == 1: if spifi_check_program(openocd, address, 256, bytes) == 1:
return 1 return 1
if (len(bytes) % 256) != 0: if (len(bytes) % 256) != 0:
print( print(
f"address = {address}, +{len(bytes) - address-1}[{address + len(bytes) - address-1}]") f"address = {address}, +{len(bytes) - address-1}[{address + len(bytes) - address-1}]")
spifi_write(openocd, address, bytes, len(bytes) - address) spifi_write(openocd, address, bytes, len(bytes) - address)
if spifi_read_data(openocd, address, len(bytes) - address, bytes) == 1: if spifi_check_program(openocd, address, len(bytes) - address, bytes) == 1:
return 1 return 1
print("end") print("end")
if is_resume: if is_resume:
@ -417,6 +446,7 @@ def spifi_quad_page_program(openocd: OpenOcdTclRpc, ByteAddress: int, data: List
if byte_count > 256: if byte_count > 256:
raise Exception("Byte count more than 256") raise Exception("Byte count more than 256")
print("Writing page %s..." % hex(ByteAddress))
# spifi_intrq_clear(openocd) # spifi_intrq_clear(openocd)
openocd.write_word(SPIFI_CONFIG_STAT, openocd.read_word( openocd.write_word(SPIFI_CONFIG_STAT, openocd.read_word(
SPIFI_CONFIG_STAT) | SPIFI_CONFIG_STAT_INTRQ_M) SPIFI_CONFIG_STAT) | SPIFI_CONFIG_STAT_INTRQ_M)
@ -481,18 +511,26 @@ def get_segments_list(pages_offsets: List[int], segment_size: int) -> List[int]:
return list(segments) return list(segments)
def write_pages(pages: Dict[int, List[int]], openocd: OpenOcdTclRpc, is_resume=True, use_quad_spi=False): def write_pages(pages: Dict[int, List[int]], openocd: OpenOcdTclRpc, is_resume=True, use_quad_spi=False, use_chip_erase=False):
result = 0 result = 0
openocd.halt() openocd.halt()
spifi_init(openocd) spifi_init(openocd)
spifi_erase(openocd, EraseType.SECTOR_ERASE, get_segments_list(list(pages), 4*1024))
address = 0 if use_chip_erase:
erase_type = EraseType.CHIP_ERASE
else:
erase_type = EraseType.SECTOR_ERASE
result = spifi_erase(openocd, erase_type, get_segments_list(list(pages), 4*1024))
if result == 1:
print("Erase error")
return result
spifi_quad_enable(openocd) spifi_quad_enable(openocd)
for page_offset in list(pages): for page_offset in list(pages):
print("Writing page %s..." % hex(page_offset))
page_bytes = pages[page_offset] page_bytes = pages[page_offset]
spifi_write_enable(openocd) spifi_write_enable(openocd)
@ -502,10 +540,10 @@ def write_pages(pages: Dict[int, List[int]], openocd: OpenOcdTclRpc, is_resume=T
spifi_page_program(openocd, page_offset, page_bytes, 256) spifi_page_program(openocd, page_offset, page_bytes, 256)
spifi_wait_busy(openocd) spifi_wait_busy(openocd)
result = spifi_read_data(openocd, page_offset, 256, page_bytes) result = spifi_check_program(openocd, page_offset, 256, page_bytes)
if result == 1: if result == 1:
print("Data error") print("Program error")
return result return result
spifi_quad_disable(openocd) spifi_quad_disable(openocd)

View File

@ -3,12 +3,13 @@ import argparse
import subprocess import subprocess
import os import os
from enum import Enum from enum import Enum
from typing import List, Dict, NamedTuple from typing import List, Dict, NamedTuple, Union
from tclrpc import OpenOcdTclRpc from tclrpc import OpenOcdTclRpc
import mik32_eeprom import mik32_eeprom
import mik32_spifi import mik32_spifi
import mik32_ram import mik32_ram
from mik32_parsers import * from mik32_parsers import *
import config
# class bcolors(Enum): # class bcolors(Enum):
@ -26,6 +27,8 @@ DEFAULT_OPENOCD_SCRIPTS_PATH = os.path.join(
supported_formats = [".hex"] supported_formats = [".hex"]
is_verbose = False
def test_connection(): def test_connection():
output = "" output = ""
@ -50,8 +53,11 @@ class MemorySection(NamedTuple):
length: int # Memory section length in bytes length: int # Memory section length in bytes
MEMORY_SECTION_BOOT = MemorySection(MemoryType.BOOT, 0x0, 16 * 1024)
mik32v0_sections: List[MemorySection] = [ mik32v0_sections: List[MemorySection] = [
MemorySection(MemoryType.BOOT, 0x0, 16 * 1024), MEMORY_SECTION_BOOT,
MemorySection(MemoryType.EEPROM, 0x01000000, 8 * 1024), MemorySection(MemoryType.EEPROM, 0x01000000, 8 * 1024),
MemorySection(MemoryType.RAM, 0x02000000, 16 * 1024), MemorySection(MemoryType.RAM, 0x02000000, 16 * 1024),
MemorySection(MemoryType.SPIFI, 0x80000000, 8 * 1024 * 1024), MemorySection(MemoryType.SPIFI, 0x80000000, 8 * 1024 * 1024),
@ -61,7 +67,7 @@ mik32v0_sections: List[MemorySection] = [
@dataclass @dataclass
class Segment: class Segment:
offset: int offset: int
memory: MemorySection | None memory: Union[MemorySection, None]
data: List[int] data: List[int]
@ -74,7 +80,7 @@ def belongs_memory_section(memory_section: MemorySection, offset: int) -> bool:
return True return True
def find_memory_section(offset: int) -> MemorySection | None: def find_memory_section(offset: int) -> Union[MemorySection, None]:
for section in mik32v0_sections: for section in mik32v0_sections:
if belongs_memory_section(section, offset): if belongs_memory_section(section, offset):
return section return section
@ -94,7 +100,7 @@ def read_file(filename: str) -> List[Segment]:
with open(filename, "rb") as f: with open(filename, "rb") as f:
contents = list(f.read()) contents = list(f.read())
segments.append( segments.append(
Segment(offset=0, memory=find_memory_section(0), data=contents)) Segment(offset=0, memory=MEMORY_SECTION_BOOT, data=contents))
else: else:
raise Exception("Unsupported file format: %s" % (file_extension)) raise Exception("Unsupported file format: %s" % (file_extension))
@ -107,8 +113,10 @@ def read_file(filename: str) -> List[Segment]:
drlo: int = record.address # Data Record Load Offset drlo: int = record.address # Data Record Load Offset
if (expect_address != lba+drlo) or (segments.__len__() == 0): if (expect_address != lba+drlo) or (segments.__len__() == 0):
expect_address = lba+drlo expect_address = lba+drlo
section = find_memory_section(expect_address)
if section is not None:
segments.append(Segment( segments.append(Segment(
offset=expect_address, memory=find_memory_section(expect_address), data=[])) offset=expect_address, memory=section, data=[]))
for byte in record.data: for byte in record.data:
segments[-1].data.append(byte) segments[-1].data.append(byte)
@ -149,7 +157,18 @@ def segments_to_pages(segments: List[Segment], page_size: int) -> Dict[int, List
return pages return pages
def upload_file(filename: str, host: str = '127.0.0.1', port: int = OpenOcdTclRpc.DEFAULT_PORT, is_resume=True, run_openocd=False, use_quad_spi=False) -> int: def upload_file(
filename: str,
openocd_path: str,
scripts_path: str,
adapter_speed: str,
host: str = '127.0.0.1',
port: int = OpenOcdTclRpc.DEFAULT_PORT,
is_resume=True,
run_openocd=False,
use_quad_spi=False,
use_chip_erase=False,
) -> int:
""" """
Write ihex or binary file into MIK32 EEPROM or external flash memory Write ihex or binary file into MIK32 EEPROM or external flash memory
@ -165,6 +184,7 @@ def upload_file(filename: str, host: str = '127.0.0.1', port: int = OpenOcdTclRp
result = 0 result = 0
print(filename)
if not os.path.exists(filename): if not os.path.exists(filename):
print("ERROR: File %s does not exist" % filename) print("ERROR: File %s does not exist" % filename)
exit(1) exit(1)
@ -181,10 +201,10 @@ def upload_file(filename: str, host: str = '127.0.0.1', port: int = OpenOcdTclRp
raise Exception("ERROR: segment with offset %s and length %s overflows section %s" % ( raise Exception("ERROR: segment with offset %s and length %s overflows section %s" % (
hex(segment.offset), segment.data.__len__(), segment.memory.type.name)) hex(segment.offset), segment.data.__len__(), segment.memory.type.name))
proc: subprocess.Popen | None = None proc: Union[subprocess.Popen, None] = None
if run_openocd: if run_openocd:
cmd = shlex.split("%s -s %s -f interface/ftdi/m-link.cfg -f target/mcu32.cfg" % ( cmd = shlex.split("%s -s %s -f interface/ftdi/m-link.cfg -f target/mik32.cfg" % (
DEFAULT_OPENOCD_EXEC_FILE_PATH, DEFAULT_OPENOCD_SCRIPTS_PATH), posix=False) openocd_path, scripts_path), posix=False)
proc = subprocess.Popen( proc = subprocess.Popen(
cmd, creationflags=subprocess.CREATE_NEW_CONSOLE | subprocess.SW_HIDE) cmd, creationflags=subprocess.CREATE_NEW_CONSOLE | subprocess.SW_HIDE)
@ -197,10 +217,12 @@ def upload_file(filename: str, host: str = '127.0.0.1', port: int = OpenOcdTclRp
lambda segment: (segment.memory is not None) and (segment.memory.type == MemoryType.RAM), segments)) lambda segment: (segment.memory is not None) and (segment.memory.type == MemoryType.RAM), segments))
if (pages_eeprom.__len__() > 0): if (pages_eeprom.__len__() > 0):
result |= mik32_eeprom.write_pages(pages_eeprom, openocd, is_resume) result |= mik32_eeprom.write_pages(
pages_eeprom, openocd, is_resume)
if (pages_spifi.__len__() > 0): if (pages_spifi.__len__() > 0):
# print(pages_spifi) # print(pages_spifi)
result |= mik32_spifi.write_pages(pages_spifi, openocd, is_resume, use_quad_spi) result |= mik32_spifi.write_pages(
pages_spifi, openocd, is_resume, use_quad_spi, use_chip_erase)
if (segments_ram.__len__() > 0): if (segments_ram.__len__() > 0):
mik32_ram.write_segments(segments_ram, openocd, is_resume) mik32_ram.write_segments(segments_ram, openocd, is_resume)
result |= 0 result |= 0
@ -214,6 +236,12 @@ def upload_file(filename: str, host: str = '127.0.0.1', port: int = OpenOcdTclRp
def createParser(): def createParser():
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument('filepath', nargs='?') parser.add_argument('filepath', nargs='?')
parser.add_argument('--openocd-path', dest='openocd_path',
default=DEFAULT_OPENOCD_EXEC_FILE_PATH)
parser.add_argument('--scripts-path', dest='scripts_path',
default=DEFAULT_OPENOCD_SCRIPTS_PATH)
parser.add_argument('--adapter-speed', dest='adapter_speed',
default=500)
parser.add_argument('--run-openocd', dest='run_openocd', parser.add_argument('--run-openocd', dest='run_openocd',
action='store_true', default=False) action='store_true', default=False)
parser.add_argument('--use-quad-spi', dest='use_quad_spi', parser.add_argument('--use-quad-spi', dest='use_quad_spi',
@ -224,6 +252,10 @@ def createParser():
default=OpenOcdTclRpc.DEFAULT_PORT) default=OpenOcdTclRpc.DEFAULT_PORT)
parser.add_argument('--keep-halt', dest='keep_halt', parser.add_argument('--keep-halt', dest='keep_halt',
action='store_true', default=False) action='store_true', default=False)
parser.add_argument('-v', '--verbose', dest='is_verbose',
action='store_true', default=False)
parser.add_argument('--use-chip-erase', dest='use_chip_erase',
action='store_true', default=False)
# parser.add_argument('-b', '--boot-mode', default='undefined') # parser.add_argument('-b', '--boot-mode', default='undefined')
return parser return parser
@ -232,9 +264,20 @@ def createParser():
if __name__ == '__main__': if __name__ == '__main__':
parser = createParser() parser = createParser()
namespace = parser.parse_args() namespace = parser.parse_args()
config.is_verbose = namespace.is_verbose
if namespace.filepath: if namespace.filepath:
upload_file(namespace.filepath, namespace.openocd_host, upload_file(
namespace.openocd_port, is_resume=(not namespace.keep_halt), run_openocd=namespace.run_openocd, use_quad_spi=namespace.use_quad_spi) namespace.filepath,
namespace.openocd_path,
namespace.scripts_path,
namespace.adapter_speed,
host=namespace.openocd_host,
port=namespace.openocd_port,
is_resume=(not namespace.keep_halt),
run_openocd=namespace.run_openocd,
use_quad_spi=namespace.use_quad_spi,
use_chip_erase=namespace.use_chip_erase,
)
else: else:
print("Nothing to upload") print("Nothing to upload")