The function memTestDataBus shows how to implement the walking 1's test in C. It assumes that the caller will select the test address, and tests the entire set of data values at that address. If the data bus is working properly, the function will return 0. Otherwise it will return the data value for which the test failed. The bit that is set in the returned value corresponds to the first faulty data line, if any.
typedef unsigned char datum; /* Set the data bus width to 8 bits. */
/**********************************************************************
*
* 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 nonzero 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() */
After confirming that the data bus works properly, you should next test the address bus. Remember that address bus problems lead to overlapping memory locations. There are many possible addresses that could overlap. However, it is not necessary to check every possible combination. You should instead follow the example of the previous data bus test and try to isolate each address bit during testing. You simply need to confirm that each of the address pins can be set to and 1 without affecting any of the others.
The smallest set of addresses that will cover all possible combinations is the set of "power-of-two" addresses. These addresses are analogous to the set of data values used in the walking 1's test. The corresponding memory locations are 00001h, 00002h, 00004h, 00008h, 00010h, 00020h, and so forth. In addition, address 00000h must also be tested. The possibility of overlapping locations makes the address bus test harder to implement. After writing to one of the addresses, you must check that none of the others has been overwritten.
It is important to note that not all of the address lines can be tested in this way. Part of the address — the leftmost bits — selects the memory chip itself. Another part — the rightmost bits — might not be significant if the data bus width is greater than 8 bits. These extra bits will remain constant throughout the test and reduce the number of test addresses. For example, if the processor has 20 address bits, as the 80188EB does, then it can address up to 1 megabyte of memory. If you want to test a 128-kilobyte block of memory, the three most significant address bits will remain constant. [14] 128 kilobytes is one-eighth of the total 1-megabyte address space.
In that case, only the 17 rightmost bits of the address bus can actually be tested.
To confirm that no two memory locations overlap, you should first write some initial data value at each power-of-two offset within the device. Then write a new value — an inverted copy of the initial value is a good choice — to the first test offset, and verify that the initial data value is still stored at every other power-of-two offset. If you find a location (other than the one just written) that contains the new data value, you have found a problem with the current address bit. If no overlapping is found, repeat the procedure for each of the remaining offsets.
The function memTestAddressBus shows how this can be done in practice. The function accepts two parameters. The first parameter is the base address of the memory block to be tested, and the second is its size, in bytes. The size is used to determine which address bits should be tested. For best results, the base address should contain a in each of those bits. If the address bus test fails, the address at which the first error was detected will be returned. Otherwise, the function returns NULL to indicate success.
/**********************************************************************
* 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. The 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 KB region, select
* a base address on a 64 KB boundary. Also, select the
* region size as a power-of-two — if at all possible.
*
* Returns: NULL if the test succeeds.
* A nonzero 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 – 1);
unsigned long offset;
unsigned long testOffset;
datum pattern = (datum) 0xAAAAAAAA;
datum antipattern = (datun) 0x55555555;
/*
* Write the default pattern at each of the power-of-two offsets..
*/
for (offset = sizeof(datum); (offset & addressMask) != 0; offset <<= 1) {
baseAddress[offset] = pattern;
}
/*
* Check for address bits stuck high.
*/
testOffset = 0;
baseAddress[testOffset] = antipattern;
for (offset = sizeof(datum); (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 = sizeof(datum); (testOffset & addressMask) != 0; testOffset <<= 1) {
baseAddress[testOffset] = antipattern;
for (offset = sizeof(datum); (offset & addressMask) != 0; offset <<= 1) {
Читать дальше