mirror of
https://github.com/MikronMIK32/mik32-uploader.git
synced 2026-01-01 13:37:03 +03:00
205 lines
6.1 KiB
Python
205 lines
6.1 KiB
Python
from enum import Enum
|
|
import time
|
|
from typing import List, Union
|
|
from tclrpc import OpenOcdTclRpc
|
|
import mik32_debug_hal.spifi as spifi
|
|
import mik32_debug_hal.dma as dma
|
|
|
|
|
|
# --------------------------
|
|
# Commands
|
|
# --------------------------
|
|
SREG1_BUSY = 1
|
|
|
|
READ_LEN = 256
|
|
|
|
ENABLE_RESET_COMMAND = 0x66
|
|
RESET_COMMAND = 0x99
|
|
|
|
CHIP_ERASE_COMMAND = 0xC7
|
|
SECTOR_ERASE_COMMAND = 0x20
|
|
|
|
WRITE_ENABLE_COMMAND = 0x06
|
|
WRITE_DISABLE_COMMAND = 0x04
|
|
|
|
MEM_CONFIG_COMMAND = 0x61
|
|
MEM_CONFIG_VALUE = 0x7F
|
|
|
|
READ_DATA_COMMAND = 0x03
|
|
|
|
FAST_READ_QUAD_OUTPUT_COMMAND = 0x6B
|
|
|
|
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
|
|
|
|
PAGE_PROGRAM_COMMAND = 0x02
|
|
|
|
QUAD_PAGE_PROGRAM_COMMAND = 0x32
|
|
|
|
JEDEC_ID_COMMAND = 0x9F
|
|
|
|
|
|
class SREG_Num(Enum):
|
|
SREG1 = 0x00
|
|
SREG2 = 0x30
|
|
|
|
|
|
def write_enable(openocd: OpenOcdTclRpc):
|
|
spifi.send_command(openocd, WRITE_ENABLE_COMMAND,
|
|
spifi.Frameform.OPCODE_NOADDR, spifi.Fieldform.ALL_SERIAL)
|
|
|
|
|
|
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(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)
|
|
|
|
|
|
def wait_busy(openocd: OpenOcdTclRpc):
|
|
while 1:
|
|
sreg1 = read_sreg(openocd, SREG_Num.SREG1)
|
|
if not (sreg1 & SREG1_BUSY):
|
|
break
|
|
|
|
|
|
RESET_DELAY = 0.001
|
|
|
|
|
|
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)
|
|
|
|
|
|
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)
|
|
|
|
|
|
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 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)
|
|
|
|
|
|
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,
|
|
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 Exception("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)
|
|
|
|
|
|
class EraseType(Enum):
|
|
CHIP_ERASE = CHIP_ERASE_COMMAND
|
|
SECTOR_ERASE = SECTOR_ERASE_COMMAND
|
|
|
|
|
|
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)
|
|
|
|
|
|
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 Exception("Byte count more than 256")
|
|
|
|
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)
|
|
|
|
|
|
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
|
|
)
|
|
|
|
|
|
def check_quad_enable(openocd):
|
|
return (read_sreg(openocd, SREG_Num.SREG2) & SREG2_QUAD_ENABLE_M) != 0
|