[SC64][SW] Added SD card FatFs tests, rearranged SDRAM tests

This commit is contained in:
Mateusz Faderewski 2024-05-12 02:45:56 +02:00
parent a884d69308
commit 92838da349
5 changed files with 259 additions and 137 deletions

View File

@ -15,7 +15,7 @@
/ and optional writing functions as well. */
#define FF_FS_MINIMIZE 2
#define FF_FS_MINIMIZE 0
/* This option defines minimization level to remove some basic API functions.
/
/ 0: Basic functions are fully enabled.
@ -47,7 +47,7 @@
/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */
#define FF_USE_LABEL 0
#define FF_USE_LABEL 1
/* This option switches volume label functions, f_getlabel() and f_setlabel().
/ (0:Disable or 1:Enable) */

View File

@ -2,15 +2,19 @@
#include <stdlib.h>
#include "display.h"
#include "error.h"
#include "fatfs/ff.h"
#include "init.h"
#include "io.h"
#include "sc64.h"
#include "test.h"
#define TEST_BUFFER_SIZE (128 * 1024)
#define SD_TEST_FILE_SIZE (16 * 1024 * 1024)
#define SDRAM_ADDRESS (0x10000000)
#define SDRAM_SIZE (64 * 1024 * 1024)
#define SDRAM_BUFFER_SIZE (128 * 1024)
typedef struct {
@ -23,8 +27,8 @@ typedef struct {
static uint32_t random_seed = 0;
static uint32_t w_buffer[SDRAM_BUFFER_SIZE / sizeof(uint32_t)] __attribute__((aligned(8)));
static uint32_t r_buffer[SDRAM_BUFFER_SIZE / sizeof(uint32_t)] __attribute__((aligned(8)));
static uint32_t w_buffer[TEST_BUFFER_SIZE / sizeof(uint32_t)] __attribute__((aligned(8)));
static uint32_t r_buffer[TEST_BUFFER_SIZE / sizeof(uint32_t)] __attribute__((aligned(8)));
static void fill_own_address (uint32_t *buffer, int size, uint32_t pattern, uint32_t offset) {
@ -67,17 +71,14 @@ static void test_sc64_cfg (void) {
if ((error = sc64_get_identifier(&identifier)) != SC64_OK) {
error_display("Command IDENTIFIER_GET failed: %d", error);
return;
}
if ((error = sc64_get_version(&major, &minor, &revision)) != SC64_OK) {
error_display("Command VERSION_GET failed: %d", error);
return;
}
if ((error = sc64_get_diagnostic(DIAGNOSTIC_ID_VOLTAGE_TEMPERATURE, &tmp)) != SC64_OK) {
error_display("Command DIAGNOSTIC_GET failed: %d", error);
return;
}
uint16_t voltage = (uint16_t) (tmp >> 16);
@ -154,7 +155,7 @@ static void test_pi (void) {
display_printf("\n");
}
static void test_sd_card (void) {
static void test_sd_card_io (void) {
sc64_error_t error;
sc64_sd_card_status_t card_status;
uint8_t card_info[32] __attribute__((aligned(8)));
@ -170,9 +171,12 @@ static void test_sd_card (void) {
display_printf("SD card is not inserted\n");
}
if ((error = sc64_sd_card_deinit()) != SC64_OK) {
return display_printf("SD card deinit error: %d", error);
}
if ((error = sc64_sd_card_init()) != SC64_OK) {
display_printf("SD card init error: %d\n", error);
return;
return display_printf("SD card init error: %d\n", error);
}
if ((error = sc64_sd_card_get_status(&card_status)) != SC64_OK) {
@ -193,8 +197,7 @@ static void test_sd_card (void) {
}
if ((error = sc64_sd_card_get_info((uint32_t *) (SC64_BUFFERS->BUFFER))) != SC64_OK) {
display_printf("SD card get info error: %d\n", error);
return;
return display_printf("SD card get info error: %d\n", error);
}
pi_dma_read((io32_t *) (SC64_BUFFERS->BUFFER), card_info, sizeof(card_info));
@ -214,8 +217,7 @@ static void test_sd_card (void) {
display_printf("\n");
if ((error = sc64_sd_read_sectors((void *) (SC64_BUFFERS->BUFFER), 0, 1)) != SC64_OK) {
display_printf("SD card read sector 0 error: %d\n", error);
return;
return display_printf("SD card read sector 0 error: %d\n", error);
}
pi_dma_read((io32_t *) (SC64_BUFFERS->BUFFER), sector, sizeof(sector));
@ -232,6 +234,128 @@ static void test_sd_card (void) {
display_printf(" Boot signature: 0x%02X%02X\n", sector[510], sector[511]);
}
static void test_sd_card_fatfs (void) {
sc64_error_t error;
FRESULT fresult;
FATFS fs;
TCHAR label[23];
DWORD vsn;
FIL fil;
UINT left;
UINT bytes;
if ((error = sc64_sd_card_deinit()) != SC64_OK) {
return display_printf("SD card deinit error: %d", error);
}
if ((fresult = f_mount(&fs, "", 1)) != FR_OK) {
return display_printf("f_mount error: %d\n", fresult);
}
if ((fresult = f_getlabel("", label, &vsn)) != FR_OK) {
return display_printf("f_getlabel error: %d\n", fresult);
}
display_printf("Volume [%s] / [%08lX]\n\n", label, vsn);
if ((fresult = f_open(&fil, "sc64test.bin", FA_CREATE_ALWAYS | FA_WRITE)) != FR_OK) {
return display_printf("f_open (write) error: %d\n", fresult);
}
srand(random_seed);
left = SD_TEST_FILE_SIZE;
while (left) {
if ((left % (SD_TEST_FILE_SIZE / 64)) == 0) {
display_printf("w");
}
UINT block_size = (left > TEST_BUFFER_SIZE) ? TEST_BUFFER_SIZE : left;
fill_random(w_buffer, block_size, 0, 0);
if ((fresult = f_write(&fil, w_buffer, block_size, &bytes)) != FR_OK) {
return display_printf("\nf_write error: %d\n", fresult);
}
if (bytes != block_size) {
return display_printf("\nf_write (%ld!=%ld) error: %d\n", bytes, block_size, fresult);
}
left -= block_size;
}
display_printf("\n");
if ((fresult = f_close(&fil)) != FR_OK) {
return display_printf("f_close (write) error: %d\n", fresult);
}
if ((fresult = f_open(&fil, "sc64test.bin", FA_OPEN_EXISTING | FA_READ)) != FR_OK) {
return display_printf("f_open (read) error: %d\n", fresult);
}
if (f_size(&fil) != SD_TEST_FILE_SIZE) {
return display_printf("f_size (%d!=%d) error\n", f_size(&fil), SD_TEST_FILE_SIZE);
}
srand(random_seed);
left = SD_TEST_FILE_SIZE;
while (left) {
if ((left % (SD_TEST_FILE_SIZE / 64)) == 0) {
display_printf("r");
}
UINT block_size = (left > TEST_BUFFER_SIZE) ? TEST_BUFFER_SIZE : left;
fill_random(w_buffer, block_size, 0, 0);
if ((fresult = f_read(&fil, r_buffer, block_size, &bytes)) != FR_OK) {
return display_printf("\nf_read error: %d\n", fresult);
}
if (bytes != block_size) {
return display_printf("\nf_read (%ld!=%ld) error: %d\n", bytes, block_size, fresult);
}
for (UINT i = 0; i < (block_size / sizeof(uint32_t)); i++) {
if (w_buffer[i] != r_buffer[i]) {
display_printf(
"\n"
" > Mismatch error at file offset 0x%08lX\n"
" > 0x%08lX (W) != 0x%08lX (R)",
f_tell(&fil) + (i * sizeof(uint32_t)),
w_buffer[i],
r_buffer[i]
);
while (true);
}
}
left -= block_size;
}
display_printf("\n");
if ((fresult = f_close(&fil)) != FR_OK) {
return display_printf("f_close (read) error: %d\n", fresult);
}
if ((fresult = f_unlink("sc64test.bin")) != FR_OK) {
return display_printf("f_unlink error: %d\n", fresult);
}
if ((fresult = f_unmount("")) != FR_OK) {
return display_printf("f_unmount error: %d\n", fresult);
}
random_seed += c0_count();
}
static void test_sdram (void) {
static int phase = 0;
@ -239,11 +363,11 @@ static void test_sdram (void) {
{ .name = "Own address: ", .fill = fill_own_address, .pattern = 0x00000000, .fade = 0 },
{ .name = "All zeros: ", .fill = fill_pattern, .pattern = 0x00000000, .fade = 0 },
{ .name = "All ones: ", .fill = fill_pattern, .pattern = 0xFFFFFFFF, .fade = 0 },
{ .name = "0xAAAA5555: ", .fill = fill_pattern, .pattern = 0xAAAA5555, .fade = 0 },
{ .name = "0x5555AAAA: ", .fill = fill_pattern, .pattern = 0x5555AAAA, .fade = 0 },
{ .name = "Random (1/3): ", .fill = fill_random, .pattern = 0x00000000, .fade = 0 },
{ .name = "Random (2/3): ", .fill = fill_random, .pattern = 0x00000000, .fade = 0 },
{ .name = "Random (3/3): ", .fill = fill_random, .pattern = 0x00000000, .fade = 0 },
{ .name = "Fadeout S (0):", .fill = fill_pattern, .pattern = 0x00000000, .fade = 60 },
{ .name = "Fadeout S (1):", .fill = fill_pattern, .pattern = 0xFFFFFFFF, .fade = 60 },
{ .name = NULL },
};
@ -296,8 +420,8 @@ static void test_sdram (void) {
};
sdram_test_t phase_5_tests[] = {
{ .name = "Fadeout L (0):", .fill = fill_pattern, .pattern = 0x00000000, .fade = 300 },
{ .name = "Fadeout L (1):", .fill = fill_pattern, .pattern = 0xFFFFFFFF, .fade = 300 },
{ .name = "Fadeout (0): ", .fill = fill_pattern, .pattern = 0x00000000, .fade = 60 },
{ .name = "Fadeout (1): ", .fill = fill_pattern, .pattern = 0xFFFFFFFF, .fade = 60 },
{ .name = NULL },
};
@ -317,14 +441,14 @@ static void test_sdram (void) {
srand(random_seed);
for (int offset = 0; offset < SDRAM_SIZE; offset += SDRAM_BUFFER_SIZE) {
for (int offset = 0; offset < SDRAM_SIZE; offset += TEST_BUFFER_SIZE) {
if ((offset % (SDRAM_SIZE / 16)) == 0) {
display_printf("w");
}
test->fill(w_buffer, SDRAM_BUFFER_SIZE, test->pattern, offset);
test->fill(w_buffer, TEST_BUFFER_SIZE, test->pattern, offset);
pi_dma_write((io32_t *) (SDRAM_ADDRESS + offset), w_buffer, SDRAM_BUFFER_SIZE);
pi_dma_write((io32_t *) (SDRAM_ADDRESS + offset), w_buffer, TEST_BUFFER_SIZE);
}
for (int fade = test->fade; fade > 0; fade--) {
@ -335,19 +459,19 @@ static void test_sdram (void) {
srand(random_seed);
for (int offset = 0; offset < SDRAM_SIZE; offset += SDRAM_BUFFER_SIZE) {
for (int offset = 0; offset < SDRAM_SIZE; offset += TEST_BUFFER_SIZE) {
if ((offset % (SDRAM_SIZE / 16)) == 0) {
display_printf("r");
}
test->fill(w_buffer, SDRAM_BUFFER_SIZE, test->pattern, offset);
test->fill(w_buffer, TEST_BUFFER_SIZE, test->pattern, offset);
pi_dma_read((io32_t *) (SDRAM_ADDRESS + offset), r_buffer, SDRAM_BUFFER_SIZE);
pi_dma_read((io32_t *) (SDRAM_ADDRESS + offset), r_buffer, TEST_BUFFER_SIZE);
uint64_t *test_data = (uint64_t *) (w_buffer);
uint64_t *check_data = (uint64_t *) (r_buffer);
for (int i = 0; i < SDRAM_BUFFER_SIZE / sizeof(uint64_t); i++) {
for (int i = 0; i < TEST_BUFFER_SIZE / sizeof(uint64_t); i++) {
if (test_data[i] != check_data[i]) {
display_printf(
"\n"
@ -399,7 +523,8 @@ static struct {
} tests[] = {
{ "SC64 CFG", test_sc64_cfg },
{ "PI", test_pi },
{ "SD card", test_sd_card },
{ "SD card (I/O)", test_sd_card_io },
{ "SD card (FatFs)", test_sd_card_fatfs },
{ "SDRAM (1/6)", test_sdram },
{ "SDRAM (2/6)", test_sdram },
{ "SDRAM (3/6)", test_sdram },
@ -415,12 +540,10 @@ void test_execute (void) {
if ((error = sc64_set_config(CFG_ID_ROM_WRITE_ENABLE, true))) {
error_display("Command CONFIG_SET [ROM_WRITE_ENABLE] failed: %d", error);
return;
}
if ((error = sc64_set_config(CFG_ID_ROM_SHADOW_ENABLE, false))) {
error_display("Command CONFIG_SET [ROM_SHADOW_ENABLE] failed: %d", error);
return;
}
random_seed = __entropy + c0_count();

View File

@ -884,69 +884,68 @@ 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());
println!("{}: SDRAM (pattern)", "[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_pattern_tests = [
(sc64::MemoryTestPattern::OwnAddress, None),
(sc64::MemoryTestPattern::AllZeros, None),
(sc64::MemoryTestPattern::AllOnes, None),
(sc64::MemoryTestPattern::Custom(0xAAAA5555), None),
(sc64::MemoryTestPattern::Custom(0x5555AAAA), None),
(sc64::MemoryTestPattern::Random, None),
(sc64::MemoryTestPattern::Random, None),
(sc64::MemoryTestPattern::Custom(0x00010001), None),
(sc64::MemoryTestPattern::Custom(0xFFFEFFFE), None),
(sc64::MemoryTestPattern::Custom(0x00020002), None),
(sc64::MemoryTestPattern::Custom(0xFFFDFFFD), None),
(sc64::MemoryTestPattern::Custom(0x00040004), None),
(sc64::MemoryTestPattern::Custom(0xFFFBFFFB), None),
(sc64::MemoryTestPattern::Custom(0x00080008), None),
(sc64::MemoryTestPattern::Custom(0xFFF7FFF7), None),
(sc64::MemoryTestPattern::Custom(0x00100010), None),
(sc64::MemoryTestPattern::Custom(0xFFEFFFEF), None),
(sc64::MemoryTestPattern::Custom(0x00200020), None),
(sc64::MemoryTestPattern::Custom(0xFFDFFFDF), None),
(sc64::MemoryTestPattern::Custom(0x00400040), None),
(sc64::MemoryTestPattern::Custom(0xFFBFFFBF), None),
(sc64::MemoryTestPattern::Custom(0x00800080), None),
(sc64::MemoryTestPattern::Custom(0xFF7FFF7F), None),
(sc64::MemoryTestPattern::Custom(0x01000100), None),
(sc64::MemoryTestPattern::Custom(0xFEFFFEFF), None),
(sc64::MemoryTestPattern::Custom(0x02000200), None),
(sc64::MemoryTestPattern::Custom(0xFDFFFDFF), None),
(sc64::MemoryTestPattern::Custom(0x04000400), None),
(sc64::MemoryTestPattern::Custom(0xFBFFFBFF), None),
(sc64::MemoryTestPattern::Custom(0x08000800), None),
(sc64::MemoryTestPattern::Custom(0xF7FFF7FF), None),
(sc64::MemoryTestPattern::Custom(0x10001000), None),
(sc64::MemoryTestPattern::Custom(0xEFFFEFFF), None),
(sc64::MemoryTestPattern::Custom(0x20002000), None),
(sc64::MemoryTestPattern::Custom(0xDFFFDFFF), None),
(sc64::MemoryTestPattern::Custom(0x40004000), None),
(sc64::MemoryTestPattern::Custom(0xBFFFBFFF), None),
(sc64::MemoryTestPattern::Custom(0x80008000), None),
(sc64::MemoryTestPattern::Custom(0x7FFF7FFF), None),
(sc64::MemoryTestPattern::AllZeros, Some(60)),
(sc64::MemoryTestPattern::AllOnes, Some(60)),
];
let sdram_tests_count = sdram_tests.len();
let sdram_pattern_tests_count = sdram_pattern_tests.len();
let mut sdram_tests_failed = false;
for (i, (test_type, fade)) in sdram_tests.into_iter().enumerate() {
for (i, (pattern, fade)) in sdram_pattern_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}... ",
" ({} / {sdram_pattern_tests_count}) Testing {pattern}{fadeout_text}... ",
i + 1
);
stdout().flush().unwrap();
let result = sc64.test_sdram(test_type, fade)?;
let result = sc64.test_sdram_pattern(pattern, fade)?;
if let Some((address, (written, read))) = result.first_error {
sdram_tests_failed = true;

View File

@ -12,8 +12,8 @@ pub use self::{
server::ServerEvent,
types::{
BootMode, ButtonMode, ButtonState, CicSeed, DataPacket, DdDiskState, DdDriveType, DdMode,
DebugPacket, DiagnosticData, DiskPacket, DiskPacketKind, FpgaDebugData, MemoryTestResult,
MemoryTestType, SaveType, SaveWriteback, Switch, TvType,
DebugPacket, DiagnosticData, DiskPacket, DiskPacketKind, FpgaDebugData, MemoryTestPattern,
MemoryTestPatternResult, SaveType, SaveWriteback, Switch, TvType,
},
};
@ -750,24 +750,24 @@ impl SC64 {
}
}
pub fn test_sdram(
pub fn test_sdram_pattern(
&mut self,
test_type: MemoryTestType,
pattern: MemoryTestPattern,
fade: Option<u64>,
) -> Result<MemoryTestResult, Error> {
) -> Result<MemoryTestPatternResult, Error> {
let item_size = std::mem::size_of::<u32>();
let mut test_data = vec![0u32; SDRAM_LENGTH / item_size];
match test_type {
MemoryTestType::OwnAddress => {
match pattern {
MemoryTestPattern::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[..]),
MemoryTestPattern::AllZeros => test_data.fill(0x00000000u32),
MemoryTestPattern::AllOnes => test_data.fill(0xFFFFFFFFu32),
MemoryTestPattern::Custom(pattern) => test_data.fill(pattern),
MemoryTestPattern::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();
@ -799,7 +799,7 @@ impl SC64 {
None
};
return Ok(MemoryTestResult {
return Ok(MemoryTestPatternResult {
first_error,
all_errors,
});

View File

@ -983,27 +983,27 @@ impl Display for DiagnosticData {
}
}
pub enum MemoryTestType {
pub enum MemoryTestPattern {
OwnAddress,
AllZeros,
AllOnes,
Pattern(u32),
Random,
Custom(u32),
}
pub struct MemoryTestResult {
pub struct MemoryTestPatternResult {
pub first_error: Option<(usize, (u32, u32))>,
pub all_errors: Vec<(usize, (u32, u32))>,
}
impl Display for MemoryTestType {
impl Display for MemoryTestPattern {
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) => {
MemoryTestPattern::OwnAddress => f.write_str("Own address"),
MemoryTestPattern::AllZeros => f.write_str("All zeros"),
MemoryTestPattern::AllOnes => f.write_str("All ones"),
MemoryTestPattern::Random => f.write_str("Random"),
MemoryTestPattern::Custom(pattern) => {
f.write_fmt(format_args!("Pattern 0x{pattern:08X}"))
}
}