summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ports/stm32/main.c2
-rw-r--r--ports/stm32/sdram.c88
-rw-r--r--ports/stm32/sdram.h2
3 files changed, 73 insertions, 19 deletions
diff --git a/ports/stm32/main.c b/ports/stm32/main.c
index d7afb9e4a..3ff7077ac 100644
--- a/ports/stm32/main.c
+++ b/ports/stm32/main.c
@@ -404,7 +404,7 @@ void stm32_main(uint32_t reset_mode) {
bool sdram_valid = true;
UNUSED(sdram_valid);
#if MICROPY_HW_SDRAM_STARTUP_TEST
- sdram_valid = sdram_test(true);
+ sdram_valid = sdram_test(false);
#endif
#endif
#if MICROPY_PY_THREAD
diff --git a/ports/stm32/sdram.c b/ports/stm32/sdram.c
index 514192519..e0e350083 100644
--- a/ports/stm32/sdram.c
+++ b/ports/stm32/sdram.c
@@ -283,52 +283,106 @@ void sdram_leave_low_power(void) {
#pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif
-bool sdram_test(bool fast) {
+bool __attribute__((optimize("O0"))) sdram_test(bool exhaustive) {
uint8_t const pattern = 0xaa;
uint8_t const antipattern = 0x55;
uint8_t *const mem_base = (uint8_t *)sdram_start();
- /* test data bus */
- for (uint8_t i = 1; i; i <<= 1) {
- *mem_base = i;
- if (*mem_base != i) {
- printf("data bus lines test failed! data (%d)\n", i);
+ #if MICROPY_HW_SDRAM_TEST_FAIL_ON_ERROR
+ char error_buffer[1024];
+ #endif
+
+ #if (__DCACHE_PRESENT == 1)
+ bool i_cache_disabled = false;
+ bool d_cache_disabled = false;
+
+ // Disable caches for testing.
+ if (SCB->CCR & (uint32_t)SCB_CCR_IC_Msk) {
+ SCB_DisableICache();
+ i_cache_disabled = true;
+ }
+
+ if (SCB->CCR & (uint32_t)SCB_CCR_DC_Msk) {
+ SCB_DisableDCache();
+ d_cache_disabled = true;
+ }
+ #endif
+
+ // Test data bus
+ for (uint32_t i = 0; i < MICROPY_HW_SDRAM_MEM_BUS_WIDTH; i++) {
+ *((uint32_t *)mem_base) = (1 << i);
+ if (*((uint32_t *)mem_base) != (1 << i)) {
+ #if MICROPY_HW_SDRAM_TEST_FAIL_ON_ERROR
+ snprintf(error_buffer, sizeof(error_buffer),
+ "Data bus test failed at 0x%p expected 0x%x found 0x%lx",
+ &mem_base[0], (1 << i), ((uint32_t *)mem_base)[0]);
+ __fatal_error(error_buffer);
+ #endif
return false;
}
}
- /* test address bus */
- /* Check individual address lines */
+ // Test address bus
for (uint32_t i = 1; i < MICROPY_HW_SDRAM_SIZE; i <<= 1) {
mem_base[i] = pattern;
if (mem_base[i] != pattern) {
- printf("address bus lines test failed! address (%p)\n", &mem_base[i]);
+ #if MICROPY_HW_SDRAM_TEST_FAIL_ON_ERROR
+ snprintf(error_buffer, sizeof(error_buffer),
+ "Address bus test failed at 0x%p expected 0x%x found 0x%x",
+ &mem_base[i], pattern, mem_base[i]);
+ __fatal_error(error_buffer);
+ #endif
return false;
}
}
- /* Check for aliasing (overlaping addresses) */
+ // Check for aliasing (overlaping addresses)
mem_base[0] = antipattern;
for (uint32_t i = 1; i < MICROPY_HW_SDRAM_SIZE; i <<= 1) {
if (mem_base[i] != pattern) {
- printf("address bus overlap %p\n", &mem_base[i]);
+ #if MICROPY_HW_SDRAM_TEST_FAIL_ON_ERROR
+ snprintf(error_buffer, sizeof(error_buffer),
+ "Address bus overlap at 0x%p expected 0x%x found 0x%x",
+ &mem_base[i], pattern, mem_base[i]);
+ __fatal_error(error_buffer);
+ #endif
return false;
}
}
- /* test all ram cells */
- if (!fast) {
- for (uint32_t i = 0; i < MICROPY_HW_SDRAM_SIZE; ++i) {
+ // Test all RAM cells
+ if (exhaustive) {
+ // Write all memory first then compare, so even if the cache
+ // is enabled, it's not just writing and reading from cache.
+ // Note: This test should also detect refresh rate issues.
+ for (uint32_t i = 0; i < MICROPY_HW_SDRAM_SIZE; i++) {
mem_base[i] = pattern;
+ }
+
+ for (uint32_t i = 0; i < MICROPY_HW_SDRAM_SIZE; i++) {
if (mem_base[i] != pattern) {
- printf("address bus test failed! address (%p)\n", &mem_base[i]);
+ #if MICROPY_HW_SDRAM_TEST_FAIL_ON_ERROR
+ snprintf(error_buffer, sizeof(error_buffer),
+ "Address bus slow test failed at 0x%p expected 0x%x found 0x%x",
+ &mem_base[i], pattern, mem_base[i]);
+ __fatal_error(error_buffer);
+ #endif
return false;
}
}
- } else {
- memset(mem_base, pattern, MICROPY_HW_SDRAM_SIZE);
}
+ #if (__DCACHE_PRESENT == 1)
+ // Re-enable caches if they were enabled before the test started.
+ if (i_cache_disabled) {
+ SCB_EnableICache();
+ }
+
+ if (d_cache_disabled) {
+ SCB_EnableDCache();
+ }
+ #endif
+
return true;
}
diff --git a/ports/stm32/sdram.h b/ports/stm32/sdram.h
index 773a30802..f7a124add 100644
--- a/ports/stm32/sdram.h
+++ b/ports/stm32/sdram.h
@@ -13,5 +13,5 @@ void *sdram_start(void);
void *sdram_end(void);
void sdram_enter_low_power(void);
void sdram_leave_low_power(void);
-bool sdram_test(bool fast);
+bool sdram_test(bool exhaustive);
#endif // __SDRAM_H__