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.

6678 多核访问EDMA 冲突问题



您好,

 想实现6678 多核访问EDMA,如何做到避免多核冲突。目前做法:8核使用不同的region,8核DMA事件用不同的channel。请问还需做哪些工作保证8核用EDMA传输数据时都能正确传送,目前8核分别单核运行都没问题,8核group 运行只有一个核完成传送。

谢谢!

  • 使用不同的parameter set,以及中断事件的映射;最好你把两个核上的EDMA配置代码贴出来看看

  • 您好,部分代码如下

    //define EDMA3 instances
    #define CSL_EDMA3 CSL_EDMA3CC_1

    //region
    #define SP_CORE0_EDMA_REGION CSL_EDMA3_REGION_0
    #define SP_CORE1_EDMA_REGION CSL_EDMA3_REGION_1

    //channel
    #define SP_CORE0_FFTDATAIN_EDMA_CHANNEL 33
    #define SP_CORE1_FFTDATAIN_EDMA_CHANNEL 34

    //tcc
    #define SP_CORE0_FFTDATAIN_EDMA_TCC SP_CORE0_FFTDATAIN_EDMA_CHANNEL //chain to self
    #define SP_CORE1_FFTDATAIN_EDMA_TCC SP_CORE1_FFTDATAIN_EDMA_CHANNEL

    //param set
    #define SP_CORE0_FFTDATAIN_EDMA_PARAM 1
    #define SP_CORE1_FFTDATAIN_EDMA_PARAM 2

    //queue
    #define SP_FFTDATAIN_EDMA_QUE CSL_EDMA3_QUE_0

    int edma_config(int core_num){

    CSL_Edma3HwSetup hwSetup;

    CSL_Edma3CmdIntr regionIntr;
    CSL_Edma3CmdDrae regionAccess;

    CSL_Edma3ChannelAttr chAttr;
    CSL_Status status;
    CSL_Edma3HwDmaChannelSetup dmahwSetup[64];
    CSL_Edma3CmdQuePri que_pri;

    //--------------global edma setup---------------//
    status = CSL_edma3Init(NULL);
    if (status != CSL_SOK) {
    DEBUG1("Edma module initialization failed\n");
    return SP_FAIL;
    }

    hModule = CSL_edma3Open(&edmaObj,CSL_EDMA3,NULL,&status);
    if ( (hModule == NULL) || (status != CSL_SOK)) {
    DEBUG1 ("Edma module open failed\n");
    return SP_FAIL;
    }

    if(core_num == 0){

    dmahwSetup[SP_CORE0_FFTDATAIN_EDMA_CHANNEL].paramNum = SP_CORE0_FFTDATAIN_EDMA_PARAM;
    dmahwSetup[SP_CORE0_FFTDATAIN_EDMA_CHANNEL].que = SP_FFTDATAIN_EDMA_QUE;

    //FFTDATAIN Region
    regionAccess.region = SP_CORE0_EDMA_REGION ;
    regionAccess.drae = 0x0;
    regionAccess.draeh = 1 <<(SP_CORE0_FFTDATAIN_EDMA_CHANNEL-32);
    //tcc and channel are same. for chaining
    status = CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_DMAREGION_ENABLE,&regionAccess);
    if (status != CSL_SOK) {
    DEBUG1("Edma region enable command failed\n");
    return SP_FAIL;
    }

    //---FFTDATAIN CH---//
    // Channel open
    chAttr.regionNum = SP_CORE0_EDMA_REGION;
    chAttr.chaNum = SP_CORE0_FFTDATAIN_EDMA_CHANNEL;
    hEdmaChannel_FFTDATAIN = CSL_edma3ChannelOpen(&chObj_FFTDATAIN, CSL_EDMA3, &chAttr, &status);
    if ( (hEdmaChannel_FFTDATAIN== NULL) || (status != CSL_SOK)) {
    DEBUG1 ("Edma channel open failed\n");
    return SP_FAIL;
    }
    //Enable channel
    status = CSL_edma3HwChannelControl (hEdmaChannel_FFTDATAIN,CSL_EDMA3_CMD_CHANNEL_ENABLE,NULL);
    if (status != CSL_SOK) {
    DEBUG1 ("Edma channel enable command failed\n");
    return SP_FAIL;
    }

    /* Map the System Interrupt       EDMA3CC1 CCINT0 */
    CpIntc_dispatchPlug(8, (CpIntc_FuncPtr)fftdatain_edmacc_core0_isr, (UArg)hEdmaChannel_FFTDATAIN, TRUE);

    /* The configuration is for CPINTC0. We map system interrupt x to Host Interrupt y. */
    CpIntc_mapSysIntToHostInt(0, 8, 32);

    /* Enable the Host Interrupt. */
    CpIntc_enableHostInt(0, 32);

    /* Enable the System Interrupt */
    CpIntc_enableSysInt(0, 8);

    // Enable interrupts
    regionIntr.region = SP_CORE0_EDMA_REGION ;
    regionIntr.intr = 0x0;
    regionIntr.intrh = 1<<(SP_CORE0_FFTDATAIN_EDMA_TCC-32);
    status = CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_INTR_ENABLE,&regionIntr);
    if (status != CSL_SOK) {
    DEBUG1 ("Edma interrupt enable command failed\n");
    return SP_FAIL;
    }

    }

    if(core_num == 1){

    dmahwSetup[SP_CORE1_FFTDATAIN_EDMA_CHANNEL].paramNum = SP_CORE1_FFTDATAIN_EDMA_PARAM;
    dmahwSetup[SP_CORE1_FFTDATAIN_EDMA_CHANNEL].que = SP_FFTDATAIN_EDMA_QUE;

    //FFTDATAIN Region
    regionAccess.region = SP_CORE1_EDMA_REGION ;
    regionAccess.drae = 0x0;
    regionAccess.draeh = 1 <<(SP_CORE1_FFTDATAIN_EDMA_CHANNEL-32);
    //tcc and channel are same. for chaining
    status = CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_DMAREGION_ENABLE,&regionAccess);
    if (status != CSL_SOK) {
    DEBUG1("Edma region enable command failed\n");
    return SP_FAIL;
    }

    //---FFTDATAIN CH---//
    // Channel open
    chAttr.regionNum = SP_CORE1_EDMA_REGION;
    chAttr.chaNum = SP_CORE1_FFTDATAIN_EDMA_CHANNEL;
    hEdmaChannel_FFTDATAIN = CSL_edma3ChannelOpen(&chObj_FFTDATAIN, CSL_EDMA3, &chAttr, &status);
    if ( (hEdmaChannel_FFTDATAIN== NULL) || (status != CSL_SOK)) {
    DEBUG1 ("Edma channel open failed\n");
    return SP_FAIL;
    }
    //Enable channel
    status = CSL_edma3HwChannelControl (hEdmaChannel_FFTDATAIN,CSL_EDMA3_CMD_CHANNEL_ENABLE,NULL);
    if (status != CSL_SOK) {
    DEBUG1 ("Edma channel enable command failed\n");
    return SP_FAIL;
    }

    /* Map the System Interrupt         EDMA3CC1 CCINT0*/
    CpIntc_dispatchPlug(8, (CpIntc_FuncPtr)fftdatain_edmacc_core1_isr, (UArg)hEdmaChannel_FFTDATAIN, TRUE);

    /* The configuration is for CPINTC0. We map system interrupt x to Host Interrupt y. */
    CpIntc_mapSysIntToHostInt(0, 8, 43);

    /* Enable the Host Interrupt. */
    CpIntc_enableHostInt(0, 43);

    /* Enable the System Interrupt */
    CpIntc_enableSysInt(0, 8);

    // Enable interrupts
    regionIntr.region = SP_CORE1_EDMA_REGION ;
    regionIntr.intr = 0x0;
    regionIntr.intrh = 1<<(SP_CORE1_FFTDATAIN_EDMA_TCC-32);
    status = CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_INTR_ENABLE,&regionIntr);
    if (status != CSL_SOK) {
    DEBUG1 ("Edma interrupt enable command failed\n");
    return SP_FAIL;
    }

    }

    hwSetup.dmaChaSetup = dmahwSetup;
    hwSetup.qdmaChaSetup = NULL;
    status = CSL_edma3HwSetup(hModule,&hwSetup);
    if (status != CSL_SOK) {
    DEBUG1 ("Hardware setup failed\n");
    CSL_edma3Close (hModule);
    return SP_FAIL;

    }

    //Setup queue priority.
    que_pri.que = CSL_EDMA3_QUE_0;
    que_pri.pri = CSL_EDMA3_QUE_PRI_0;
    status = CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_QUEPRIORITY_SET,(void *)&que_pri);

    que_pri.que = CSL_EDMA3_QUE_1;
    que_pri.pri = CSL_EDMA3_QUE_PRI_1;
    status = CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_QUEPRIORITY_SET,(void *)&que_pri);

    que_pri.que = CSL_EDMA3_QUE_2;
    que_pri.pri = CSL_EDMA3_QUE_PRI_2;
    status = CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_QUEPRIORITY_SET,(void *)&que_pri);

    que_pri.que = CSL_EDMA3_QUE_3;
    que_pri.pri = CSL_EDMA3_QUE_PRI_3;
    status = CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_QUEPRIORITY_SET,(void *)&que_pri);

    return SP_OK;

    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////

    int setup_fftdatain_edma(fft_dma_ctl_t *dma_ctl,int core_num){

    CSL_Edma3ParamHandle hParamBasic;
    CSL_Edma3ParamSetup myParamSetup;
    CSL_Status status;
    CSL_Edma3ChannelErr chErrClear;

    chErrClear.missed = TRUE;
    chErrClear.secEvt = TRUE;
    CSL_edma3HwChannelControl (hEdmaChannel_FFTDATAIN, CSL_EDMA3_CMD_CHANNEL_DISABLE, NULL);
    CSL_edma3HwChannelControl (hEdmaChannel_FFTDATAIN, CSL_EDMA3_CMD_CHANNEL_CLEARERR,&chErrClear);
    CSL_edma3HwChannelControl (hEdmaChannel_FFTDATAIN, CSL_EDMA3_CMD_CHANNEL_CLEAR, NULL);
    status = CSL_edma3HwChannelControl (hEdmaChannel_FFTDATAIN,CSL_EDMA3_CMD_CHANNEL_ENABLE,NULL);

    /* Get the parameter handle */
    if(core_num == 0){

    hParamBasic = CSL_edma3GetParamHandle(hEdmaChannel_FFTDATAIN,SP_CORE0_FFTDATAIN_EDMA_PARAM,&status);
    if (hParamBasic == NULL) {
    DEBUG1("Edma get param handle failed\n");
    return SP_FAIL;
    }

    /* Edma parameter entry Setup */
    myParamSetup.option = CSL_EDMA3_OPT_MAKE(CSL_EDMA3_ITCCH_EN, \
    CSL_EDMA3_TCCH_DIS, \
    CSL_EDMA3_ITCINT_DIS, \
    CSL_EDMA3_TCINT_EN,\
    SP_CORE0_FFTDATAIN_EDMA_TCC,\
    CSL_EDMA3_TCC_NORMAL,\
    CSL_EDMA3_FIFOWIDTH_NONE, \
    CSL_EDMA3_STATIC_DIS, \
    CSL_EDMA3_SYNC_AB, \
    CSL_EDMA3_ADDRMODE_INCR, \
    CSL_EDMA3_ADDRMODE_INCR);

    }

    if(core_num == 1){

    hParamBasic = CSL_edma3GetParamHandle(hEdmaChannel_FFTDATAIN,SP_CORE1_FFTDATAIN_EDMA_PARAM,&status);
    if (hParamBasic == NULL) {
    DEBUG1("Edma get param handle failed\n");
    return SP_FAIL;
    }

    /* Edma parameter entry Setup */
    myParamSetup.option = CSL_EDMA3_OPT_MAKE(CSL_EDMA3_ITCCH_EN, \
    CSL_EDMA3_TCCH_DIS, \
    CSL_EDMA3_ITCINT_DIS, \
    CSL_EDMA3_TCINT_EN,\
    SP_CORE1_FFTDATAIN_EDMA_TCC,\
    CSL_EDMA3_TCC_NORMAL,\
    CSL_EDMA3_FIFOWIDTH_NONE, \
    CSL_EDMA3_STATIC_DIS, \
    CSL_EDMA3_SYNC_AB, \
    CSL_EDMA3_ADDRMODE_INCR, \
    CSL_EDMA3_ADDRMODE_INCR);

    }

    myParamSetup.srcAddr = GLOBAL_ADDR((Uint32)dma_ctl->src);
    myParamSetup.aCntbCnt = CSL_EDMA3_CNT_MAKE(dma_ctl->acnt,dma_ctl->bcnt);
    myParamSetup.dstAddr = GLOBAL_ADDR((Uint32)dma_ctl->dst);
    myParamSetup.srcDstBidx = CSL_EDMA3_BIDX_MAKE(dma_ctl->src_bindex,dma_ctl->dst_bindex);
    myParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE (CSL_EDMA3_LINK_NULL,1);
    myParamSetup.srcDstCidx = CSL_EDMA3_CIDX_MAKE(dma_ctl->src_cindex,dma_ctl->dst_cindex);
    myParamSetup.cCnt = dma_ctl->ccnt;

    status = CSL_edma3ParamSetup(hParamBasic,&myParamSetup);
    if (status != CSL_SOK) {
    DEBUG1 ("Edma param setup failed\n");
    return SP_FAIL;
    }

    return SP_OK;

    }

    还有一个问题:就是中断未响应,敬请赐教,工程在BIOS下,edma_config做了CPINTC 的映射配置

    Int main()
    {
    Task_Handle task;
    Error_Block eb;
    Int intNum;
    Hwi_Params params;

    System_printf("enter main()\n");

    edma_config(DNUM);

    Error_init(&eb);
    task = Task_create(taskFxn, NULL, &eb);
    if (task == NULL) {
    System_printf("Task_create() failed!\n");
    BIOS_exit(0);
    }

    // Initialize the Hwi parameters
    Hwi_Params_init(&params);

    //FFTIN
    // Set the GEM event id in the params
    params.eventId = 21;

    // Specify the interrupt vector number
    intNum = 4;

    /* When using CpIntc, you must plug the Hwi fxn with CpIntc_dispatch */
    /* so it knows how to process the CpIntc interrupts.*/
    Hwi_create(intNum, &CpIntc_dispatch, &params, &eb);

    BIOS_start(); /* does not return */

    return(0);
    }

    总结一下中断配置:两核用了相同的中断事件EDMA3CC1 CCINT0 (ps:同一类型的EDMA搬移8核使用相同的edma完成中断事件,不同类型EDMA搬移选择不同edma完成中断事件),即edma中断完成事件,,在CIC0输入为8号事件,通道映射核0输出为32,核1输出为43,对应的GEM event id  都是21,再有INT4输出给CPU,两核有各自的中断服务子程序

    希望我的叙述没有让您觉得混乱,期待您的解答

    谢谢!

  • hi,

    现多核冲突已经解决,我将上述中断部分代码改写为在非 BIOS 下,发现只能响应一次中断,就是刚上电运行能进入中断,之后再执行EDMA 搬移或者 restart 均无法进入中断。请问这是哪方面原因造成的?还有就是BIOS 下依然无法响应中断,请问BIOS 下我的中断配置是否正确?

    谢谢!

  • Biios及非bios下中断配置参考:http://processors.wiki.ti.com/index.php/Configuring_Interrupts_on_Keystone_Devices

    搬完数据后如果不能产生中断,先check一下相应IPR bit是否置位,如果已经置位,则说明EDMA搬移数据正常,说明与中断配置有关;由于EDMA ISR是路由到CPINTC,在中断响应函数中需要清system event,清IPR bit,然后才能保证响应接下来的中断。