From ebb1383957c7181f2edf698372f0d16a02b8cee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 22 May 2021 11:25:55 +0200 Subject: [PATCH] Write memory test for system RAM --- stm-firmware/boot/startup-tests.c | 62 +++++++++++++++++++++++++ stm-firmware/boot/startup-tests.h | 7 +++ stm-firmware/boot/startup_stm32f407vx.c | 44 ++++++++++++++++-- 3 files changed, 108 insertions(+), 5 deletions(-) diff --git a/stm-firmware/boot/startup-tests.c b/stm-firmware/boot/startup-tests.c index 561ce84..587cfcb 100644 --- a/stm-firmware/boot/startup-tests.c +++ b/stm-firmware/boot/startup-tests.c @@ -62,3 +62,65 @@ uint32_t startup_test_perform_ccm_ram_check(void) exit_ret_address: return ret; } + +uint32_t startup_test_perform_system_ram_check() +{ + const void *ram_base = (void *)0x20000000UL; + const uint32_t ram_size = 128U * 1024UL; + volatile uint32_t *word_ptr; + uint32_t target_val; + uint32_t idx; + uint32_t ret = 0UL; + + + /* Perform inversion test with 0x55 and 0xAA, Part 1 */ + for (idx = 0, word_ptr = (volatile uint32_t *)ram_base; idx < ram_size / 4U; idx++) { + word_ptr[idx] = idx & 1 ? 0x55AA55AAUL : 0xAA55AA55UL; + } + for (idx = 0, word_ptr = (volatile uint32_t *)ram_base; idx < ram_size / 4U; idx++) { + target_val = idx & 1 ? 0x55AA55AAUL : 0xAA55AA55UL; + if (target_val != word_ptr[idx]) { + ret = (uint32_t)&word_ptr[idx]; + goto exit_ret_address; + } + } + + /* Perform inversion test with 0x55 and 0xAA, Part 2 */ + for (idx = 0, word_ptr = (volatile uint32_t *)ram_base; idx < ram_size / 4U; idx++) { + word_ptr[idx] = idx & 1 ? 0xAA55AA55UL : 0x55AA55AAUL; + } + for (idx = 0, word_ptr = (volatile uint32_t *)ram_base; idx < ram_size / 4U; idx++) { + target_val = idx & 1 ? 0xAA55AA55UL : 0x55AA55AAUL; + if (target_val != word_ptr[idx]) { + ret = (uint32_t)&word_ptr[idx]; + goto exit_ret_address; + } + } + + /* Perform static test with 0xFF */ + for (idx = 0, word_ptr = (volatile uint32_t *)ram_base; idx < ram_size / 4U; idx++) { + word_ptr[idx] = 0xFFFFFFFFUL; + } + for (idx = 0, word_ptr = (volatile uint32_t *)ram_base; idx < ram_size / 4U; idx++) { + target_val = 0xFFFFFFFFUL; + if (target_val != word_ptr[idx]) { + ret = (uint32_t)&word_ptr[idx]; + goto exit_ret_address; + } + } + + /* Perform static test with 0x00 */ + for (idx = 0, word_ptr = (volatile uint32_t *)ram_base; idx < ram_size / 4U; idx++) { + word_ptr[idx] = 0x0UL; + } + for (idx = 0, word_ptr = (volatile uint32_t *)ram_base; idx < ram_size / 4U; idx++) { + target_val = 0x0UL; + if (target_val != word_ptr[idx]) { + ret = (uint32_t)&word_ptr[idx]; + goto exit_ret_address; + } + } + +exit_ret_address: + return ret; +} diff --git a/stm-firmware/boot/startup-tests.h b/stm-firmware/boot/startup-tests.h index 90ebdb9..cfeb64f 100644 --- a/stm-firmware/boot/startup-tests.h +++ b/stm-firmware/boot/startup-tests.h @@ -14,5 +14,12 @@ */ uint32_t startup_test_perform_ccm_ram_check(void); +/** + * @brief Do a RAM check of the stnadard SRAM regions + * @return 0 if successful. If an error is found, the faulty address is returned + * @warning This completely destroys all content in the memory! + * @warning Ensure that the stack pointer is moved to a different memory reagion (CCM RAM)! + */ +uint32_t startup_test_perform_system_ram_check(void); #endif /* _STARTUP_TESTS_H_ */ diff --git a/stm-firmware/boot/startup_stm32f407vx.c b/stm-firmware/boot/startup_stm32f407vx.c index d159ff5..544daf2 100644 --- a/stm-firmware/boot/startup_stm32f407vx.c +++ b/stm-firmware/boot/startup_stm32f407vx.c @@ -289,7 +289,7 @@ extern unsigned int __ld_eheap; #define CPACR (*((volatile uint32_t *)0xE000ED88)) -void Reset_Handler(void) { +void __attribute__((noreturn)) Reset_Handler(void) { /* Stack is already initialized by hardware */ /* The first thing we do here, is to initialize the FPU @@ -298,10 +298,9 @@ void Reset_Handler(void) { */ CPACR |= (0xF << 20); - if (startup_test_perform_ccm_ram_check()) { - /* Hang forever in case of an error. We cannot handle this (yet?) */ - while (1); - } + /** + * Prepare RAM etc for the System Init function. This ensures, the RAM tests execute at max speed. + */ /* Copy .data section */ __init_section(&__ld_load_data, &__ld_sdata, &__ld_edata); @@ -316,6 +315,41 @@ void Reset_Handler(void) { /* Set clocks, waitstates, ART operation etc. */ SystemInit(); + + if (startup_test_perform_ccm_ram_check()) { + /* Hang forever in case of an error. We cannot handle this (yet?) */ + while (1); + } + + /* Move the Stack pointer to CCMRAM + * This allows us to perform a RAM test on the main RAM. + * Note: sp is not required to be inside the clobber list! + */ + __asm__ __volatile__ ("mov sp, %0\n\t" :: "r"(0x10000000UL + (64U * 1024UL)) :); + + if (startup_test_perform_system_ram_check()) { + while (1); + } + + /* Move the stack pointer back. Note: This only works if this function does not use the stack for variables. + * Otherwise everything will be broken. + */ + __asm__ __volatile__ ("mov sp, %0\n\t" :: "r"(&__ld_top_of_stack) :); + + /** + * RAM tests destroyed our values. So we have to copy them again... + */ + + /* Copy .data section */ + __init_section(&__ld_load_data, &__ld_sdata, &__ld_edata); + /* Fill bss with zero */ + __fill_zero(&__ld_sbss, &__ld_ebss); + /* Fill Heap with zero */ + __fill_zero(&__ld_sheap, &__ld_eheap); + /* Fill static CCM memory with zeroes */ + __fill_zero(&__ld_sbss_ccm, &__ld_ebss_ccm); + /* Init CCM RAM data section */ + __init_section(&__ld_load_ccm_data, &__ld_sdata_ccm, &__ld_edata_ccm); /* C++ init function */ #if defined(__cplusplus)