📄 sma_mem_test.c
字号:
/***********************************************************************
* $Workfile: SMA_mem_test.c $
* $Revision: 1.1 $
* $Author: KovitzP $
* $Date: May 30 2002 17:36:22 $
*
* Project:
*
* Description:
* This file contains data, function and macro definitions for
* testing memory. These functions may be used with any chip
* that addresses memory sequentially.
*
*
* Revision History:
* $Log: //smaicnt2/pvcs/VM/CHIPS/archives/SOC/Source/SMA_mem_test.c-arc $
*
* Rev 1.1 May 30 2002 17:36:22 KovitzP
* Added random address testing.
*
* Rev 1.0 May 28 2002 13:15:16 KovitzP
* Initial revision.
*
*
***********************************************************************
*
* Copyright (c) 2002 Sharp Microelectronics of the Americas
*
* All rights reserved
*
* SHARP MICROELECTRONICS OF THE AMERICAS MAKES NO REPRESENTATION
* OR WARRANTIES WITH RESPECT TO THE PERFORMANCE OF THIS SOFTWARE,
* AND SPECIFICALLY DISCLAIMS ANY RESPONSIBILITY FOR ANY DAMAGES,
* SPECIAL OR CONSEQUENTIAL, CONNECTED WITH THE USE OF THIS SOFTWARE.
*
* SHARP MICROELECTRONICS OF THE AMERICAS PROVIDES THIS SOFTWARE SOLELY
* FOR THE PURPOSE OF SOFTWARE DEVELOPMENT INCORPORATING THE USE OF A
* SHARP MICROCONTROLLER OR SYSTEM-ON-CHIP PRODUCT. USE OF THIS SOURCE
* FILE IMPLIES ACCEPTANCE OF THESE CONDITIONS.
*
**********************************************************************/
#include "SMA_mem_test.h"
#include "SMA_mls.h"
#ifndef NULL
#define NULL 0
#endif
#define MEM_ZEROS 0x00000000
#define MEM_CHECKERBOARD 0x55555555
#define MEM_CHECKERBOARDBAR 0xAAAAAAAA
#define MEM_ONES 0xFFFFFFFF
#define MEM_ADDR_UNIQ_8 0x01
#define MEM_ADDR_UNIQ_16 0x0102
#define MEM_ADDR_UNIQ_32 0x01020304
/***********************************************************************
*
* Macro: MEM_TEST
*
* Purpose:
* generate memory test function bodies for 8, 16, and 32-bt accesses
*
* Processing:
* write zeros, read zeros, write checkerboard, read checkerboard,
* write checkerboardbar, read checkerboardbar, write all ones,
* read back all ones, write address-unique pattern, read back
* address unique pattern.
*
* Parameters:
* bits: The number of bits to generate code for
* start: The start address
* end: The end address
* log: An array of error data log[0:max_err - 1]
* max_err: The maximum number of errors before abort.
*
* Outputs:
* writes to the log array the address, intended value and
* value read back for each error
*
* Returns:
* the number of errors found. 0 indicates the test passed.
*
* Notes:
* If log is NULL, no errors will be logged.
* The "returns" is not a left-hand side. It describes what the
* return statement returns.
*
* Example usage:
*
* UNS_32 mem_test16(UNS_16 * start, UNS_16 * end,
* MEM_ERROR_T log, UNS_32 max_err)
* {
* MEM_TEST(16,start,end,log,max_err);
* }
*
*
**********************************************************************/
#define MEM_TEST(bits, start, end, log, max_err) \
{ \
UNS_32 ret; \
/* all zeros */ \
mem_fill##bits (start,end,(UNS_##bits)MEM_ZEROS); \
ret = mem_verify##bits (start,end,(UNS_##bits)MEM_ZEROS,log, max_err, "zeros"); \
if (ret != 0) \
return ret; \
/* checkerboard */ \
mem_fill##bits (start,end,(UNS_##bits)MEM_CHECKERBOARD); \
ret = mem_verify##bits (start,end,(UNS_##bits)MEM_CHECKERBOARD,log,max_err,"checkerboard"); \
if (ret != 0) \
return ret; \
/* checkerboardbar */ \
mem_fill##bits (start,end,(UNS_##bits)MEM_CHECKERBOARDBAR); \
ret = mem_verify##bits (start,end,(UNS_##bits)MEM_CHECKERBOARDBAR, \
log,max_err,"checkerboardbar"); \
if (ret != 0) \
return ret; \
/* all ones */ \
mem_fill##bits (start,end,(UNS_##bits)MEM_ONES); \
ret = mem_verify##bits (start,end,(UNS_##bits)MEM_ONES,log, max_err,"all ones"); \
if (ret != 0) \
return ret; \
/* address uniqueness */ \
mem_fill_modify##bits (start,end,(UNS_##bits)MEM_ADDR_UNIQ_##bits); \
ret = mem_verify_modify##bits (start,end,(UNS_##bits)MEM_ADDR_UNIQ_##bits, \
log, max_err,"address uniqueness"); \
return ret; \
}
/***********************************************************************
*
* Macro: MEM_TEST_DATA_BUS
*
* Purpose:
* Test the data bus one bit at a time at the specified address
* Use this test to verify that all pins of an off-chip data bus
* are wired to a memory device.
*
* Processing:
* Write and then read back a single 1 at each bit of the data bus
* all other bits read 0. If either read back fails, fail the test.
*
* Parameters:
* bits: one of 8, 16 or 32
* addr: the address to read
*
* Outputs: None
*
* Returns:
* 0 if the test passed. _BIT(failed_bit) if the test failed
*
* Notes:
* This macro is based on the function memTestDataBus from
* the file memtest.c version 1.0
*
* The "returns" is not a left-hand side. It describes what the
* return statement returns.
*
* Example usage:
*
* UNS_16 mem_test_data_bus16(UNS_16 * addr)
* {
* MEM_TEST_DATA_BUS(16,addr);
* }
*
*
**********************************************************************/
#define MEM_TEST_DATA_BUS(bits, addr) \
{ \
UNS_##bits pattern; \
for (pattern = 1; pattern != 0; pattern <<= 1) \
{ \
*addr = pattern; \
if (*addr != pattern) \
return (pattern); \
} \
return (0); \
}
/***********************************************************************
*
* Macro: MEM_TEST_ADDR_BUS
*
* Purpose:
* Test the address bus one bit at a time starting at the the specified
* base address address over the range of nbytes. Use this test to
* verify that all pins of an off-chip address bus are wired to a
* memory device.
*
* Processing:
* Write a pattern (0xAAAAAAAA) to memory at byte, halfword, or
* word offsets, 0, 1, 2, 4, 8, 16..., etc.
* Write a different pattern (0x55555555) at offset 0
* Verify that the memory at locations 1, 2, 4, 8, 16,..etc are
* unchanged.
* Change the memory at offset 0 back to the original pattern.
* For each offset 1, 2, 4, 8, 16, ...etc:
* Change the memory at the offset to the different pattern.
* Verify that all memory at offsets not equal to the offset
* where memory was changed contain the orignal pattern.
* Change the memory at the changed offset back to the original
* pattern.
*
* Parameters:
* bits: one of 8, 16 or 32
* base_addr: the address to read
* nbytes: number of bytes in the address range.
*
* Outputs: None
*
* Returns:
* 0 if the test passed. _BIT(failed_address) if the test failed
*
* Notes:
* This macro is based on the function memTestAddressBus from
* the file memtest.c version 1.0
*
* This macro assumes that (base_addr & (nbytes - 1)) == 0 if
* nbytes is the number of bytes in the address range to test.
*
* The "returns" is not a left-hand side. It describes what the
* return statement returns.
*
* Example usage:
*
* UNS_16 * mem_test_addr_bus16(UNS_16 * addr, UNS_32 nbytes)
* {
* MEM_TEST_ADDR_BUS(16,addr,nbytes);
* }
*
*
**********************************************************************/
#define MEM_TEST_ADDR_BUS(bits, base_addr, nbytes) \
{ \
UNS_32 addr_mask = (nbytes - 1); \
UNS_32 offset; \
UNS_32 test_offset; \
\
UNS_##bits pattern = (UNS_##bits) 0xAAAAAAAA; \
UNS_##bits antipattern = (UNS_##bits) 0x55555555; \
\
/* \
* For each bit of the address bus, form an address with that bit set \
* and all others clear. Assign the data stored at that address to \
* the value kept in pattern. Note that since array index notation \
* is being used, offset == 1 implies the least significant \
* bit of the data bus no matter what the size is. \
*/ \
for (offset = 1; (offset & addr_mask) != 0; offset <<= 1) \
base_addr[offset] = pattern; \
\
/* \
* Write antipattern to the first memory location in the addres range \
* tested and verify that the write did not change any of the writes \
* of pattern to the addresses previously written. Note that since \
* array index notation is being used, offset == 1 implies the \
* least significant bit of the data bus no matter what the size is. \
*/ \
test_offset = 0; \
base_addr[test_offset] = antipattern; \
for (offset = 1; (offset & addr_mask) != 0; offset <<= 1) \
{ \
if (base_addr[offset] != pattern) \
return ((UNS_##bits *) &base_addr[offset]); \
} \
\
/* \
* Write pattern to the first memory location in the addres range \
* tested. Next, for each bit of the address bus, for an address \
* with that bit set and all other clear. Set that offset to \
* antipattern. Verify that all previously written values of \
* pattern are unchanged. If any of the values are changed, \
* return the address that was written as anti-pattern. \
* Re-assign the value back to pattern prior to the next \
* iteration of the loop to maintain the initial condition \
* that memory at address offsets 0, 1, 2, 4, etc. contain pattern. \
*/ \
base_addr[test_offset] = pattern; \
for (test_offset = 1; (test_offset & addr_mask) != 0; \
test_offset <<= 1) \
{ \
base_addr[test_offset] = antipattern; \
\
if (base_addr[0] != pattern) \
return ((UNS_##bits *) &base_addr[test_offset]); \
for (offset = 1; (offset & addr_mask) != 0; offset <<= 1) \
if (base_addr[offset] != pattern && (offset != test_offset)) \
return ((UNS_##bits *) &base_addr[test_offset]); \
\
base_addr[test_offset] = pattern; \
} \
return (0); \
}
/***********************************************************************
*
* Macro: MEM_TEST_RANDOM
*
* Purpose:
* Test memory for address uniquness.
*
* Processing:
* Write a simple pattern to a pseudo-random address and verify it.
*
* Parameters:
* bits: The number of bits in the data bus; must be 8, 16 or 32
* start: The start address
* length: The number of bytes to test
* log: A pointer to an array of MEM_ERROR_T log entries.
* If log is NULL, then don't log errors
* max_err: The number of errors that can occur before the test
* aborts
* test_name: A pointer to a zero-terminated character string
* constant that names the test.
*
* Outputs:
* Errors are logged in the log file.
*
* Returns:
* _ERROR if parameters are out of range
* or the number of errors detected (can be 0).
*
* Notes:
* This function works best if the length is a power of 2.
* Use this as a test for address uniqueness. The probability of
* two memory locations at aliased addresses having the same
* value is very low.
*
**********************************************************************/
#define MEM_TEST_RANDOM(bits, start, length, log,max_err, test_name) \
{ \
UNS_##bits pattern; \
UNS_32 generators[MLS_MAXTAPS]; \
UNS_32 mask; \
UNS_32 reg, reg_len = 1; \
UNS_32 err_count = 0; \
volatile UNS_##bits read; \
\
/* convert length to units of the data size */ \
length /= sizeof(UNS_##bits); \
\
if (length == 0) \
return _ERROR; \
\
/* handle the case of one element separately */ \
if (length == 1) \
{ \
*start = 0; \
read = *start; \
if (read != 0) \
{ \
if (log != NULL) \
{ \
log[err_count].test_name = test_name; \
log[err_count].addr = start; \
log[err_count].written = pattern; \
log[err_count].read = read; \
} \
err_count++; \
} \
return err_count; \
\
} \
\
/* setup the MULS generator to make a sequence long enough */ \
mls_setup(reg_len,generators,&mask); \
while (mask < length - 1) \
{ \
if (++reg_len > MLS_MAXREG) \
return _ERROR; /* too big, can't do it. */ \
\
mls_setup(reg_len,generators,&mask); \
} \
\
/* fill memory */ \
pattern = 0; \
reg = mask; \
start[0] = pattern++; \
while (reg >= length) \
{ \
reg = mls_next_reg(reg, generators, mask); \
} \
\
do \
{ \
start[reg] = pattern++; \
do \
{ \
reg = mls_next_reg(reg, generators, mask); \
} while (reg >= length && reg != mask); \
} while (reg != mask); \
\
/* verify memory */ \
pattern = 0; \
reg = mask; \
read = start[0]; \
if (read != pattern) \
{ \
if (log != NULL) \
{ \
log[err_count].test_name = test_name; \
log[err_count].addr = &start[0]; \
log[err_count].written = pattern; \
log[err_count].read = read; \
} \
err_count++; \
} \
if (err_count >= max_err) \
return err_count; \
\
while (reg >= length) \
{ \
reg = mls_next_reg(reg, generators, mask); \
} \
\
pattern++; \
do \
{ \
read = start[reg]; \
if (read != pattern) \
{ \
if (log != NULL) \
{ \
log[err_count].test_name = test_name; \
log[err_count].addr = &start[reg]; \
log[err_count].written = pattern; \
log[err_count].read = read; \
} \
err_count++; \
} \
\
pattern++; \
do \
{ \
reg = mls_next_reg(reg, generators, mask); \
} while (reg >= length && reg != mask); \
\
} while (reg != mask && err_count < max_err); \
\
return err_count; \
}
/***********************************************************************
*
* Function: mem_fill8
*
* Purpose:
* fill the address range with an 8-bit pattern
*
* Processing:
*
* Parameters:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -