📄 sdramtest.c
字号:
#include "vxWorks.h"
#include "config.h"
#include "semLib.h"
#include "cacheLib.h"
#include "ioLib.h"
#include "taskLib.h"
#include "BoardApi.h" /*added by jack*/
/*****************************************************************************
* 函数名称 : TestSdramData(*)
* 功能描述 : 测试内存数据线是否正常工作
* 读全局变量 : 无
* 写全局变量 : 无
* 输入参数 : 无
* 输出参数 : 无
* 返 回 值 : 成功与否
* 其它说明 :
*---------------------------------------------------------------------------
* 历史记录(变更单, 责任人@修改日期, 操作说明)
* $0000000(N/A), 田瑞忠@2007-12-14 9:36:42
*----------------------------------------------------------------------------
*/
ULONG TestSdramData(void)
{
register ULONG i, j, testVal;
int testAdrVal;
printf("\nTest Data Bus of SDRAM at %p...\n\n", &testAdrVal);
testAdrVal = testVal = 0;
if (testAdrVal != testVal)
{
printf("\nCan't write to zero at %p!\n", &testAdrVal);
}
for (i = j = 0, testVal = 1; i < 32; i++, testVal <<= 1)
{
testAdrVal = testVal;
printf("Test SDRAM data bus line #%d, ", i);
if (testAdrVal != testVal)
{
printf("read %p while %p expected\n!", testAdrVal, testVal);
j++;
}
else
{
printf("OK!\n");
}
taskDelay(sysClkRateGet() / 4);
}
printf("\nSDRAM test, data line OK!\n");
return j;
}
/*****************************************************************************
* 函数名称 : TestSdramAddr(*)
* 功能描述 : 测试内存地址线
* 读全局变量 : 无
* 写全局变量 : 无
* 输入参数 : 无
* 输出参数 : 无
* 返 回 值 : 成功与否
* 其它说明 : 部分借鉴了中兴3G平台的思想(最大内存获取, 高端地址开始)
*---------------------------------------------------------------------------
* 历史记录(变更单, 责任人@修改日期, 操作说明)
* $0000000(N/A), 田瑞忠@2007-12-14 9:34:07
*----------------------------------------------------------------------------
*/
ULONG TestSdramAddr(void)
{
UCHAR ucTotalLine, ucErrorLine, ucCountLine, ucIndex, ucBitCount;
ULONG dwSafeStart, dwSafeEnd, dwTestAddr, dwBitMask;
ULONG dwTestCount, *pBaseAddr, *pStoreVal, *pStoreAdrs;
register ULONG dwTestedBit;
/* 计算有效地址比特数, 减4去除边界单元计数 */
dwTestAddr = (ULONG)sysPhysMemTop() - sizeof(ULONG);
for (ucIndex = 0; dwTestAddr; dwTestAddr >>= 1) ucIndex++;
ucTotalLine = ucIndex;
printf("\nTest Address Bus of SDRAM...\n");
/* 取得最大的可用测试内存, 实际上是找到最小的低端可用内存地址 */
dwTestCount = (ULONG)memFindMax() / sizeof(ULONG) * sizeof(ULONG);
for (pStoreAdrs = NULL; dwTestCount >= 0x2000; dwTestCount -= 0x2000)
{
if (NULL != (pStoreAdrs = (ULONG *)malloc(dwTestCount))) break;
}
if (pStoreAdrs == NULL)
{
printf("\nCan't allocate memory for SDRAM address test!\n");
return BSP_ERROR;
}
pBaseAddr = 0;
pStoreVal = pStoreAdrs + 32;
dwSafeStart = (ULONG)(pStoreVal + 32) / sizeof(ULONG);
dwSafeEnd = ((ULONG)pStoreAdrs + dwTestCount) / sizeof(ULONG);
/* 通常情况下, 系统驻留在低端内存, 测试从终止地址(高端)开始,
* 通过切换地址比特位, 可以尽可能地测试到最多的地址线,
* 只要系统占用的内存不超过物理存储区的一半, 理论上说就可以遍历所有地址线 */
printf("\nSafe start address %p, end address %p.\n",
dwSafeStart * sizeof(ULONG), dwSafeEnd * sizeof(ULONG));
ucCountLine = ucErrorLine = 0;
/* 对于测试地址线用到的存储区, 将原来的数据保留,
* 以便在测试结束后可以恢复 */
pStoreAdrs[ucCountLine] = dwSafeEnd;
pStoreVal[ucCountLine] = pBaseAddr[dwSafeEnd];
/* 第一个测试地址中的数据清0 */
pBaseAddr[dwSafeEnd] = 0, dwBitMask = 1, dwTestedBit = 0;
/* 找到可用的测试地址, 并往相应的存储单元中填入测试数据 */
for(ucIndex = 2; ucIndex < ucTotalLine; ucIndex++, dwBitMask <<= 1)
{
dwTestAddr = dwSafeEnd ^ dwBitMask;
/* 对于高端内存的数据, 一般不是核心数据, 由于这些数据都可以恢复,
* 所以对于超过安全测试区的地址, 也可以进行测试 */
if (dwTestAddr >= dwSafeStart &&
dwTestAddr <= (ULONG)sysPhysMemTop() / sizeof(ULONG))
{
ucCountLine++, dwTestedBit |= 0x1 << ucIndex;
pStoreAdrs[ucCountLine] = dwTestAddr;
pStoreVal[ucCountLine] = pBaseAddr[dwTestAddr];
pBaseAddr[dwTestAddr] = 0x01010101 * ucIndex;
}
}
/* 当测试的地址线并不充分时, 给出警示信息 */
if (ucCountLine + 2 < ucTotalLine)
{
printf("nOnly test %d address line for all %d line\n",
ucCountLine, ucTotalLine);
}
/* 对比测试数据, 与期望值是否匹配, 从读出来的数据分析,
* 不仅可以判断地址线存在问题, 还可以判断存在串扰及部分判断数据线的问题 */
dwTestAddr = pStoreAdrs[0];
if (pBaseAddr[dwTestAddr] != 0)
{
printf("Begin address read %p at %p while 0 is expected!",
pBaseAddr[dwTestAddr], dwTestAddr * 4);
}
for (ucBitCount = 2, ucIndex = 1; ucIndex <= ucCountLine;)
{
dwTestAddr = pStoreAdrs[ucIndex];
while ((dwTestedBit & (1 << ucBitCount)) == 0) ucBitCount++;
printf("test SDRAM address bus line #%d at %p, ",
31 - ucBitCount, dwTestAddr * 4);
if (pBaseAddr[dwTestAddr] != 0x01010101 * ucBitCount)
{
printf("read %p, %p expected!\n",
pBaseAddr[dwTestAddr], 0x01010101 * ucBitCount);
ucErrorLine++;
}
else
{
printf("OK!\n");
}
taskDelay(sysClkRateGet() / 4);
ucIndex++, ucBitCount++;
}
/* 恢复测试用到的内存单元中的数据 */
for(ucIndex = 0; ucIndex <= ucCountLine; ucIndex++)
{
dwTestAddr = pStoreAdrs[ucIndex];
pBaseAddr[dwTestAddr] = pStoreVal[ucIndex];
}
free(pStoreAdrs);
if (ucErrorLine)
{
printf("\nTest Address Bus %d lines Failed, %d error\n.",
ucCountLine, ucErrorLine);
return BSP_ERROR;
}
printf("\nTest Address Bus %d lines OK!\n", ucCountLine);
return BSP_OK;
} /* TestSdramAddr() */
/*****************************************************************************
* 函数名称 : TestSdramWR(*)
* 功能描述 : 内存存储单元遍历测试
* 读全局变量 : 无
* 写全局变量 : 无
* 输入参数 : 无
* 输出参数 : 无
* 返 回 值 : 成功与否
* 其它说明 :
*---------------------------------------------------------------------------
* 历史记录(变更单, 责任人@修改日期, 操作说明)
* $0000000(N/A), 田瑞忠@2007-12-14 9:34:07
*----------------------------------------------------------------------------
*/
ULONG TestSdramWR(void)
{
ULONG dwBadCells, dwBadCount, dwCount, dwTestCount, dwBadAll;
ULONG *pBaseAddr;
/* 取得最大的可用测试内存, 实际上是找到最小的低端可用内存地址 */
dwTestCount = (ULONG)memFindMax() & 0xffff0000;
for (pBaseAddr = NULL; dwTestCount >= 0x10000; dwTestCount -= 0x10000)
{
if (NULL != (pBaseAddr = (ULONG *)malloc(dwTestCount))) break;
}
if (pBaseAddr == NULL)
{
printf("\nCan't allocate memory for SDRAM address test!\n");
return BSP_ERROR;
}
printf("\nTest memory cell of SDRAM...\n");
printf("Start address %p, end address %p, length %lu Bytes\n",
pBaseAddr, pBaseAddr + dwTestCount / sizeof(ULONG), dwTestCount);
printf("Writing first time(0x55555555):\n");
dwBadCells = 0, dwBadCount = 0;
for (dwCount = 0; dwCount < dwTestCount / sizeof(ULONG);)
{
pBaseAddr[dwCount++] = 0x55555555;
if ((dwCount & 0x7fff) == 0) printf(".");
}
printf("\nReading first time('.' for OK, '0'~'9' for error):\n");
for (dwCount = 0; dwCount < dwTestCount / sizeof(ULONG);)
{
if (pBaseAddr[dwCount++] != 0x55555555)
{
dwBadCells++, dwBadCount++;
}
if ((dwCount & 0x7fff) == 0)
{
if (dwBadCount)
{
printf("%c", '0' + (dwBadCount - 1) * 10 / 0x4000);
}
else
{
printf(".");
}
dwBadCount = 0;
}
}
printf("\nfirst cycle ended, bad cells %lu\n", dwBadCells);
taskDelay(sysClkRateGet() / 2);
printf("Writing seconed time(0xaaaaaaaa):\n");
dwBadAll = dwBadCells, dwBadCells = 0, dwBadCount = 0;
for (dwCount = 0; dwCount < dwTestCount / sizeof(ULONG); )
{
pBaseAddr[dwCount++] = 0xaaaaaaaa;
if ((dwCount & 0x7fff) == 0) printf(".");
}
printf("\nReading second time('.' for OK, '0'~'9' for error):\n");
for (dwCount = 0; dwCount < dwTestCount / sizeof(ULONG); )
{
if (pBaseAddr[dwCount++] != 0xaaaaaaaa)
{
dwBadCells++, dwBadCount++;
}
if ((dwCount & 0x7fff) == 0)
{
if (dwBadCount)
{
printf("%c", '0' + (dwBadCount - 1) * 10 / 0x4000);
}
else
{
printf(".");
}
dwBadCount = 0;
}
}
printf("\nsecond cycle ended, bad cells %lu\n", dwBadCells);
dwBadAll += dwBadCells;
free(pBaseAddr);
return dwBadAll;
}
/*****************************************************************************
* 函数名称 : SdramTest(*)
* 功能描述 : 测试内存地址线
* 读全局变量 : 无
* 写全局变量 : 无
* 输入参数 : 无
* 输出参数 : 无
* 返 回 值 : 成功与否
* 其它说明 : 部分借鉴了中兴3G平台的思想(最大内存获取, 高端地址开始)
*---------------------------------------------------------------------------
* 历史记录(变更单, 责任人@修改日期, 操作说明)
* $0000000(N/A), 田瑞忠@2007-12-14 9:34:07
*----------------------------------------------------------------------------
*/
ULONG SdramTest(void)
{
UCHAR ucGet;
ULONG ulRet;
/* 禁用CACHE, 以便立即访问数据及地址总线 */
cacheDisable(DATA_CACHE);
cacheDisable(INSTRUCTION_CACHE);
/* 首先测试数据总线 */
ulRet = TestSdramData();
printf("Press 'q' to abort, other key to continue...");
ucGet = getQuitChar("", WAIT_FOREVER);
if (ucGet == 'q' || ucGet == 'Q')
{
return ulRet;
}
/* 其次测试地址总线 */
(ulRet == BSP_OK) ? (ulRet = TestSdramAddr()) : TestSdramAddr();
printf("Press 'q' to abort, other key to continue...");
ucGet = getQuitChar("", WAIT_FOREVER);
if (ucGet == 'q' || ucGet == 'Q')
{
return ulRet;
}
/* 最后测试读写 */
(ulRet == BSP_OK) ? (ulRet = TestSdramWR()) : TestSdramWR();
cacheEnable(DATA_CACHE);
cacheEnable(INSTRUCTION_CACHE);
return ulRet;
} /* SdramTest() */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -