[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. */ / 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. /* This option defines minimization level to remove some basic API functions.
/ /
/ 0: Basic functions are fully enabled. / 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. */ / (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(). /* This option switches volume label functions, f_getlabel() and f_setlabel().
/ (0:Disable or 1:Enable) */ / (0:Disable or 1:Enable) */

View File

@ -2,15 +2,19 @@
#include <stdlib.h> #include <stdlib.h>
#include "display.h" #include "display.h"
#include "error.h" #include "error.h"
#include "fatfs/ff.h"
#include "init.h" #include "init.h"
#include "io.h" #include "io.h"
#include "sc64.h" #include "sc64.h"
#include "test.h" #include "test.h"
#define TEST_BUFFER_SIZE (128 * 1024)
#define SD_TEST_FILE_SIZE (16 * 1024 * 1024)
#define SDRAM_ADDRESS (0x10000000) #define SDRAM_ADDRESS (0x10000000)
#define SDRAM_SIZE (64 * 1024 * 1024) #define SDRAM_SIZE (64 * 1024 * 1024)
#define SDRAM_BUFFER_SIZE (128 * 1024)
typedef struct { typedef struct {
@ -23,8 +27,8 @@ typedef struct {
static uint32_t random_seed = 0; static uint32_t random_seed = 0;
static uint32_t w_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[SDRAM_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) { 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) { if ((error = sc64_get_identifier(&identifier)) != SC64_OK) {
error_display("Command IDENTIFIER_GET failed: %d", error); error_display("Command IDENTIFIER_GET failed: %d", error);
return;
} }
if ((error = sc64_get_version(&major, &minor, &revision)) != SC64_OK) { if ((error = sc64_get_version(&major, &minor, &revision)) != SC64_OK) {
error_display("Command VERSION_GET failed: %d", error); error_display("Command VERSION_GET failed: %d", error);
return;
} }
if ((error = sc64_get_diagnostic(DIAGNOSTIC_ID_VOLTAGE_TEMPERATURE, &tmp)) != SC64_OK) { if ((error = sc64_get_diagnostic(DIAGNOSTIC_ID_VOLTAGE_TEMPERATURE, &tmp)) != SC64_OK) {
error_display("Command DIAGNOSTIC_GET failed: %d", error); error_display("Command DIAGNOSTIC_GET failed: %d", error);
return;
} }
uint16_t voltage = (uint16_t) (tmp >> 16); uint16_t voltage = (uint16_t) (tmp >> 16);
@ -88,7 +89,7 @@ static void test_sc64_cfg (void) {
display_printf("Voltage: %d.%03d V\n", (voltage / 1000), (voltage % 1000)); display_printf("Voltage: %d.%03d V\n", (voltage / 1000), (voltage % 1000));
display_printf("Temperature: %d.%01d `C\n\n", (temperature / 10), (temperature % 10)); display_printf("Temperature: %d.%01d `C\n\n", (temperature / 10), (temperature % 10));
const char *weekdays[8] = { const char *weekdays[8] = {
"Unknown day", "Unknown day",
"Monday", "Monday",
@ -154,7 +155,7 @@ static void test_pi (void) {
display_printf("\n"); display_printf("\n");
} }
static void test_sd_card (void) { static void test_sd_card_io (void) {
sc64_error_t error; sc64_error_t error;
sc64_sd_card_status_t card_status; sc64_sd_card_status_t card_status;
uint8_t card_info[32] __attribute__((aligned(8))); 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"); 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) { if ((error = sc64_sd_card_init()) != SC64_OK) {
display_printf("SD card init error: %d\n", error); return display_printf("SD card init error: %d\n", error);
return;
} }
if ((error = sc64_sd_card_get_status(&card_status)) != SC64_OK) { 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) { 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 display_printf("SD card get info error: %d\n", error);
return;
} }
pi_dma_read((io32_t *) (SC64_BUFFERS->BUFFER), card_info, sizeof(card_info)); 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"); display_printf("\n");
if ((error = sc64_sd_read_sectors((void *) (SC64_BUFFERS->BUFFER), 0, 1)) != SC64_OK) { 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 display_printf("SD card read sector 0 error: %d\n", error);
return;
} }
pi_dma_read((io32_t *) (SC64_BUFFERS->BUFFER), sector, sizeof(sector)); pi_dma_read((io32_t *) (SC64_BUFFERS->BUFFER), sector, sizeof(sector));
@ -232,72 +234,194 @@ static void test_sd_card (void) {
display_printf(" Boot signature: 0x%02X%02X\n", sector[510], sector[511]); 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 void test_sdram (void) {
static int phase = 0; static int phase = 0;
sdram_test_t phase_0_tests[] = { sdram_test_t phase_0_tests[] = {
{ .name = "Own address: ", .fill = fill_own_address, .pattern = 0x00000000, .fade = 0 }, { .name = "Own address: ", .fill = fill_own_address, .pattern = 0x00000000, .fade = 0 },
{ .name = "All zeros: ", .fill = fill_pattern, .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 = "All ones: ", .fill = fill_pattern, .pattern = 0xFFFFFFFF, .fade = 0 },
{ .name = "Random (1/3): ", .fill = fill_random, .pattern = 0x00000000, .fade = 0 }, { .name = "0xAAAA5555: ", .fill = fill_pattern, .pattern = 0xAAAA5555, .fade = 0 },
{ .name = "Random (2/3): ", .fill = fill_random, .pattern = 0x00000000, .fade = 0 }, { .name = "0x5555AAAA: ", .fill = fill_pattern, .pattern = 0x5555AAAA, .fade = 0 },
{ .name = "Random (3/3): ", .fill = fill_random, .pattern = 0x00000000, .fade = 0 }, { .name = "Random (1/3): ", .fill = fill_random, .pattern = 0x00000000, .fade = 0 },
{ .name = "Fadeout S (0):", .fill = fill_pattern, .pattern = 0x00000000, .fade = 60 }, { .name = "Random (2/3): ", .fill = fill_random, .pattern = 0x00000000, .fade = 0 },
{ .name = "Fadeout S (1):", .fill = fill_pattern, .pattern = 0xFFFFFFFF, .fade = 60 }, { .name = "Random (3/3): ", .fill = fill_random, .pattern = 0x00000000, .fade = 0 },
{ .name = NULL }, { .name = NULL },
}; };
sdram_test_t phase_1_tests[] = { sdram_test_t phase_1_tests[] = {
{ .name = "0x00010001: ", .fill = fill_pattern, .pattern = 0x00010001, .fade = 0 }, { .name = "0x00010001: ", .fill = fill_pattern, .pattern = 0x00010001, .fade = 0 },
{ .name = "0xFFFEFFFE: ", .fill = fill_pattern, .pattern = 0xFFFEFFFE, .fade = 0 }, { .name = "0xFFFEFFFE: ", .fill = fill_pattern, .pattern = 0xFFFEFFFE, .fade = 0 },
{ .name = "0x00020002: ", .fill = fill_pattern, .pattern = 0x00020002, .fade = 0 }, { .name = "0x00020002: ", .fill = fill_pattern, .pattern = 0x00020002, .fade = 0 },
{ .name = "0xFFFDFFFD: ", .fill = fill_pattern, .pattern = 0xFFFDFFFD, .fade = 0 }, { .name = "0xFFFDFFFD: ", .fill = fill_pattern, .pattern = 0xFFFDFFFD, .fade = 0 },
{ .name = "0x00040004: ", .fill = fill_pattern, .pattern = 0x00040004, .fade = 0 }, { .name = "0x00040004: ", .fill = fill_pattern, .pattern = 0x00040004, .fade = 0 },
{ .name = "0xFFFBFFFB: ", .fill = fill_pattern, .pattern = 0xFFFBFFFB, .fade = 0 }, { .name = "0xFFFBFFFB: ", .fill = fill_pattern, .pattern = 0xFFFBFFFB, .fade = 0 },
{ .name = "0x00080008: ", .fill = fill_pattern, .pattern = 0x00080008, .fade = 0 }, { .name = "0x00080008: ", .fill = fill_pattern, .pattern = 0x00080008, .fade = 0 },
{ .name = "0xFFF7FFF7: ", .fill = fill_pattern, .pattern = 0xFFF7FFF7, .fade = 0 }, { .name = "0xFFF7FFF7: ", .fill = fill_pattern, .pattern = 0xFFF7FFF7, .fade = 0 },
{ .name = NULL }, { .name = NULL },
}; };
sdram_test_t phase_2_tests[] = { sdram_test_t phase_2_tests[] = {
{ .name = "0x00100010: ", .fill = fill_pattern, .pattern = 0x00100010, .fade = 0 }, { .name = "0x00100010: ", .fill = fill_pattern, .pattern = 0x00100010, .fade = 0 },
{ .name = "0xFFEFFFEF: ", .fill = fill_pattern, .pattern = 0xFFEFFFEF, .fade = 0 }, { .name = "0xFFEFFFEF: ", .fill = fill_pattern, .pattern = 0xFFEFFFEF, .fade = 0 },
{ .name = "0x00200020: ", .fill = fill_pattern, .pattern = 0x00200020, .fade = 0 }, { .name = "0x00200020: ", .fill = fill_pattern, .pattern = 0x00200020, .fade = 0 },
{ .name = "0xFFDFFFDF: ", .fill = fill_pattern, .pattern = 0xFFDFFFDF, .fade = 0 }, { .name = "0xFFDFFFDF: ", .fill = fill_pattern, .pattern = 0xFFDFFFDF, .fade = 0 },
{ .name = "0x00400040: ", .fill = fill_pattern, .pattern = 0x00400040, .fade = 0 }, { .name = "0x00400040: ", .fill = fill_pattern, .pattern = 0x00400040, .fade = 0 },
{ .name = "0xFFBFFFBF: ", .fill = fill_pattern, .pattern = 0xFFBFFFBF, .fade = 0 }, { .name = "0xFFBFFFBF: ", .fill = fill_pattern, .pattern = 0xFFBFFFBF, .fade = 0 },
{ .name = "0x00800080: ", .fill = fill_pattern, .pattern = 0x00800080, .fade = 0 }, { .name = "0x00800080: ", .fill = fill_pattern, .pattern = 0x00800080, .fade = 0 },
{ .name = "0xFF7FFF7F: ", .fill = fill_pattern, .pattern = 0xFF7FFF7F, .fade = 0 }, { .name = "0xFF7FFF7F: ", .fill = fill_pattern, .pattern = 0xFF7FFF7F, .fade = 0 },
{ .name = NULL }, { .name = NULL },
}; };
sdram_test_t phase_3_tests[] = { sdram_test_t phase_3_tests[] = {
{ .name = "0x01000100: ", .fill = fill_pattern, .pattern = 0x01000100, .fade = 0 }, { .name = "0x01000100: ", .fill = fill_pattern, .pattern = 0x01000100, .fade = 0 },
{ .name = "0xFEFFFEFF: ", .fill = fill_pattern, .pattern = 0xFEFFFEFF, .fade = 0 }, { .name = "0xFEFFFEFF: ", .fill = fill_pattern, .pattern = 0xFEFFFEFF, .fade = 0 },
{ .name = "0x02000200: ", .fill = fill_pattern, .pattern = 0x02000200, .fade = 0 }, { .name = "0x02000200: ", .fill = fill_pattern, .pattern = 0x02000200, .fade = 0 },
{ .name = "0xFDFFFDFF: ", .fill = fill_pattern, .pattern = 0xFDFFFDFF, .fade = 0 }, { .name = "0xFDFFFDFF: ", .fill = fill_pattern, .pattern = 0xFDFFFDFF, .fade = 0 },
{ .name = "0x04000400: ", .fill = fill_pattern, .pattern = 0x04000400, .fade = 0 }, { .name = "0x04000400: ", .fill = fill_pattern, .pattern = 0x04000400, .fade = 0 },
{ .name = "0xFBFFFBFF: ", .fill = fill_pattern, .pattern = 0xFBFFFBFF, .fade = 0 }, { .name = "0xFBFFFBFF: ", .fill = fill_pattern, .pattern = 0xFBFFFBFF, .fade = 0 },
{ .name = "0x08000800: ", .fill = fill_pattern, .pattern = 0x08000800, .fade = 0 }, { .name = "0x08000800: ", .fill = fill_pattern, .pattern = 0x08000800, .fade = 0 },
{ .name = "0xF7FFF7FF: ", .fill = fill_pattern, .pattern = 0xF7FFF7FF, .fade = 0 }, { .name = "0xF7FFF7FF: ", .fill = fill_pattern, .pattern = 0xF7FFF7FF, .fade = 0 },
{ .name = NULL }, { .name = NULL },
}; };
sdram_test_t phase_4_tests[] = { sdram_test_t phase_4_tests[] = {
{ .name = "0x10001000: ", .fill = fill_pattern, .pattern = 0x10001000, .fade = 0 }, { .name = "0x10001000: ", .fill = fill_pattern, .pattern = 0x10001000, .fade = 0 },
{ .name = "0xEFFFEFFF: ", .fill = fill_pattern, .pattern = 0xEFFFEFFF, .fade = 0 }, { .name = "0xEFFFEFFF: ", .fill = fill_pattern, .pattern = 0xEFFFEFFF, .fade = 0 },
{ .name = "0x20002000: ", .fill = fill_pattern, .pattern = 0x20002000, .fade = 0 }, { .name = "0x20002000: ", .fill = fill_pattern, .pattern = 0x20002000, .fade = 0 },
{ .name = "0xDFFFDFFF: ", .fill = fill_pattern, .pattern = 0xDFFFDFFF, .fade = 0 }, { .name = "0xDFFFDFFF: ", .fill = fill_pattern, .pattern = 0xDFFFDFFF, .fade = 0 },
{ .name = "0x40004000: ", .fill = fill_pattern, .pattern = 0x40004000, .fade = 0 }, { .name = "0x40004000: ", .fill = fill_pattern, .pattern = 0x40004000, .fade = 0 },
{ .name = "0xBFFFBFFF: ", .fill = fill_pattern, .pattern = 0xBFFFBFFF, .fade = 0 }, { .name = "0xBFFFBFFF: ", .fill = fill_pattern, .pattern = 0xBFFFBFFF, .fade = 0 },
{ .name = "0x80008000: ", .fill = fill_pattern, .pattern = 0x80008000, .fade = 0 }, { .name = "0x80008000: ", .fill = fill_pattern, .pattern = 0x80008000, .fade = 0 },
{ .name = "0x7FFF7FFF: ", .fill = fill_pattern, .pattern = 0x7FFF7FFF, .fade = 0 }, { .name = "0x7FFF7FFF: ", .fill = fill_pattern, .pattern = 0x7FFF7FFF, .fade = 0 },
{ .name = NULL }, { .name = NULL },
}; };
sdram_test_t phase_5_tests[] = { sdram_test_t phase_5_tests[] = {
{ .name = "Fadeout L (0):", .fill = fill_pattern, .pattern = 0x00000000, .fade = 300 }, { .name = "Fadeout (0): ", .fill = fill_pattern, .pattern = 0x00000000, .fade = 60 },
{ .name = "Fadeout L (1):", .fill = fill_pattern, .pattern = 0xFFFFFFFF, .fade = 300 }, { .name = "Fadeout (1): ", .fill = fill_pattern, .pattern = 0xFFFFFFFF, .fade = 60 },
{ .name = NULL }, { .name = NULL },
}; };
@ -317,14 +441,14 @@ static void test_sdram (void) {
srand(random_seed); 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) { if ((offset % (SDRAM_SIZE / 16)) == 0) {
display_printf("w"); 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--) { for (int fade = test->fade; fade > 0; fade--) {
@ -335,19 +459,19 @@ static void test_sdram (void) {
srand(random_seed); 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) { if ((offset % (SDRAM_SIZE / 16)) == 0) {
display_printf("r"); 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 *test_data = (uint64_t *) (w_buffer);
uint64_t *check_data = (uint64_t *) (r_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]) { if (test_data[i] != check_data[i]) {
display_printf( display_printf(
"\n" "\n"
@ -399,7 +523,8 @@ static struct {
} tests[] = { } tests[] = {
{ "SC64 CFG", test_sc64_cfg }, { "SC64 CFG", test_sc64_cfg },
{ "PI", test_pi }, { "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 (1/6)", test_sdram },
{ "SDRAM (2/6)", test_sdram }, { "SDRAM (2/6)", test_sdram },
{ "SDRAM (3/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))) { if ((error = sc64_set_config(CFG_ID_ROM_WRITE_ENABLE, true))) {
error_display("Command CONFIG_SET [ROM_WRITE_ENABLE] failed: %d", error); error_display("Command CONFIG_SET [ROM_WRITE_ENABLE] failed: %d", error);
return;
} }
if ((error = sc64_set_config(CFG_ID_ROM_SHADOW_ENABLE, false))) { if ((error = sc64_set_config(CFG_ID_ROM_SHADOW_ENABLE, false))) {
error_display("Command CONFIG_SET [ROM_SHADOW_ENABLE] failed: %d", error); error_display("Command CONFIG_SET [ROM_SHADOW_ENABLE] failed: %d", error);
return;
} }
random_seed = __entropy + c0_count(); random_seed = __entropy + c0_count();

View File

@ -884,69 +884,68 @@ fn handle_firmware_command(
fn handle_test_command(connection: Connection) -> Result<(), sc64::Error> { fn handle_test_command(connection: Connection) -> Result<(), sc64::Error> {
let mut sc64 = init_sc64(connection, false)?; let mut sc64 = init_sc64(connection, false)?;
println!("{}: SDRAM", "[SC64 Tests]".bold()); println!("{}: SDRAM (pattern)", "[SC64 Tests]".bold());
let sdram_tests = [ let sdram_pattern_tests = [
(sc64::MemoryTestType::OwnAddress, None), (sc64::MemoryTestPattern::OwnAddress, None),
(sc64::MemoryTestType::AllZeros, None), (sc64::MemoryTestPattern::AllZeros, None),
(sc64::MemoryTestType::AllOnes, None), (sc64::MemoryTestPattern::AllOnes, None),
(sc64::MemoryTestType::Random, None), (sc64::MemoryTestPattern::Custom(0xAAAA5555), None),
(sc64::MemoryTestType::Random, None), (sc64::MemoryTestPattern::Custom(0x5555AAAA), None),
(sc64::MemoryTestType::Random, None), (sc64::MemoryTestPattern::Random, None),
(sc64::MemoryTestType::AllZeros, Some(60)), (sc64::MemoryTestPattern::Random, None),
(sc64::MemoryTestType::AllOnes, Some(60)), (sc64::MemoryTestPattern::Custom(0x00010001), None),
(sc64::MemoryTestType::Pattern(0x00010001), None), (sc64::MemoryTestPattern::Custom(0xFFFEFFFE), None),
(sc64::MemoryTestType::Pattern(0xFFFEFFFE), None), (sc64::MemoryTestPattern::Custom(0x00020002), None),
(sc64::MemoryTestType::Pattern(0x00020002), None), (sc64::MemoryTestPattern::Custom(0xFFFDFFFD), None),
(sc64::MemoryTestType::Pattern(0xFFFDFFFD), None), (sc64::MemoryTestPattern::Custom(0x00040004), None),
(sc64::MemoryTestType::Pattern(0x00040004), None), (sc64::MemoryTestPattern::Custom(0xFFFBFFFB), None),
(sc64::MemoryTestType::Pattern(0xFFFBFFFB), None), (sc64::MemoryTestPattern::Custom(0x00080008), None),
(sc64::MemoryTestType::Pattern(0x00080008), None), (sc64::MemoryTestPattern::Custom(0xFFF7FFF7), None),
(sc64::MemoryTestType::Pattern(0xFFF7FFF7), None), (sc64::MemoryTestPattern::Custom(0x00100010), None),
(sc64::MemoryTestType::Pattern(0x00100010), None), (sc64::MemoryTestPattern::Custom(0xFFEFFFEF), None),
(sc64::MemoryTestType::Pattern(0xFFEFFFEF), None), (sc64::MemoryTestPattern::Custom(0x00200020), None),
(sc64::MemoryTestType::Pattern(0x00200020), None), (sc64::MemoryTestPattern::Custom(0xFFDFFFDF), None),
(sc64::MemoryTestType::Pattern(0xFFDFFFDF), None), (sc64::MemoryTestPattern::Custom(0x00400040), None),
(sc64::MemoryTestType::Pattern(0x00400040), None), (sc64::MemoryTestPattern::Custom(0xFFBFFFBF), None),
(sc64::MemoryTestType::Pattern(0xFFBFFFBF), None), (sc64::MemoryTestPattern::Custom(0x00800080), None),
(sc64::MemoryTestType::Pattern(0x00800080), None), (sc64::MemoryTestPattern::Custom(0xFF7FFF7F), None),
(sc64::MemoryTestType::Pattern(0xFF7FFF7F), None), (sc64::MemoryTestPattern::Custom(0x01000100), None),
(sc64::MemoryTestType::Pattern(0x01000100), None), (sc64::MemoryTestPattern::Custom(0xFEFFFEFF), None),
(sc64::MemoryTestType::Pattern(0xFEFFFEFF), None), (sc64::MemoryTestPattern::Custom(0x02000200), None),
(sc64::MemoryTestType::Pattern(0x02000200), None), (sc64::MemoryTestPattern::Custom(0xFDFFFDFF), None),
(sc64::MemoryTestType::Pattern(0xFDFFFDFF), None), (sc64::MemoryTestPattern::Custom(0x04000400), None),
(sc64::MemoryTestType::Pattern(0x04000400), None), (sc64::MemoryTestPattern::Custom(0xFBFFFBFF), None),
(sc64::MemoryTestType::Pattern(0xFBFFFBFF), None), (sc64::MemoryTestPattern::Custom(0x08000800), None),
(sc64::MemoryTestType::Pattern(0x08000800), None), (sc64::MemoryTestPattern::Custom(0xF7FFF7FF), None),
(sc64::MemoryTestType::Pattern(0xF7FFF7FF), None), (sc64::MemoryTestPattern::Custom(0x10001000), None),
(sc64::MemoryTestType::Pattern(0x10001000), None), (sc64::MemoryTestPattern::Custom(0xEFFFEFFF), None),
(sc64::MemoryTestType::Pattern(0xEFFFEFFF), None), (sc64::MemoryTestPattern::Custom(0x20002000), None),
(sc64::MemoryTestType::Pattern(0x20002000), None), (sc64::MemoryTestPattern::Custom(0xDFFFDFFF), None),
(sc64::MemoryTestType::Pattern(0xDFFFDFFF), None), (sc64::MemoryTestPattern::Custom(0x40004000), None),
(sc64::MemoryTestType::Pattern(0x40004000), None), (sc64::MemoryTestPattern::Custom(0xBFFFBFFF), None),
(sc64::MemoryTestType::Pattern(0xBFFFBFFF), None), (sc64::MemoryTestPattern::Custom(0x80008000), None),
(sc64::MemoryTestType::Pattern(0x80008000), None), (sc64::MemoryTestPattern::Custom(0x7FFF7FFF), None),
(sc64::MemoryTestType::Pattern(0x7FFF7FFF), None), (sc64::MemoryTestPattern::AllZeros, Some(60)),
(sc64::MemoryTestType::AllZeros, Some(300)), (sc64::MemoryTestPattern::AllOnes, Some(60)),
(sc64::MemoryTestType::AllOnes, Some(300)),
]; ];
let sdram_tests_count = sdram_tests.len(); let sdram_pattern_tests_count = sdram_pattern_tests.len();
let mut sdram_tests_failed = false; 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 { let fadeout_text = if let Some(fade) = fade {
format!(", fadeout {fade} seconds") format!(", fadeout {fade} seconds")
} else { } else {
"".to_string() "".to_string()
}; };
print!( print!(
" ({} / {sdram_tests_count}) Testing {test_type}{fadeout_text}... ", " ({} / {sdram_pattern_tests_count}) Testing {pattern}{fadeout_text}... ",
i + 1 i + 1
); );
stdout().flush().unwrap(); 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 { if let Some((address, (written, read))) = result.first_error {
sdram_tests_failed = true; sdram_tests_failed = true;

View File

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

View File

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