переработка eeprom и spifi

функции сгруппированы в классы, для spifi улучшено разделение функционала между контроллерами интерфейса и флеш памяти
This commit is contained in:
sh-sergey 2025-01-16 16:21:35 +03:00
parent d55a5242a8
commit 9bec497601
5 changed files with 828 additions and 902 deletions

View File

@ -1,212 +1,452 @@
from enum import Enum
import os
import pathlib
import sys
import time
from typing import List, Union
from typing import Dict, List, Union
from tclrpc import OpenOcdTclRpc
import mik32_debug_hal.spifi as spifi
from mik32_debug_hal.spifi import SPIFI
# import mik32_debug_hal.spifi as spifi
import mik32_debug_hal.dma as dma
# --------------------------
# Commands
# --------------------------
SREG1_BUSY = 1
class GenericFlash():
# --------------------------
# Commands
# --------------------------
SREG1_BUSY = 1
READ_LEN = 256
READ_LEN = 256
ENABLE_RESET_COMMAND = 0x66
RESET_COMMAND = 0x99
ENABLE_RESET_COMMAND = 0x66
RESET_COMMAND = 0x99
CHIP_ERASE_COMMAND = 0xC7
SECTOR_ERASE_COMMAND = 0x20
CHIP_ERASE_COMMAND = 0xC7
SECTOR_ERASE_COMMAND = 0x20
WRITE_ENABLE_COMMAND = 0x06
WRITE_DISABLE_COMMAND = 0x04
WRITE_ENABLE_COMMAND = 0x06
WRITE_DISABLE_COMMAND = 0x04
MEM_CONFIG_COMMAND = 0x61
MEM_CONFIG_VALUE = 0x7F
MEM_CONFIG_COMMAND = 0x61
MEM_CONFIG_VALUE = 0x7F
READ_DATA_COMMAND = 0x03
READ_DATA_COMMAND = 0x03
FAST_READ_QUAD_OUTPUT_COMMAND = 0x6B
FAST_READ_QUAD_OUTPUT_COMMAND = 0x6B
READ_SREG1_COMMAND = 0x05
READ_SREG2_COMMAND = 0x35
WRITE_SREG_COMMAND = 0x01
READ_SREG1_COMMAND = 0x05
READ_SREG2_COMMAND = 0x35
WRITE_SREG_COMMAND = 0x01
SREG2_QUAD_ENABLE = 9
SREG2_QUAD_ENABLE_S = (SREG2_QUAD_ENABLE-8)
SREG2_QUAD_ENABLE_M = 1 << SREG2_QUAD_ENABLE_S
SREG2_QUAD_ENABLE = 9
SREG2_QUAD_ENABLE_S = (SREG2_QUAD_ENABLE-8)
SREG2_QUAD_ENABLE_M = 1 << SREG2_QUAD_ENABLE_S
PAGE_PROGRAM_COMMAND = 0x02
PAGE_PROGRAM_COMMAND = 0x02
QUAD_PAGE_PROGRAM_COMMAND = 0x32
QUAD_PAGE_PROGRAM_COMMAND = 0x32
JEDEC_ID_COMMAND = 0x9F
JEDEC_ID_COMMAND = 0x9F
class FlashError(Exception):
def __init__(self, value):
self.value = value
class FlashError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return ("ERROR: " + repr(self.value))
def __str__(self):
return ("ERROR: " + repr(self.value))
class SREG_Num(Enum):
SREG1 = 0x00
SREG2 = 0x30
openocd: OpenOcdTclRpc
spifi: SPIFI
class SREG_Num(Enum):
SREG1 = 0x00
SREG2 = 0x30
def __init__(self, spifi: SPIFI):
self.spifi = spifi
self.openocd = self.spifi.openocd
# self.init()
def write_enable(openocd: OpenOcdTclRpc):
spifi.send_command(openocd, WRITE_ENABLE_COMMAND,
spifi.Frameform.OPCODE_NOADDR, spifi.Fieldform.ALL_SERIAL)
def write_enable(self):
self.spifi.send_command(self.WRITE_ENABLE_COMMAND,
self.spifi.Frameform.OPCODE_NOADDR, self.spifi.Fieldform.ALL_SERIAL)
def read_sreg(self, sreg: SREG_Num) -> int:
return self.spifi.send_command(
self.READ_SREG1_COMMAND | sreg.value,
self.spifi.Frameform.OPCODE_NOADDR,
self.spifi.Fieldform.ALL_SERIAL,
byte_count=1
)[0]
def read_sreg(openocd: OpenOcdTclRpc, sreg: SREG_Num) -> int:
return spifi.send_command(
openocd,
READ_SREG1_COMMAND | sreg.value,
spifi.Frameform.OPCODE_NOADDR,
spifi.Fieldform.ALL_SERIAL,
byte_count=1
)[0]
def write_sreg(self, sreg1: int, sreg2: int):
self.write_enable()
self.spifi.send_command(
self.WRITE_SREG_COMMAND,
self.spifi.Frameform.OPCODE_NOADDR,
self.spifi.Fieldform.ALL_SERIAL,
byte_count=2,
direction=self.spifi.Direction.WRITE,
data=[sreg1, sreg2]
)
self.wait_busy()
def wait_busy(self):
while 1:
sreg1 = self.read_sreg(self.SREG_Num.SREG1)
if not (sreg1 & self.SREG1_BUSY):
break
def write_sreg(openocd: OpenOcdTclRpc, sreg1: int, sreg2: int):
write_enable(openocd)
spifi.send_command(
openocd,
WRITE_SREG_COMMAND,
spifi.Frameform.OPCODE_NOADDR,
spifi.Fieldform.ALL_SERIAL,
byte_count=2,
direction=spifi.Direction.WRITE,
data=[sreg1, sreg2]
)
wait_busy(openocd)
RESET_DELAY = 0.001
def chip_reset(self):
self.spifi.send_command(self.ENABLE_RESET_COMMAND,
self.spifi.Frameform.OPCODE_NOADDR, self.spifi.Fieldform.ALL_SERIAL)
self.spifi.send_command(self.RESET_COMMAND,
self.spifi.Frameform.OPCODE_NOADDR, self.spifi.Fieldform.ALL_SERIAL)
time.sleep(self.RESET_DELAY)
def wait_busy(openocd: OpenOcdTclRpc):
while 1:
sreg1 = read_sreg(openocd, SREG_Num.SREG1)
if not (sreg1 & SREG1_BUSY):
break
def chip_reset_qpi(self):
self.spifi.send_command(self.ENABLE_RESET_COMMAND,
self.spifi.Frameform.OPCODE_NOADDR, self.spifi.Fieldform.ALL_PARALLEL)
self.spifi.send_command(self.RESET_COMMAND,
self.spifi.Frameform.OPCODE_NOADDR, self.spifi.Fieldform.ALL_PARALLEL)
time.sleep(self.RESET_DELAY)
def chip_erase(self):
print("Chip erase...", flush=True)
self.spifi.send_command(self.CHIP_ERASE_COMMAND,
self.spifi.Frameform.OPCODE_NOADDR, self.spifi.Fieldform.ALL_SERIAL)
RESET_DELAY = 0.001
def sector_erase(self, address: int):
print(f"Erase sector {address:#010x}...", flush=True)
self.spifi.send_command(self.SECTOR_ERASE_COMMAND,
self.spifi.Frameform.OPCODE_3ADDR, self.spifi.Fieldform.ALL_SERIAL, address=address)
def read_data(self, address: int, byte_count: int, bin_data: List[int], dma: Union[dma.DMA, None] = None, use_quad_spi=False) -> int:
read_data: List[int] = []
def chip_reset(openocd: OpenOcdTclRpc):
spifi.send_command(openocd, ENABLE_RESET_COMMAND,
spifi.Frameform.OPCODE_NOADDR, spifi.Fieldform.ALL_SERIAL)
spifi.send_command(openocd, RESET_COMMAND,
spifi.Frameform.OPCODE_NOADDR, spifi.Fieldform.ALL_SERIAL)
time.sleep(RESET_DELAY)
if (use_quad_spi):
read_data = self.spifi.send_command(self.FAST_READ_QUAD_OUTPUT_COMMAND, self.spifi.Frameform.OPCODE_3ADDR,
self.spifi.Fieldform.DATA_PARALLEL, byte_count=byte_count, address=address, idata_length=1, dma=dma)
else:
read_data = self.spifi.send_command(self.READ_DATA_COMMAND, self.spifi.Frameform.OPCODE_3ADDR,
self.spifi.Fieldform.ALL_SERIAL, byte_count=byte_count, address=address, dma=dma)
for i in range(byte_count):
if read_data[i] != bin_data[i]:
print(
f"DATA[{i+address}] = {read_data[i]:#0x} expect {bin_data[i]:#0x}", flush=True)
def chip_reset_qpi(openocd: OpenOcdTclRpc):
spifi.send_command(openocd, ENABLE_RESET_COMMAND,
spifi.Frameform.OPCODE_NOADDR, spifi.Fieldform.ALL_PARALLEL)
spifi.send_command(openocd, RESET_COMMAND,
spifi.Frameform.OPCODE_NOADDR, spifi.Fieldform.ALL_PARALLEL)
time.sleep(RESET_DELAY)
return 1
return 0
def chip_erase(openocd: OpenOcdTclRpc):
print("Chip erase...", flush=True)
spifi.send_command(openocd, CHIP_ERASE_COMMAND,
spifi.Frameform.OPCODE_NOADDR, spifi.Fieldform.ALL_SERIAL)
def page_program(
self,
ByteAddress: int,
data: List[int],
byte_count: int,
progress: str = "",
dma: Union[dma.DMA, None] = None
):
print(
f"Writing Flash page {ByteAddress:#010x}... {progress}", flush=True)
if byte_count > 256:
raise self.FlashError("Byte count more than 256")
self.write_enable()
self.spifi.send_command(self.PAGE_PROGRAM_COMMAND, self.spifi.Frameform.OPCODE_3ADDR,
self.spifi.Fieldform.ALL_SERIAL, byte_count=byte_count, address=ByteAddress,
idata=0, cache_limit=0, direction=self.spifi.Direction.WRITE, data=data, dma=dma)
self.wait_busy()
def sector_erase(openocd: OpenOcdTclRpc, address: int):
print(f"Erase sector {address:#010x}...", flush=True)
spifi.send_command(openocd, SECTOR_ERASE_COMMAND,
spifi.Frameform.OPCODE_3ADDR, spifi.Fieldform.ALL_SERIAL, address=address)
class EraseType(Enum):
CHIP_ERASE = 0
SECTOR_ERASE = 1
def erase(self, erase_type: EraseType = EraseType.CHIP_ERASE, sectors: List[int] = []):
if erase_type == self.EraseType.CHIP_ERASE:
self.write_enable()
self.chip_erase()
self.wait_busy()
elif erase_type == self.EraseType.SECTOR_ERASE:
for sector in sectors:
self.write_enable()
self.sector_erase(sector)
self.wait_busy()
def read_data(openocd: OpenOcdTclRpc, address: int, byte_count: int, bin_data: List[int], dma: Union[dma.DMA, None] = None, use_quad_spi=False) -> int:
read_data: List[int] = []
if (use_quad_spi):
read_data = spifi.send_command(openocd, FAST_READ_QUAD_OUTPUT_COMMAND, spifi.Frameform.OPCODE_3ADDR,
spifi.Fieldform.DATA_PARALLEL, byte_count=byte_count, address=address, idata_length=1, dma=dma)
else:
read_data = spifi.send_command(openocd, READ_DATA_COMMAND, spifi.Frameform.OPCODE_3ADDR,
spifi.Fieldform.ALL_SERIAL, byte_count=byte_count, address=address, dma=dma)
for i in range(byte_count):
if read_data[i] != bin_data[i]:
print(
f"DATA[{i+address}] = {read_data[i]:#0x} expect {bin_data[i]:#0x}", flush=True)
return 1
return 0
def page_program(
openocd: OpenOcdTclRpc,
def quad_page_program(
self,
ByteAddress: int,
data: List[int],
byte_count: int,
progress: str = "",
dma: Union[dma.DMA, None] = None
):
print(f"Writing Flash page {ByteAddress:#010x}... {progress}", flush=True)
if byte_count > 256:
raise FlashError("Byte count more than 256")
):
print(f"Writing page {ByteAddress:#010x}... {progress}", flush=True)
if byte_count > 256:
raise self.FlashError("Byte count more than 256")
write_enable(openocd)
spifi.send_command(openocd, PAGE_PROGRAM_COMMAND, spifi.Frameform.OPCODE_3ADDR,
spifi.Fieldform.ALL_SERIAL, byte_count=byte_count, address=ByteAddress,
idata=0, cache_limit=0, direction=spifi.Direction.WRITE, data=data, dma=dma)
wait_busy(openocd)
self.write_enable()
self.spifi.send_command(self.QUAD_PAGE_PROGRAM_COMMAND, self.spifi.Frameform.OPCODE_3ADDR,
self.spifi.Fieldform.DATA_PARALLEL, byte_count=byte_count, address=ByteAddress,
idata=0, cache_limit=0, direction=self.spifi.Direction.WRITE, data=data, dma=dma)
self.wait_busy()
def quad_enable(self):
if (self.check_quad_enable(self.openocd) != True):
self.write_sreg(
self.read_sreg(self.SREG_Num.SREG1),
self.read_sreg(self.SREG_Num.SREG2) | self.SREG2_QUAD_ENABLE_M
)
class EraseType(Enum):
CHIP_ERASE = CHIP_ERASE_COMMAND
SECTOR_ERASE = SECTOR_ERASE_COMMAND
def check_quad_enable(self):
return (self.read_sreg(self.SREG_Num.SREG2) & self.SREG2_QUAD_ENABLE_M) != 0
def check_pages(self, pages: Dict[int, List[int]], use_quad_spi=False, use_chip_erase=False):
result = 0
def erase(openocd, erase_type: EraseType = EraseType.CHIP_ERASE, sectors: List[int] = []):
if erase_type == EraseType.CHIP_ERASE:
write_enable(openocd)
chip_erase(openocd)
wait_busy(openocd)
elif erase_type == EraseType.SECTOR_ERASE:
for sector in sectors:
write_enable(openocd)
sector_erase(openocd, sector)
wait_busy(openocd)
self.openocd.halt()
# self.init()
# Сбрасываем микросхему в режиме QPI из всех состояний в нормальный SPI режим.
self.chip_reset_qpi()
def quad_page_program(
openocd: OpenOcdTclRpc,
ByteAddress: int,
data: List[int],
byte_count: int,
progress: str = "",
dma: Union[dma.DMA, None] = None
):
print(f"Writing page {ByteAddress:#010x}... {progress}", flush=True)
if byte_count > 256:
raise FlashError("Byte count more than 256")
# Сбрасываем микросхему в режиме SPI из всех состояний в нормальный SPI режим.
self.chip_reset()
write_enable(openocd)
spifi.send_command(openocd, QUAD_PAGE_PROGRAM_COMMAND, spifi.Frameform.OPCODE_3ADDR,
spifi.Fieldform.DATA_PARALLEL, byte_count=byte_count, address=ByteAddress,
idata=0, cache_limit=0, direction=spifi.Direction.WRITE, data=data, dma=dma)
wait_busy(openocd)
JEDEC_ID = self.spifi.send_command(self.JEDEC_ID_COMMAND,
self.spifi.Frameform.OPCODE_NOADDR, self.spifi.Fieldform.ALL_SERIAL, 3)
print(
f"JEDEC ID = {JEDEC_ID[0]:02x} {JEDEC_ID[1]:02x} {JEDEC_ID[2]:02x}")
def quad_enable(openocd):
if (check_quad_enable(openocd) != True):
write_sreg(
openocd,
read_sreg(openocd, SREG_Num.SREG1),
read_sreg(openocd, SREG_Num.SREG2) | SREG2_QUAD_ENABLE_M
)
dma_instance = self.spifi.dma_config()
if (use_quad_spi):
print("Using Quad SPI")
self.quad_enable(self.openocd)
else:
print("Using Single SPI")
# spifi_quad_disable(openocd)
def check_quad_enable(openocd):
return (read_sreg(openocd, SREG_Num.SREG2) & SREG2_QUAD_ENABLE_M) != 0
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 = self.read_data(
self.openocd, page_offset, 256, page_bytes, dma=dma_instance, use_quad_spi=use_quad_spi)
if result == 1:
print("Data error")
# if (use_quad_spi):
# spifi_quad_disable(openocd)
return result
if result == 0:
print("SPIFI pages checking completed", flush=True)
return 0
def write_pages(self, pages: Dict[int, List[int]], use_quad_spi=False, use_chip_erase=False):
result = 0
self.openocd.halt()
# self.init()
# Сбрасываем микросхему в режиме QPI из всех состояний в нормальный SPI режим.
self.chip_reset_qpi()
# Сбрасываем микросхему в режиме SPI из всех состояний в нормальный SPI режим.
self.chip_reset()
JEDEC_ID = self.spifi.send_command(self.JEDEC_ID_COMMAND,
self.spifi.Frameform.OPCODE_NOADDR, self.spifi.Fieldform.ALL_SERIAL, 3)
print(
f"JEDEC ID = {JEDEC_ID[0]:02x} {JEDEC_ID[1]:02x} {JEDEC_ID[2]:02x}")
dma_instance = self.spifi.dma_config()
if use_chip_erase:
self.erase(
self.openocd, self.EraseType.CHIP_ERASE)
else:
self.erase(self.openocd, self.EraseType.SECTOR_ERASE,
self.get_segments_list(list(pages), 4*1024))
print("Quad Enable", self.check_quad_enable(self.openocd))
if (use_quad_spi):
print("Using Quad SPI")
self.quad_enable(self.openocd)
else:
print("Using Single SPI")
# spifi_quad_disable(openocd)
# print("SREG1", spifi_read_sreg(openocd, SREG_Num.SREG1))
# print("SREG2", spifi_read_sreg(openocd, SREG_Num.SREG2))
pages_offsets = list(pages)
for index, page_offset in enumerate(pages_offsets):
page_bytes = pages[page_offset]
if (use_quad_spi):
self.quad_page_program(
self.openocd, page_offset, page_bytes, 256, f"{(index*100)//pages_offsets.__len__()}%", dma=dma_instance)
else:
self.page_program(self.openocd, page_offset, page_bytes,
256, f"{(index*100)//pages_offsets.__len__()}%", dma=dma_instance)
result = self.read_data(
self.openocd, page_offset, 256, page_bytes, dma=dma_instance, use_quad_spi=use_quad_spi)
if result == 1:
print("Data error")
return result
if result == 0:
# Прошивка страниц флеш памяти по SPIFI была завершена
print(
"Flashing of flash memory pages via SPIFI has been completed", flush=True)
return 0
def wait_halted(self, timeout_seconds: float = 2):
self.openocd.run(f'wait_halt {int(timeout_seconds * 1000)}')
def write_pages_by_sectors(self, pages: Dict[int, List[int]],
driver_path: str,
use_quad_spi=False,
use_chip_erase=False,
):
result = 0
self.openocd.halt()
# Отключение прерываний
self.openocd.run("riscv.cpu set_reg {mstatus 0 mie 0}")
# self.init()
# openocd.run("rwp")
# Сбрасываем микросхему в режиме QPI из всех состояний в нормальный SPI режим.
self.chip_reset_qpi()
# Сбрасываем микросхему в режиме SPI из всех состояний в нормальный SPI режим.
self.chip_reset()
JEDEC_ID = self.spifi.send_command(
0x9F, self.spifi.Frameform.OPCODE_NOADDR, self.spifi.Fieldform.ALL_SERIAL, 3)
print(
f"JEDEC_ID {JEDEC_ID[0]:02x} {JEDEC_ID[1]:02x} {JEDEC_ID[2]:02x}")
sectors_list = self.get_segments_list(list(pages), 4*1024)
self.openocd.halt()
pathname = os.path.dirname(sys.argv[0])
self.openocd.run("wp 0x2003000 4 w")
print("Uploading driver... ", end="", flush=True)
self.openocd.run(f"load_image {{{pathlib.Path(driver_path)}}}")
print("OK!", flush=True)
self.openocd.resume(0x2000000)
self.wait_halted()
print("Writing Flash by sectors...", flush=True)
for i, sector in enumerate(sectors_list):
ByteAddress = sector
progress = f"{(i*100)//len(sectors_list)}%"
print(f" {ByteAddress:#010x} {progress:>4}", end="", flush=True)
bytes_list: List[int] = []
for page in range(16):
page = pages.get(page * 256 + sector)
if page is not None:
bytes_list.extend(page)
else:
bytes_list.extend([0]*256)
result = self.openocd.write_memory(0x02002000, 8, bytes_list)
if result:
print("ERROR!", flush=True)
print("An error occurred while writing data to the buffer area!")
print("Aborting...", flush=True)
return 1
self.openocd.run(f"set_reg {{t6 {sector}}}")
self.openocd.resume()
self.wait_halted(10) # ждем, когда watchpoint сработает
# watchpoint ловит до изменения слова
# делаем шаг, чтобы прочитать новое слово
self.openocd.run("step")
result = self.openocd.read_memory(0x2003000, 32, 1)[0]
if result == 0:
print(" OK!", flush=True)
else:
print(" FAIL!", flush=True)
print("result =", result)
break
if result == 0:
print(f" {sectors_list[-1]:#010x} 100% OK!", flush=True)
self.openocd.run("rwp 0x02003000")
self.spifi.init_memory()
if result == 0:
# Прошивка страниц флеш памяти по SPIFI была завершена
print("SPIFI writing successfully completed!", flush=True)
else:
print(f"SPIFI writing failed!", flush=True)
return 1
return result
def write(self, address: int, data: List[int], data_len: int):
if data_len > 256:
raise self.SpifiError("Byte count more than 256")
self.page_program(self.openocd, address, data, data_len)
print("written")
def write_file(self, bytes: List[int]):
# print(bytes)
print(f"Write {len(bytes)} bytes")
self.openocd.halt()
# self.init()
self.erase()
print("bin_data_len = ", len(bytes))
address = 0
for address in range(0, len(bytes), 256):
if ((address + 256) > len(bytes)):
break
print("address = ", address)
self.write(address, bytes, 256)
if self.read_data(address, 256, bytes) == 1:
return 1
if (len(bytes) % 256) != 0:
print(
f"address = {address}, +{len(bytes) - address-1}[{address + len(bytes) - address-1}]")
self.write(address, bytes, len(bytes) - address)
if self.read_data(address, len(bytes) - address, bytes) == 1:
return 1
print("end")
return 0
def get_segments_list(self, pages_offsets: List[int], segment_size: int) -> List[int]:
segments = set()
for offset in pages_offsets:
segments.add(offset & ~(segment_size - 1))
return sorted(list(segments))

View File

@ -9,11 +9,12 @@ from typing import List, Union
from mik32_debug_hal.power_manager 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, mik32_sections, OpenOCDError, adapter_speed_not_supported, memory_page_size
from mik32_debug_hal.gpio import MIK32_Version, gpio_init, gpio_deinit
import mik32_debug_hal.eeprom as eeprom
import mik32_debug_hal.spifi as spifi
import mik32_debug_hal.ram as ram
from hex_parser import FirmwareFile, MemoryType, Segment
from tclrpc import OpenOcdTclRpc, TclException
from mik32_debug_hal.eeprom import EEPROM
from mik32_debug_hal.spifi import SPIFI
from flash_drivers.generic_flash import GenericFlash
def upload_file(
@ -78,6 +79,8 @@ def upload_file(
logging.debug("PM configured!")
if (pages.pages_eeprom.__len__() > 0):
eeprom = EEPROM(openocd)
start_time = time.perf_counter()
result |= eeprom.check_pages(
@ -90,10 +93,12 @@ def upload_file(
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)
spifi = SPIFI(openocd)
flash = GenericFlash(spifi)
start_time = time.perf_counter()
result |= spifi.check_pages(
pages.pages_spifi, openocd, use_quad_spi=use_quad_spi)
result |= flash.check_pages(
pages.pages_spifi, use_quad_spi=use_quad_spi)
write_time = time.perf_counter() - start_time
write_size = pages.pages_spifi.__len__(

View File

@ -1,9 +1,8 @@
import datetime
from enum import Enum
import os
import pathlib
import sys
from typing import Dict, List, Tuple
from typing import Dict, List
import time
from tclrpc import OpenOcdTclRpc, TclException
from utils import bytes2words
@ -12,262 +11,6 @@ import mik32_debug_hal.registers.memory_map as mem_map
import mik32_debug_hal.registers.bitfields.eeprom as eeprom_fields
def eeprom_sysinit(openocd: OpenOcdTclRpc):
print("MCU clock init...", flush=True)
class EEPROM_Operation(Enum):
READ = eeprom_fields.OP_RD
ERASE = eeprom_fields.OP_ER
PROGRAM = eeprom_fields.OP_PR
class EEPROM_AffectedPages(Enum):
SINGLE = 0
EVEN = eeprom_fields.BEH_EVEN
ODD = eeprom_fields.BEH_ODD
GLOBAL = eeprom_fields.BEH_GLOB
def eeprom_execute_operation(openocd: OpenOcdTclRpc, op: EEPROM_Operation, affected_pages: EEPROM_AffectedPages, offset: int, buffer: List[int]):
# buffer write enable and select affected pages
openocd.write_memory(mem_map.EEPROM_REGS_EEA, 32, [offset, (1 << eeprom_fields.EECON_BWE_S)
| (affected_pages.value << eeprom_fields.EECON_WRBEH_S)])
if buffer.__len__() > 32:
return
for word in buffer:
openocd.write_word(mem_map.EEPROM_REGS_EEDAT, word)
# start operation
openocd.write_word(mem_map.EEPROM_REGS_EECON, (
(1 << eeprom_fields.EECON_EX_S) | (1 << eeprom_fields.EECON_BWE_S) |
(op.value << eeprom_fields.EECON_OP_S) | (
affected_pages.value << eeprom_fields.EECON_WRBEH_S)
))
def eeprom_configure_cycles(openocd: OpenOcdTclRpc, LD=1, R_1=2, R_2=1, CYCEP1=66667, CYCEP2=500):
openocd.write_word(mem_map.EEPROM_REGS_NCYCRL, LD << eeprom_fields.NCYCRL_N_LD_S |
R_1 << eeprom_fields.NCYCRL_N_R_1_S | R_2 << eeprom_fields.NCYCRL_N_R_2_S)
openocd.write_word(mem_map.EEPROM_REGS_NCYCEP1, CYCEP1)
openocd.write_word(mem_map.EEPROM_REGS_NCYCEP2, CYCEP2)
def eeprom_global_erase(openocd: OpenOcdTclRpc):
print("EEPROM global erase...", flush=True)
# configure cycles duration
eeprom_execute_operation(
openocd, EEPROM_Operation.ERASE, EEPROM_AffectedPages.GLOBAL, 0x0, [0] * 32)
def eeprom_global_erase_check(openocd: OpenOcdTclRpc):
print("EEPROM global erase check through APB...", flush=True)
print(" Read Data at ...", flush=True)
ex_value = 0x00000000
openocd.write_word(mem_map.EEPROM_REGS_EEA, 0x00000000)
for i in range(0, 64):
print(f" Row={i+1}/64")
for j in range(0, 32):
value = openocd.read_memory(mem_map.EEPROM_REGS_EEDAT, 32, 1)[0]
if ex_value != value:
print(
f"Unexpect value at Row {i}, Word {j}, expect {ex_value:#0x}, {value:#0x}", flush=True)
def eeprom_write_word(openocd: OpenOcdTclRpc, address: int, word: int):
eeprom_execute_operation(
openocd, EEPROM_Operation.PROGRAM, EEPROM_AffectedPages.SINGLE, address, [word])
time.sleep(0.001)
def eeprom_write_page(openocd: OpenOcdTclRpc, address: int, data: List[int]):
eeprom_execute_operation(
openocd, EEPROM_Operation.PROGRAM, EEPROM_AffectedPages.SINGLE, address, data)
time.sleep(0.001)
def eeprom_check_data_apb(openocd: OpenOcdTclRpc, words: List[int], offset: int, print_progress=True) -> int:
if print_progress:
print("EEPROM check through APB...", flush=True)
# address load
openocd.write_word(mem_map.EEPROM_REGS_EEA, offset)
word_num = 0
progress = 0
if print_progress:
print("[", end="", flush=True)
for word in words:
value: int = openocd.read_word(mem_map.EEPROM_REGS_EEDAT)
if words[word_num] != value:
print(
f"Unexpect value at {word_num} word, expect {word:#0x}, get {value:#0x}", flush=True)
return 1
word_num += 1
curr_progress = int((word_num * 50) / len(words))
if print_progress and (curr_progress > progress):
print("#"*(curr_progress - progress), end="", flush=True)
progress = curr_progress
if print_progress:
print("]", flush=True)
print("EEPROM check through APB done!", flush=True)
return 0
def eeprom_check_data_ahb_lite(openocd: OpenOcdTclRpc, words: List[int], offset: int, print_progress=True) -> int:
if print_progress:
print("EEPROM check through AHB-Lite...", flush=True)
mem_array = openocd.read_memory(0x01000000 + offset, 32, len(words))
if len(words) != len(mem_array):
print("ERROR: Wrong number of words in read_memory output!")
return 1
progress = 0
if print_progress:
print("[", end="", flush=True)
for word_num in range(len(words)):
if words[word_num] != mem_array[word_num]:
print(f"Unexpect value at {word_num} word, expect {words[word_num]:#0x}, "
f"get {mem_array[word_num]:#0x}", flush=True)
return 1
curr_progress = int((word_num * 50) / len(words))
if print_progress and (curr_progress > progress):
print("#"*(curr_progress - progress), end="", flush=True)
progress = curr_progress
if print_progress:
print("]", flush=True)
print("EEPROM check through APB done!", flush=True)
return 0
def eeprom_check_data(openocd: OpenOcdTclRpc, words: List[int], offset: int, print_progress=True, read_through_apb=False) -> int:
if read_through_apb:
return eeprom_check_data_apb(openocd, words, offset, print_progress)
else:
return eeprom_check_data_ahb_lite(openocd, words, offset, print_progress)
def write_words(words: List[int], openocd: OpenOcdTclRpc, write_by_word=False, read_through_apb=False) -> int:
"""
Write words in MIK32 EEPROM through APB bus
@words: list of words to write at offset 0x0
@write_by_word: if True, write every word in separete page flash operation
@read_through_apb: if True, check written words through APB instead of AHB-Lite
TODO: implement setting byte array offset, add error handling,
improve progress visualization, add option check page immidiately after writing
@return: return 0 if successful, 1 if failed
"""
print(f"Write {len(words*4)} bytes", flush=True)
openocd.halt()
eeprom_sysinit(openocd)
eeprom_global_erase(openocd)
# eeprom_global_erase_check(openocd)
# configure cycles duration
eeprom_configure_cycles(openocd, 1, 3, 1, 100000, 1000)
time.sleep(0.1)
word_num: int = 0
progress: int = 0
print("EEPROM writing...", flush=True)
print("[", end="", flush=True)
if write_by_word:
for word in words:
eeprom_write_word(openocd, word_num*4, word)
word_num += 1
curr_progress = int((word_num * 50) / len(words))
if curr_progress > progress:
print("#"*(curr_progress - progress), end="", flush=True)
progress = curr_progress
else:
page = []
page_num = 0
page_size = 32
while word_num < len(words):
if word_num < page_size*(page_num+1):
page.append(words[word_num])
word_num += 1
else:
# print(list(map(lambda word: f"{word:#0x}", page)))
eeprom_write_page(openocd, page_num*page_size*4, page)
page_num += 1
page.clear()
curr_progress = int((word_num * 50) / len(words))
if curr_progress > progress:
print("#"*(curr_progress - progress), end="", flush=True)
progress = curr_progress
eeprom_write_page(openocd, page_num*page_size*4, page)
print("]", flush=True)
if read_through_apb:
result = eeprom_check_data_apb(openocd, words, 0)
else:
result = eeprom_check_data_ahb_lite(openocd, words, 0)
if result == 0:
print("EEPROM write file done!", flush=True)
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)
eeprom_global_erase(openocd)
if eeprom_check_data_ahb_lite(openocd, [0]*2048, 0, False):
print("EEPROM global erase failed, try again", flush=True)
eeprom_global_erase(openocd)
if eeprom_check_data_ahb_lite(openocd, [0]*2048, 0, False):
print("EEPROM global erase failed", flush=True)
return 1
# configure cycles duration
eeprom_configure_cycles(openocd, 1, 3, 1, 100000, 1000)
time.sleep(0.1)
print("EEPROM writing...", flush=True)
pages_offsets = list(pages)
for index, page_offset in enumerate(pages_offsets):
page_words = bytes2words(pages[page_offset])
print(
f"Writing page {page_offset:#06x}... {(index*100)//pages_offsets.__len__()}%", flush=True)
eeprom_write_page(openocd, page_offset, page_words)
if eeprom_check_data(openocd, page_words, page_offset, False):
print("Page mismatch!", flush=True)
return 1
print("EEPROM page recording completed", flush=True)
return 0
def wait_halted(openocd: OpenOcdTclRpc, timeout_seconds: float = 2):
openocd.run(f'wait_halt {int(timeout_seconds * 1000)}')
def combine_pages(pages: Dict[int, List[int]]) -> List[int]:
"""
Объединить страницы в последовательность байт с заполнением промежутков
@ -287,83 +30,270 @@ def combine_pages(pages: Dict[int, List[int]]) -> List[int]:
return bytes_list
def write_memory(pages: Dict[int, List[int]], openocd: OpenOcdTclRpc, driver_path: str) -> int:
"""
Записать всю память с использованием драйвера.
class EEPROM():
openocd: OpenOcdTclRpc
pages: Dict[int, List[int]] -- страница - список байт, ключ - адрес в EEPROM
"""
def __init__(self, openocd: OpenOcdTclRpc):
self.openocd = openocd
# TODO: добавить проверку на версию mik32 - текущий драйвер поддерживает
# только версию mik32v2
self.eeprom_sysinit()
RAM_OFFSET = 0x02000000
RAM_BUFFER_OFFSET = 0x02001800
RAM_DRIVER_STATUS = 0x02003800
def eeprom_sysinit(self):
print("MCU clock init...", flush=True)
bytes_list = combine_pages(pages)
openocd.halt()
openocd.run("riscv.cpu set_reg {mstatus 0 mie 0}") # Отключение прерываний
class EEPROM_Operation(Enum):
READ = eeprom_fields.OP_RD
ERASE = eeprom_fields.OP_ER
PROGRAM = eeprom_fields.OP_PR
STATUS_CODE_M = 0xFF
class EEPROM_AffectedPages(Enum):
SINGLE = 0
EVEN = eeprom_fields.BEH_EVEN
ODD = eeprom_fields.BEH_ODD
GLOBAL = eeprom_fields.BEH_GLOB
max_address = len(bytes_list) // 128
openocd.write_memory(RAM_DRIVER_STATUS, 32, [1 | (max_address << 8)])
def eeprom_execute_operation(self, op: EEPROM_Operation, affected_pages: EEPROM_AffectedPages, offset: int, buffer: List[int]):
# buffer write enable and select affected pages
self.openocd.write_memory(mem_map.EEPROM_REGS_EEA, 32, [offset, (1 << eeprom_fields.EECON_BWE_S)
| (affected_pages.value << eeprom_fields.EECON_WRBEH_S)])
pathname = os.path.dirname(sys.argv[0])
if buffer.__len__() > 32:
return
for word in buffer:
self.openocd.write_word(mem_map.EEPROM_REGS_EEDAT, word)
# start operation
self.openocd.write_word(mem_map.EEPROM_REGS_EECON, (
(1 << eeprom_fields.EECON_EX_S) | (1 << eeprom_fields.EECON_BWE_S) |
(op.value << eeprom_fields.EECON_OP_S) | (
affected_pages.value << eeprom_fields.EECON_WRBEH_S)
))
print("Uploading driver... ", end="", flush=True)
openocd.run(f"load_image {{{pathlib.Path(driver_path)}}}")
print("OK!", flush=True)
def eeprom_configure_cycles(self, LD=1, R_1=2, R_2=1, CYCEP1=66667, CYCEP2=500):
self.openocd.write_word(mem_map.EEPROM_REGS_NCYCRL, LD << eeprom_fields.NCYCRL_N_LD_S |
R_1 << eeprom_fields.NCYCRL_N_R_1_S | R_2 << eeprom_fields.NCYCRL_N_R_2_S)
self.openocd.write_word(mem_map.EEPROM_REGS_NCYCEP1, CYCEP1)
self.openocd.write_word(mem_map.EEPROM_REGS_NCYCEP2, CYCEP2)
print("Uploading data... ", end="", flush=True)
result = openocd.write_memory(RAM_BUFFER_OFFSET, 8, bytes_list)
if result:
print("ERROR!", flush=True)
print("An error occurred while writing data to the buffer area!")
print("Aborting...", flush=True)
return 1
else:
def eeprom_global_erase(self):
print("EEPROM global erase...", flush=True)
# configure cycles duration
self.eeprom_execute_operation(
self.EEPROM_Operation.ERASE, self.EEPROM_AffectedPages.GLOBAL, 0x0, [0] * 32)
def eeprom_global_erase_check(self):
print("EEPROM global erase check through APB...", flush=True)
print(" Read Data at ...", flush=True)
ex_value = 0x00000000
self.openocd.write_word(mem_map.EEPROM_REGS_EEA, 0x00000000)
for i in range(0, 64):
print(f" Row={i+1}/64")
for j in range(0, 32):
value = self.openocd.read_memory(
mem_map.EEPROM_REGS_EEDAT, 32, 1)[0]
if ex_value != value:
print(
f"Unexpect value at Row {i}, Word {j}, expect {ex_value:#0x}, {value:#0x}", flush=True)
def eeprom_write_word(self, address: int, word: int):
self.eeprom_execute_operation(
self.EEPROM_Operation.PROGRAM, self.EEPROM_AffectedPages.SINGLE, address, [word])
time.sleep(0.001)
def eeprom_write_page(self, address: int, data: List[int]):
self.eeprom_execute_operation(
self.EEPROM_Operation.PROGRAM, self.EEPROM_AffectedPages.SINGLE, address, data)
time.sleep(0.001)
def eeprom_check_data_apb(self, words: List[int], offset: int, print_progress=True) -> int:
if print_progress:
print("EEPROM check through APB...", flush=True)
# address load
self.openocd.write_word(mem_map.EEPROM_REGS_EEA, offset)
word_num = 0
progress = 0
if print_progress:
print("[", end="", flush=True)
for word in words:
value: int = self.openocd.read_word(mem_map.EEPROM_REGS_EEDAT)
if words[word_num] != value:
print(
f"Unexpect value at {word_num} word, expect {word:#0x}, get {value:#0x}", flush=True)
return 1
word_num += 1
curr_progress = int((word_num * 50) / len(words))
if print_progress and (curr_progress > progress):
print("#"*(curr_progress - progress), end="", flush=True)
progress = curr_progress
if print_progress:
print("]", flush=True)
print("EEPROM check through APB done!", flush=True)
return 0
def eeprom_check_data_ahb_lite(self, words: List[int], offset: int, print_progress=True) -> int:
if print_progress:
print("EEPROM check through AHB-Lite...", flush=True)
mem_array = self.openocd.read_memory(
0x01000000 + offset, 32, len(words))
if len(words) != len(mem_array):
print("ERROR: Wrong number of words in read_memory output!")
return 1
progress = 0
if print_progress:
print("[", end="", flush=True)
for word_num in range(len(words)):
if words[word_num] != mem_array[word_num]:
print(f"Unexpect value at {word_num} word, expect {words[word_num]:#0x}, "
f"get {mem_array[word_num]:#0x}", flush=True)
return 1
curr_progress = int((word_num * 50) / len(words))
if print_progress and (curr_progress > progress):
print("#"*(curr_progress - progress), end="", flush=True)
progress = curr_progress
if print_progress:
print("]", flush=True)
print("EEPROM check through APB done!", flush=True)
return 0
def eeprom_check_data(self, words: List[int], offset: int, print_progress=True, read_through_apb=False) -> int:
if read_through_apb:
return self.eeprom_check_data_apb(words, offset, print_progress)
else:
return self.eeprom_check_data_ahb_lite(words, offset, print_progress)
def check_pages(self, pages: Dict[int, List[int]]) -> int:
self.openocd.halt()
self.eeprom_sysinit()
# configure cycles duration
self.eeprom_configure_cycles(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 self.eeprom_check_data(page_words, page_offset, False):
print("Page mismatch!", flush=True)
return 1
print("EEPROM page check completed", flush=True)
return 0
def write_pages(self, pages: Dict[int, List[int]]) -> int:
self.openocd.halt()
self.eeprom_sysinit()
self.eeprom_global_erase()
if self.eeprom_check_data_ahb_lite([0]*2048, 0, False):
print("EEPROM global erase failed, try again", flush=True)
self.eeprom_global_erase()
if self.eeprom_check_data_ahb_lite([0]*2048, 0, False):
print("EEPROM global erase failed", flush=True)
return 1
# configure cycles duration
self.eeprom_configure_cycles(1, 3, 1, 100000, 1000)
time.sleep(0.1)
print("EEPROM writing...", flush=True)
pages_offsets = list(pages)
for index, page_offset in enumerate(pages_offsets):
page_words = bytes2words(pages[page_offset])
print(
f"Writing page {page_offset:#06x}... {(index*100)//pages_offsets.__len__()}%", flush=True)
self.eeprom_write_page(page_offset, page_words)
if self.eeprom_check_data(page_words, page_offset, False):
print("Page mismatch!", flush=True)
return 1
print("EEPROM page recording completed", flush=True)
return 0
def wait_halted(self, timeout_seconds: float = 2):
self.openocd.run(f'wait_halt {int(timeout_seconds * 1000)}')
def write_memory(self, pages: Dict[int, List[int]], driver_path: str) -> int:
"""
Записать всю память с использованием драйвера.
pages: Dict[int, List[int]] -- страница - список байт, ключ - адрес в EEPROM
"""
# TODO: добавить проверку на версию mik32 - текущий драйвер поддерживает
# только версию mik32v2
RAM_OFFSET = 0x02000000
RAM_BUFFER_OFFSET = 0x02001800
RAM_DRIVER_STATUS = 0x02003800
bytes_list = combine_pages(pages)
self.openocd.halt()
# Отключение прерываний
self.openocd.run("riscv.cpu set_reg {mstatus 0 mie 0}")
STATUS_CODE_M = 0xFF
max_address = len(bytes_list) // 128
self.openocd.write_memory(RAM_DRIVER_STATUS, 32, [
1 | (max_address << 8)])
pathname = os.path.dirname(sys.argv[0])
print("Uploading driver... ", end="", flush=True)
self.openocd.run(f"load_image {{{pathlib.Path(driver_path)}}}")
print("OK!", flush=True)
# mem = openocd.read_memory(0x01000000, 8, len(bytes_list))
# print(f"total bytes read {len(bytes_list)}")
print("Uploading data... ", end="", flush=True)
result = self.openocd.write_memory(RAM_BUFFER_OFFSET, 8, bytes_list)
if result:
print("ERROR!", flush=True)
print("An error occurred while writing data to the buffer area!")
print("Aborting...", flush=True)
return 1
else:
print("OK!", flush=True)
# for i in range(len(bytes_list)):
# if bytes_list[i] != mem[i]:
# print(f"RAM data mismatch at address 0x{i:08x};"
# f"expect 0x{bytes_list[i]:08x} get 0x{mem[i]:08x}!", flush=True)
# return 1
# готовимся поймать результат записи
self.openocd.run(f"wp 0x{RAM_DRIVER_STATUS:08x} 4 w")
openocd.run(f"wp 0x{RAM_DRIVER_STATUS:08x} 4 w") # готовимся поймать результат записи
print("Run driver...", flush=True)
self.openocd.resume(RAM_OFFSET)
print("Run driver...", flush=True)
openocd.resume(RAM_OFFSET)
try:
# ждем, когда watchpoint сработает
self.wait_halted(10)
except TclException:
print("Timeout!", flush=True)
# return 1
try:
# ждем, когда watchpoint сработает
wait_halted(openocd, 10)
except TclException:
print("Timeout!", flush=True)
# return 1
# watchpoint ловит до изменения слова
self.openocd.run(f"rwp 0x{RAM_DRIVER_STATUS:08x}")
# делаем шаг, чтобы прочитать новое слово
self.openocd.run("step")
openocd.run(f"rwp 0x{RAM_DRIVER_STATUS:08x}") # watchpoint ловит до изменения слова
openocd.run("step") # делаем шаг, чтобы прочитать новое слово
result = self.openocd.read_memory(RAM_DRIVER_STATUS, 32, 1)[0]
result = openocd.read_memory(RAM_DRIVER_STATUS, 32, 1)[0]
if (result & STATUS_CODE_M) == 0:
print(f"EEPROM writing successfully completed!", flush=True)
else:
miss_page = (result >> 8) & (64 - 1)
miss_byte = (result >> 16) & (128 - 1)
expected_byte = pages[miss_page*128][miss_byte]
miss_byte = (result >> 24) & 0xFF
if (result & STATUS_CODE_M) == 0:
print(f"EEPROM writing successfully completed!", flush=True)
else:
miss_page = (result >> 8) & (64 - 1)
miss_byte = (result >> 16) & (128 - 1)
expected_byte = pages[miss_page*128][miss_byte]
miss_byte = (result >> 24) & 0xFF
print(f"EEPROM writing failed!", flush=True)
print(f"First mismatched byte in page {miss_page},")
print(
f"byte {miss_byte}, expected {expected_byte}, read {miss_byte}")
print(f"EEPROM writing failed!", flush=True)
print(f"First mismatched byte in page {miss_page},")
print(f"byte {miss_byte}, expected {expected_byte}, read {miss_byte}")
return 1
return 1
return 0
return 0

View File

@ -1,466 +1,214 @@
import datetime
from enum import Enum
import os
import pathlib
import sys
from typing import Dict, List, Union
from typing import List, Union
import time
from tclrpc import TclException
from tclrpc import OpenOcdTclRpc
import mik32_debug_hal.registers.memory_map as mem_map
import mik32_debug_hal.registers.bitfields.spifi as spifi_fields
import mik32_debug_hal.dma as dma
import flash_drivers.generic_flash as generic_flash
class SpifiError(Exception):
def __init__(self, value):
self.value = value
class SPIFI():
def __str__(self):
return ("ERROR: " + repr(self.value))
DEFAULT_READ_DATA_COMMAND = 0x03
class SpifiError(Exception):
def __init__(self, value):
self.value = value
def spifi_intrq_clear(openocd: OpenOcdTclRpc):
openocd.write_word(mem_map.SPIFI_CONFIG_STAT, openocd.read_word(mem_map.SPIFI_CONFIG_STAT) |
spifi_fields.SPIFI_CONFIG_STAT_INTRQ_M)
def __str__(self):
return ("ERROR: " + repr(self.value))
class Frameform(Enum):
RESERVED = 0
OPCODE_NOADDR = 1
OPCODE_1ADDR = 2
OPCODE_2ADDR = 3
OPCODE_3ADDR = 4
OPCODE_4ADDR = 5
NOOPCODE_3ADDR = 6
NOOPCODE_4ADDR = 7
INIT_DELAY = 0.001
class Fieldform(Enum):
ALL_SERIAL = 0
DATA_PARALLEL = 1
OPCODE_SERIAL = 2
ALL_PARALLEL = 3
TIMEOUT = 1.0
class Direction(Enum):
READ = 0
WRITE = 1
INIT_DELAY = 0.001
def init_periphery(openocd: OpenOcdTclRpc):
openocd.write_word(mem_map.SPIFI_CONFIG_STAT, openocd.read_word(mem_map.SPIFI_CONFIG_STAT) |
# SPIFI_CONFIG_STAT_INTRQ_M |
spifi_fields.SPIFI_CONFIG_STAT_RESET_M)
# openocd.write_word(SPIFI_CONFIG_CTRL, openocd.read_word(
# SPIFI_CONFIG_CTRL) | (7 << SPIFI_CONFIG_CTRL_SCK_DIV_S))
openocd.write_word(mem_map.SPIFI_CONFIG_ADDR, 0x00)
openocd.write_word(mem_map.SPIFI_CONFIG_IDATA, 0x00)
openocd.write_word(mem_map.SPIFI_CONFIG_CLIMIT, 0x00)
TIMEOUT = 1.0
time.sleep(INIT_DELAY)
openocd: OpenOcdTclRpc
def __init__(self, openocd: OpenOcdTclRpc):
self.openocd = openocd
def init(openocd: OpenOcdTclRpc):
self.init()
init_periphery(openocd)
def intrq_clear(self):
self.openocd.write_word(mem_map.SPIFI_CONFIG_STAT, self.openocd.read_word(mem_map.SPIFI_CONFIG_STAT) |
spifi_fields.SPIFI_CONFIG_STAT_INTRQ_M)
control = openocd.read_word(mem_map.SPIFI_CONFIG_CTRL)
control |= spifi_fields.SPIFI_CONFIG_CTRL_DMAEN_M
openocd.write_word(mem_map.SPIFI_CONFIG_CTRL, control)
def init_periphery(self):
self.openocd.write_word(mem_map.SPIFI_CONFIG_STAT, self.openocd.read_word(mem_map.SPIFI_CONFIG_STAT) |
# SPIFI_CONFIG_STAT_INTRQ_M |
spifi_fields.SPIFI_CONFIG_STAT_RESET_M)
# openocd.write_word(SPIFI_CONFIG_CTRL, openocd.read_word(
# SPIFI_CONFIG_CTRL) | (7 << SPIFI_CONFIG_CTRL_SCK_DIV_S))
self.openocd.write_word(mem_map.SPIFI_CONFIG_ADDR, 0x00)
self.openocd.write_word(mem_map.SPIFI_CONFIG_IDATA, 0x00)
self.openocd.write_word(mem_map.SPIFI_CONFIG_CLIMIT, 0x00)
time.sleep(INIT_DELAY)
time.sleep(self.INIT_DELAY)
def init(self):
def init_memory(openocd: OpenOcdTclRpc):
openocd.write_word(mem_map.SPIFI_CONFIG_STAT, openocd.read_word(mem_map.SPIFI_CONFIG_STAT) |
spifi_fields.SPIFI_CONFIG_STAT_INTRQ_M |
spifi_fields.SPIFI_CONFIG_STAT_RESET_M)
# openocd.write_word(SPIFI_CONFIG_CTRL, openocd.read_word(
# SPIFI_CONFIG_CTRL) | (7 << SPIFI_CONFIG_CTRL_SCK_DIV_S))
openocd.write_word(mem_map.SPIFI_CONFIG_ADDR, 0x00)
openocd.write_word(mem_map.SPIFI_CONFIG_IDATA, 0x00)
openocd.write_word(mem_map.SPIFI_CONFIG_CLIMIT, 0x00)
openocd.write_word(mem_map.SPIFI_CONFIG_MCMD, (0 << spifi_fields.SPIFI_CONFIG_MCMD_INTLEN_S) |
(spifi_fields.SPIFI_CONFIG_CMD_FIELDFORM_ALL_SERIAL << spifi_fields.SPIFI_CONFIG_MCMD_FIELDFORM_S) |
(spifi_fields.SPIFI_CONFIG_CMD_FRAMEFORM_OPCODE_3ADDR << spifi_fields.SPIFI_CONFIG_MCMD_FRAMEFORM_S) |
(generic_flash.READ_DATA_COMMAND << spifi_fields.SPIFI_CONFIG_MCMD_OPCODE_S))
self.init_periphery()
time.sleep(INIT_DELAY)
control = self.openocd.read_word(mem_map.SPIFI_CONFIG_CTRL)
control |= spifi_fields.SPIFI_CONFIG_CTRL_DMAEN_M
self.openocd.write_word(mem_map.SPIFI_CONFIG_CTRL, control)
time.sleep(self.INIT_DELAY)
def spifi_wait_intrq_timeout(openocd: OpenOcdTclRpc, error_message: str):
time_end = time.perf_counter() + TIMEOUT
while time.perf_counter() < time_end:
if (openocd.read_word(mem_map.SPIFI_CONFIG_STAT) & spifi_fields.SPIFI_CONFIG_STAT_INTRQ_M) != 0:
return
raise SpifiError(error_message)
def init_memory(self):
self.openocd.write_word(mem_map.SPIFI_CONFIG_STAT, self.openocd.read_word(mem_map.SPIFI_CONFIG_STAT) |
spifi_fields.SPIFI_CONFIG_STAT_INTRQ_M |
spifi_fields.SPIFI_CONFIG_STAT_RESET_M)
# openocd.write_word(SPIFI_CONFIG_CTRL, openocd.read_word(
# SPIFI_CONFIG_CTRL) | (7 << SPIFI_CONFIG_CTRL_SCK_DIV_S))
self.openocd.write_word(mem_map.SPIFI_CONFIG_ADDR, 0x00)
self.openocd.write_word(mem_map.SPIFI_CONFIG_IDATA, 0x00)
self.openocd.write_word(mem_map.SPIFI_CONFIG_CLIMIT, 0x00)
self.openocd.write_word(mem_map.SPIFI_CONFIG_MCMD, (0 << spifi_fields.SPIFI_CONFIG_MCMD_INTLEN_S) |
(spifi_fields.SPIFI_CONFIG_CMD_FIELDFORM_ALL_SERIAL << spifi_fields.SPIFI_CONFIG_MCMD_FIELDFORM_S) |
(spifi_fields.SPIFI_CONFIG_CMD_FRAMEFORM_OPCODE_3ADDR << spifi_fields.SPIFI_CONFIG_MCMD_FRAMEFORM_S) |
(self.DEFAULT_READ_DATA_COMMAND << spifi_fields.SPIFI_CONFIG_MCMD_OPCODE_S))
time.sleep(self.INIT_DELAY)
class Frameform(Enum):
RESERVED = 0
OPCODE_NOADDR = 1
OPCODE_1ADDR = 2
OPCODE_2ADDR = 3
OPCODE_3ADDR = 4
OPCODE_4ADDR = 5
NOOPCODE_3ADDR = 6
NOOPCODE_4ADDR = 7
def spifi_wait_intrq_timeout(self, error_message: str):
time_end = time.perf_counter() + self.TIMEOUT
while time.perf_counter() < time_end:
if (self.openocd.read_word(mem_map.SPIFI_CONFIG_STAT) & spifi_fields.SPIFI_CONFIG_STAT_INTRQ_M) != 0:
return
raise self.SpifiError(error_message)
def send_command(
self,
cmd: int,
frameform: Frameform,
fieldform: Fieldform,
byte_count=0,
address=0,
idata=0,
cache_limit=0,
idata_length=0,
direction=Direction.READ,
data: List[int] = [],
dma: Union[dma.DMA, None] = None
) -> List[int]:
if (dma is not None) and (direction == self.Direction.WRITE):
self.openocd.write_memory(0x02003F00, 8, data)
class Fieldform(Enum):
ALL_SERIAL = 0
DATA_PARALLEL = 1
OPCODE_SERIAL = 2
ALL_PARALLEL = 3
dma.channels[0].start(
0x02003F00,
mem_map.SPIFI_CONFIG_DATA32,
255
)
elif (dma is not None) and (direction == self.Direction.READ):
dma.channels[1].start(
mem_map.SPIFI_CONFIG_DATA32,
0x02003F00,
255
)
self.openocd.write_memory(
mem_map.SPIFI_CONFIG_ADDR, 32, [address, idata])
class Direction(Enum):
READ = 0
WRITE = 1
cmd_write_value = ((cmd << spifi_fields.SPIFI_CONFIG_CMD_OPCODE_S) |
(frameform.value << spifi_fields.SPIFI_CONFIG_CMD_FRAMEFORM_S) |
(fieldform.value << spifi_fields.SPIFI_CONFIG_CMD_FIELDFORM_S) |
(byte_count << spifi_fields.SPIFI_CONFIG_CMD_DATALEN_S) |
(idata_length << spifi_fields.SPIFI_CONFIG_CMD_INTLEN_S) |
(direction.value << spifi_fields.SPIFI_CONFIG_CMD_DOUT_S))
self.openocd.write_memory(
mem_map.SPIFI_CONFIG_CMD, 32, [cmd_write_value])
def send_command(
openocd: OpenOcdTclRpc,
cmd: int,
frameform: Frameform,
fieldform: Fieldform,
byte_count=0,
address=0,
idata=0,
cache_limit=0,
idata_length=0,
direction=Direction.READ,
data: List[int] = [],
dma: Union[dma.DMA, None] = None
) -> List[int]:
if (dma is not None) and (direction == Direction.WRITE):
openocd.write_memory(0x02003F00, 8, data)
if direction == self.Direction.READ:
out_list = []
if dma is not None:
dma.dma_wait(dma.channels[1], 0.1)
out_list.extend(self.openocd.read_memory(
0x02003F00, 8, byte_count))
dma.channels[0].start(
0x02003F00,
mem_map.SPIFI_CONFIG_DATA32,
255
)
elif (dma is not None) and (direction == Direction.READ):
dma.channels[1].start(
mem_map.SPIFI_CONFIG_DATA32,
0x02003F00,
255
)
openocd.write_memory(mem_map.SPIFI_CONFIG_ADDR, 32, [address, idata])
cmd_write_value = ((cmd << spifi_fields.SPIFI_CONFIG_CMD_OPCODE_S) |
(frameform.value << spifi_fields.SPIFI_CONFIG_CMD_FRAMEFORM_S) |
(fieldform.value << spifi_fields.SPIFI_CONFIG_CMD_FIELDFORM_S) |
(byte_count << spifi_fields.SPIFI_CONFIG_CMD_DATALEN_S) |
(idata_length << spifi_fields.SPIFI_CONFIG_CMD_INTLEN_S) |
(direction.value << spifi_fields.SPIFI_CONFIG_CMD_DOUT_S))
openocd.write_memory(mem_map.SPIFI_CONFIG_CMD, 32, [cmd_write_value])
if direction == Direction.READ:
out_list = []
if dma is not None:
dma.dma_wait(dma.channels[1], 0.1)
out_list.extend(openocd.read_memory(0x02003F00, 8, byte_count))
return out_list
else:
for i in range(byte_count):
out_list.append(openocd.read_memory(
mem_map.SPIFI_CONFIG_DATA32, 8, 1)[0])
return out_list
if direction == Direction.WRITE:
if dma is not None:
dma.dma_wait(dma.channels[0], 0.1)
else:
if (byte_count % 4) == 0:
for i in range(0, byte_count, 4):
openocd.write_memory(mem_map.SPIFI_CONFIG_DATA32, 32, [
data[i] + data[i+1] * 256 + data[i+2] * 256 * 256 + data[i+3] * 256 * 256 * 256])
return out_list
else:
for i in range(byte_count):
openocd.write_memory(
mem_map.SPIFI_CONFIG_DATA32, 8, [data[i]])
out_list.append(self.openocd.read_memory(
mem_map.SPIFI_CONFIG_DATA32, 8, 1)[0])
return out_list
return []
def write(openocd: OpenOcdTclRpc, address: int, data: List[int], data_len: int):
if data_len > 256:
raise SpifiError("Byte count more than 256")
generic_flash.page_program(openocd, address, data, data_len)
print("written")
def write_file(bytes: List[int], openocd: OpenOcdTclRpc):
# print(bytes)
print(f"Write {len(bytes)} bytes")
openocd.halt()
init(openocd)
generic_flash.erase(openocd)
print("bin_data_len = ", len(bytes))
address = 0
for address in range(0, len(bytes), 256):
if ((address + 256) > len(bytes)):
break
print("address = ", address)
write(openocd, address, bytes, 256)
if generic_flash.read_data(openocd, address, 256, bytes) == 1:
return 1
if (len(bytes) % 256) != 0:
print(
f"address = {address}, +{len(bytes) - address-1}[{address + len(bytes) - address-1}]")
write(openocd, address, bytes, len(bytes) - address)
if generic_flash.read_data(openocd, address, len(bytes) - address, bytes) == 1:
return 1
print("end")
return 0
def get_segments_list(pages_offsets: List[int], segment_size: int) -> List[int]:
segments = set()
for offset in pages_offsets:
segments.add(offset & ~(segment_size - 1))
return sorted(list(segments))
def dma_config(openocd: OpenOcdTclRpc) -> dma.DMA:
dma_instance = dma.DMA(openocd)
dma_instance.init()
dma_instance.channels[0].write_buffer = 0
dma_instance.channels[0].channel = dma.ChannelIndex.CHANNEL_0
dma_instance.channels[0].priority = dma.ChannelPriority.VERY_HIGH
dma_instance.channels[0].read_mode = dma.ChannelMode.MEMORY
dma_instance.channels[0].read_increment = dma.ChannelIncrement.ENABLE
dma_instance.channels[0].read_size = dma.ChannelSize.WORD
dma_instance.channels[0].read_burst_size = 2
dma_instance.channels[0].read_request = dma.ChannelRequest.SPIFI_REQUEST
dma_instance.channels[0].read_ack = dma.ChannelAck.DISABLE
dma_instance.channels[0].write_mode = dma.ChannelMode.PERIPHERY
dma_instance.channels[0].write_increment = dma.ChannelIncrement.DISABLE
dma_instance.channels[0].write_size = dma.ChannelSize.WORD
dma_instance.channels[0].write_burst_size = 2
dma_instance.channels[0].write_request = dma.ChannelRequest.SPIFI_REQUEST
dma_instance.channels[0].write_ack = dma.ChannelAck.DISABLE
dma_instance.channels[1].write_buffer = 0
dma_instance.channels[1].channel = dma.ChannelIndex.CHANNEL_1
dma_instance.channels[1].priority = dma.ChannelPriority.VERY_HIGH
dma_instance.channels[1].write_mode = dma.ChannelMode.MEMORY
dma_instance.channels[1].write_increment = dma.ChannelIncrement.ENABLE
dma_instance.channels[1].write_size = dma.ChannelSize.WORD
dma_instance.channels[1].write_burst_size = 2
dma_instance.channels[1].write_request = dma.ChannelRequest.SPIFI_REQUEST
dma_instance.channels[1].write_ack = dma.ChannelAck.DISABLE
dma_instance.channels[1].read_mode = dma.ChannelMode.PERIPHERY
dma_instance.channels[1].read_increment = dma.ChannelIncrement.DISABLE
dma_instance.channels[1].read_size = dma.ChannelSize.WORD
dma_instance.channels[1].read_burst_size = 2
dma_instance.channels[1].read_request = dma.ChannelRequest.SPIFI_REQUEST
dma_instance.channels[1].read_ack = dma.ChannelAck.DISABLE
return dma_instance
def check_pages(pages: Dict[int, List[int]], openocd: OpenOcdTclRpc, use_quad_spi=False, use_chip_erase=False):
result = 0
openocd.halt()
init(openocd)
# Сбрасываем микросхему в режиме QPI из всех состояний в нормальный SPI режим.
generic_flash.chip_reset_qpi(openocd)
# Сбрасываем микросхему в режиме SPI из всех состояний в нормальный SPI режим.
generic_flash.chip_reset(openocd)
JEDEC_ID = send_command(openocd, generic_flash.JEDEC_ID_COMMAND,
Frameform.OPCODE_NOADDR, Fieldform.ALL_SERIAL, 3)
print(f"JEDEC ID = {JEDEC_ID[0]:02x} {JEDEC_ID[1]:02x} {JEDEC_ID[2]:02x}")
dma_instance = dma_config(openocd)
if (use_quad_spi):
print("Using Quad SPI")
generic_flash.quad_enable(openocd)
else:
print("Using Single SPI")
# 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 = generic_flash.read_data(
openocd, page_offset, 256, page_bytes, dma=dma_instance, use_quad_spi=use_quad_spi)
if result == 1:
print("Data error")
# if (use_quad_spi):
# spifi_quad_disable(openocd)
return result
if result == 0:
print("SPIFI pages 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
openocd.halt()
init(openocd)
# Сбрасываем микросхему в режиме QPI из всех состояний в нормальный SPI режим.
generic_flash.chip_reset_qpi(openocd)
# Сбрасываем микросхему в режиме SPI из всех состояний в нормальный SPI режим.
generic_flash.chip_reset(openocd)
JEDEC_ID = send_command(openocd, generic_flash.JEDEC_ID_COMMAND,
Frameform.OPCODE_NOADDR, Fieldform.ALL_SERIAL, 3)
print(f"JEDEC ID = {JEDEC_ID[0]:02x} {JEDEC_ID[1]:02x} {JEDEC_ID[2]:02x}")
dma_instance = dma_config(openocd)
if use_chip_erase:
generic_flash.erase(openocd, generic_flash.EraseType.CHIP_ERASE)
else:
generic_flash.erase(openocd, generic_flash.EraseType.SECTOR_ERASE,
get_segments_list(list(pages), 4*1024))
print("Quad Enable", generic_flash.check_quad_enable(openocd))
if (use_quad_spi):
print("Using Quad SPI")
generic_flash.quad_enable(openocd)
else:
print("Using Single SPI")
# spifi_quad_disable(openocd)
# print("SREG1", spifi_read_sreg(openocd, SREG_Num.SREG1))
# print("SREG2", spifi_read_sreg(openocd, SREG_Num.SREG2))
pages_offsets = list(pages)
for index, page_offset in enumerate(pages_offsets):
page_bytes = pages[page_offset]
if (use_quad_spi):
generic_flash.quad_page_program(
openocd, page_offset, page_bytes, 256, f"{(index*100)//pages_offsets.__len__()}%", dma=dma_instance)
else:
generic_flash.page_program(openocd, page_offset, page_bytes,
256, f"{(index*100)//pages_offsets.__len__()}%", dma=dma_instance)
result = generic_flash.read_data(
openocd, page_offset, 256, page_bytes, dma=dma_instance, use_quad_spi=use_quad_spi)
if result == 1:
print("Data error")
return result
if result == 0:
# Прошивка страниц флеш памяти по SPIFI была завершена
print("Flashing of flash memory pages via SPIFI has been completed", flush=True)
return 0
def wait_halted(openocd: OpenOcdTclRpc, timeout_seconds: float = 2):
openocd.run(f'wait_halt {int(timeout_seconds * 1000)}')
def write_pages_by_sectors(pages: Dict[int, List[int]],
openocd: OpenOcdTclRpc,
driver_path: str,
use_quad_spi=False,
use_chip_erase=False,
):
result = 0
openocd.halt()
openocd.run("riscv.cpu set_reg {mstatus 0 mie 0}") # Отключение прерываний
init(openocd)
# openocd.run("rwp")
# Сбрасываем микросхему в режиме QPI из всех состояний в нормальный SPI режим.
generic_flash.chip_reset_qpi(openocd)
# Сбрасываем микросхему в режиме SPI из всех состояний в нормальный SPI режим.
generic_flash.chip_reset(openocd)
JEDEC_ID = send_command(
openocd, 0x9F, Frameform.OPCODE_NOADDR, Fieldform.ALL_SERIAL, 3)
print(f"JEDEC_ID {JEDEC_ID[0]:02x} {JEDEC_ID[1]:02x} {JEDEC_ID[2]:02x}")
dma_instance = dma_config(openocd)
sectors_list = get_segments_list(list(pages), 4*1024)
openocd.halt()
pathname = os.path.dirname(sys.argv[0])
openocd.run("wp 0x2003000 4 w")
print("Uploading driver... ", end="", flush=True)
openocd.run(f"load_image {{{pathlib.Path(driver_path)}}}")
print("OK!", flush=True)
openocd.resume(0x2000000)
wait_halted(openocd)
print("Writing Flash by sectors...", flush=True)
for i, sector in enumerate(sectors_list):
ByteAddress = sector
progress = f"{(i*100)//len(sectors_list)}%"
print(f" {ByteAddress:#010x} {progress:>4}", end="", flush=True)
bytes_list: List[int] = []
for page in range(16):
page = pages.get(page * 256 + sector)
if page is not None:
bytes_list.extend(page)
if direction == self.Direction.WRITE:
if dma is not None:
dma.dma_wait(dma.channels[0], 0.1)
else:
bytes_list.extend([0]*256)
if (byte_count % 4) == 0:
for i in range(0, byte_count, 4):
self.openocd.write_memory(mem_map.SPIFI_CONFIG_DATA32, 32, [
data[i] + data[i+1] * 256 + data[i+2] * 256 * 256 + data[i+3] * 256 * 256 * 256])
else:
for i in range(byte_count):
self.openocd.write_memory(
mem_map.SPIFI_CONFIG_DATA32, 8, [data[i]])
result = openocd.write_memory(0x02002000, 8, bytes_list)
if result:
print("ERROR!", flush=True)
print("An error occurred while writing data to the buffer area!")
print("Aborting...", flush=True)
return 1
return []
openocd.run(f"set_reg {{t6 {sector}}}")
openocd.resume()
wait_halted(openocd, 10) # ждем, когда watchpoint сработает
# watchpoint ловит до изменения слова
openocd.run("step") # делаем шаг, чтобы прочитать новое слово
def dma_config(self) -> dma.DMA:
dma_instance = dma.DMA(self.openocd)
dma_instance.init()
result = openocd.read_memory(0x2003000, 32, 1)[0]
dma_instance.channels[0].write_buffer = 0
if result == 0:
print(" OK!", flush=True)
else:
print(" FAIL!", flush=True)
print("result =", result)
break
if result == 0:
print(f" {sectors_list[-1]:#010x} 100% OK!", flush=True)
dma_instance.channels[0].channel = dma.ChannelIndex.CHANNEL_0
dma_instance.channels[0].priority = dma.ChannelPriority.VERY_HIGH
openocd.run("rwp 0x02003000")
init_memory(openocd)
dma_instance.channels[0].read_mode = dma.ChannelMode.MEMORY
dma_instance.channels[0].read_increment = dma.ChannelIncrement.ENABLE
dma_instance.channels[0].read_size = dma.ChannelSize.WORD
dma_instance.channels[0].read_burst_size = 2
dma_instance.channels[0].read_request = dma.ChannelRequest.SPIFI_REQUEST
dma_instance.channels[0].read_ack = dma.ChannelAck.DISABLE
if result == 0:
# Прошивка страниц флеш памяти по SPIFI была завершена
print("SPIFI writing successfully completed!", flush=True)
else:
print(f"SPIFI writing failed!", flush=True)
return 1
dma_instance.channels[0].write_mode = dma.ChannelMode.PERIPHERY
dma_instance.channels[0].write_increment = dma.ChannelIncrement.DISABLE
dma_instance.channels[0].write_size = dma.ChannelSize.WORD
dma_instance.channels[0].write_burst_size = 2
dma_instance.channels[0].write_request = dma.ChannelRequest.SPIFI_REQUEST
dma_instance.channels[0].write_ack = dma.ChannelAck.DISABLE
return result
dma_instance.channels[1].write_buffer = 0
dma_instance.channels[1].channel = dma.ChannelIndex.CHANNEL_1
dma_instance.channels[1].priority = dma.ChannelPriority.VERY_HIGH
dma_instance.channels[1].write_mode = dma.ChannelMode.MEMORY
dma_instance.channels[1].write_increment = dma.ChannelIncrement.ENABLE
dma_instance.channels[1].write_size = dma.ChannelSize.WORD
dma_instance.channels[1].write_burst_size = 2
dma_instance.channels[1].write_request = dma.ChannelRequest.SPIFI_REQUEST
dma_instance.channels[1].write_ack = dma.ChannelAck.DISABLE
dma_instance.channels[1].read_mode = dma.ChannelMode.PERIPHERY
dma_instance.channels[1].read_increment = dma.ChannelIncrement.DISABLE
dma_instance.channels[1].read_size = dma.ChannelSize.WORD
dma_instance.channels[1].read_burst_size = 2
dma_instance.channels[1].read_request = dma.ChannelRequest.SPIFI_REQUEST
dma_instance.channels[1].read_ack = dma.ChannelAck.DISABLE
return dma_instance

View File

@ -9,8 +9,9 @@ from typing import List, Dict, NamedTuple, Union
from hex_parser import FirmwareFile, MemorySection, MemoryType, Segment
from tclrpc import OpenOcdTclRpc, TclException, TclPortError
from mik32_debug_hal.gpio import MIK32_Version, gpio_init, gpio_deinit
import mik32_debug_hal.eeprom as eeprom
import mik32_debug_hal.spifi as spifi
from mik32_debug_hal.eeprom import EEPROM
from mik32_debug_hal.spifi import SPIFI
from flash_drivers.generic_flash import GenericFlash
import mik32_debug_hal.ram as ram
import mik32_debug_hal.power_manager as power_manager
from _version import applicaton_version
@ -261,12 +262,13 @@ def upload_file(
logging.debug("PM configured!")
if (pages.pages_eeprom.__len__() > 0):
eeprom = EEPROM(openocd)
start_time = time.perf_counter()
if use_driver:
result |= eeprom.write_memory(
pages.pages_eeprom,
openocd,
os.path.join(
default_drivers_path,
'jtag-eeprom',
@ -290,12 +292,13 @@ def upload_file(
f"[{current_time}] 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)
spifi = SPIFI(openocd)
flash = GenericFlash(spifi)
start_time = time.perf_counter()
if use_driver:
result |= spifi.write_pages_by_sectors(
result |= flash.write_pages_by_sectors(
pages.pages_spifi,
openocd,
os.path.join(
default_drivers_path,
'jtag-spifi',
@ -304,7 +307,7 @@ def upload_file(
)
)
else:
result |= spifi.write_pages(
result |= flash.write_pages(
pages.pages_spifi,
openocd,
use_quad_spi=use_quad_spi