mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-25 15:16:53 +01:00
[SC64][SW] Added very basic SDRAM test in the primer before flashing bootloader
This commit is contained in:
parent
f27f644a7e
commit
c156b72bee
@ -6,7 +6,9 @@
|
|||||||
- [**Putting it together**](#putting-it-together)
|
- [**Putting it together**](#putting-it-together)
|
||||||
- [**Initial programming**](#initial-programming)
|
- [**Initial programming**](#initial-programming)
|
||||||
- [**Troubleshooting**](#troubleshooting)
|
- [**Troubleshooting**](#troubleshooting)
|
||||||
- [*`primer.py` threw error on `Bootloader -> SC64 FLASH` step*](#primerpy-threw-error-on-bootloader---sc64-flash-step)
|
- [*`primer.py` threw `No SC64 USB device found` error*](#primerpy-threw-no-sc64-usb-device-found-error)
|
||||||
|
- [*`primer.py` threw `SDRAM test error...` message*](#primerpy-threw-sdram-test-error-message)
|
||||||
|
- [*`primer.py` threw other error message*](#primerpy-threw-other-error-message)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -115,9 +117,23 @@ Congratulations! Your SC64 flashcart should be ready for use!
|
|||||||
|
|
||||||
### **Troubleshooting**
|
### **Troubleshooting**
|
||||||
|
|
||||||
#### *`primer.py` threw error on `Bootloader -> SC64 FLASH` step*
|
#### *`primer.py` threw `No SC64 USB device found` error*
|
||||||
|
|
||||||
This issue can be attributed to incorrectly programmed FT232H EEPROM in the first programming step.
|
This issue can be attributed to incorrectly programmed FT232H EEPROM in the first programming step.
|
||||||
Check again in `FT_PROG` application if device was configured properly.
|
Check again in `FT_PROG` application if device was configured properly.
|
||||||
|
Make sure default FTDI drivers are installed for the SC64 in the device manager (only on Windows OS).
|
||||||
|
Make sure you have correct access to `/dev/ttyUSBx` device and `ftdi_sio` and `usbserial` modules are loaded (only on Linux OS).
|
||||||
|
|
||||||
|
#### *`primer.py` threw `SDRAM test error...` message*
|
||||||
|
|
||||||
|
This issue shows up when there's a problem with the connection to the SDRAM chip or the chip itself is malfunctioning.
|
||||||
|
Check for any solder bridges and unconnected pins on U8/U9 chips.
|
||||||
Once FPGA and microcontroller has been programmed successfully `primer.py` script needs to be run in special mode.
|
Once FPGA and microcontroller has been programmed successfully `primer.py` script needs to be run in special mode.
|
||||||
Please use command `python3 primer.py COMx sc64-firmware-{version}.bin --bootloader-only` to try programming bootloader again.
|
Please use command `python3 primer.py COMx sc64-firmware-{version}.bin --bootloader-only` to test SDRAM again and continue bootloader programming process.
|
||||||
|
|
||||||
|
#### *`primer.py` threw other error message*
|
||||||
|
Due to multiple possible causes of the problem it's best to start visually inspecting SC64's board for any defects, like bad solder work or chips soldered backwards.
|
||||||
|
If visual inspection didn't yield any obvious culprits then next step would be to check if everything is connected correctly.
|
||||||
|
Check if TX/RX signals aren't swapped and if SC64 is getting power from the USB cable. Best place to check supply voltage are the exposed test pads on the left of U8 chip.
|
||||||
|
If everything at this point was checked and looked fine, then feel free to open new thread in the [*Discussions*](https://github.com/Polprzewodnikowy/SummerCart64/discussions) tab.
|
||||||
|
Make sure to describe your problem extensively, attach SC64 board photos **from the both sides**, and paste all logs/screenshots from the `primer.py` output.
|
||||||
|
@ -5,10 +5,11 @@ import os
|
|||||||
import queue
|
import queue
|
||||||
import serial
|
import serial
|
||||||
import signal
|
import signal
|
||||||
|
import struct
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
from binascii import crc32
|
from binascii import crc32
|
||||||
from enum import IntEnum
|
from enum import IntEnum, StrEnum
|
||||||
from serial.tools import list_ports
|
from serial.tools import list_ports
|
||||||
from sys import exit
|
from sys import exit
|
||||||
from typing import Callable, Optional
|
from typing import Callable, Optional
|
||||||
@ -478,6 +479,8 @@ class SC64:
|
|||||||
__serial: Optional[serial.Serial] = None
|
__serial: Optional[serial.Serial] = None
|
||||||
__packets = queue.Queue()
|
__packets = queue.Queue()
|
||||||
|
|
||||||
|
SDRAM_SIZE = 64 * 1024 * 1024
|
||||||
|
|
||||||
class __UpdateStatus(IntEnum):
|
class __UpdateStatus(IntEnum):
|
||||||
MCU = 1
|
MCU = 1
|
||||||
FPGA = 2
|
FPGA = 2
|
||||||
@ -485,7 +488,8 @@ class SC64:
|
|||||||
DONE = 0x80
|
DONE = 0x80
|
||||||
ERROR = 0xFF
|
ERROR = 0xFF
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self, progress: Callable[[int, int, str], None]) -> None:
|
||||||
|
self.__progress = progress
|
||||||
SC64_VID = 0x0403
|
SC64_VID = 0x0403
|
||||||
SC64_PID = 0x6014
|
SC64_PID = 0x6014
|
||||||
SC64_SID = "SC64"
|
SC64_SID = "SC64"
|
||||||
@ -575,14 +579,36 @@ class SC64:
|
|||||||
return packet
|
return packet
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def update_firmware(self, data: bytes) -> None:
|
def __cmd_state_reset(self) -> None:
|
||||||
|
self.__execute_command(b'R')
|
||||||
|
|
||||||
|
def __cmd_memory_read(self, address: int, length: int) -> bytes:
|
||||||
|
return self.__execute_command(b'm', [address, length])
|
||||||
|
|
||||||
|
def __cmd_memory_write(self, address: int, data: bytes) -> None:
|
||||||
|
self.__execute_command(b'M', [address, len(data)], data)
|
||||||
|
|
||||||
|
def __cmd_firmware_update(self, address: int, length: int) -> None:
|
||||||
|
self.__execute_command(b'F', [address, length])
|
||||||
|
|
||||||
|
def update_firmware(self, data: bytes, description: str) -> None:
|
||||||
FIRMWARE_ADDRESS = 0x00100000
|
FIRMWARE_ADDRESS = 0x00100000
|
||||||
FIRMWARE_UPDATE_TIMEOUT = 90.0
|
FIRMWARE_UPDATE_TIMEOUT = 90.0
|
||||||
|
STEPS = 6
|
||||||
|
|
||||||
|
self.__progress(STEPS, 0, description)
|
||||||
|
|
||||||
self.__reset()
|
self.__reset()
|
||||||
self.__execute_command(b'R')
|
self.__progress(STEPS, 1, description)
|
||||||
self.__execute_command(b'M', [FIRMWARE_ADDRESS, len(data)], data)
|
|
||||||
self.__execute_command(b'F', [FIRMWARE_ADDRESS, len(data)])
|
self.__cmd_state_reset()
|
||||||
|
self.__progress(STEPS, 2, description)
|
||||||
|
|
||||||
|
self.__cmd_memory_write(FIRMWARE_ADDRESS, data)
|
||||||
|
self.__progress(STEPS, 3, description)
|
||||||
|
|
||||||
|
self.__cmd_firmware_update(FIRMWARE_ADDRESS, len(data))
|
||||||
|
self.__progress(STEPS, 4, description)
|
||||||
|
|
||||||
timeout = time.time() + FIRMWARE_UPDATE_TIMEOUT
|
timeout = time.time() + FIRMWARE_UPDATE_TIMEOUT
|
||||||
while True:
|
while True:
|
||||||
@ -596,11 +622,62 @@ class SC64:
|
|||||||
if (id != b'F'):
|
if (id != b'F'):
|
||||||
raise SC64Exception('Unexpected packet id received')
|
raise SC64Exception('Unexpected packet id received')
|
||||||
status = self.__UpdateStatus(int.from_bytes(packet_data[0:4], byteorder='big'))
|
status = self.__UpdateStatus(int.from_bytes(packet_data[0:4], byteorder='big'))
|
||||||
if (status == self.__UpdateStatus.ERROR):
|
if (status == self.__UpdateStatus.BOOTLOADER):
|
||||||
raise SC64Exception('Firmware update error')
|
self.__progress(STEPS, 5, description)
|
||||||
if (status == self.__UpdateStatus.DONE):
|
elif (status == self.__UpdateStatus.DONE):
|
||||||
|
self.__progress(STEPS, 6, description)
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
break
|
break
|
||||||
|
elif (status == self.__UpdateStatus.ERROR):
|
||||||
|
raise SC64Exception('Firmware update error')
|
||||||
|
|
||||||
|
class __RamTestPattern(StrEnum):
|
||||||
|
OWN_ADDRESS = 'own address'
|
||||||
|
ALL_ZEROS = 'all zeros'
|
||||||
|
ALL_ONES = 'all ones'
|
||||||
|
RANDOM_DATA = 'random data'
|
||||||
|
|
||||||
|
def __create_ram_test_pattern(self, pattern: __RamTestPattern) -> bytes:
|
||||||
|
if (pattern == self.__RamTestPattern.OWN_ADDRESS):
|
||||||
|
addresses = list(range(0, self.SDRAM_SIZE, 4))
|
||||||
|
data = struct.pack(f'>{len(addresses)}I', *addresses)
|
||||||
|
elif (pattern == self.__RamTestPattern.ALL_ZEROS):
|
||||||
|
data = b'\x00' * self.SDRAM_SIZE
|
||||||
|
elif (pattern == self.__RamTestPattern.ALL_ONES):
|
||||||
|
data = b'\xFF' * self.SDRAM_SIZE
|
||||||
|
elif (pattern == self.__RamTestPattern.RANDOM_DATA):
|
||||||
|
data = os.urandom(self.SDRAM_SIZE)
|
||||||
|
return bytes(data)
|
||||||
|
|
||||||
|
def sdram_test(self, description: str) -> None:
|
||||||
|
CHUNK_LENGTH = 1 * 1024 * 1024
|
||||||
|
|
||||||
|
self.__reset()
|
||||||
|
|
||||||
|
self.__cmd_state_reset()
|
||||||
|
|
||||||
|
for pattern in self.__RamTestPattern:
|
||||||
|
write_description = f'{description} / Write {pattern.value}'
|
||||||
|
check_description = f'{description} / Check {pattern.value}'
|
||||||
|
|
||||||
|
test_data = self.__create_ram_test_pattern(pattern)
|
||||||
|
|
||||||
|
self.__progress(self.SDRAM_SIZE, 0, write_description)
|
||||||
|
for offset in range(0, self.SDRAM_SIZE, CHUNK_LENGTH):
|
||||||
|
self.__cmd_memory_write(offset, test_data[offset:offset+CHUNK_LENGTH])
|
||||||
|
self.__progress(self.SDRAM_SIZE, offset + CHUNK_LENGTH, write_description)
|
||||||
|
|
||||||
|
self.__progress(self.SDRAM_SIZE, 0, check_description)
|
||||||
|
for offset in range(0, self.SDRAM_SIZE, CHUNK_LENGTH):
|
||||||
|
check_data = self.__cmd_memory_read(offset, CHUNK_LENGTH)
|
||||||
|
if (check_data != test_data[offset:offset+CHUNK_LENGTH]):
|
||||||
|
for chunk_offset in range(0, CHUNK_LENGTH, 4):
|
||||||
|
test_address = offset + chunk_offset
|
||||||
|
expected_value = int.from_bytes(test_data[test_address:test_address+4], byteorder='big')
|
||||||
|
read_value = int.from_bytes(check_data[chunk_offset:chunk_offset+4], byteorder='big')
|
||||||
|
if (read_value != expected_value or test_address == 0x00100000):
|
||||||
|
raise SC64Exception(f'SDRAM test error at 0x{test_address:08X}: read 0x{read_value:08X} != expected 0x{expected_value:08X}')
|
||||||
|
self.__progress(self.SDRAM_SIZE, offset + CHUNK_LENGTH, check_description)
|
||||||
|
|
||||||
|
|
||||||
class SC64BringUp:
|
class SC64BringUp:
|
||||||
@ -621,7 +698,7 @@ class SC64BringUp:
|
|||||||
|
|
||||||
def start_bring_up(self, port: str, bootloader_only: bool=False) -> None:
|
def start_bring_up(self, port: str, bootloader_only: bool=False) -> None:
|
||||||
link = None
|
link = None
|
||||||
sc64 = SC64()
|
sc64 = SC64(self.__progress)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if (not bootloader_only):
|
if (not bootloader_only):
|
||||||
@ -651,11 +728,8 @@ class SC64BringUp:
|
|||||||
time.sleep(self.__INTERVAL_TIME)
|
time.sleep(self.__INTERVAL_TIME)
|
||||||
link.read_all()
|
link.read_all()
|
||||||
|
|
||||||
bootloader_description = 'Bootloader -> SC64 FLASH (no progress reporting)'
|
sc64.sdram_test('SC64 SDRAM test')
|
||||||
bootloader_length = len(self.__bootloader_only_firmware)
|
sc64.update_firmware(self.__bootloader_only_firmware, 'Bootloader -> SC64 FLASH')
|
||||||
self.__progress(bootloader_length, 0, bootloader_description)
|
|
||||||
sc64.update_firmware(self.__bootloader_only_firmware)
|
|
||||||
self.__progress(bootloader_length, bootloader_length, bootloader_description)
|
|
||||||
finally:
|
finally:
|
||||||
if (link and link.is_open):
|
if (link and link.is_open):
|
||||||
link.close()
|
link.close()
|
||||||
|
Loading…
Reference in New Issue
Block a user