stm32/sdram: Make SDRAM test cache aware, and optional failure with msg.
* Make SDRAM test cache-aware for newer MCUs. * Use the defined data bus width (instead of the fixed 8-bits). * Allow optional failure on error with verbose error messages. * Test speed is now inverted (test accepts exhaustive instead fast).
This commit is contained in:
parent
6214fa3f9e
commit
7649f5fbd2
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
|
Loading…
Reference in New Issue