переработка 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 from enum import Enum
import os
import pathlib
import sys
import time import time
from typing import List, Union from typing import Dict, List, Union
from tclrpc import OpenOcdTclRpc 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 import mik32_debug_hal.dma as dma
# -------------------------- class GenericFlash():
# Commands # --------------------------
# -------------------------- # Commands
SREG1_BUSY = 1 # --------------------------
SREG1_BUSY = 1
READ_LEN = 256 READ_LEN = 256
ENABLE_RESET_COMMAND = 0x66 ENABLE_RESET_COMMAND = 0x66
RESET_COMMAND = 0x99 RESET_COMMAND = 0x99
CHIP_ERASE_COMMAND = 0xC7 CHIP_ERASE_COMMAND = 0xC7
SECTOR_ERASE_COMMAND = 0x20 SECTOR_ERASE_COMMAND = 0x20
WRITE_ENABLE_COMMAND = 0x06 WRITE_ENABLE_COMMAND = 0x06
WRITE_DISABLE_COMMAND = 0x04 WRITE_DISABLE_COMMAND = 0x04
MEM_CONFIG_COMMAND = 0x61 MEM_CONFIG_COMMAND = 0x61
MEM_CONFIG_VALUE = 0x7F 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_SREG1_COMMAND = 0x05
READ_SREG2_COMMAND = 0x35 READ_SREG2_COMMAND = 0x35
WRITE_SREG_COMMAND = 0x01 WRITE_SREG_COMMAND = 0x01
SREG2_QUAD_ENABLE = 9 SREG2_QUAD_ENABLE = 9
SREG2_QUAD_ENABLE_S = (SREG2_QUAD_ENABLE-8) SREG2_QUAD_ENABLE_S = (SREG2_QUAD_ENABLE-8)
SREG2_QUAD_ENABLE_M = 1 << SREG2_QUAD_ENABLE_S 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 __str__(self):
def __init__(self, value): return ("ERROR: " + repr(self.value))
self.value = value
def __str__(self): class SREG_Num(Enum):
return ("ERROR: " + repr(self.value)) SREG1 = 0x00
SREG2 = 0x30
openocd: OpenOcdTclRpc
spifi: SPIFI
class SREG_Num(Enum): def __init__(self, spifi: SPIFI):
SREG1 = 0x00 self.spifi = spifi
SREG2 = 0x30 self.openocd = self.spifi.openocd
# self.init()
def write_enable(openocd: OpenOcdTclRpc): def write_enable(self):
spifi.send_command(openocd, WRITE_ENABLE_COMMAND, self.spifi.send_command(self.WRITE_ENABLE_COMMAND,
spifi.Frameform.OPCODE_NOADDR, spifi.Fieldform.ALL_SERIAL) 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: def write_sreg(self, sreg1: int, sreg2: int):
return spifi.send_command( self.write_enable()
openocd, self.spifi.send_command(
READ_SREG1_COMMAND | sreg.value, self.WRITE_SREG_COMMAND,
spifi.Frameform.OPCODE_NOADDR, self.spifi.Frameform.OPCODE_NOADDR,
spifi.Fieldform.ALL_SERIAL, self.spifi.Fieldform.ALL_SERIAL,
byte_count=1 byte_count=2,
)[0] 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): RESET_DELAY = 0.001
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)
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): def chip_reset_qpi(self):
while 1: self.spifi.send_command(self.ENABLE_RESET_COMMAND,
sreg1 = read_sreg(openocd, SREG_Num.SREG1) self.spifi.Frameform.OPCODE_NOADDR, self.spifi.Fieldform.ALL_PARALLEL)
if not (sreg1 & SREG1_BUSY): self.spifi.send_command(self.RESET_COMMAND,
break 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): if (use_quad_spi):
spifi.send_command(openocd, ENABLE_RESET_COMMAND, read_data = self.spifi.send_command(self.FAST_READ_QUAD_OUTPUT_COMMAND, self.spifi.Frameform.OPCODE_3ADDR,
spifi.Frameform.OPCODE_NOADDR, spifi.Fieldform.ALL_SERIAL) self.spifi.Fieldform.DATA_PARALLEL, byte_count=byte_count, address=address, idata_length=1, dma=dma)
spifi.send_command(openocd, RESET_COMMAND, else:
spifi.Frameform.OPCODE_NOADDR, spifi.Fieldform.ALL_SERIAL) read_data = self.spifi.send_command(self.READ_DATA_COMMAND, self.spifi.Frameform.OPCODE_3ADDR,
time.sleep(RESET_DELAY) 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): return 1
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 0
def chip_erase(openocd: OpenOcdTclRpc): def page_program(
print("Chip erase...", flush=True) self,
spifi.send_command(openocd, CHIP_ERASE_COMMAND, ByteAddress: int,
spifi.Frameform.OPCODE_NOADDR, spifi.Fieldform.ALL_SERIAL) 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): class EraseType(Enum):
print(f"Erase sector {address:#010x}...", flush=True) CHIP_ERASE = 0
spifi.send_command(openocd, SECTOR_ERASE_COMMAND, SECTOR_ERASE = 1
spifi.Frameform.OPCODE_3ADDR, spifi.Fieldform.ALL_SERIAL, address=address)
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: def quad_page_program(
read_data: List[int] = [] self,
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,
ByteAddress: int, ByteAddress: int,
data: List[int], data: List[int],
byte_count: int, byte_count: int,
progress: str = "", progress: str = "",
dma: Union[dma.DMA, None] = None dma: Union[dma.DMA, None] = None
): ):
print(f"Writing Flash page {ByteAddress:#010x}... {progress}", flush=True) print(f"Writing page {ByteAddress:#010x}... {progress}", flush=True)
if byte_count > 256: if byte_count > 256:
raise FlashError("Byte count more than 256") raise self.FlashError("Byte count more than 256")
write_enable(openocd) self.write_enable()
spifi.send_command(openocd, PAGE_PROGRAM_COMMAND, spifi.Frameform.OPCODE_3ADDR, self.spifi.send_command(self.QUAD_PAGE_PROGRAM_COMMAND, self.spifi.Frameform.OPCODE_3ADDR,
spifi.Fieldform.ALL_SERIAL, byte_count=byte_count, address=ByteAddress, self.spifi.Fieldform.DATA_PARALLEL, byte_count=byte_count, address=ByteAddress,
idata=0, cache_limit=0, direction=spifi.Direction.WRITE, data=data, dma=dma) idata=0, cache_limit=0, direction=self.spifi.Direction.WRITE, data=data, dma=dma)
wait_busy(openocd) 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): def check_quad_enable(self):
CHIP_ERASE = CHIP_ERASE_COMMAND return (self.read_sreg(self.SREG_Num.SREG2) & self.SREG2_QUAD_ENABLE_M) != 0
SECTOR_ERASE = SECTOR_ERASE_COMMAND
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] = []): self.openocd.halt()
if erase_type == EraseType.CHIP_ERASE: # self.init()
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)
# Сбрасываем микросхему в режиме QPI из всех состояний в нормальный SPI режим.
self.chip_reset_qpi()
def quad_page_program( # Сбрасываем микросхему в режиме SPI из всех состояний в нормальный SPI режим.
openocd: OpenOcdTclRpc, self.chip_reset()
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")
write_enable(openocd) JEDEC_ID = self.spifi.send_command(self.JEDEC_ID_COMMAND,
spifi.send_command(openocd, QUAD_PAGE_PROGRAM_COMMAND, spifi.Frameform.OPCODE_3ADDR, self.spifi.Frameform.OPCODE_NOADDR, self.spifi.Fieldform.ALL_SERIAL, 3)
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)
print(
f"JEDEC ID = {JEDEC_ID[0]:02x} {JEDEC_ID[1]:02x} {JEDEC_ID[2]:02x}")
def quad_enable(openocd): dma_instance = self.spifi.dma_config()
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
)
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): pages_offsets = list(pages)
return (read_sreg(openocd, SREG_Num.SREG2) & SREG2_QUAD_ENABLE_M) != 0
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_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_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 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 import mik32_debug_hal.ram as ram
from hex_parser import FirmwareFile, MemoryType, Segment from hex_parser import FirmwareFile, MemoryType, Segment
from tclrpc import OpenOcdTclRpc, TclException 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( def upload_file(
@ -78,6 +79,8 @@ def upload_file(
logging.debug("PM configured!") logging.debug("PM configured!")
if (pages.pages_eeprom.__len__() > 0): if (pages.pages_eeprom.__len__() > 0):
eeprom = EEPROM(openocd)
start_time = time.perf_counter() start_time = time.perf_counter()
result |= eeprom.check_pages( 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)") 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): if (pages.pages_spifi.__len__() > 0):
gpio_init(openocd, mik_version) gpio_init(openocd, mik_version)
spifi = SPIFI(openocd)
flash = GenericFlash(spifi)
start_time = time.perf_counter() start_time = time.perf_counter()
result |= spifi.check_pages( result |= flash.check_pages(
pages.pages_spifi, openocd, use_quad_spi=use_quad_spi) pages.pages_spifi, use_quad_spi=use_quad_spi)
write_time = time.perf_counter() - start_time write_time = time.perf_counter() - start_time
write_size = pages.pages_spifi.__len__( write_size = pages.pages_spifi.__len__(

View File

@ -1,9 +1,8 @@
import datetime
from enum import Enum from enum import Enum
import os import os
import pathlib import pathlib
import sys import sys
from typing import Dict, List, Tuple from typing import Dict, List
import time import time
from tclrpc import OpenOcdTclRpc, TclException from tclrpc import OpenOcdTclRpc, TclException
from utils import bytes2words 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 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]: 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 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 - текущий драйвер поддерживает self.eeprom_sysinit()
# только версию mik32v2
RAM_OFFSET = 0x02000000 def eeprom_sysinit(self):
RAM_BUFFER_OFFSET = 0x02001800 print("MCU clock init...", flush=True)
RAM_DRIVER_STATUS = 0x02003800
bytes_list = combine_pages(pages) class EEPROM_Operation(Enum):
openocd.halt() READ = eeprom_fields.OP_RD
openocd.run("riscv.cpu set_reg {mstatus 0 mie 0}") # Отключение прерываний 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 def eeprom_execute_operation(self, op: EEPROM_Operation, affected_pages: EEPROM_AffectedPages, offset: int, buffer: List[int]):
openocd.write_memory(RAM_DRIVER_STATUS, 32, [1 | (max_address << 8)]) # 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) def eeprom_configure_cycles(self, LD=1, R_1=2, R_2=1, CYCEP1=66667, CYCEP2=500):
openocd.run(f"load_image {{{pathlib.Path(driver_path)}}}") self.openocd.write_word(mem_map.EEPROM_REGS_NCYCRL, LD << eeprom_fields.NCYCRL_N_LD_S |
print("OK!", flush=True) 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) def eeprom_global_erase(self):
result = openocd.write_memory(RAM_BUFFER_OFFSET, 8, bytes_list) print("EEPROM global erase...", flush=True)
if result: # configure cycles duration
print("ERROR!", flush=True) self.eeprom_execute_operation(
print("An error occurred while writing data to the buffer area!") self.EEPROM_Operation.ERASE, self.EEPROM_AffectedPages.GLOBAL, 0x0, [0] * 32)
print("Aborting...", flush=True)
return 1 def eeprom_global_erase_check(self):
else: 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) print("OK!", flush=True)
# mem = openocd.read_memory(0x01000000, 8, len(bytes_list)) print("Uploading data... ", end="", flush=True)
# print(f"total bytes read {len(bytes_list)}") 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]: self.openocd.run(f"wp 0x{RAM_DRIVER_STATUS:08x} 4 w")
# 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
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) try:
openocd.resume(RAM_OFFSET) # ждем, когда watchpoint сработает
self.wait_halted(10)
except TclException:
print("Timeout!", flush=True)
# return 1
try: # watchpoint ловит до изменения слова
# ждем, когда watchpoint сработает self.openocd.run(f"rwp 0x{RAM_DRIVER_STATUS:08x}")
wait_halted(openocd, 10) # делаем шаг, чтобы прочитать новое слово
except TclException: self.openocd.run("step")
print("Timeout!", flush=True)
# return 1
openocd.run(f"rwp 0x{RAM_DRIVER_STATUS:08x}") # watchpoint ловит до изменения слова result = self.openocd.read_memory(RAM_DRIVER_STATUS, 32, 1)[0]
openocd.run("step") # делаем шаг, чтобы прочитать новое слово
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 failed!", flush=True)
print(f"EEPROM writing successfully completed!", flush=True) print(f"First mismatched byte in page {miss_page},")
else: print(
miss_page = (result >> 8) & (64 - 1) f"byte {miss_byte}, expected {expected_byte}, read {miss_byte}")
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) return 1
print(f"First mismatched byte in page {miss_page},")
print(f"byte {miss_byte}, expected {expected_byte}, read {miss_byte}")
return 1 return 0
return 0

View File

@ -1,466 +1,214 @@
import datetime
from enum import Enum from enum import Enum
import os from typing import List, Union
import pathlib
import sys
from typing import Dict, List, Union
import time import time
from tclrpc import TclException
from tclrpc import OpenOcdTclRpc from tclrpc import OpenOcdTclRpc
import mik32_debug_hal.registers.memory_map as mem_map import mik32_debug_hal.registers.memory_map as mem_map
import mik32_debug_hal.registers.bitfields.spifi as spifi_fields import mik32_debug_hal.registers.bitfields.spifi as spifi_fields
import mik32_debug_hal.dma as dma import mik32_debug_hal.dma as dma
import flash_drivers.generic_flash as generic_flash
class SpifiError(Exception): class SPIFI():
def __init__(self, value):
self.value = value
def __str__(self): DEFAULT_READ_DATA_COMMAND = 0x03
return ("ERROR: " + repr(self.value))
class SpifiError(Exception):
def __init__(self, value):
self.value = value
def spifi_intrq_clear(openocd: OpenOcdTclRpc): def __str__(self):
openocd.write_word(mem_map.SPIFI_CONFIG_STAT, openocd.read_word(mem_map.SPIFI_CONFIG_STAT) | return ("ERROR: " + repr(self.value))
spifi_fields.SPIFI_CONFIG_STAT_INTRQ_M)
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): TIMEOUT = 1.0
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)
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) def init_periphery(self):
control |= spifi_fields.SPIFI_CONFIG_CTRL_DMAEN_M self.openocd.write_word(mem_map.SPIFI_CONFIG_STAT, self.openocd.read_word(mem_map.SPIFI_CONFIG_STAT) |
openocd.write_word(mem_map.SPIFI_CONFIG_CTRL, control) # 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): self.init_periphery()
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))
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): def init_memory(self):
time_end = time.perf_counter() + TIMEOUT self.openocd.write_word(mem_map.SPIFI_CONFIG_STAT, self.openocd.read_word(mem_map.SPIFI_CONFIG_STAT) |
while time.perf_counter() < time_end: spifi_fields.SPIFI_CONFIG_STAT_INTRQ_M |
if (openocd.read_word(mem_map.SPIFI_CONFIG_STAT) & spifi_fields.SPIFI_CONFIG_STAT_INTRQ_M) != 0: spifi_fields.SPIFI_CONFIG_STAT_RESET_M)
return # openocd.write_word(SPIFI_CONFIG_CTRL, openocd.read_word(
raise SpifiError(error_message) # 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): def spifi_wait_intrq_timeout(self, error_message: str):
RESERVED = 0 time_end = time.perf_counter() + self.TIMEOUT
OPCODE_NOADDR = 1 while time.perf_counter() < time_end:
OPCODE_1ADDR = 2 if (self.openocd.read_word(mem_map.SPIFI_CONFIG_STAT) & spifi_fields.SPIFI_CONFIG_STAT_INTRQ_M) != 0:
OPCODE_2ADDR = 3 return
OPCODE_3ADDR = 4 raise self.SpifiError(error_message)
OPCODE_4ADDR = 5
NOOPCODE_3ADDR = 6
NOOPCODE_4ADDR = 7
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): dma.channels[0].start(
ALL_SERIAL = 0 0x02003F00,
DATA_PARALLEL = 1 mem_map.SPIFI_CONFIG_DATA32,
OPCODE_SERIAL = 2 255
ALL_PARALLEL = 3 )
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): cmd_write_value = ((cmd << spifi_fields.SPIFI_CONFIG_CMD_OPCODE_S) |
READ = 0 (frameform.value << spifi_fields.SPIFI_CONFIG_CMD_FRAMEFORM_S) |
WRITE = 1 (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( if direction == self.Direction.READ:
openocd: OpenOcdTclRpc, out_list = []
cmd: int, if dma is not None:
frameform: Frameform, dma.dma_wait(dma.channels[1], 0.1)
fieldform: Fieldform, out_list.extend(self.openocd.read_memory(
byte_count=0, 0x02003F00, 8, byte_count))
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)
dma.channels[0].start( return out_list
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])
else: else:
for i in range(byte_count): for i in range(byte_count):
openocd.write_memory( out_list.append(self.openocd.read_memory(
mem_map.SPIFI_CONFIG_DATA32, 8, [data[i]]) mem_map.SPIFI_CONFIG_DATA32, 8, 1)[0])
return out_list
return [] if direction == self.Direction.WRITE:
if dma is not None:
dma.dma_wait(dma.channels[0], 0.1)
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)
else: 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) return []
if result:
print("ERROR!", flush=True)
print("An error occurred while writing data to the buffer area!")
print("Aborting...", flush=True)
return 1
openocd.run(f"set_reg {{t6 {sector}}}") def dma_config(self) -> dma.DMA:
openocd.resume() dma_instance = dma.DMA(self.openocd)
wait_halted(openocd, 10) # ждем, когда watchpoint сработает dma_instance.init()
# watchpoint ловит до изменения слова
openocd.run("step") # делаем шаг, чтобы прочитать новое слово
result = openocd.read_memory(0x2003000, 32, 1)[0] dma_instance.channels[0].write_buffer = 0
if result == 0: dma_instance.channels[0].channel = dma.ChannelIndex.CHANNEL_0
print(" OK!", flush=True) dma_instance.channels[0].priority = dma.ChannelPriority.VERY_HIGH
else:
print(" FAIL!", flush=True)
print("result =", result)
break
if result == 0:
print(f" {sectors_list[-1]:#010x} 100% OK!", flush=True)
openocd.run("rwp 0x02003000") dma_instance.channels[0].read_mode = dma.ChannelMode.MEMORY
init_memory(openocd) 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: dma_instance.channels[0].write_mode = dma.ChannelMode.PERIPHERY
# Прошивка страниц флеш памяти по SPIFI была завершена dma_instance.channels[0].write_increment = dma.ChannelIncrement.DISABLE
print("SPIFI writing successfully completed!", flush=True) dma_instance.channels[0].write_size = dma.ChannelSize.WORD
else: dma_instance.channels[0].write_burst_size = 2
print(f"SPIFI writing failed!", flush=True) dma_instance.channels[0].write_request = dma.ChannelRequest.SPIFI_REQUEST
return 1 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 hex_parser import FirmwareFile, MemorySection, MemoryType, Segment
from tclrpc import OpenOcdTclRpc, TclException, TclPortError from tclrpc import OpenOcdTclRpc, TclException, TclPortError
from mik32_debug_hal.gpio import MIK32_Version, gpio_init, gpio_deinit from mik32_debug_hal.gpio import MIK32_Version, gpio_init, gpio_deinit
import mik32_debug_hal.eeprom as eeprom from mik32_debug_hal.eeprom import EEPROM
import mik32_debug_hal.spifi as spifi 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.ram as ram
import mik32_debug_hal.power_manager as power_manager import mik32_debug_hal.power_manager as power_manager
from _version import applicaton_version from _version import applicaton_version
@ -261,12 +262,13 @@ def upload_file(
logging.debug("PM configured!") logging.debug("PM configured!")
if (pages.pages_eeprom.__len__() > 0): if (pages.pages_eeprom.__len__() > 0):
eeprom = EEPROM(openocd)
start_time = time.perf_counter() start_time = time.perf_counter()
if use_driver: if use_driver:
result |= eeprom.write_memory( result |= eeprom.write_memory(
pages.pages_eeprom, pages.pages_eeprom,
openocd,
os.path.join( os.path.join(
default_drivers_path, default_drivers_path,
'jtag-eeprom', '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)") 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): if (pages.pages_spifi.__len__() > 0):
gpio_init(openocd, mik_version) gpio_init(openocd, mik_version)
spifi = SPIFI(openocd)
flash = GenericFlash(spifi)
start_time = time.perf_counter() start_time = time.perf_counter()
if use_driver: if use_driver:
result |= spifi.write_pages_by_sectors( result |= flash.write_pages_by_sectors(
pages.pages_spifi, pages.pages_spifi,
openocd,
os.path.join( os.path.join(
default_drivers_path, default_drivers_path,
'jtag-spifi', 'jtag-spifi',
@ -304,7 +307,7 @@ def upload_file(
) )
) )
else: else:
result |= spifi.write_pages( result |= flash.write_pages(
pages.pages_spifi, pages.pages_spifi,
openocd, openocd,
use_quad_spi=use_quad_spi use_quad_spi=use_quad_spi