| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- /*
- * Copyright (C) 2012 by Ole Reinhardt (ole.reinhardt@embedded-it.de)
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * For additional information see http://www.ethernut.de/
- *
- ***********************************************************************
- *
- * The test algorithms are taken from the original public domain source
- * code from Michael Barr:
- *
- * 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.
- *
- */
- /*
- * \verbatim
- * $Id: $
- * \endverbatim
- */
- /*
- * The following functions implement three well known memory test algorithm
- * that can test most common memory problems.
- * These tree algorithms are in the public domain.
- *
- * A nice description of these algorithms can be found at:
- * http://www.esacademy.com/en/library/technical-articles-and-documents/miscellaneous/software-based-memory-testing.html
- *
- * And also at:
- * [1] Barr, Michael. "Software-Based Memory Testing," Embedded Systems Programming, July 2000, pp. 28-40.
- */
- /*!
- * \brief Check data bus wiring on a 8 bit databus
- *
- * 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.
- *
- * \param addr memory address that shall be used for this test
- *
- * \return 0 on success, a non-zero result is the first pattern that failed
- */
- datum MemtestDataBus(volatile datum* addr)
- {
- datum pattern;
- /*
- * Perform a walking 1's test at the given address.
- */
- for (pattern = 1; pattern != 0; pattern <<= 1) {
- /*
- * Write the test pattern.
- */
- *addr = pattern;
- /*
- * Read it back (immediately is okay for this test).
- */
- if (*addr != pattern) {
- return (pattern);
- }
- }
- return 0;
- }
- /*!
- * \brief Check address bus wiring on a 8 bit databus
- *
- * 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.
- *
- * \param base memory base address that shall be used for this test
- * \param size size of the memory region
- *
- * \return 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 *MemtestAddrBus(volatile datum *base, size_t size)
- {
- uint32_t addressMask = (size/sizeof(datum) - 1);
- uint32_t offset;
- uint32_t 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) {
- base[offset] = pattern;
- }
- /*
- * Check for address bits stuck high.
- */
- testOffset = 0;
- base[testOffset] = antipattern;
- for (offset = 1; (offset & addressMask) != 0; offset <<= 1) {
- if (base[offset] != pattern) {
- return ((datum *) &base[offset]);
- }
- }
- base[testOffset] = pattern;
- /*
- * Check for address bits stuck low or shorted.
- */
- for (testOffset = 1; (testOffset & addressMask) != 0; testOffset <<= 1) {
- base[testOffset] = antipattern;
- if (base[0] != pattern) {
- return ((datum *) &base[testOffset]);
- }
- for (offset = 1; (offset & addressMask) != 0; offset <<= 1) {
- if ((base[offset] != pattern) && (offset != testOffset)) {
- return ((datum *) &base[testOffset]);
- }
- }
- base[testOffset] = pattern;
- }
- return NULL;
- }
- /*!
- * \brief Check address bus wiring on a 8 bit databus
- *
- * 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 size of the region are selected by the caller.
- *
- * \param base memory base address that shall be used for this test
- * \param size size of the memory region
- *
- * \return NULL if the test succeeds. Also, in that case, the
- * entire memory region will be filled with zeros.
- *
- * 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 * base, size_t size)
- {
- unsigned long offset;
- size_t nWords = size / sizeof(datum);
- datum pattern;
- datum antipattern;
- /*
- * Fill memory with a known pattern.
- */
- for (pattern = 1, offset = 0; offset < nWords; pattern++, offset++) {
- base[offset] = pattern;
- }
- /*
- * Check each location and invert it for the second pass.
- */
- for (pattern = 1, offset = 0; offset < nWords; pattern++, offset++) {
- if (base[offset] != pattern) {
- return ((datum *) &base[offset]);
- }
- antipattern = ~pattern;
- base[offset] = antipattern;
- }
- /*
- * Check each location for the inverted pattern and zero it.
- */
- for (pattern = 1, offset = 0; offset < nWords; pattern++, offset++) {
- antipattern = ~pattern;
- if (base[offset] != antipattern) {
- return ((datum *) &base[offset]);
- }
- }
- return NULL;
- }
|