288 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			288 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/**********************************************************************
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Filename:    memtest.c
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Description: General-purpose memory testing functions.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Notes:       This software can be easily ported to systems with
							 | 
						||
| 
								 | 
							
								 *              different data bus widths by redefining 'datum'.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Copyright (c) 1998 by Michael Barr.  This software is placed into
							 | 
						||
| 
								 | 
							
								 * the public domain and may be used for any purpose.  However, this
							 | 
						||
| 
								 | 
							
								 * notice must not be changed or removed and no warranty is either
							 | 
						||
| 
								 | 
							
								 * expressed or implied by its publication or distribution.
							 | 
						||
| 
								 | 
							
								 **********************************************************************/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "os_types.h"
							 | 
						||
| 
								 | 
							
								#include "os_utils.h"
							 | 
						||
| 
								 | 
							
								#include "dbg_io.h"
							 | 
						||
| 
								 | 
							
								#include "iot_io.h"
							 | 
						||
| 
								 | 
							
								#include "iot_clock.h"
							 | 
						||
| 
								 | 
							
								#include "memtest.h"
							 | 
						||
| 
								 | 
							
								#include "system.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**********************************************************************
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Function:    memTestDataBus()
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Description: Test the data bus wiring in a memory region by
							 | 
						||
| 
								 | 
							
								 *              performing a walking 1's test at a fixed address
							 | 
						||
| 
								 | 
							
								 *              within that region.  The address (and hence the
							 | 
						||
| 
								 | 
							
								 *              memory region) is selected by the caller.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Notes:       
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Returns:     0 if the test succeeds.  
							 | 
						||
| 
								 | 
							
								 *              A non-zero result is the first pattern that failed.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 **********************************************************************/
							 | 
						||
| 
								 | 
							
								datum
							 | 
						||
| 
								 | 
							
								memTestDataBus(volatile datum * address)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    datum pattern;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /*
							 | 
						||
| 
								 | 
							
								     * Perform a walking 1's test at the given address.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    for (pattern = 1; pattern != 0; pattern <<= 1)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        /*
							 | 
						||
| 
								 | 
							
								         * Write the test pattern.
							 | 
						||
| 
								 | 
							
								         */
							 | 
						||
| 
								 | 
							
								        *address = pattern;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /*
							 | 
						||
| 
								 | 
							
								         * Read it back (immediately is okay for this test).
							 | 
						||
| 
								 | 
							
								         */
							 | 
						||
| 
								 | 
							
								        if (*address != pattern) 
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            return (pattern);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return (0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}   /* memTestDataBus() */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**********************************************************************
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Function:    memTestAddressBus()
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Description: Test the address bus wiring in a memory region by
							 | 
						||
| 
								 | 
							
								 *              performing a walking 1's test on the relevant bits
							 | 
						||
| 
								 | 
							
								 *              of the address and checking for aliasing. This test
							 | 
						||
| 
								 | 
							
								 *              will find single-bit address failures such as stuck
							 | 
						||
| 
								 | 
							
								 *              -high, stuck-low, and shorted pins.  The base address
							 | 
						||
| 
								 | 
							
								 *              and size of the region are selected by the caller.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Notes:       For best results, the selected base address should
							 | 
						||
| 
								 | 
							
								 *              have enough LSB 0's to guarantee single address bit
							 | 
						||
| 
								 | 
							
								 *              changes.  For example, to test a 64-Kbyte region, 
							 | 
						||
| 
								 | 
							
								 *              select a base address on a 64-Kbyte boundary.  Also, 
							 | 
						||
| 
								 | 
							
								 *              select the region size as a power-of-two--if at all 
							 | 
						||
| 
								 | 
							
								 *              possible.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Returns:     NULL if the test succeeds.  
							 | 
						||
| 
								 | 
							
								 *              A non-zero result is the first address at which an
							 | 
						||
| 
								 | 
							
								 *              aliasing problem was uncovered.  By examining the
							 | 
						||
| 
								 | 
							
								 *              contents of memory, it may be possible to gather
							 | 
						||
| 
								 | 
							
								 *              additional information about the problem.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 **********************************************************************/
							 | 
						||
| 
								 | 
							
								datum * 
							 | 
						||
| 
								 | 
							
								memTestAddressBus(volatile datum * baseAddress, unsigned long nBytes)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    unsigned long addressMask = (nBytes/sizeof(datum) - 1);
							 | 
						||
| 
								 | 
							
								    unsigned long offset;
							 | 
						||
| 
								 | 
							
								    unsigned long testOffset;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    datum pattern     = (datum) 0xAAAAAAAA;
							 | 
						||
| 
								 | 
							
								    datum antipattern = (datum) 0x55555555;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /*
							 | 
						||
| 
								 | 
							
								     * Write the default pattern at each of the power-of-two offsets.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        baseAddress[offset] = pattern;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* 
							 | 
						||
| 
								 | 
							
								     * Check for address bits stuck high.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    testOffset = 0;
							 | 
						||
| 
								 | 
							
								    baseAddress[testOffset] = antipattern;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if (baseAddress[offset] != pattern)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            return ((datum *) &baseAddress[offset]);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    baseAddress[testOffset] = pattern;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /*
							 | 
						||
| 
								 | 
							
								     * Check for address bits stuck low or shorted.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    for (testOffset = 1; (testOffset & addressMask) != 0; testOffset <<= 1)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        baseAddress[testOffset] = antipattern;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (baseAddress[0] != pattern)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											return ((datum *) &baseAddress[testOffset]);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            if ((baseAddress[offset] != pattern) && (offset != testOffset))
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                return ((datum *) &baseAddress[testOffset]);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        baseAddress[testOffset] = pattern;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return (NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}   /* memTestAddressBus() */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**********************************************************************
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Function:    memTestDevice()
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Description: Test the integrity of a physical memory device by
							 | 
						||
| 
								 | 
							
								 *              performing an increment/decrement test over the
							 | 
						||
| 
								 | 
							
								 *              entire region.  In the process every storage bit 
							 | 
						||
| 
								 | 
							
								 *              in the device is tested as a zero and a one.  The
							 | 
						||
| 
								 | 
							
								 *              base address and the size of the region are
							 | 
						||
| 
								 | 
							
								 *              selected by the caller.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Notes:       
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Returns:     NULL if the test succeeds.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *              A non-zero result is the first address at which an
							 | 
						||
| 
								 | 
							
								 *              incorrect value was read back.  By examining the
							 | 
						||
| 
								 | 
							
								 *              contents of memory, it may be possible to gather
							 | 
						||
| 
								 | 
							
								 *              additional information about the problem.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 **********************************************************************/
							 | 
						||
| 
								 | 
							
								datum * 
							 | 
						||
| 
								 | 
							
								memTestDevice(volatile datum * baseAddress, unsigned long nBytes)	
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    unsigned long offset;
							 | 
						||
| 
								 | 
							
								    unsigned long nWords = nBytes / sizeof(datum);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    datum pattern;
							 | 
						||
| 
								 | 
							
								    datum antipattern;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /*
							 | 
						||
| 
								 | 
							
								     * Fill memory with a known pattern.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    for (pattern = 1, offset = 0; offset < nWords; pattern++, offset++)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        baseAddress[offset] = pattern;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /*
							 | 
						||
| 
								 | 
							
								     * Check each location and invert it for the second pass.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    for (pattern = 1, offset = 0; offset < nWords; pattern++, offset++)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if (baseAddress[offset] != pattern)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            return ((datum *) &baseAddress[offset]);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        antipattern = ~pattern;
							 | 
						||
| 
								 | 
							
								        baseAddress[offset] = antipattern;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /*
							 | 
						||
| 
								 | 
							
								     * Check each location for the inverted pattern and zero it.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    for (pattern = 1, offset = 0; offset < nWords; pattern++, offset++)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        antipattern = ~pattern;
							 | 
						||
| 
								 | 
							
								        if (baseAddress[offset] != antipattern)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            return ((datum *) &baseAddress[offset]);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return (NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}   /* memTestDevice() */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int
							 | 
						||
| 
								 | 
							
								memTest(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    #define BASE_ADDRESS  (volatile datum *) 0x00fd3000
							 | 
						||
| 
								 | 
							
								    #define NUM_BYTES     (180 * 1024)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    volatile datum* addr = NULL;
							 | 
						||
| 
								 | 
							
								    if (memTestDataBus(BASE_ADDRESS) != 0)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        iot_printf("data bus failed....\n");
							 | 
						||
| 
								 | 
							
								        return (-1);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    addr = memTestAddressBus(BASE_ADDRESS, NUM_BYTES);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if( addr != NULL)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        iot_printf("address failed:0x%x\n", addr);
							 | 
						||
| 
								 | 
							
								        return (-1);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    addr = memTestDevice(BASE_ADDRESS, NUM_BYTES);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if( addr != NULL)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        iot_printf("device failed:0x%x\n", addr);
							 | 
						||
| 
								 | 
							
								        return (-1);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return (0);
							 | 
						||
| 
								 | 
							
								}   /* memTest() */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int main(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    int test_result = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    dbg_uart_init();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    test_result = memTest();
							 | 
						||
| 
								 | 
							
								    if (0 == test_result) {
							 | 
						||
| 
								 | 
							
								        iot_printf("memory test passed....\n");
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        iot_printf("memory test failed....\n");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    iot_printf("MEMTEST VERSION(HEX): 11.0.1.1\n");
							 | 
						||
| 
								 | 
							
								    iot_printf("build date: "__DATE__". time: "__TIME__".\r\n");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (0 == test_result) {
							 | 
						||
| 
								 | 
							
								        iot_printf("restart by software after test passed.\n");
							 | 
						||
| 
								 | 
							
								        iot_delay_us_cpu_cycle(100000);
							 | 
						||
| 
								 | 
							
								        system_restart_chip_by_soft();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    while(1);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								}
							 |