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).
pull/7557/head
iabdalkader 2021-07-09 15:49:25 +02:00 zatwierdzone przez Damien George
rodzic 6214fa3f9e
commit 7649f5fbd2
3 zmienionych plików z 73 dodań i 19 usunięć

Wyświetl plik

@ -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

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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__