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.

EDMA:L2与L2成功,DDR3与L2却失败



大家好,

我用的平台是我们这边自己做的TCI6618的一块板子

现在我打算测试EDMA在DDR3内 搬移数据的效率什么的

我简单的用*(DDR3_BASE_ADDR++) = temp;这样的语句是可以操作DDR3的

但是换成EDMA去操作DDR3就不行了

而我在EDMA中,把源地址、目的地址都设在Core0的L2上(0x10800000处开始),EDMA是能够正常搬移数据的

而源地址为L2、目的地址为DDR3的话,

    do {
        CSL_edma3GetHwStatus(hModule,CSL_EDMA3_QUERY_INTRPEND,&regionIntr);
    } while (!(regionIntr.intr & 0x1));

这个while循环也通过了

但是目的地址端看不到源地址的数据!!

有人遇到过这种情况吗?求赐教!

是不是跟Memory Protection之类的有关?

或者跟Privilege有关?我设置PaRAM的OPT为0x00100008,但是观察得0x801000008,即运行在Supervisor level privilege模式下。。。

  • 1. 先使用core对DDR进行memory测试,确认DDR配置正确,memory测试没有问题;

    2. 使用EDMA时,在配置完后可以看看对应param set的配置是否正确;

    3. 默认情况下是可以直接访问DDR,与内存保护应该没有关系。

  • 1. 我在测试EDMA之前,用*(DDR3_BASE_ADDR++) = temp;这个样的语句去操作DDR3,从Memory Broswer能正确观察到所写的值。应该说明了DDR配置正确了。

    2.在使用EDMA时,配置完参数后,观察了param set,发现配置正确。唯一不同的是OPT的第31位PRIV,为1,即supervisor level privilege,即使我没有设置。

    3. 我测试L2到DDR3测数据传输,发现poll while循环都已经过了,但是却在Memory Broswer中无法观察到DDR3中有传输过来的数据。

  • 1 你的代码中有对MPAX进行重配么,如果有的话确认一下SES MPAX的配置是否有将DDR逻辑地址映射;

    2 PRIV bit不会影响,这是反映状态的值,你可以比较看看初始化之后及运行完成后的PaRAM set配置值,看EDMA是否真的被触发并且执行完成。

  • 我的程序用到了SYS/BIOS,

    参照了例子程序,用子函数

    static Int32 EDMA_test (Int32 instNum, Uint8 channelNum);

    进行了EDMA测试。您应该对这个EDMA的例子程序非常熟悉的。

    我在主函数中的调用是

    EDMA_test(1,6);

    即计划使用EDMACC1的通道6,用于数据传输。

    例子程序是pingpong操作,我改了一些地方,只想实现从L2到DDR进行一次的数据搬移(或者DDR3到DDR3的数据搬移),而不做pingpong。

    更改如下:

    1.首先改了源地址和目的地址

        Uint16 * srcBuff1 = (Uint16 *)0x10800000;//源地址,L2
        Uint16 * dstBuff1= (Uint16 *)0x80000000;//目的地址,DDR3

    2.初始化了源地址、目的地址的数据

        for (loopIndex = 0; loopIndex < 256; loopIndex++)
        {
            srcBuff1[loopIndex] = 0xABCD;
            dstBuff1[loopIndex] = 0;
        }

    3.没有修改例子程序中EDMA句柄的打开、pamset参数的初始化等等

    CSL_edma3Init(&context)

    hModule = CSL_edma3Open(&edmaObj, instNum, NULL, &status);

    chAttr.regionNum = CSL_EDMA3_REGION_GLOBAL; 

    chAttr.chaNum    = channelNum;

    chChannel = CSL_edma3ChannelOpen(&chObj, instNum, &chAttr, &status);

    CSL_edma3HwChannelSetupQue(hChannel,CSL_EDMA3_QUE_3);

    CSL_edma3MapDMAChannelToParamBlock (hModule, channelNum, 2);

     hParamPing = CSL_edma3GetParamHandle(hChannel, 2, &status);

    4.修改了Param Set参数,acnt=256,bcnt=ccnt=1,bidx=cidx=0,使能Transfer completion  interrupt,没用LINK

        myParamSetup.option = CSL_EDMA3_OPT_MAKE(CSL_EDMA3_ITCCH_DIS, \
                                                 CSL_EDMA3_TCCH_DIS, \
                                                 CSL_EDMA3_ITCINT_DIS, \
                                                 CSL_EDMA3_TCINT_EN, \
                                                 0x6, CSL_EDMA3_TCC_NORMAL,\
                                                 CSL_EDMA3_FIFOWIDTH_NONE, \
                                                 CSL_EDMA3_STATIC_EN, \
                                                 CSL_EDMA3_SYNC_A, \
                                                 CSL_EDMA3_ADDRMODE_INCR, \
                                                 CSL_EDMA3_ADDRMODE_INCR );
        myParamSetup.srcAddr    = (Uint32)srcBuff1;
        myParamSetup.aCntbCnt   = CSL_EDMA3_CNT_MAKE(256,1);
        myParamSetup.dstAddr    = (Uint32)dstBuff1;
        myParamSetup.srcDstBidx = CSL_EDMA3_BIDX_MAKE(0,0);
        myParamSetup.linkBcntrld= 0xFFFF;
        myParamSetup.srcDstCidx = CSL_EDMA3_CIDX_MAKE(0,0);
        myParamSetup.cCnt = 1;
        if (CSL_edma3ParamSetup(hParamPing,&myParamSetup) != CSL_SOK)
        {
            printf ("Error: EDMA Parameter Entry Setup failed\n");
            return -1;
        }
    5.使能第6通道的中断
        /* Interrupt enable (Bits 0-1)  for the global region interrupts */
        regionIntr.region = CSL_EDMA3_REGION_GLOBAL;
        regionIntr.intr   = 0x40;
        regionIntr.intrh  = 0x0000;
        CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_INTR_ENABLE,&regionIntr);

    6.手动触发EDMA

    CSL_edma3HwChannelControl(hChannel,CSL_EDMA3_CMD_CHANNEL_SET,NULL);

    7.poll第6通道中断的完成标识位

        regionIntr.region = CSL_EDMA3_REGION_GLOBAL;
        regionIntr.intr   = 0;
        regionIntr.intrh  = 0;
        do {
            CSL_edma3GetHwStatus(hModule,CSL_EDMA3_QUERY_INTRPEND,&regionIntr);
        } while (!(regionIntr.intr & 0x40));

    ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

    对于上面的程序

    如果我把源地址和目的地址都放在L2内的话,CC1的第6通道中断完成标识位可以poll到,并且能够在目的地址段能观察到源地址发送来的数据。

    现在的问题是:

    如果我把源地址设在L2内,目的地址设在DDR3内,CC1的第6通道中断完成标识位可以poll到,但是在目的地址段却无法观察到数据。

    烦您再看一下程序配置在什么地方出问题了?

    非常感谢!!

  • 还有一点是:

    我的程序加载GEL完毕之后,发现

    segment1~7:SMS_MPAXL的值为0x00C00080,而手册上标明其reset值为0x00C00000

    segment1~7:SES_MPAXL的值为0x00000080,而手册上标明其reset值为0x000000000

    segment0的值正常,为reset值

    请问,这有影响吗?

  • 还有就是我截了两个param set的图

    1. L2到L2的,数据传输成功

    2. L2到DDR3,中断标志位起来了,但是目的地址端无法观察到相应的数据!

  • 1. 你在对目的地址DDR进行初始化后,需要进行cache write back and invalid,这样可以保证core向DDR写数据完成,并且invalid cache可以保证EDMA更新的数据不会被cache中的旧数据覆盖;

    2 确认SES中的配置存在一个MPAX将0x80000000开始的逻辑地址与DDR物理地址0x8 0000 0000相映射,从你给出的SMS配置来看有可能是DDR物理地址没有映射正确,但是gel文件时不会修改默认的SMS配置的,只会修改XMC中的MPAX。

  • Andy Yin1 说:

    1. 你在对目的地址DDR进行初始化后,需要进行cache write back and invalid,这样可以保证core向DDR写数据完成,并且invalid cache可以保证EDMA更新的数据不会被cache中的旧数据覆盖;

    2 确认SES中的配置存在一个MPAX将0x80000000开始的逻辑地址与DDR物理地址0x8 0000 0000相映射,从你给出的SMS配置来看有可能是DDR物理地址没有映射正确,但是gel文件时不会修改默认的SMS配置的,只会修改XMC中的MPAX。

    谢谢您的回复!

    1.main函数中,初始化了DDR3的PLL和controller,然后调用了EDMA测试子函数EDMA_test();

    /*XMC memory address extension/mapping and memory protection*/
    KeyStone_XM_cfg();
    
    KeyStone_main_PLL_init(624,31);
    KeyStone_DDR_PLL_init (79, 2);
    TCI6618_EVM_DDR_Init(666.667); 	
    
    EDMA_test(1,6);

    而在这个函数之前,有一段这样的初始化代码

    int i;
    
    CACHE_setL1PSize(CACHE_L1_32KCACHE);
    CACHE_setL1DSize(CACHE_L1_32KCACHE);
    CACHE_setL2Size(CACHE_1024KCACHE);
    CACHE_invAllL1p(CACHE_WAIT);
    CACHE_wbInvAllL1d(CACHE_WAIT);
    CACHE_wbInvAllL2(CACHE_WAIT);
    
    /*make other cores local memory cacheable and prefetchable*/
    for(i=16; i<24; i++)
    	CGEM_regs->MAR[i]=1|(1<<CSL_CGEM_MAR0_PFX_SHIFT)
    /*make DDR cacheable and prefetchable*/
    for(i=128; i<256; i++)
    	CGEM_regs->MAR[i]=1|(1<<CSL_CGEM_MAR0_PFX_SHIFT);
    /*make other space non-cacheable and non-prefetchable*/
    for(i=24; i<128; i++)
           CGEM_regs->MAR[i]=0;
    
    

    这段代码似乎是对cache进行了invalidate。

    如果没有这段代码的话,如果对DDR3进行写操作,似乎无法在Memory Broswer中观察到相应的值。而且观察到的数据一直在变。

    关于这一点,请问是涉及什么方面的知识?有相应的文档吗?我打算看看,想把这块搞懂。

    2. SES以及MPAX的机制,我还在看MSMC文档。还看得晕头晕脑的。有这样的几个问题:

    (1)SES_MPAXL/H好像有15组,每组对应一个PrivilegeID。这个PrivilegeID是什么含义?EDMA是对应其中的一个PrivilegeID吗?那么是说,对于EDMA操作,只需要保证其对应的SES_MPAXL/H设置正确,即使其他PrivilegeID对应的SES不正确,也行?

    (2)每个PrivilegeID对应的SES_MPAXL/H似乎有8个segment,这每个segment有是什么含义?

    (3)您提到的,需要保证SES_MPAXL/H配置正确(将0x80000000开始的逻辑地址与DDR物理地址0x8 0000 0000相映射)。而有这么多个PrivilegeID,分别又对应很多个segment,那么到底要配置哪个PrivilegeID对应的哪个segment的SES_MPAXL/H正确?

    (4)我们板子上的芯片是TCI6618,GEL文件用的是C6660EVM的GEL文件,似乎没有配置默认的SES参数。似乎您的意思是,只要没修改默认的SES参数,肯定就可以EDMA操作DDR3的。这就很奇怪了。我的程序中也没有修改SES参数。难道是用了SYS/BIOS的问题?

  • 你看一下函数Keystone_XM_cfg(),这里面应该配置了MPAX相关定义,是不是这部分代码对DDR地址做了重映射。

    1. 在MSMC中,有SES和SMS两个模块用来对芯片中的各种DMA的地址进行映射,其中SES是用来控制访问DDR3的请求,SMS是用来控制访问shared memory的请求

    2. 每个Privilege ID对应一组MPAX配置,privilege ID用来表示不同的DMA,例如QMSS PktDMA是9, PASS PktDMA 是 10,也就是不同的master都有对应的一组MPAX寄存器配置

    3. 每个Segment代表一组访问的地址范围,假设EDMA 中的Dst address为 0x80000000,但是SES对应的Segment MPAX配置中,把0x80000000映射到了0x81000000中,这样EDMA只要访问0x80000000的地址就会访问到实际物理地址为0x81000000的memory中,每个segment可以设置需要转换地址范围的大小,如果该地址不在segment的定义中,那么要么报错,要么按照默认地址访问。当出现同一个地址在多个segment中都有定义时,那么最后segment number最大的来访问,例如segment 0定义了0x80000000转换到0x81000000,segment 3定义了0x80000000转换到0x82000000,那么访问0x80000000时,最终会访问0x82000000.

  • Zhan Xiang 说:

    你看一下函数Keystone_XM_cfg(),这里面应该配置了MPAX相关定义,是不是这部分代码对DDR地址做了重映射。

    1. 在MSMC中,有SES和SMS两个模块用来对芯片中的各种DMA的地址进行映射,其中SES是用来控制访问DDR3的请求,SMS是用来控制访问shared memory的请求

    2. 每个Privilege ID对应一组MPAX配置,privilege ID用来表示不同的DMA,例如QMSS PktDMA是9, PASS PktDMA 是 10,也就是不同的master都有对应的一组MPAX寄存器配置

    3. 每个Segment代表一组访问的地址范围,假设EDMA 中的Dst address为 0x80000000,但是SES对应的Segment MPAX配置中,把0x80000000映射到了0x81000000中,这样EDMA只要访问0x80000000的地址就会访问到实际物理地址为0x81000000的memory中,每个segment可以设置需要转换地址范围的大小,如果该地址不在segment的定义中,那么要么报错,要么按照默认地址访问。当出现同一个地址在多个segment中都有定义时,那么最后segment number最大的来访问,例如segment 0定义了0x80000000转换到0x81000000,segment 3定义了0x80000000转换到0x82000000,那么访问0x80000000时,最终会访问0x82000000.

    谢谢您的回复!

    1. 印象中我注释过Keystone_XM_cfg()这句话,也是不可以的。Keystone_XM_cfg()这句代码似乎是对XMC(MSMC上的一路system master port进行配置,而非SES对应的MPAX)。板子不在手头,明天再去测试。

    2. 您提到的不同master对应一组SES_MPAXL/H。那么请问,我打算使用EDMA的CC1的通道0,请问是对应哪组SES_MPAXL/H?我关于MSMC那个文档,最主要的困惑点就是master与PrivilegeID,或者什么SES_MPAXL/H,之间的对应关系。

    3.在我的程序中,EDMA手动触发之前,我观察了一下SES_MPAXL/H的值,发现:

    (1)每一个PrivilegeID中:segment0的SES_MPAXH的值为0x8000001E,SES_MPAXL的值为0x800000BF。对MSMC文档描述reset值一致。

    (2)每一个PrivilegeID中:segment1~7的SES_MPAXH的值为0x00000000,与MSMC文档描述的reset值一致;但是SES_MPAXL的值为0x00000080,与MSMC文档描述的reset值0x00000000,不一致。

    请问,我遇到的问题,是因为segment1~7对应的SES_MPAXL值为0x00000080而导致的吗?

  • 您好!

    我在EDMA操作之前,观察了SES_MPAXL/H寄存器,如下图

    这个应该就是SES_MPAXL/H寄存器的reset值,没有修改,地址映射应该没有问题的吧?

    (除了segment1~7中,SES_MPAXL的值为0x00000080,而手册上说其reset值为0x00000000。但是不一样的bit位是reserved的,应该没问题的。)

    ************************************************************************

    所以,我现在怀疑的是:

    在我的程序中,SES、MPAX没有问题,EDMA的各个参数配置也没问题。

    而问题出在DDR3本身。

    *************************************************************************

    我先描述一下我这边的情况吧:

    1. 我们用的是TCI6618芯片,用了4片MT41J128M16-125(16×16×8 Bank)

    RAM0~1:组成data line的低32bit,CK1p/n以及CKE1接RAM0~1

    RAM2~3:组成data line的高32bit,CK0p/n以及CKE0接RAM0~1

    2. GEL文件用的是C6670EVM的GEL文件,修改了ddr3_setup_auto_lvl_1333()其中的几个参数:

    NM设置为64bit,ROWSIZE设置为14bit,EBANK设置为同时使用CKE0和CKE1

    3.主程序中有了这几句代码:

    int i;
    
    CACHE_setL1PSize(CACHE_L1_32KCACHE);
    CACHE_setL1DSize(CACHE_L1_32KCACHE);
    CACHE_setL2Size(CACHE_1024KCACHE);
    CACHE_invAllL1p(CACHE_WAIT);
    CACHE_wbInvAllL1d(CACHE_WAIT);
    CACHE_wbInvAllL2(CACHE_WAIT);
    
    /*make other cores local memory cacheable and prefetchable*/
    for(i=16; i<24; i++)
    	CGEM_regs->MAR[i]=1|(1<<CSL_CGEM_MAR0_PFX_SHIFT);
    /*make DDR cacheable and prefetchable*/
    for(i=128; i<256; i++)
    	CGEM_regs->MAR[i]=1|(1<<CSL_CGEM_MAR0_PFX_SHIFT);
    /*make other space non-cacheable and non-prefetchable*/
    for(i=24; i<128; i++)
    	CGEM_regs->MAR[i]=0;
    
    
    /*XMC memory address extension/mapping and memory protection*/
    KeyStone_XM_cfg();
    
    KeyStone_main_PLL_init(624,31);
    KeyStone_DDR_PLL_init (79, 2);
    TCI6618_EVM_DDR_Init(666.667); 	

    TCI6618_EVM_DDR_init()这句代码应该是重复了GEL中的操作

    结果显示:leveling failed

    3. 然后,在程序中用*(DDR3_BASE_ADDR++)=0xABCD;可以正常写DDR3,Memory Broswer观察也没问题

    4.换成EDMA方式,现在的测试情况是:

    (1)L2到L2、L2到MSMC、MSMC到MSMC,EDMA正常

    (2)DDR3到MSMC传数据,一半的数据,而且有一些数据是错的

    (3)DDR3到DDR3传数据,目的地址段,完全看不到数据

    我现在怀疑:

    是不是因为DDR3 leveling没通过,所以可以*(DDR3_BASE_ADDR++)=0xABCD;这样间歇操作DDR3,但是换成EDMA这样高速操作DDR3,就会失败??


       

  • 如果leveling没过,DDR3工作不正常,你最好根据你自己单板的配置修改DDR3的参数。

  • 我遇到了用Memory  Broswer 中观察 DDR3的数据,数据一直在跳的问题,不知道有什么建议,6678单核没有问题,改成2核就会出现跳的问题。