mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-12-24 12:01:56 +01:00
[SC64][SW] sc64deployer: added SDRAM tests
This commit is contained in:
parent
a0bd0ddd98
commit
7bc4e6d180
37
sw/deployer/Cargo.lock
generated
37
sw/deployer/Cargo.lock
generated
@ -696,6 +696,12 @@ dependencies = [
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.5.20+deprecated"
|
||||
@ -729,6 +735,36 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.9.0"
|
||||
@ -810,6 +846,7 @@ dependencies = [
|
||||
"include-flate",
|
||||
"md5",
|
||||
"panic-message",
|
||||
"rand",
|
||||
"rust-ini",
|
||||
"serial2",
|
||||
"serialport",
|
||||
|
@ -19,6 +19,7 @@ image = "0.24.5"
|
||||
include-flate = { version = "0.2.0", features = ["stable"] }
|
||||
md5 = "0.7.0"
|
||||
panic-message = "0.3.0"
|
||||
rand = "0.8.5"
|
||||
rust-ini = "0.18.0"
|
||||
serial2 = "0.2.20"
|
||||
serialport = "4.3.0"
|
||||
|
@ -75,6 +75,9 @@ enum Commands {
|
||||
command: FirmwareCommands,
|
||||
},
|
||||
|
||||
/// Test SC64 hardware
|
||||
Test,
|
||||
|
||||
/// Expose SC64 device over network
|
||||
Server(ServerArgs),
|
||||
}
|
||||
@ -333,6 +336,7 @@ fn handle_command(command: &Commands, port: Option<String>, remote: Option<Strin
|
||||
Commands::Reset => handle_reset_command(connection),
|
||||
Commands::Set { command } => handle_set_command(connection, command),
|
||||
Commands::Firmware { command } => handle_firmware_command(connection, command),
|
||||
Commands::Test => handle_test_command(connection),
|
||||
Commands::Server(args) => handle_server_command(connection, args),
|
||||
};
|
||||
match result {
|
||||
@ -781,7 +785,7 @@ fn handle_set_command(connection: Connection, command: &SetCommands) -> Result<(
|
||||
sc64.set_datetime(datetime)?;
|
||||
println!(
|
||||
"SC64 RTC datetime synchronized to: {}",
|
||||
datetime.format("%Y-%m-%d %H:%M:%S %Z").to_string().green()
|
||||
datetime.format("%Y-%m-%d %H:%M:%S").to_string().green()
|
||||
);
|
||||
}
|
||||
|
||||
@ -877,6 +881,96 @@ fn handle_firmware_command(
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_test_command(connection: Connection) -> Result<(), sc64::Error> {
|
||||
let mut sc64 = init_sc64(connection, false)?;
|
||||
|
||||
println!("{}: SDRAM", "[SC64 Tests]".bold());
|
||||
|
||||
let sdram_tests = [
|
||||
(sc64::MemoryTestType::OwnAddress, None),
|
||||
(sc64::MemoryTestType::AllZeros, None),
|
||||
(sc64::MemoryTestType::AllOnes, None),
|
||||
(sc64::MemoryTestType::Random, None),
|
||||
(sc64::MemoryTestType::Random, None),
|
||||
(sc64::MemoryTestType::Random, None),
|
||||
(sc64::MemoryTestType::AllZeros, Some(60)),
|
||||
(sc64::MemoryTestType::AllOnes, Some(60)),
|
||||
(sc64::MemoryTestType::Pattern(0x00010001), None),
|
||||
(sc64::MemoryTestType::Pattern(0xFFFEFFFE), None),
|
||||
(sc64::MemoryTestType::Pattern(0x00020002), None),
|
||||
(sc64::MemoryTestType::Pattern(0xFFFDFFFD), None),
|
||||
(sc64::MemoryTestType::Pattern(0x00040004), None),
|
||||
(sc64::MemoryTestType::Pattern(0xFFFBFFFB), None),
|
||||
(sc64::MemoryTestType::Pattern(0x00080008), None),
|
||||
(sc64::MemoryTestType::Pattern(0xFFF7FFF7), None),
|
||||
(sc64::MemoryTestType::Pattern(0x00100010), None),
|
||||
(sc64::MemoryTestType::Pattern(0xFFEFFFEF), None),
|
||||
(sc64::MemoryTestType::Pattern(0x00200020), None),
|
||||
(sc64::MemoryTestType::Pattern(0xFFDFFFDF), None),
|
||||
(sc64::MemoryTestType::Pattern(0x00400040), None),
|
||||
(sc64::MemoryTestType::Pattern(0xFFBFFFBF), None),
|
||||
(sc64::MemoryTestType::Pattern(0x00800080), None),
|
||||
(sc64::MemoryTestType::Pattern(0xFF7FFF7F), None),
|
||||
(sc64::MemoryTestType::Pattern(0x01000100), None),
|
||||
(sc64::MemoryTestType::Pattern(0xFEFFFEFF), None),
|
||||
(sc64::MemoryTestType::Pattern(0x02000200), None),
|
||||
(sc64::MemoryTestType::Pattern(0xFDFFFDFF), None),
|
||||
(sc64::MemoryTestType::Pattern(0x04000400), None),
|
||||
(sc64::MemoryTestType::Pattern(0xFBFFFBFF), None),
|
||||
(sc64::MemoryTestType::Pattern(0x08000800), None),
|
||||
(sc64::MemoryTestType::Pattern(0xF7FFF7FF), None),
|
||||
(sc64::MemoryTestType::Pattern(0x10001000), None),
|
||||
(sc64::MemoryTestType::Pattern(0xEFFFEFFF), None),
|
||||
(sc64::MemoryTestType::Pattern(0x20002000), None),
|
||||
(sc64::MemoryTestType::Pattern(0xDFFFDFFF), None),
|
||||
(sc64::MemoryTestType::Pattern(0x40004000), None),
|
||||
(sc64::MemoryTestType::Pattern(0xBFFFBFFF), None),
|
||||
(sc64::MemoryTestType::Pattern(0x80008000), None),
|
||||
(sc64::MemoryTestType::Pattern(0x7FFF7FFF), None),
|
||||
(sc64::MemoryTestType::AllZeros, Some(300)),
|
||||
(sc64::MemoryTestType::AllOnes, Some(300)),
|
||||
];
|
||||
let sdram_tests_count = sdram_tests.len();
|
||||
|
||||
let mut sdram_tests_failed = false;
|
||||
|
||||
for (i, (test_type, fade)) in sdram_tests.into_iter().enumerate() {
|
||||
let fadeout_text = if let Some(fade) = fade {
|
||||
format!(", fadeout {fade} seconds")
|
||||
} else {
|
||||
"".to_string()
|
||||
};
|
||||
print!(
|
||||
" ({} / {sdram_tests_count}) Testing {test_type}{fadeout_text}... ",
|
||||
i + 1
|
||||
);
|
||||
stdout().flush().unwrap();
|
||||
|
||||
let result = sc64.test_sdram(test_type, fade)?;
|
||||
|
||||
if let Some((address, (written, read))) = result.first_error {
|
||||
sdram_tests_failed = true;
|
||||
println!("{}", "error!".bright_red());
|
||||
println!(" Found a mismatch at address 0x{address:08X}",);
|
||||
println!(" 0x{written:08X} (W) != 0x{read:08X} (R)");
|
||||
println!(" Total errors found: {}", result.all_errors.len());
|
||||
} else {
|
||||
println!("{}", "ok".bright_green());
|
||||
}
|
||||
}
|
||||
|
||||
if sdram_tests_failed {
|
||||
println!(
|
||||
"{}",
|
||||
"Some SDRAM tests failed, SDRAM chip might be defective".bright_red()
|
||||
);
|
||||
} else {
|
||||
println!("{}", "All SDRAM tests passed without error".bright_green());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_server_command(connection: Connection, args: &ServerArgs) -> Result<(), sc64::Error> {
|
||||
let port = if let Connection::Local(port) = connection {
|
||||
port
|
||||
|
@ -12,8 +12,8 @@ pub use self::{
|
||||
server::ServerEvent,
|
||||
types::{
|
||||
BootMode, ButtonMode, ButtonState, CicSeed, DataPacket, DdDiskState, DdDriveType, DdMode,
|
||||
DebugPacket, DiagnosticData, DiskPacket, DiskPacketKind, FpgaDebugData, SaveType,
|
||||
SaveWriteback, Switch, TvType,
|
||||
DebugPacket, DiagnosticData, DiskPacket, DiskPacketKind, FpgaDebugData, MemoryTestResult,
|
||||
MemoryTestType, SaveType, SaveWriteback, Switch, TvType,
|
||||
},
|
||||
};
|
||||
|
||||
@ -26,10 +26,12 @@ use self::{
|
||||
},
|
||||
};
|
||||
use chrono::{DateTime, Local};
|
||||
use rand::Rng;
|
||||
use std::{
|
||||
cmp::min,
|
||||
io::{Read, Seek, Write},
|
||||
time::Instant,
|
||||
{cmp::min, time::Duration},
|
||||
thread::sleep,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
pub struct SC64 {
|
||||
@ -748,6 +750,58 @@ impl SC64 {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn test_sdram(
|
||||
&mut self,
|
||||
test_type: MemoryTestType,
|
||||
fade: Option<u64>,
|
||||
) -> Result<MemoryTestResult, Error> {
|
||||
let item_size = std::mem::size_of::<u32>();
|
||||
let mut test_data = vec![0u32; SDRAM_LENGTH / item_size];
|
||||
|
||||
match test_type {
|
||||
MemoryTestType::OwnAddress => {
|
||||
for (index, item) in test_data.iter_mut().enumerate() {
|
||||
*item = (index * item_size) as u32;
|
||||
}
|
||||
}
|
||||
MemoryTestType::AllZeros => test_data.fill(0x00000000u32),
|
||||
MemoryTestType::AllOnes => test_data.fill(0xFFFFFFFFu32),
|
||||
MemoryTestType::Pattern(pattern) => test_data.fill(pattern),
|
||||
MemoryTestType::Random => rand::thread_rng().fill(&mut test_data[..]),
|
||||
};
|
||||
|
||||
let raw_test_data: Vec<u8> = test_data.iter().flat_map(|v| v.to_be_bytes()).collect();
|
||||
self.command_memory_write(SDRAM_ADDRESS, &raw_test_data)?;
|
||||
|
||||
if let Some(fade) = fade {
|
||||
sleep(Duration::from_secs(fade));
|
||||
}
|
||||
|
||||
let raw_check_data = self.command_memory_read(SDRAM_ADDRESS, SDRAM_LENGTH)?;
|
||||
let check_data = raw_check_data
|
||||
.chunks(4)
|
||||
.map(|a| u32::from_be_bytes(a[0..4].try_into().unwrap()));
|
||||
|
||||
let all_errors: Vec<(usize, (u32, u32))> = test_data
|
||||
.into_iter()
|
||||
.zip(check_data)
|
||||
.enumerate()
|
||||
.filter(|(_, (a, b))| a != b)
|
||||
.map(|(i, (a, b))| (i * item_size, (a, b)))
|
||||
.collect();
|
||||
|
||||
let first_error = if all_errors.len() > 0 {
|
||||
Some(all_errors.get(0).copied().unwrap())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
return Ok(MemoryTestResult {
|
||||
first_error,
|
||||
all_errors,
|
||||
});
|
||||
}
|
||||
|
||||
fn memory_read_chunked(
|
||||
&mut self,
|
||||
writer: &mut dyn Write,
|
||||
|
@ -983,6 +983,33 @@ impl Display for DiagnosticData {
|
||||
}
|
||||
}
|
||||
|
||||
pub enum MemoryTestType {
|
||||
OwnAddress,
|
||||
AllZeros,
|
||||
AllOnes,
|
||||
Pattern(u32),
|
||||
Random,
|
||||
}
|
||||
|
||||
pub struct MemoryTestResult {
|
||||
pub first_error: Option<(usize, (u32, u32))>,
|
||||
pub all_errors: Vec<(usize, (u32, u32))>,
|
||||
}
|
||||
|
||||
impl Display for MemoryTestType {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
MemoryTestType::OwnAddress => f.write_str("Own address"),
|
||||
MemoryTestType::AllZeros => f.write_str("All zeros"),
|
||||
MemoryTestType::AllOnes => f.write_str("All ones"),
|
||||
MemoryTestType::Random => f.write_str("Random"),
|
||||
MemoryTestType::Pattern(pattern) => {
|
||||
f.write_fmt(format_args!("Pattern 0x{pattern:08X}"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! get_config {
|
||||
($sc64:ident, $config:ident) => {{
|
||||
if let Config::$config(value) = $sc64.command_config_get(ConfigId::$config)? {
|
||||
|
Loading…
Reference in New Issue
Block a user