Перенос драйверов и регистров в модуль

This commit is contained in:
Sergey Shchelkanov committed 2024-08-21 14:56:22 +03:00
1 parent 537deb8860
commit e0408a03aa
16 files changed
+686 -681

No files matched your search

+204
View File
@@ -0,0 +1,204 @@
from enum import Enum
from typing import Dict, List
import time
from tclrpc import TclException
from tclrpc import OpenOcdTclRpc
from dataclasses import dataclass
import mik32_debug_hal.registers.memory_map as mem_map
import mik32_debug_hal.registers.bitfields.dma as dma_fields
# ReadStatus. Разрешить читать текущий статус канала
class CurrentValue(Enum):
ENABLE = 0 # Текущие значения
DISABLE = 1 # Значения при настройке
class ChannelIndex(Enum):
CHANNEL_0 = 0
CHANNEL_1 = 1
CHANNEL_2 = 2
CHANNEL_3 = 3
class ChannelPriority(Enum):
LOW = 0
MEDIUM = 1
HIGH = 2
VERY_HIGH = 3
class ChannelMode(Enum):
PERIPHERY = 0
MEMORY = 1
class ChannelIncrement(Enum):
DISABLE = 0
ENABLE = 1
class ChannelSize(Enum):
BYTE = 0
HALFWORD = 1
WORD = 1
class ChannelAck(Enum):
DISABLE = 0
ENABLE = 1
class ChannelRequest(Enum):
USART_0_REQUEST = 0
USART_1_REQUEST = 1
CRYPTO_REQUEST = 2
SPI_0_REQUEST = 3
SPI_1_REQUEST = 4
I2C_0_REQUEST = 5
I2C_1_REQUEST = 6
SPIFI_REQUEST = 7
TIMER32_1_REQUEST = 8
TIMER32_2_REQUEST = 9
TIMER32_0_REQUEST = 10
class DMA_Channel:
openocd: OpenOcdTclRpc
write_buffer: int = 0
channel: ChannelIndex
priority: ChannelPriority
read_mode: ChannelMode
read_increment: ChannelIncrement
read_size: ChannelSize
read_ack: ChannelAck
read_burst_size: int
read_request: ChannelRequest
write_mode: ChannelMode
write_increment: ChannelIncrement
write_size: ChannelSize
write_ack: ChannelAck
write_burst_size: int
write_request: ChannelRequest
def __init__(self, openocd: OpenOcdTclRpc):
self.openocd = openocd
def set_source(self, source: int):
self.openocd.write_word(mem_map.DMA_CHANNEL_SOURCE(1), source)
def set_destination(self, source: int):
self.openocd.write_word(mem_map.DMA_CHANNEL_DESTINATION(1), source)
def set_length(self, source: int):
self.openocd.write_word(mem_map.DMA_CHANNEL_LEN(1), source)
def set_config(self, source: int):
self.openocd.write_word(mem_map.DMA_CHANNEL_CONFIG(1), source)
def start(
self,
source_address: int,
destination_address: int,
length: int,
):
self.write_buffer |= (dma_fields.CFG_CH_ENABLE_M
| (self.priority.value << dma_fields.CFG_CH_PRIOR_S)
| (self.read_mode.value << dma_fields.CFG_CH_READ_MODE_S)
| (self.read_increment.value << dma_fields.CFG_CH_READ_INCREMENT_S)
| (self.read_size.value << dma_fields.CFG_CH_READ_SIZE_S)
| (self.read_burst_size << dma_fields.CFG_CH_READ_BURST_SIZE_S)
| (self.read_request.value << dma_fields.CFG_CH_READ_REQ_S)
| (self.read_ack.value << dma_fields.CFG_CH_ACK_READ_S)
| (self.write_mode.value << dma_fields.CFG_CH_WRITE_MODE_S)
| (self.write_increment.value << dma_fields.CFG_CH_WRITE_INCREMENT_S)
| (self.write_size.value << dma_fields.CFG_CH_WRITE_SIZE_S)
| (self.write_burst_size << dma_fields.CFG_CH_WRITE_BURST_SIZE_S)
| (self.write_request.value << dma_fields.CFG_CH_WRITE_REQ_S)
| (self.write_ack.value << dma_fields.CFG_CH_ACK_WRITE_S))
self.openocd.write_memory(mem_map.DMA_CHANNEL_DESTINATION(
1), 32, [destination_address, source_address, length, self.write_buffer])
class DMA:
openocd: OpenOcdTclRpc
current_value: CurrentValue = CurrentValue.ENABLE
write_buffer: int = 0
channels: List[DMA_Channel] = []
def __init__(self, openocd: OpenOcdTclRpc):
self.openocd = openocd
self.channels.append(DMA_Channel(self.openocd))
self.channels.append(DMA_Channel(self.openocd))
self.channels.append(DMA_Channel(self.openocd))
self.channels.append(DMA_Channel(self.openocd))
def init(self):
self.current_value = CurrentValue.ENABLE
self.write_buffer = 0
self.openocd.write_memory(0x40000, 32, [0] * 16)
self.clear_irq()
self.set_current_value(self.current_value)
def set_control(self, control: int):
if (control > 2**32 or control < 0):
raise ValueError
self.openocd.write_word(mem_map.DMA_CONTROL, control)
def get_control(self) -> int:
return self.openocd.read_word(mem_map.DMA_CONTROL)
def clear_irq(self):
self.clear_local_irq()
self.clear_global_irq()
self.clear_error_irq()
def clear_local_irq(self):
self.write_buffer &= ~(dma_fields.CONTROL_CLEAR_LOCAL_IRQ_M |
dma_fields.CONTROL_CLEAR_GLOBAL_IRQ_M | dma_fields.CONTROL_CLEAR_ERROR_IRQ_M)
self.write_buffer |= dma_fields.CONTROL_CLEAR_LOCAL_IRQ_M
self.set_control(self.write_buffer)
self.write_buffer &= ~(dma_fields.CONTROL_CLEAR_LOCAL_IRQ_M |
dma_fields.CONTROL_CLEAR_GLOBAL_IRQ_M | dma_fields.CONTROL_CLEAR_ERROR_IRQ_M)
def clear_global_irq(self):
self.write_buffer &= ~(dma_fields.CONTROL_CLEAR_LOCAL_IRQ_M |
dma_fields.CONTROL_CLEAR_GLOBAL_IRQ_M | dma_fields.CONTROL_CLEAR_ERROR_IRQ_M)
self.write_buffer |= dma_fields.CONTROL_CLEAR_GLOBAL_IRQ_M
self.set_control(self.write_buffer)
self.write_buffer &= ~(dma_fields.CONTROL_CLEAR_LOCAL_IRQ_M |
dma_fields.CONTROL_CLEAR_GLOBAL_IRQ_M | dma_fields.CONTROL_CLEAR_ERROR_IRQ_M)
def clear_error_irq(self):
self.write_buffer &= ~(dma_fields.CONTROL_CLEAR_LOCAL_IRQ_M |
dma_fields.CONTROL_CLEAR_GLOBAL_IRQ_M | dma_fields.CONTROL_CLEAR_ERROR_IRQ_M)
self.write_buffer |= dma_fields.CONTROL_CLEAR_ERROR_IRQ_M
self.set_control(self.write_buffer)
self.write_buffer &= ~(dma_fields.CONTROL_CLEAR_LOCAL_IRQ_M |
dma_fields.CONTROL_CLEAR_GLOBAL_IRQ_M | dma_fields.CONTROL_CLEAR_ERROR_IRQ_M)
def set_current_value(self, current_value: CurrentValue):
self.current_value = current_value
self.write_buffer &= ~(dma_fields.CONTROL_CURRENT_VALUE_M)
self.write_buffer |= current_value.value << dma_fields.CONTROL_CURRENT_VALUE_S
self.set_control(self.write_buffer)
def dma_wait(self, channel: DMA_Channel, timeout: float):
channel_index = channel.channel.value
mask = (1 << channel_index) << dma_fields.STATUS_READY_S
begin = time.perf_counter()
while (begin - time.perf_counter()) < timeout:
if self.get_control() & mask != 0:
return
raise Exception
+302
View File
@@ -0,0 +1,302 @@
from enum import Enum
from typing import Dict, List
import time
from tclrpc import OpenOcdTclRpc
from utils import bytes2words
# --------------------------
# EEPROM register offset
# --------------------------
EEPROM_REGS_BASE_ADDRESS = 0x00070400
EEPROM_REGS_EEDAT = EEPROM_REGS_BASE_ADDRESS + 0x00
EEPROM_REGS_EEA = EEPROM_REGS_BASE_ADDRESS + 0x04
EEPROM_REGS_EECON = EEPROM_REGS_BASE_ADDRESS + 0x08
EEPROM_REGS_EESTA = EEPROM_REGS_BASE_ADDRESS + 0x0C
EEPROM_REGS_EERB = EEPROM_REGS_BASE_ADDRESS + 0x10
EEPROM_REGS_EEADJ = EEPROM_REGS_BASE_ADDRESS + 0x14
EEPROM_REGS_NCYCRL = EEPROM_REGS_BASE_ADDRESS + 0x18
EEPROM_REGS_NCYCEP1 = EEPROM_REGS_BASE_ADDRESS + 0x1C
EEPROM_REGS_NCYCEP2 = EEPROM_REGS_BASE_ADDRESS + 0x20
# --------------------------
# EEPROM register fields
# --------------------------
# EECON
EEPROM_EX_S = 0
EEPROM_OP_S = 1
EEPROM_WRBEH_S = 3
EEPROM_APBNWS_S = 5
EEPROM_DISECC_S = 6
EEPROM_BWE_S = 7
EEPROM_IESERR_S = 8
# EESTA
EEPROM_BSY_S = 0
EEPROM_SERR_S = 1
# NCYCRL
EEPROM_N_LD_S = 0
EEPROM_N_R_1_S = 8
EEPROM_N_R_2_S = 16
# --------------------------
# EEPROM codes
# --------------------------
EEPROM_OP_RD = 0
EEPROM_OP_ER = 1
EEPROM_OP_PR = 2
EEPROM_BEH_EVEN = 1
EEPROM_BEH_ODD = 2
EEPROM_BEH_GLOB = 3
EEPROM_PAGE_MASK = 0x1F80
def eeprom_sysinit(openocd: OpenOcdTclRpc):
print("MCU clock init...", flush=True)
class EEPROM_Operation(Enum):
READ = EEPROM_OP_RD
ERASE = EEPROM_OP_ER
PROGRAM = EEPROM_OP_PR
class EEPROM_AffectedPages(Enum):
SINGLE = 0
EVEN = EEPROM_BEH_EVEN
ODD = EEPROM_BEH_ODD
GLOBAL = EEPROM_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(EEPROM_REGS_EEA, 32, [offset, (1 << EEPROM_BWE_S)
| (affected_pages.value << EEPROM_WRBEH_S)])
if buffer.__len__() > 32:
return
for word in buffer:
openocd.write_word(EEPROM_REGS_EEDAT, word)
# start operation
openocd.write_word(EEPROM_REGS_EECON, (
(1 << EEPROM_EX_S) | (1 << EEPROM_BWE_S) |
(op.value << EEPROM_OP_S) | (affected_pages.value << EEPROM_WRBEH_S)
))
def eeprom_configure_cycles(openocd: OpenOcdTclRpc, LD=1, R_1=2, R_2=1, CYCEP1=66667, CYCEP2=500):
openocd.write_word(EEPROM_REGS_NCYCRL, LD << EEPROM_N_LD_S |
R_1 << EEPROM_N_R_1_S | R_2 << EEPROM_N_R_2_S)
openocd.write_word(EEPROM_REGS_NCYCEP1, CYCEP1)
openocd.write_word(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(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(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(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(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):
raise Exception(
"Wrong number of words in read_memory output!")
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
+56
View File
@@ -0,0 +1,56 @@
from enum import Enum
from tclrpc import OpenOcdTclRpc
import mik32_debug_hal.registers.memory_map as mem_map
class MIK32_Version(Enum):
MIK32V0 = "MIK32V0"
MIK32V2 = "MIK32V2"
def __str__(self):
return self.value
port2_value = 0
def gpio_init(openocd: OpenOcdTclRpc, version: MIK32_Version):
port2_addr = 0
if version == MIK32_Version.MIK32V0:
port2_addr = mem_map.PAD_CONFIG_REGS + mem_map.PAD_CONFIG_REGS_V0.PORT_2_CFG.value
elif version == MIK32_Version.MIK32V2:
port2_addr = mem_map.PAD_CONFIG_REGS + mem_map.PAD_CONFIG_REGS_V2.PORT_2_CFG.value
else:
return
openocd.halt()
port2_value = openocd.read_memory(port2_addr, 32, 1)[0]
port2_value_updated = port2_value
port2_value_updated &= 0xF000
if version == MIK32_Version.MIK32V0:
port2_value_updated |= 0x000
elif version == MIK32_Version.MIK32V2:
port2_value_updated |= 0x555
else:
return
openocd.write_word(port2_addr, port2_value_updated)
openocd.write_word(port2_addr + 8, 0x0500)
def gpio_deinit(openocd: OpenOcdTclRpc, version: MIK32_Version):
if version == MIK32_Version.MIK32V0:
port2_addr = mem_map.PAD_CONFIG_REGS + mem_map.PAD_CONFIG_REGS_V0.PORT_2_CFG.value
elif version == MIK32_Version.MIK32V2:
port2_addr = mem_map.PAD_CONFIG_REGS + mem_map.PAD_CONFIG_REGS_V2.PORT_2_CFG.value
else:
return
openocd.write_word(port2_addr, port2_value)
+33
View File
@@ -0,0 +1,33 @@
from tclrpc import OpenOcdTclRpc
import mik32_debug_hal.registers.memory_map as mem_map
import mik32_debug_hal.registers.bitfields.power_manager as pm_fields
import mik32_debug_hal.registers.bitfields.wakeup as wake_fields
def pm_init(openocd: OpenOcdTclRpc):
WU_CLOCKS_default = 128 << wake_fields.CLOCKS_BU_ADJ_RC32K_S
AHB_default = (
pm_fields.CLOCK_AHB_CPU_M |
pm_fields.CLOCK_AHB_EEPROM_M |
pm_fields.CLOCK_AHB_RAM_M |
pm_fields.CLOCK_AHB_SPIFI_M |
pm_fields.CLOCK_AHB_TCB_M |
pm_fields.CLOCK_AHB_DMA_M
)
# 0x1F
APB_M_default = (
pm_fields.CLOCK_APB_M_PM_M |
pm_fields.CLOCK_APB_M_PAD_CONFIG_M |
pm_fields.CLOCK_APB_M_WU_M
)
# 0x89
APB_P_default = pm_fields.CLOCK_APB_P_GPIO_2_M
# 0x00
openocd.halt()
openocd.write_word(mem_map.WU_CLOCKS_BU_OFFSET, WU_CLOCKS_default)
openocd.write_word(mem_map.PM_Clk_APB_P_Set_OFFSET, APB_P_default)
openocd.write_word(mem_map.PM_Clk_APB_M_Set_OFFSET, APB_M_default)
openocd.write_word(mem_map.PM_Clk_AHB_Set_OFFSET, AHB_default)
+40
View File
@@ -0,0 +1,40 @@
from typing import List
from mik32_upload import Segment
from tclrpc import TclException
from tclrpc import OpenOcdTclRpc
from pathlib import Path
import time
from utils import bytes2words
def write_file(filename):
with OpenOcdTclRpc() as openocd:
openocd.halt()
print(openocd.run("load_image {%s} 0x0" % Path(filename)))
print("RAM write file maybe done")
def write_segments(segments: List[Segment], openocd: OpenOcdTclRpc):
openocd.halt()
for segment in segments:
t = time.localtime()
current_time = time.strftime("%H:%M:%S", t)
print(f"[{current_time}] Writing segment %s with size %d..." % (hex(segment.offset), segment.data.__len__()))
segment_words = bytes2words(segment.data)
openocd.write_memory(segment.offset, 32, segment_words)
def check_segments(segments: List[Segment], openocd: OpenOcdTclRpc) -> int:
openocd.halt()
for segment in segments:
print("Checking segment %s with size %d..." % (hex(segment.offset), segment.data.__len__()))
segment_words = bytes2words(segment.data)
segment_memory_words = openocd.read_memory(segment.offset, 32, len(segment_words))
for i in range(len(segment_words)):
if segment_words[i] != segment_memory_words[i]:
print(f"Word [{i}] expect {segment_words[i]} != read {segment_memory_words[i]} in segment {segment.offset}")
return 1
return 0
@@ -0,0 +1,96 @@
# --------------------------
# DMA register fields
# --------------------------
CHANNEL_COUNT = 4
CHANNEL_M = ((1 << CHANNEL_COUNT) - 1)
# CONTROL
CONTROL_CLEAR_LOCAL_IRQ_S = 0
CONTROL_CLEAR_LOCAL_IRQ_M = (
CHANNEL_M << CONTROL_CLEAR_LOCAL_IRQ_S)
def CONTROL_CLEAR_LOCAL_IRQ(i):
return ((1 << (CONTROL_CLEAR_LOCAL_IRQ_S + (i))) & CONTROL_CLEAR_LOCAL_IRQ_M)
CONTROL_CLEAR_GLOBAL_IRQ_S = (CHANNEL_COUNT + 0)
CONTROL_CLEAR_GLOBAL_IRQ_M = (1 << CONTROL_CLEAR_GLOBAL_IRQ_S)
CONTROL_CLEAR_ERROR_IRQ_S = (CHANNEL_COUNT + 1)
CONTROL_CLEAR_ERROR_IRQ_M = (1 << CONTROL_CLEAR_ERROR_IRQ_S)
CONTROL_GLOBAL_IRQ_ENA_S = (CHANNEL_COUNT + 2)
CONTROL_GLOBAL_IRQ_ENA_M = (1 << CONTROL_GLOBAL_IRQ_ENA_S)
CONTROL_ERROR_IRQ_ENA_S = (CHANNEL_COUNT + 3)
CONTROL_ERROR_IRQ_ENA_M = (1 << CONTROL_ERROR_IRQ_ENA_S)
CONTROL_CURRENT_VALUE_S = (CHANNEL_COUNT + 4)
CONTROL_CURRENT_VALUE_M = (1 << CONTROL_CURRENT_VALUE_S)
CFG_CH_ENABLE_S = 0
CFG_CH_ENABLE_M = (1 << CFG_CH_ENABLE_S)
CFG_CH_DISABLE_M = (0 << CFG_CH_ENABLE_S)
CFG_CH_PRIOR_S = 1
CFG_CH_PRIOR_M = (0x3 << CFG_CH_PRIOR_S)
CFG_CH_READ_MODE_S = 3
CFG_CH_READ_MODE_memory_M = (1 << CFG_CH_READ_MODE_S)
CFG_CH_READ_MODE_periphery_M = (0 << CFG_CH_READ_MODE_S)
CFG_CH_WRITE_MODE_S = 4
CFG_CH_WRITE_MODE_memory_M = (1 << CFG_CH_WRITE_MODE_S)
CFG_CH_WRITE_MODE_periphery_M = (0 << CFG_CH_WRITE_MODE_S)
CFG_CH_READ_INCREMENT_S = 5
CFG_CH_READ_INCREMENT_M = (1 << CFG_CH_READ_INCREMENT_S)
CFG_CH_READ_no_INCREMENT_M = (0 << CFG_CH_READ_INCREMENT_S)
CFG_CH_READ_INCREMENT_S = 5
CFG_CH_READ_INCREMENT_M = (1 << CFG_CH_READ_INCREMENT_S)
CFG_CH_READ_no_INCREMENT_M = (0 << CFG_CH_READ_INCREMENT_S)
CFG_CH_WRITE_INCREMENT_S = 6
CFG_CH_WRITE_INCREMENT_M = (1 << CFG_CH_WRITE_INCREMENT_S)
CFG_CH_WRITE_no_INCREMENT_M = (0 << CFG_CH_WRITE_INCREMENT_S)
CFG_CH_READ_SIZE_S = 7
CFG_CH_READ_SIZE_byte_M = (0B00 << CFG_CH_READ_SIZE_S) # байт
CFG_CH_READ_SIZE_2byte_M = (0B01 << CFG_CH_READ_SIZE_S) # полуслово
CFG_CH_READ_SIZE_4byte_M = (0B10 << CFG_CH_READ_SIZE_S) # слово
CFG_CH_READ_SIZE_rez_M = (0B11 << CFG_CH_READ_SIZE_S) # резерв
CFG_CH_WRITE_SIZE_S = 9
CFG_CH_WRITE_SIZE_byte_M = (0B00 << CFG_CH_WRITE_SIZE_S) # байт
CFG_CH_WRITE_SIZE_2byte_M = (0B01 << CFG_CH_WRITE_SIZE_S) # полуслово
CFG_CH_WRITE_SIZE_4byte_M = (0B10 << CFG_CH_WRITE_SIZE_S) # слово
CFG_CH_WRITE_SIZE_rez_M = (0B11 << CFG_CH_WRITE_SIZE_S) # резерв
# Кол-во байт пакетной передачи: 2^Read_burst_size
CFG_CH_READ_BURST_SIZE_S = 11
# Кол-во байт пакетной передачи: 2^Write_burst_size
CFG_CH_WRITE_BURST_SIZE_S = 14
CFG_CH_READ_REQ_S = 17 # выбор канала чтения
CFG_CH_READ_REQ_M = (0xF << CFG_CH_READ_REQ_S)
def CFG_CH_READ_REQ(v):
return (((v) << CFG_CH_READ_REQ_S) & CFG_CH_READ_REQ_M)
CFG_CH_WRITE_REQ_S = 21 # выбор канала записи
CFG_CH_WRITE_REQ_M = (0xF << CFG_CH_WRITE_REQ_S)
def CFG_CH_WRITE_REQ(v):
return (((v) << CFG_CH_WRITE_REQ_S) & CFG_CH_WRITE_REQ_M)
CFG_CH_ACK_READ_S = 25
CFG_CH_ACK_READ_M = (1 << CFG_CH_ACK_READ_S)
CFG_CH_ACK_WRITE_S = 26
CFG_CH_ACK_WRITE_M = (1 << CFG_CH_ACK_WRITE_S)
STATUS_READY_S = 0
@@ -0,0 +1,77 @@
# --------------------------
# PM register fields
# --------------------------
# AHB BUS
CLOCK_AHB_CPU_S = 0
CLOCK_AHB_CPU_M = (1 << CLOCK_AHB_CPU_S)
CLOCK_AHB_EEPROM_S = 1
CLOCK_AHB_EEPROM_M = (1 << CLOCK_AHB_EEPROM_S)
CLOCK_AHB_RAM_S = 2
CLOCK_AHB_RAM_M = (1 << CLOCK_AHB_RAM_S)
CLOCK_AHB_SPIFI_S = 3
CLOCK_AHB_SPIFI_M = (1 << CLOCK_AHB_SPIFI_S)
CLOCK_AHB_TCB_S = 4
CLOCK_AHB_TCB_M = (1 << CLOCK_AHB_TCB_S)
CLOCK_AHB_DMA_S = 5
CLOCK_AHB_DMA_M = (1 << CLOCK_AHB_DMA_S)
CLOCK_AHB_CRYPTO_S = 6
CLOCK_AHB_CRYPTO_M = (1 << CLOCK_AHB_CRYPTO_S)
CLOCK_AHB_CRC32_S = 7
CLOCK_AHB_CRC32_M = (1 << CLOCK_AHB_CRC32_S)
# APB M
CLOCK_APB_M_PM_S = 0
CLOCK_APB_M_PM_M = (1 << CLOCK_APB_M_PM_S)
CLOCK_APB_M_EPIC_S = 1
CLOCK_APB_M_EPIC_M = (1 << CLOCK_APB_M_EPIC_S)
CLOCK_APB_M_TIMER32_0_S = 2
CLOCK_APB_M_TIMER32_0_M = (1 << CLOCK_APB_M_TIMER32_0_S)
CLOCK_APB_M_PAD_CONFIG_S = 3
CLOCK_APB_M_PAD_CONFIG_M = (1 << CLOCK_APB_M_PAD_CONFIG_S)
CLOCK_APB_M_WDT_BUS_S = 4
CLOCK_APB_M_WDT_BUS_M = (1 << CLOCK_APB_M_WDT_BUS_S)
CLOCK_APB_M_OTP_S = 5
CLOCK_APB_M_OTP_M = (1 << CLOCK_APB_M_OTP_S)
CLOCK_APB_M_PMON_S = 6
CLOCK_APB_M_PMON_M = (1 << CLOCK_APB_M_PMON_S)
CLOCK_APB_M_WU_S = 7
CLOCK_APB_M_WU_M = (1 << CLOCK_APB_M_WU_S)
CLOCK_APB_M_RTC_S = 8
CLOCK_APB_M_RTC_M = (1 << CLOCK_APB_M_RTC_S)
# APB_P
CLOCK_APB_P_WDT_S = 0
CLOCK_APB_P_WDT_M = (1 << CLOCK_APB_P_WDT_S)
CLOCK_APB_P_UART_0_S = 1
CLOCK_APB_P_UART_0_M = (1 << CLOCK_APB_P_UART_0_S)
CLOCK_APB_P_UART_1_S = 2
CLOCK_APB_P_UART_1_M = (1 << CLOCK_APB_P_UART_1_S)
CLOCK_APB_P_TIMER16_0_S = 3
CLOCK_APB_P_TIMER16_0_M = (1 << CLOCK_APB_P_TIMER16_0_S)
CLOCK_APB_P_TIMER16_1_S = 4
CLOCK_APB_P_TIMER16_1_M = (1 << CLOCK_APB_P_TIMER16_1_S)
CLOCK_APB_P_TIMER16_2_S = 5
CLOCK_APB_P_TIMER16_2_M = (1 << CLOCK_APB_P_TIMER16_2_S)
CLOCK_APB_P_TIMER32_1_S = 6
CLOCK_APB_P_TIMER32_1_M = (1 << CLOCK_APB_P_TIMER32_1_S)
CLOCK_APB_P_TIMER32_2_S = 7
CLOCK_APB_P_TIMER32_2_M = (1 << CLOCK_APB_P_TIMER32_2_S)
CLOCK_APB_P_SPI_0_S = 8
CLOCK_APB_P_SPI_0_M = (1 << CLOCK_APB_P_SPI_0_S)
CLOCK_APB_P_SPI_1_S = 9
CLOCK_APB_P_SPI_1_M = (1 << CLOCK_APB_P_SPI_1_S)
CLOCK_APB_P_I2C_0_S = 10
CLOCK_APB_P_I2C_0_M = (1 << CLOCK_APB_P_I2C_0_S)
CLOCK_APB_P_I2C_1_S = 11
CLOCK_APB_P_I2C_1_M = (1 << CLOCK_APB_P_I2C_1_S)
CLOCK_APB_P_GPIO_0_S = 12
CLOCK_APB_P_GPIO_0_M = (1 << CLOCK_APB_P_GPIO_0_S)
CLOCK_APB_P_GPIO_1_S = 13
CLOCK_APB_P_GPIO_1_M = (1 << CLOCK_APB_P_GPIO_1_S)
CLOCK_APB_P_GPIO_2_S = 14
CLOCK_APB_P_GPIO_2_M = (1 << CLOCK_APB_P_GPIO_2_S)
CLOCK_APB_P_ANALOG_S = 15
CLOCK_APB_P_ANALOG_M = (1 << CLOCK_APB_P_ANALOG_S)
CLOCK_APB_P_GPIO_IRQ_S = 16
CLOCK_APB_P_GPIO_IRQ_M = (1 << CLOCK_APB_P_GPIO_IRQ_S)
@@ -0,0 +1,111 @@
# --------------------------
# SPIFI register fields
# --------------------------
# CTRL
SPIFI_CONFIG_CTRL_TIMEOUT_S = 0
SPIFI_CONFIG_CTRL_TIMEOUT_M = (0xFFFF << SPIFI_CONFIG_CTRL_TIMEOUT_S)
def SPIFI_CONFIG_CTRL_TIMEOUT(v):
return (((v) << SPIFI_CONFIG_CTRL_TIMEOUT_S) & SPIFI_CONFIG_CTRL_TIMEOUT_M)
SPIFI_CONFIG_CTRL_CSHIGH_S = 16
SPIFI_CONFIG_CTRL_CSHIGH_M = (0xF << SPIFI_CONFIG_CTRL_CSHIGH_S)
def SPIFI_CONFIG_CTRL_CSHIGH(v):
return (((v) << SPIFI_CONFIG_CTRL_CSHIGH_S) & SPIFI_CONFIG_CTRL_CSHIGH_M)
SPIFI_CONFIG_CTRL_CACHE_EN_S = 20
SPIFI_CONFIG_CTRL_CACHE_EN_M = (0x1 << SPIFI_CONFIG_CTRL_CACHE_EN_S)
SPIFI_CONFIG_CTRL_D_CACHE_DIS_S = 21
SPIFI_CONFIG_CTRL_D_CACHE_DIS_M = (0x1 << SPIFI_CONFIG_CTRL_D_CACHE_DIS_S)
SPIFI_CONFIG_CTRL_INTEN_S = 22
SPIFI_CONFIG_CTRL_INTEN_M = (0x1 << SPIFI_CONFIG_CTRL_INTEN_S)
SPIFI_CONFIG_CTRL_MODE3_S = 23
SPIFI_CONFIG_CTRL_MODE3_M = (0x1 << SPIFI_CONFIG_CTRL_MODE3_S)
SPIFI_CONFIG_CTRL_SCK_DIV_S = 24
SPIFI_CONFIG_CTRL_SCK_DIV_M = (0x7 << SPIFI_CONFIG_CTRL_SCK_DIV_S)
def SPIFI_CONFIG_CTRL_SCK_DIV(v):
return (((v) << SPIFI_CONFIG_CTRL_SCK_DIV_S) & SPIFI_CONFIG_CTRL_SCK_DIV_M)
SPIFI_CONFIG_CTRL_PREFETCH_DIS_S = 27
SPIFI_CONFIG_CTRL_PREFETCH_DIS_M = (0x1 << SPIFI_CONFIG_CTRL_PREFETCH_DIS_S)
SPIFI_CONFIG_CTRL_DUAL_S = 28
SPIFI_CONFIG_CTRL_DUAL_M = (0x1 << SPIFI_CONFIG_CTRL_DUAL_S)
SPIFI_CONFIG_CTRL_RFCLK_S = 29
SPIFI_CONFIG_CTRL_RFCLK_M = (0x1 << SPIFI_CONFIG_CTRL_RFCLK_S)
SPIFI_CONFIG_CTRL_FBCLK_S = 30
SPIFI_CONFIG_CTRL_FBCLK_M = (0x1 << SPIFI_CONFIG_CTRL_FBCLK_S)
SPIFI_CONFIG_CTRL_DMAEN_S = 31
SPIFI_CONFIG_CTRL_DMAEN_M = (0x1 << SPIFI_CONFIG_CTRL_DMAEN_S)
# CMD
SPIFI_CONFIG_CMD_DATALEN_S = 0
SPIFI_CONFIG_CMD_DATALEN_M = (0x3FFF << SPIFI_CONFIG_CMD_DATALEN_S)
def SPIFI_CONFIG_CMD_DATALEN(v):
return (((v) << SPIFI_CONFIG_CMD_DATALEN_S) & SPIFI_CONFIG_CMD_DATALEN_M)
SPIFI_CONFIG_CMD_POLL_S = 14
SPIFI_CONFIG_CMD_POLL_M = (0x1 << SPIFI_CONFIG_CMD_POLL_S)
SPIFI_CONFIG_CMD_DOUT_S = 15
SPIFI_CONFIG_CMD_DOUT_M = (0x1 << SPIFI_CONFIG_CMD_DOUT_S)
SPIFI_CONFIG_CMD_INTLEN_S = 16
SPIFI_CONFIG_CMD_INTLEN_M = (0x7 << SPIFI_CONFIG_CMD_INTLEN_S)
SPIFI_CONFIG_CMD_FIELDFORM_S = 19
SPIFI_CONFIG_CMD_FIELDFORM_M = (0x3 << SPIFI_CONFIG_CMD_FIELDFORM_S)
SPIFI_CONFIG_CMD_FRAMEFORM_S = 21
SPIFI_CONFIG_CMD_FRAMEFORM_M = (0x7 << SPIFI_CONFIG_CMD_FRAMEFORM_S)
SPIFI_CONFIG_CMD_OPCODE_S = 24
SPIFI_CONFIG_CMD_OPCODE_M = (0xFF << SPIFI_CONFIG_CMD_OPCODE_S)
SPIFI_CONFIG_CMD_DATALEN_BUSY_INDEX_S = 0
SPIFI_CONFIG_CMD_DATALEN_BUSY_DONE_VALUE_S = 3
SPIFI_CONFIG_CMD_FRAMEFORM_RESERVED = 0
SPIFI_CONFIG_CMD_FRAMEFORM_OPCODE_NOADDR = 1
SPIFI_CONFIG_CMD_FRAMEFORM_OPCODE_1ADDR = 2
SPIFI_CONFIG_CMD_FRAMEFORM_OPCODE_2ADDR = 3
SPIFI_CONFIG_CMD_FRAMEFORM_OPCODE_3ADDR = 4
SPIFI_CONFIG_CMD_FRAMEFORM_OPCODE_4ADDR = 5
SPIFI_CONFIG_CMD_FRAMEFORM_NOOPCODE_3ADDR = 6
SPIFI_CONFIG_CMD_FRAMEFORM_NOOPCODE_4ADDR = 7
SPIFI_CONFIG_CMD_FIELDFORM_ALL_SERIAL = 0
SPIFI_CONFIG_CMD_FIELDFORM_DATA_PARALLEL = 1
SPIFI_CONFIG_CMD_FIELDFORM_OPCODE_SERIAL = 2
SPIFI_CONFIG_CMD_FIELDFORM_ALL_PARALLEL = 3
# MCMD
SPIFI_CONFIG_MCMD_POLL_S = 14
SPIFI_CONFIG_MCMD_POLL_M = (0x1 << SPIFI_CONFIG_MCMD_POLL_S)
SPIFI_CONFIG_MCMD_DOUT_S = 15
SPIFI_CONFIG_MCMD_DOUT_M = (0x1 << SPIFI_CONFIG_MCMD_DOUT_S)
SPIFI_CONFIG_MCMD_INTLEN_S = 16
SPIFI_CONFIG_MCMD_INTLEN_M = (0x7 << SPIFI_CONFIG_MCMD_INTLEN_S)
SPIFI_CONFIG_MCMD_FIELDFORM_S = 19
SPIFI_CONFIG_MCMD_FIELDFORM_M = (0x3 << SPIFI_CONFIG_MCMD_FIELDFORM_S)
SPIFI_CONFIG_MCMD_FRAMEFORM_S = 21
SPIFI_CONFIG_MCMD_FRAMEFORM_M = (0x7 << SPIFI_CONFIG_MCMD_FRAMEFORM_S)
SPIFI_CONFIG_MCMD_OPCODE_S = 24
SPIFI_CONFIG_MCMD_OPCODE_M = (0xFF << SPIFI_CONFIG_MCMD_OPCODE_S)
# STATUS
SPIFI_CONFIG_STAT_MCINIT_S = 0
SPIFI_CONFIG_STAT_MCINIT_M = (0x1 << SPIFI_CONFIG_STAT_MCINIT_S)
SPIFI_CONFIG_STAT_CMD_S = 1
SPIFI_CONFIG_STAT_CMD_M = (0x1 << SPIFI_CONFIG_STAT_CMD_S)
SPIFI_CONFIG_STAT_RESET_S = 4
SPIFI_CONFIG_STAT_RESET_M = (0x1 << SPIFI_CONFIG_STAT_RESET_S)
SPIFI_CONFIG_STAT_INTRQ_S = 5
SPIFI_CONFIG_STAT_INTRQ_M = (0x1 << SPIFI_CONFIG_STAT_INTRQ_S)
SPIFI_CONFIG_STAT_VERSION_S = 24
SPIFI_CONFIG_STAT_VERSION_M = (0xFF << SPIFI_CONFIG_STAT_VERSION_S)
@@ -0,0 +1,15 @@
# --------------------------
# WU register fields
# --------------------------
# CLOCKS_BU
CLOCKS_BU_OCS32K_EN_S = 0
CLOCKS_BU_OCS32K_EN_M = (1 << CLOCKS_BU_OCS32K_EN_S)
CLOCKS_BU_RC32K_EN_S = 1
CLOCKS_BU_RC32K_EN_M = (1 << CLOCKS_BU_RC32K_EN_S)
CLOCKS_BU_ADJ_RC32K_S = 2
CLOCKS_BU_ADJ_RC32K_M = (0b11111111 << CLOCKS_BU_ADJ_RC32K_S)
CLOCKS_BU_RTC_CLK_MUX_S = 10
CLOCKS_BU_RTC_CLK_MUX_M = (1 << CLOCKS_BU_RTC_CLK_MUX_S)
CLOCKS_BU_OSC32K_SM_S = 14
CLOCKS_BU_OSC32K_SM_M = (1 << CLOCKS_BU_OSC32K_SM_S)
+89
View File
@@ -0,0 +1,89 @@
# --------------------------
# DMA register offset
# --------------------------
from enum import Enum
DMA_REGS = 0x00040000
DMA_CONTROL = DMA_REGS + 0x40
DMA_CHANNEL_SIZEOF = 0x4 * 4
def DMA_CHANNEL_DESTINATION(i):
return DMA_REGS + i*DMA_CHANNEL_SIZEOF + 0x4*0
def DMA_CHANNEL_SOURCE(i):
return DMA_REGS + i*DMA_CHANNEL_SIZEOF + 0x4*1
def DMA_CHANNEL_LEN(i):
return DMA_REGS + i*DMA_CHANNEL_SIZEOF + 0x4*2
def DMA_CHANNEL_CONFIG(i):
return DMA_REGS + i*DMA_CHANNEL_SIZEOF + 0x4*3
# --------------------------
# SPIFI register offset
# --------------------------
SPIFI_REGS = 0x00070000
SPIFI_CONFIG_CTRL = SPIFI_REGS + 0x000
SPIFI_CONFIG_CMD = SPIFI_REGS + 0x004
SPIFI_CONFIG_ADDR = SPIFI_REGS + 0x008
SPIFI_CONFIG_IDATA = SPIFI_REGS + 0x00C
SPIFI_CONFIG_CLIMIT = SPIFI_REGS + 0x010
SPIFI_CONFIG_DATA32 = SPIFI_REGS + 0x014
SPIFI_CONFIG_MCMD = SPIFI_REGS + 0x018
SPIFI_CONFIG_STAT = SPIFI_REGS + 0x01C
# --------------------------
# PM register offset
# --------------------------
PM_REGS = 0x000050000
PM_Clk_AHB_Set_OFFSET = PM_REGS + 0x0C
PM_Clk_APB_M_Set_OFFSET = PM_REGS + 0x14
PM_Clk_APB_P_Set_OFFSET = PM_REGS + 0x1C
# --------------------------
# WU register offset
# --------------------------
WU_REGS = 0x00060000
WU_CLOCKS_BU_OFFSET = WU_REGS + 0x10
# --------------------------
# GPIO register offset
# --------------------------
PAD_CONFIG_REGS = 0x00050C00
class PAD_CONFIG_REGS_V0(Enum):
PORT_0_CFG = 0x00
PORT_1_CFG = 0x04
PORT_2_CFG = 0x08
PORT_0_DS = 0x0C
PORT_1_DS = 0x10
PORT_2_DS = 0x14
PORT_0_PUD = 0x18
PORT_1_PUD = 0x1C
PORT_2_PUD = 0x20
class PAD_CONFIG_REGS_V2(Enum):
PORT_0_CFG = 0x00
PORT_0_DS = 0x04
PORT_0_PUD = 0x08
PORT_1_CFG = 0x0C
PORT_1_DS = 0x10
PORT_1_PUD = 0x14
PORT_2_CFG = 0x18
PORT_2_DS = 0x1C
PORT_2_PUD = 0x20
+761
View File
@@ -0,0 +1,761 @@
from enum import Enum
import os
import pathlib
import sys
from typing import Dict, List, Union
import time
from tclrpc import TclException
from tclrpc import OpenOcdTclRpc
from mik32_debug_hal.dma import DMA, ChannelMode, ChannelIndex, ChannelAck, ChannelIncrement, ChannelPriority, ChannelRequest, ChannelSize
import mik32_debug_hal.registers.memory_map as mem_map
import mik32_debug_hal.registers.bitfields.spifi as spifi_fields
# --------------------------
# Commands
# --------------------------
SREG1_BUSY = 1
READ_LEN = 256
TIMEOUT = 1000
ENABLE_RESET_COMMAND = 0x66
RESET_COMMAND = 0x99
CHIP_ERASE_COMMAND = 0xC7
SECTOR_ERASE_COMMAND = 0x20
WRITE_ENABLE_COMMAND = 0x06
WRITE_DISABLE_COMMAND = 0x04
#DISABLE_QPI_COMMAND = 0xFF
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 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)
INIT_DELAY = 0.001
def spifi_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)
time.sleep(INIT_DELAY)
def spifi_init(openocd: OpenOcdTclRpc):
print("MCU clock init", flush=True)
spifi_init_periphery(openocd)
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)
time.sleep(INIT_DELAY)
def spifi_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) |
(READ_DATA_COMMAND << spifi_fields.SPIFI_CONFIG_MCMD_OPCODE_S))
time.sleep(INIT_DELAY)
def SPIFI_WaitIntrqTimeout(openocd: OpenOcdTclRpc, timeout: int) -> int:
timeout_inner = timeout
while timeout_inner:
timeout_inner -= 1
if (openocd.read_word(mem_map.SPIFI_CONFIG_STAT) & spifi_fields.SPIFI_CONFIG_STAT_INTRQ_M) != 0:
return 1
return 0
def spifi_wait_intrq_timeout(openocd: OpenOcdTclRpc, error_message: str):
if SPIFI_WaitIntrqTimeout(openocd, TIMEOUT) == 0:
raise Exception(error_message)
return
class SPIFI_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
class SPIFI_Fieldform(Enum):
ALL_SERIAL = 0
DATA_PARALLEL = 1
OPCODE_SERIAL = 2
ALL_PARALLEL = 3
class SPIFI_Direction(Enum):
READ = 0
WRITE = 1
def spifi_send_command(
openocd: OpenOcdTclRpc,
cmd: int,
frameform: SPIFI_Frameform,
fieldform: SPIFI_Fieldform,
byte_count=0,
address=0,
idata=0,
cache_limit=0,
idata_length=0,
direction=SPIFI_Direction.READ,
data: List[int] = [],
dma: Union[DMA, None] = None
) -> List[int]:
if (dma is not None) and (direction == SPIFI_Direction.WRITE):
openocd.write_memory(0x02003F00, 8, data)
dma.channels[0].start(
0x02003F00,
mem_map.SPIFI_CONFIG_DATA32,
255
)
elif (dma is not None) and (direction == SPIFI_Direction.READ):
dma.channels[1].start(
mem_map.SPIFI_CONFIG_DATA32,
0x02003F00,
255
)
openocd.write_memory(mem_map.SPIFI_CONFIG_ADDR, 32, [address, idata])
# # spifi_intrq_clear(openocd)
# openocd.write_word(SPIFI_CONFIG_CMD, (cmd << SPIFI_CONFIG_CMD_OPCODE_S) |
# (frameform.value << SPIFI_CONFIG_CMD_FRAMEFORM_S) |
# (fieldform.value << SPIFI_CONFIG_CMD_FIELDFORM_S) |
# (byte_count << SPIFI_CONFIG_CMD_DATALEN_S) |
# (idata_length << SPIFI_CONFIG_CMD_INTLEN_S) |
# (direction.value << SPIFI_CONFIG_CMD_DOUT_S))
# # spifi_wait_intrq_timeout(openocd, "Timeout executing write enable command")
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 == SPIFI_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 == SPIFI_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:
for i in range(byte_count):
openocd.write_memory(mem_map.SPIFI_CONFIG_DATA32, 8, [data[i]])
return []
def spifi_write_enable(openocd: OpenOcdTclRpc):
spifi_send_command(openocd, WRITE_ENABLE_COMMAND,
SPIFI_Frameform.OPCODE_NOADDR, SPIFI_Fieldform.ALL_SERIAL)
def spifi_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 spifi_write_sreg(openocd: OpenOcdTclRpc, sreg1: int, sreg2: int):
# spifi_send_command(openocd, DISABLE_QPI_COMMAND,
# SPIFI_Frameform.OPCODE_NOADDR, SPIFI_Fieldform.ALL_PARALLEL)
spifi_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]
)
spifi_wait_busy(openocd)
def spifi_wait_busy(openocd: OpenOcdTclRpc):
while 1:
sreg1 = spifi_read_sreg(openocd, SREG_Num.SREG1)
if not (sreg1 & SREG1_BUSY):
break
RESET_DELAY = 0.001
def spifi_chip_reset(openocd: OpenOcdTclRpc):
#print("Sending 'Reset' to external chip in SPI mode", flush=True)
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 spifi_chip_reset_qpi(openocd: OpenOcdTclRpc):
#print("Sending 'Reset' to external chip in QPI mode", flush=True)
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 spifi_chip_disable_qpi(openocd: OpenOcdTclRpc):
#print("Sending 'Disable QPI' command to external flash chip in QPI mode.", flush=True)
# spifi_send_command(openocd, DISABLE_QPI_COMMAND,
# SPIFI_Frameform.OPCODE_NOADDR, SPIFI_Fieldform.ALL_PARALLEL)
def spifi_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 spifi_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 spifi_read_data(openocd: OpenOcdTclRpc, address: int, byte_count: int, bin_data: List[int], dma: Union[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)
# spifi_init_periphery(openocd)
# read_periph = spifi_send_command(openocd, READ_DATA_COMMAND, SPIFI_Frameform.OPCODE_3ADDR,
# SPIFI_Fieldform.ALL_SERIAL, byte_count=1, address=(i+address))
# print(
# f"DATA[{i+address}] = {read_periph[0]:#0x} expect {bin_data[i]:#0x}", flush=True)
return 1
return 0
def spifi_page_program(
openocd: OpenOcdTclRpc,
ByteAddress: int,
data: List[int],
byte_count: int,
progress: str = "",
dma: Union[DMA, None] = None
):
print(f"Writing Flash page {ByteAddress:#010x}... {progress}", flush=True)
if byte_count > 256:
raise Exception("Byte count more than 256")
spifi_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)
spifi_wait_busy(openocd)
class EraseType(Enum):
CHIP_ERASE = CHIP_ERASE_COMMAND
SECTOR_ERASE = SECTOR_ERASE_COMMAND
def spifi_erase(openocd, erase_type: EraseType = EraseType.CHIP_ERASE, sectors: List[int] = []):
if erase_type == EraseType.CHIP_ERASE:
spifi_write_enable(openocd)
spifi_chip_erase(openocd)
spifi_wait_busy(openocd)
elif erase_type == EraseType.SECTOR_ERASE:
for sector in sectors:
spifi_write_enable(openocd)
spifi_sector_erase(openocd, sector)
spifi_wait_busy(openocd)
def spifi_write(openocd: OpenOcdTclRpc, address: int, data: List[int], data_len: int):
if data_len > 256:
raise Exception("Byte count more than 256")
spifi_page_program(openocd, address, data, data_len)
print("written")
def spifi_write_file(bytes: List[int], openocd: OpenOcdTclRpc):
# print(bytes)
print(f"Write {len(bytes)} bytes")
openocd.halt()
spifi_init(openocd)
spifi_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)
spifi_write(openocd, address, bytes, 256)
if spifi_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}]")
spifi_write(openocd, address, bytes, len(bytes) - address)
if spifi_read_data(openocd, address, len(bytes) - address, bytes) == 1:
return 1
print("end")
return 0
def spifi_quad_page_program(
openocd: OpenOcdTclRpc,
ByteAddress: int,
data: List[int],
byte_count: int,
progress: str = "",
dma: Union[DMA, None] = None
):
print(f"Writing page {ByteAddress:#010x}... {progress}", flush=True)
if byte_count > 256:
raise Exception("Byte count more than 256")
spifi_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)
spifi_wait_busy(openocd)
def spifi_quad_enable(openocd):
if (spifi_check_quad_enable(openocd) != True):
spifi_write_sreg(
openocd,
spifi_read_sreg(openocd, SREG_Num.SREG1),
spifi_read_sreg(openocd, SREG_Num.SREG2) | SREG2_QUAD_ENABLE_M
)
#def spifi_quad_disable(openocd):
# if (spifi_check_quad_enable(openocd) == True):
# spifi_write_sreg(
# openocd,
# spifi_read_sreg(openocd, SREG_Num.SREG1),
# spifi_read_sreg(openocd, SREG_Num.SREG2) & (0xFF ^ SREG2_QUAD_ENABLE_M)
# )
def spifi_check_quad_enable(openocd):
return (spifi_read_sreg(openocd, SREG_Num.SREG2) & SREG2_QUAD_ENABLE_M) != 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 list(segments)
def check_pages(pages: Dict[int, List[int]], openocd: OpenOcdTclRpc, use_quad_spi=False, use_chip_erase=False):
result = 0
openocd.halt()
spifi_init(openocd)
# Сбрасываем микросхему в режиме QPI из всех состояний в нормальный SPI режим.
spifi_chip_reset_qpi(openocd)
# Сбрасываем микросхему в режиме SPI из всех состояний в нормальный SPI режим.
spifi_chip_reset(openocd)
JEDEC_ID = spifi_send_command(openocd, JEDEC_ID_COMMAND, SPIFI_Frameform.OPCODE_NOADDR, SPIFI_Fieldform.ALL_SERIAL, 3)
print(f"JEDEC ID = {JEDEC_ID[0]:02x} {JEDEC_ID[1]:02x} {JEDEC_ID[2]:02x}")
dma = DMA(openocd)
dma.init()
dma.channels[0].write_buffer = 0
dma.channels[0].channel = ChannelIndex.CHANNEL_0
dma.channels[0].priority = ChannelPriority.VERY_HIGH
dma.channels[0].read_mode = ChannelMode.MEMORY
dma.channels[0].read_increment = ChannelIncrement.ENABLE
dma.channels[0].read_size = ChannelSize.WORD
dma.channels[0].read_burst_size = 2
dma.channels[0].read_request = ChannelRequest.SPIFI_REQUEST
dma.channels[0].read_ack = ChannelAck.DISABLE
dma.channels[0].write_mode = ChannelMode.PERIPHERY
dma.channels[0].write_increment = ChannelIncrement.DISABLE
dma.channels[0].write_size = ChannelSize.WORD
dma.channels[0].write_burst_size = 2
dma.channels[0].write_request = ChannelRequest.SPIFI_REQUEST
dma.channels[0].write_ack = ChannelAck.DISABLE
dma.channels[1].write_buffer = 0
dma.channels[1].channel = ChannelIndex.CHANNEL_1
dma.channels[1].priority = ChannelPriority.VERY_HIGH
dma.channels[1].write_mode = ChannelMode.MEMORY
dma.channels[1].write_increment = ChannelIncrement.ENABLE
dma.channels[1].write_size = ChannelSize.WORD
dma.channels[1].write_burst_size = 2
dma.channels[1].write_request = ChannelRequest.SPIFI_REQUEST
dma.channels[1].write_ack = ChannelAck.DISABLE
dma.channels[1].read_mode = ChannelMode.PERIPHERY
dma.channels[1].read_increment = ChannelIncrement.DISABLE
dma.channels[1].read_size = ChannelSize.WORD
dma.channels[1].read_burst_size = 2
dma.channels[1].read_request = ChannelRequest.SPIFI_REQUEST
dma.channels[1].read_ack = ChannelAck.DISABLE
if (use_quad_spi):
print("Using Quad SPI")
spifi_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 = spifi_read_data(openocd, page_offset, 256, page_bytes, dma=dma, 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
# # PROFILING IMPORTS
# import cProfile, pstats, io
# from pstats import SortKey
def write_pages(pages: Dict[int, List[int]], openocd: OpenOcdTclRpc, use_quad_spi=False, use_chip_erase=False):
result = 0
# # PROFILING INIT
# pr = cProfile.Profile()
# pr.enable()
# # PROFILING INIT END
openocd.halt()
spifi_init(openocd)
# Сбрасываем микросхему в режиме QPI из всех состояний в нормальный SPI режим.
spifi_chip_reset_qpi(openocd)
# Сбрасываем микросхему в режиме SPI из всех состояний в нормальный SPI режим.
spifi_chip_reset(openocd)
JEDEC_ID = spifi_send_command(openocd, JEDEC_ID_COMMAND, SPIFI_Frameform.OPCODE_NOADDR, SPIFI_Fieldform.ALL_SERIAL, 3)
print(f"JEDEC ID = {JEDEC_ID[0]:02x} {JEDEC_ID[1]:02x} {JEDEC_ID[2]:02x}")
dma = DMA(openocd)
dma.init()
dma.channels[0].write_buffer = 0
dma.channels[0].channel = ChannelIndex.CHANNEL_0
dma.channels[0].priority = ChannelPriority.VERY_HIGH
dma.channels[0].read_mode = ChannelMode.MEMORY
dma.channels[0].read_increment = ChannelIncrement.ENABLE
dma.channels[0].read_size = ChannelSize.WORD
dma.channels[0].read_burst_size = 2
dma.channels[0].read_request = ChannelRequest.SPIFI_REQUEST
dma.channels[0].read_ack = ChannelAck.DISABLE
dma.channels[0].write_mode = ChannelMode.PERIPHERY
dma.channels[0].write_increment = ChannelIncrement.DISABLE
dma.channels[0].write_size = ChannelSize.WORD
dma.channels[0].write_burst_size = 2
dma.channels[0].write_request = ChannelRequest.SPIFI_REQUEST
dma.channels[0].write_ack = ChannelAck.DISABLE
dma.channels[1].write_buffer = 0
dma.channels[1].channel = ChannelIndex.CHANNEL_1
dma.channels[1].priority = ChannelPriority.VERY_HIGH
dma.channels[1].write_mode = ChannelMode.MEMORY
dma.channels[1].write_increment = ChannelIncrement.ENABLE
dma.channels[1].write_size = ChannelSize.WORD
dma.channels[1].write_burst_size = 2
dma.channels[1].write_request = ChannelRequest.SPIFI_REQUEST
dma.channels[1].write_ack = ChannelAck.DISABLE
dma.channels[1].read_mode = ChannelMode.PERIPHERY
dma.channels[1].read_increment = ChannelIncrement.DISABLE
dma.channels[1].read_size = ChannelSize.WORD
dma.channels[1].read_burst_size = 2
dma.channels[1].read_request = ChannelRequest.SPIFI_REQUEST
dma.channels[1].read_ack = ChannelAck.DISABLE
if use_chip_erase:
spifi_erase(openocd, EraseType.CHIP_ERASE)
else:
spifi_erase(openocd, EraseType.SECTOR_ERASE,
get_segments_list(list(pages), 4*1024))
# for addr in range(0, 4096*2, 256):
# result = spifi_read_data(openocd, addr, 256, [0xFF]*256, dma=dma)
# if result == 1:
# print("Data error")
# return result
print("Quad Enable", spifi_check_quad_enable(openocd))
if (use_quad_spi):
print("Using Quad SPI")
spifi_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):
spifi_quad_page_program(
openocd, page_offset, page_bytes, 256, f"{(index*100)//pages_offsets.__len__()}%", dma=dma)
else:
spifi_page_program(openocd, page_offset, page_bytes,
256, f"{(index*100)//pages_offsets.__len__()}%", dma=dma)
result = spifi_read_data(openocd, page_offset, 256, page_bytes, dma=dma, use_quad_spi=use_quad_spi)
if result == 1:
print("Data error")
return result
#if (use_quad_spi):
# spifi_quad_disable(openocd)
# # PROFILING GET STATS
# pr.disable()
# s = io.StringIO()
# sortby = SortKey.CUMULATIVE
# ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
# ps.print_stats()
# print(s.getvalue())
# # PROFILING GET STATS END
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) -> int:
start_time = time.perf_counter()
while ("halted" not in openocd.run("riscv.cpu curstate")):
if (time.perf_counter() - start_time) > timeout_seconds:
print("Wait halted TIMEOUT!")
openocd.halt()
return 1
time.sleep(0.01)
return 0
def write_pages_by_sectors(pages: Dict[int, List[int]], openocd: OpenOcdTclRpc, use_quad_spi=False, use_chip_erase=False):
result = 0
openocd.halt()
spifi_init(openocd)
JEDEC_ID = spifi_send_command(openocd, 0x9F, SPIFI_Frameform.OPCODE_NOADDR, SPIFI_Fieldform.ALL_SERIAL, 3)
print(f"JEDEC_ID {JEDEC_ID[0]:02x} {JEDEC_ID[1]:02x} {JEDEC_ID[2]:02x}")
sectors_list = get_segments_list(list(pages), 4*1024)
openocd.halt()
pathname = os.path.dirname(sys.argv[0])
# openocd.run("load_image {%s}" % pathlib.Path(os.path.join(pathname, "firmware.hex")))
openocd.run("rbp all")
openocd.run("load_image {%s}" % pathlib.Path("C:\\Users\\user\\Documents\\PlatformIO\\Projects\\SPIFI_JTAG_driver\\.pio\\build\\mik32v2\\firmware.hex"))
openocd.run("bp 0x02002010 1 hw")
openocd.resume(0x02000000)
if wait_halted(openocd) != 0:
return 1
# spifi erase
for sector in sectors_list:
print(f"Erase sector {sector}", flush=True)
openocd.write_word(0x02002000, 0b0010 | (sector << 8))
openocd.resume()
if wait_halted(openocd) != 0:
return 1
print(f"Erase sector {sector} result {openocd.read_word(0x02002008)}", flush=True)
return 1
# spifi erase check
for sector in sectors_list:
# print(f"Erase sector {sector}", flush=True)
# openocd.write_word(0x02002000, 0b0010 | sector)
# openocd.resume()
# if wait_halted(openocd) != 0:
# return 1
# print(f"Erase sector {sector} result {openocd.read_word(0x02002008)}", flush=True)
page_bytes = [0xff] * 256
result = spifi_read_data(openocd, sector, 256, page_bytes)
if result == 1:
print("Data error")
return result
for sector in sectors_list:
print(f"Program sector {sector}", flush=True)
bytes_list: List[int] = []
for page in range(16):
page = pages.get(page * 256 + sector * 4096)
if page is not None:
bytes_list.extend(page)
else:
bytes_list.extend([0]*256)
extend_value = 1 + sector
bytes_list.extend([(extend_value >> 0) & 0xFF, (extend_value >> 8) & 0xFF, (extend_value >> 16) & 0xFF, (extend_value >> 24) & 0xFF])
# print(bytes_list)
while (openocd.read_word(0x0200200c) != 1):
openocd.resume()
openocd.halt()
openocd.write_memory(0x02001000, 8, bytes_list)
while (openocd.read_word(0x0200200c) != 1):
openocd.resume()
openocd.halt()
time.sleep(0.5)
openocd.halt()
print(f"Program sector {sector} result {openocd.read_word(0x02002008)}", flush=True)
spifi_init_memory(openocd)
# check write
pages_offsets = list(pages)
for index, page_offset in enumerate(pages_offsets):
page_bytes = pages[page_offset]
memory_bytes = openocd.read_memory(page_offset + 0x80000000, 8, 256)
print(page_offset, memory_bytes)
for i, byte in enumerate(memory_bytes):
if byte != page_bytes[i]:
print("Data error!")
openocd.run("rbp 0x02002010")
return result
openocd.run("rbp 0x02002010")
if result == 0:
# Прошивка страниц флеш памяти по SPIFI была завершена
print("Flashing of flash memory pages via SPIFI has been completed", flush=True)
return 0