Write memory test for system RAM
This commit is contained in:
		@@ -62,3 +62,65 @@ uint32_t startup_test_perform_ccm_ram_check(void)
 | 
				
			|||||||
exit_ret_address:
 | 
					exit_ret_address:
 | 
				
			||||||
	return ret;
 | 
						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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,5 +14,12 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
uint32_t startup_test_perform_ccm_ram_check(void);
 | 
					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_ */
 | 
					#endif /* _STARTUP_TESTS_H_ */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -289,7 +289,7 @@ extern unsigned int __ld_eheap;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define CPACR (*((volatile uint32_t *)0xE000ED88))
 | 
					#define CPACR (*((volatile uint32_t *)0xE000ED88))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Reset_Handler(void) {
 | 
					void __attribute__((noreturn)) Reset_Handler(void) {
 | 
				
			||||||
	/* Stack is already initialized by hardware */
 | 
						/* Stack is already initialized by hardware */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* The first thing we do here, is to initialize the FPU
 | 
						/* The first thing we do here, is to initialize the FPU
 | 
				
			||||||
@@ -298,10 +298,9 @@ void Reset_Handler(void) {
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	CPACR |= (0xF << 20);
 | 
						CPACR |= (0xF << 20);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (startup_test_perform_ccm_ram_check()) {
 | 
						/**
 | 
				
			||||||
		/* Hang forever in case of an error. We cannot handle this (yet?) */
 | 
						 * Prepare RAM etc for the System Init function. This ensures, the RAM tests execute at max speed.
 | 
				
			||||||
		while (1);
 | 
						 */
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Copy .data section */
 | 
						/* Copy .data section */
 | 
				
			||||||
	__init_section(&__ld_load_data, &__ld_sdata, &__ld_edata);
 | 
						__init_section(&__ld_load_data, &__ld_sdata, &__ld_edata);
 | 
				
			||||||
@@ -317,6 +316,41 @@ void Reset_Handler(void) {
 | 
				
			|||||||
	/* Set clocks, waitstates, ART operation etc. */
 | 
						/* Set clocks, waitstates, ART operation etc. */
 | 
				
			||||||
	SystemInit();
 | 
						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 */
 | 
						/* C++ init function */
 | 
				
			||||||
#if defined(__cplusplus)
 | 
					#if defined(__cplusplus)
 | 
				
			||||||
	__libc_init_array();
 | 
						__libc_init_array();
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user