您好
请提供"DDR3读写测试代码"(或)如何在 C6678 EVM 或 K2H EVM 板上进行 DDR3测试?
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
您好
请提供"DDR3读写测试代码"(或)如何在 C6678 EVM 或 K2H EVM 板上进行 DDR3测试?
"DDR3读写测试代码"(或)如何在 C6678 EVM 或 K2H EVM 板上进行 DDR3测试?
先决条件 :
1.下载并安装 BIOSLUXMCSDK-K2 -支持 KeyStone II ARM A15 + DSP C66x 的 SYS/BIOS RTOS 和 Linux OS 的 MCSDK
版本:来自 http://software-dl.ti.com/sdoemb/sdoemb_public_sw/mcsdk/latest/index_FDS.html 的 MCSDK 3_01_04_07
(请在建议的路径中安装 SDK:C:\ti\)
2.下载并安装 CCS 9.3 , https://www.ti.com/tool/download/CCSTUDIO/9.3.0.00012
(请在建议的路径中安装:C:\ti\)
3.所讨论的 DDR3 Project 配套资料和源代码可从 http://www.ti.com/lit/zip/sprac04下载
4.解压缩 sprac04.zip 后、文件夹"keystone2-ddr3-debug-tools"包含 ddr3_eDMA_test 源代码。 (或)
从以下网址直接下载: e2e.ti.com/.../DDR3_5F00_EDMA_5F00_TEST.zip
步骤 :
=========
下面的视频中给出了相同的步骤:-
1.在 CCS 9.3中、将 DR3_EDMA_TEST 项目导入
2.在项目属性中,将 pdk_LOC 变量的路径设置为"C:\ti\pdk_keystone2_3_01_04_07\packages"
3. 在 main.c 的第47行中,将 K2K 更改为 K2H,如下所示
#include "ti/CSL/device/K2K/src/cslr_device.h"//开普勒特定存储器映射定义需要
#include "ti/CSL/device/k2h/src/cslr_device.h" //霍金特定的内存映射定义需要
4.在 CCS 项目属性--> C6000链接器-->文件搜索路径-->中,包含位于 /ti/csl/lib/k2h/c66的 CSL 库:"ti.csl.ae66"。
在 C6000编译器中-->高级选项-->预定义符号预定义名称--> SOC_C6678
4.构建并运行
5.在 C6678 EVM 或 K2H EVM 上测试
a)"无引导模式"上的 DIP 开关设置
b)启动目标配置文件并连接目标。 这将运行 GEL 文件。
c)加载 DR3_EDMA_test 的二进制文件并运行/执行程序
d)按如下所示观察输出。
下面的视频中给出了相同的步骤:-
(视频将很快上传)
e2e.ti.com/.../DDR3_5F00_EDMA_5F00_Import_5F00_Project.mp4
e2e.ti.com/.../DDR3_5F00_EDMA_5F00_Build.mp4
e2e.ti.com/.../RUn_5F00_DDR3_5F00_test_5F00_C6678.mp4
=========
对于 K2H:
=========
请遵循相同的过程。 在预定义符号中、设置 SOC_K2H 并生成
e2e.ti.com/.../Build_5F00_K2H_5F00_DDR3test.mp4
DDR3测试代码:
/****************************************************************************** * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * 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. * * * Neither the name of Texas Instruments Incorporated nor the names of * its 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. * ****************************************************************************** * * DDR3 EDMA Test * * DDR3 Stress Test for K2 Devices * * Revision v1.0, August 2015 */ // Project Includes --------------------- #include <stdio.h> #include <stdint.h> #include <c6x.h> #include "ti/csl/csl.h" // needed for CSL data type definitions #include "ti/csl/device/k2h/src/cslr_device.h" // needed for Hawking specific memory map definition #include "ti/csl/csl_cacheAux.h" // needed for cache disable functions #include "defines.h" // Project Defines (User Configurable)--- #define EDMA_ON_WRITE1 1 #define EDMA_ON_WRITE2 1 #define EDMA_ON_READ1 1 #define EDMA_ON_READ2 1 #define DDR3A_TEST 1 //Select either DDR3A OR DDR3B, not both #define DDR3B_TEST 0 //Select either DDR3A OR DDR3B, not both // Global Declarations/Definitions ------ unsigned int test_revision = 1; unsigned int errcnt; unsigned int global_count; unsigned int read_val, error_check; unsigned int delay = 2; unsigned int delay2 = 2000; unsigned int delay3a = 50000; #define L2_C66x0_GLOBAL_ADDR (0x10800000) #define L2_C66x0_GLOBAL_ADDR_2 (0x10808000) #define MSMC_MEM_ADDR (0x0c000000) #define MSMC_MEM_ADDR_2 (0x0c010000) #define MSMC_MEM_ADDR_3 (0x0c010000) #define DDR3B_PHYS_ADDR (0x60000000) unsigned int temp_val; unsigned int L1_cache_value; unsigned int L2_cache_value; /************************************************************************************ * * DDR3 MPAX Configuration * This function configures the c66x MPAX to point the local address 0x8000_0000 * to the upper bits of the physical address given by address_start * -----------------------------------------------------------------------------------*/ void ddr3_mpax_segment2_setup(unsigned int address_start){ XMPAX2_L = address_start | 0x3F; // Upper Bits of 36-bit address space XMPAX2_H = 0x8000001E; //Local address of 0x8000_0000 } void delay_func(unsigned int delay) { unsigned int i; for(i=0;i<delay;i++); } /************************************************************************************ * * DDR3A EDMA Config * This function configures the QDMA in the EDMA for burst access. The physical address * of the source/destination, and the size of the transfer block are given in the * function parameters. * -----------------------------------------------------------------------------------*/ void ddr3_edma_config(unsigned int src, unsigned int dst, unsigned int nbytes) { unsigned int acnt = nbytes; unsigned int bcnt = 1; unsigned int ccnt = 1; // Clear the pending interrupt EDMA_ICR = 0x1; // QDMA channel 0 uses parameter set 0, trigger word 7 EDMA_QCHMAP0 = 0x1C; // Enable QDMA channel 0 */ EDMA_QEESR = 0x1; // PARAM 0, opt - tciintn, static and syncdim set EDMA_PARAM_0_0 = 0x0010000c; // PARAM 1 - source address EDMA_PARAM_0_1 = src; // PARAM 2 - bcount, acount EDMA_PARAM_0_2 = (bcnt << 16) | acnt; // PARAM 3, destination EDMA_PARAM_0_3 = dst; // PARAM 4 dstbidx, srcbidx EDMA_PARAM_0_4 = acnt; // PARAM 5 - link EDMA_PARAM_0_5 = 0xffff; // PARAM 6 - dstcidx, srccidx EDMA_PARAM_0_6 = 0; // PARAM 7 - ccnt EDMA_PARAM_0_7 = ccnt; // Wait until complete interrupt while ((EDMA_IPR & 0x1) != 1){ delay_func(10); } // Scrub Interrupt EDMA_ICR = 0x1; // Disable QDMA Channel 0 //EDMA_QEECR = 0x1 // Clear the channel map EDMA_QCHMAP0 = 0x0; } /************************************************************************************ * * MSM Populate Function * This function serves to populate the MSM of pattern and size given in the function * parameters. The data patterns themselves are provided in the defines.h * project file. * -----------------------------------------------------------------------------------*/ void populate_MSM(unsigned long long int DATA_PATTERN, unsigned int nbytes) { unsigned int i; // Place First Data Pattern in MSM if (DATA_PATTERN == 1){ for(i=0;i<nbytes;i++){ (*(unsigned long long int*)(MSMC_MEM_ADDR+(i*0x08))) = DATA_PATTERN_inc[i]; } } // Place Second Data Pattern in MSM if (DATA_PATTERN == 2){ for(i=0;i<nbytes;i++){ (*(unsigned long long int*)(MSMC_MEM_ADDR+(i*0x08))) = DATA_PATTERN_zeroes[i]; } } } /************************************************************************************ * * DDR3 Write Read Memory Test * This function serves to execute the test write->read, write->read cycles * -----------------------------------------------------------------------------------*/ void ddr3a_edma_memory_test(unsigned int DDR3_TEST_START, unsigned int nbytes) { unsigned int PATTERN1 = 1; unsigned int PATTERN2 = 2; unsigned int TEST_WORDS = 2048; unsigned int TEST_READS = 2; unsigned int ERROR_MAX = 500; unsigned int i,j,k,errCnt=0; unsigned long long int doubletemp_val; // First pass // Populate MSM with 256 word pattern populate_MSM(PATTERN1, nbytes); errCnt = 0; for(i=0;i<TEST_WORDS;i++){ // Block Write MSM->DDR #if (EDMA_ON_WRITE1) ddr3_edma_config(MSMC_MEM_ADDR, (DDR3_TEST_START+(i*nbytes*8)), nbytes*8); #else for(k=0;k<(nbytes);k++){ (*(unsigned long long int*)(DDR3_TEST_START+(i*nbytes*8)+(8*k))) = DATA_PATTERN_inc[k]; } #endif } #if(EDMA_ON_READ1) //Iterate through addresses range for read for(i=0;i<TEST_WORDS;i++){ for(j=0;j<TEST_READS;j++){ // Block Read DDR->MSM ddr3_edma_config((DDR3_TEST_START+(i*nbytes*8)), MSMC_MEM_ADDR_2, nbytes*8); // Iterate through MSM, make data comparison for(k=0;k<(nbytes);k++){ doubletemp_val = (*(unsigned long long int*)(MSMC_MEM_ADDR_2 + (8*k))); if ((doubletemp_val != DATA_PATTERN_inc[k]) && (errCnt < ERROR_MAX)){ printf("DMA1 Read Error @ %x, read cycle %d. Expected: %.16llx, Got: %.16llx\n",(DDR3_TEST_START+(i*nbytes)+(8*k)), j, DATA_PATTERN_inc[k], doubletemp_val); errCnt++; } } } } #else for(i=0;i<TEST_WORDS;i++){ for(j=0;j<TEST_READS;j++){ for(k=0;k<nbytes;k++){ *(unsigned long long int*)(MSMC_MEM_ADDR_3+(8*k)) = (*(unsigned long long int*)(DDR3_TEST_START+(i*nbytes*8)+(8*k))); } for(k=0;k<(nbytes);k++){ doubletemp_val = (*(unsigned long long int*)(MSMC_MEM_ADDR_3+(8*k))); if ((doubletemp_val != DATA_PATTERN_inc[k]) && (errCnt < ERROR_MAX)){ printf("Read1 Error @ %x, read cycle %d, word %d. Expected: %.16llx, Got: %.16llx\n",(DDR3_TEST_START+(i*nbytes*8)+(8*k)), j,k, DATA_PATTERN_inc[k], doubletemp_val); errCnt++; } } } } #endif // Populate MSM with 256 word pattern populate_MSM(PATTERN2, nbytes); errCnt = 0; for(i=0;i<TEST_WORDS;i++){ // Block Write MSM->DDR #if (EDMA_ON_WRITE2) ddr3_edma_config(MSMC_MEM_ADDR, (DDR3_TEST_START+(i*nbytes*8)), nbytes*8); #else for(k=0;k<(nbytes);k++){ (*(unsigned long long int*)(DDR3_TEST_START+(i*nbytes*8)+(8*k))) = DATA_PATTERN_zeroes[k]; } #endif } #if(EDMA_ON_READ1) //Iterate through addresses range for read for(i=0;i<TEST_WORDS;i++){ for(j=0;j<TEST_READS;j++){ // Block Read DDR->MSM ddr3_edma_config((DDR3_TEST_START+(i*nbytes*8)), MSMC_MEM_ADDR_2, nbytes*8); // Iterate through MSM, make data comparison for(k=0;k<(nbytes);k++){ doubletemp_val = (*(unsigned long long int*)(MSMC_MEM_ADDR_2 + (8*k))); if ((doubletemp_val != DATA_PATTERN_zeroes[k]) && (errCnt < ERROR_MAX)){ printf("DMA2 Read Error @ %x, read cycle %d. Expected: %.16llx, Got: %.16llx\n",(DDR3_TEST_START+(i*nbytes*8)+(8*k)), j, DATA_PATTERN_zeroes[k], doubletemp_val); errCnt++; } } } } #else for(i=0;i<TEST_WORDS;i++){ for(j=0;j<TEST_READS;j++){ for(k=0;k<nbytes;k++){ *(unsigned long long int*)(MSMC_MEM_ADDR_3+(8*k)) = (*(unsigned long long int*)(DDR3_TEST_START+(i*nbytes*8)+(8*k))); } // Only check first burst (assumes nbytes=256) for(k=0;k<(nbytes);k++){ doubletemp_val = (*(unsigned long long int*)(MSMC_MEM_ADDR_3+(8*k))); if ((doubletemp_val != DATA_PATTERN_zeroes[k]) && (errCnt < ERROR_MAX)){ //GPIO_assert(); printf("Read2 Error @ %x, read cycle %d, word %d. Expected: %.16llx, Got: %.16llx\n",(DDR3_TEST_START+(i*nbytes*8)+(8*k)), j,k, DATA_PATTERN_zeroes[k], doubletemp_val); errCnt++; } } } } #endif if(errCnt >= ERROR_MAX){printf("Error count hit maximum. Not all errors displayed.\n");} // Error Conclusion if(errCnt >= 1){ printf("Error(s) found in Test iteration.\n"); } } void ddr3b_edma_memory_test(unsigned int DDR3_TEST_START, unsigned int nbytes) { unsigned int PATTERN1 = 1; unsigned int PATTERN2 = 2; unsigned int TEST_WORDS = 2048; unsigned int TEST_READS = 2; unsigned int ERROR_MAX = 5000; unsigned int i,j,k,errCnt=0; unsigned long long int doubletemp_val; // First pass // Populate MSM with 256 word pattern populate_MSM(PATTERN1, nbytes); errCnt = 0; for(i=0;i<TEST_WORDS;i++){ // Block Write MSM->DDR #if (EDMA_ON_WRITE1) ddr3_edma_config(MSMC_MEM_ADDR, (DDR3B_PHYS_ADDR+(i*nbytes*8)), nbytes*8); #else for(k=0;k<(nbytes);k++){ (*(unsigned long long int*)(DDR3_TEST_START+(i*nbytes*8)+(8*k))) = DATA_PATTERN_inc[k]; } #endif } #if(EDMA_ON_READ1) //Iterate through addresses range for read for(i=0;i<TEST_WORDS;i++){ for(j=0;j<TEST_READS;j++){ // Block Read DDR->MSM ddr3_edma_config((DDR3B_PHYS_ADDR+(i*nbytes*8)), MSMC_MEM_ADDR_2, nbytes*8); // Iterate through MSM, make data comparison for(k=0;k<(nbytes);k++){ doubletemp_val = (*(unsigned long long int*)(MSMC_MEM_ADDR_2 + (8*k))); if ((doubletemp_val != DATA_PATTERN_inc[k]) && (errCnt < ERROR_MAX)){ printf("DMA1 Read Error @ %x, read cycle %d. Expected: %.16llx, Got: %.16llx\n",(DDR3_TEST_START+(i*nbytes*8)+(8*k)), j, DATA_PATTERN_inc[k], doubletemp_val); errCnt++; } } } } #else //Iterate through addresses range for read for(i=0;i<TEST_WORDS;i++){ for(j=0;j<TEST_READS;j++){ // Read DDR->MSM for(k=0;k<nbytes;k++){ *(unsigned long long int*)(MSMC_MEM_ADDR_3+(8*k)) = (*(unsigned long long int*)(DDR3_TEST_START+(i*nbytes*8)+(8*k))); } // Iterate through MSM, make data comparison for(k=0;k<(nbytes);k++){ doubletemp_val = (*(unsigned long long int*)(MSMC_MEM_ADDR_3+(8*k))); if ((doubletemp_val != DATA_PATTERN_inc[k]) && (errCnt < ERROR_MAX)){ printf("Read1 Error @ %x, read cycle %d, word %d. Expected: %.16llx, Got: %.16llx\n",(DDR3_TEST_START+(i*nbytes*8)+(8*k)), j,k, DATA_PATTERN_inc[k], doubletemp_val); errCnt++; } } } } #endif // Second Pass // Populate MSM with 256 word pattern populate_MSM(PATTERN2, nbytes); errCnt = 0; for(i=0;i<TEST_WORDS;i++){ // Block Write MSM->DDR #if (EDMA_ON_WRITE2) ddr3_edma_config(MSMC_MEM_ADDR, (DDR3B_PHYS_ADDR+(i*nbytes*8)), nbytes*8); #else for(k=0;k<(nbytes);k++){ (*(unsigned long long int*)(DDR3_TEST_START+(i*nbytes)+(8*k))) = DATA_PATTERN_zeroes[k]; } #endif } #if(EDMA_ON_READ2) //Iterate through addresses range for read for(i=0;i<TEST_WORDS;i++){ for(j=0;j<TEST_READS;j++){ // Block Read DDR->MSM ddr3_edma_config((DDR3B_PHYS_ADDR+(i*nbytes*8)), MSMC_MEM_ADDR_2, nbytes*8); // Iterate through MSM, make data comparison for(k=0;k<(nbytes);k++){ doubletemp_val = (*(unsigned long long int*)(MSMC_MEM_ADDR_2 + (8*k))); if ((doubletemp_val != DATA_PATTERN_zeroes[k]) && (errCnt < ERROR_MAX)){ printf("DMA2 Read Error @ %x, read cycle %d. Expected: %.16llx, Got: %.16llx\n",(DDR3_TEST_START+(i*nbytes*8)+(8*k)), j, DATA_PATTERN_zeroes[k], doubletemp_val); errCnt++; } } } } #else //Iterate through addresses range for read for(i=0;i<TEST_WORDS;i++){ for(j=0;j<TEST_READS;j++){ // Read DDR->MSM for(k=0;k<nbytes;k++){ *(unsigned long long int*)(MSMC_MEM_ADDR_3+(8*k)) = (*(unsigned long long int*)(DDR3_TEST_START+(i*nbytes*8)+(8*k))); } // Iterate through MSM, make data comparison for(k=0;k<(nbytes);k++){ doubletemp_val = (*(unsigned long long int*)(MSMC_MEM_ADDR_3+(8*k))); if ((doubletemp_val != DATA_PATTERN_zeroes[k]) && (errCnt < ERROR_MAX)){ //GPIO_assert(); printf("Read2 Error @ %x, read cycle %d, word %d. Expected: %.16llx, Got: %.16llx\n",(DDR3_TEST_START+(i*nbytes*8)+(8*k)), j,k, DATA_PATTERN_zeroes[k], doubletemp_val); errCnt++; } } } } #endif if(errCnt >= ERROR_MAX){printf("Error count hit maximum. Not all errors displayed.\n");} // Error Conclusion if(errCnt >= 1){ printf("Error(s) found in Test iteration.\n"); } } void main(void) { unsigned int counter=0; printf("Beginning DDR3 Memory Test (Rev %d)\n", test_revision); printf("Turning off L1 Data Cache.\n"); CACHE_setL1DSize(CACHE_L1_0KCACHE); printf("Turning off L2 Cache.\n"); CACHE_setL2Size(CACHE_0KCACHE); #if(DDR3A_TEST) printf("Starting DDR3A memory test...\n"); #elif(DDR3B_TEST) printf("Starting DDR3B memory test...\n"); #endif while(counter < 500){ #if(DDR3A_TEST) ddr3a_edma_memory_test(0x80000000, 256); #elif(DDR3B_TEST) ddr3_mpax_segment2_setup(0x08000000); ddr3b_edma_memory_test(0x80000000, 256); ddr3_mpax_segment2_setup(0x80000000); #endif counter++; if((counter % 25) == 0){ printf("Test Pulse %d\n", counter/25); } } printf("Memory Test Completed.\n"); }
请访问有关"如何计算 KeyStone 器件的"DDR3接口–寄存器"和 Keystone EVM 上的测试/调试"的常见问题解答
梯形- I
梯形- II
此致
尚卡里