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.

TMS320C6657: EMIF16配置为SS模式,配合外部中断触发产生了片选竞争,然而中断出现了延迟以及CE0切换到CE1也出现了延迟

Part Number: TMS320C6657

EMIF16配置为SS模式,共开启两个片选信号CE0和CE1,CE0写一个16bit周期大约为208ns

 

上图为出现延迟问题:

配置:

波形0:CE0

波形1:CE1

波形2:WE

波形3:  OE

波形4:  外部输入IO信号

波形5:外部输入中断函数

在主函数内不断地往CE0进行写入数据,每次写入都为16bit,当外部输入IO信号触发高电平时进入中断处理函数,中断处理函数(优先级为0x16)先写入CE1两个16bit数据,再读取CE1一个16bit数据。

问题描述:

1.中断处理函数触发发生了延迟,大概为12个emif16 CE0写周期,该延迟正在处理CE0的数据下发。

2.写CE1时,即片选从CE0切换到CE1时也发生了延迟,大概为26个emif16 CE0写周期,该延迟正在处理CE0的数据下发。

 

 

上图操作为:

在书函数内不断地从CE0读取数据,每次读取都为16bit,当外部输入IO信号触发高电平时进入中断处理函数,中断处理函数(优先级为0x16)先写入CE1两个16bit数据,再读取CE1一个16bit数据。

读的时候中断处理函数触发时间为872ns,较为合理,并且片选切换时也不存在较大的延迟处理CE0的数据。

 

期望:

不希望出现图1的情况,导致中断处理函数以及片选切换时,仍在等待未处理完的CE0数据,因为该中断需要处理实时数据,请问有什么解决办法?

  • 您好

    已经收到了您的案例,调查需要些时间,感谢您的耐心等待

  • 您好

    感谢您迄今为止提供的详细信息。

    为了进一步缩小问题的范围,您能确认以下内容吗?

    1.请分享您当前使用的定时配置设置?

    2.CE0是否在主函数内的连续循环中编写?如果是这样,写入操作之间是否存在延迟?

  •     EMIF16_Config hEmif16Cfg;
        EMIF16_CE_Config hceCfg[4];
    
        hEmif16Cfg.ceCfg[1] = &hceCfg[1];
        hEmif16Cfg.ceCfg[1]->busWidth = EMIF_BUS_16BIT;
        hEmif16Cfg.ceCfg[1]->nor_pg_Cfg = EMIF16_4_WORDS_NOR_PAGE;
        hEmif16Cfg.ceCfg[1]->opMode = NOR_ASRAM_MODE;
        hEmif16Cfg.ceCfg[1]->strobeMode = SS_STROBE;
        hEmif16Cfg.ceCfg[1]->waitMode = EMIF_WAIT_NONE;
    
        hEmif16Cfg.ceCfg[1]->turnAroundCycles = 1;
        hEmif16Cfg.ceCfg[1]->rdSetup = 1;
        hEmif16Cfg.ceCfg[1]->rdStrobe = 10;
        hEmif16Cfg.ceCfg[1]->rdHold = 1;
    
        hEmif16Cfg.ceCfg[1]->wrSetup = 1;
        hEmif16Cfg.ceCfg[1]->wrStrobe = 6;
        hEmif16Cfg.ceCfg[1]->wrHold = 1;
    
        hEmif16Cfg.ceCfg[0] = &hceCfg[0];
        hEmif16Cfg.ceCfg[0]->busWidth = EMIF_BUS_16BIT;
        hEmif16Cfg.ceCfg[0]->nor_pg_Cfg = EMIF16_4_WORDS_NOR_PAGE;
        hEmif16Cfg.ceCfg[0]->opMode = NOR_ASRAM_MODE;
        hEmif16Cfg.ceCfg[0]->strobeMode = SS_STROBE;
        hEmif16Cfg.ceCfg[0]->waitMode = EMIF_WAIT_NONE;
    
        hEmif16Cfg.ceCfg[0]->turnAroundCycles = 1;
        hEmif16Cfg.ceCfg[0]->rdSetup = 0x0D;
        hEmif16Cfg.ceCfg[0]->rdStrobe = 0x32;
        hEmif16Cfg.ceCfg[0]->rdHold = 0x07;
    
        hEmif16Cfg.ceCfg[0]->wrSetup = 0x0D;
        hEmif16Cfg.ceCfg[0]->wrStrobe = 0x32;
        hEmif16Cfg.ceCfg[0]->wrHold = 0x07;
    
        CSL_FINS(EMIF16_Regs->NANDFCTL, EMIF16_NANDFCTL_CE0NAND, CSL_EMIF16_NANDFCTL_CE0NAND_ENABLE);
        CSL_FINS(EMIF16_Regs->NANDFCTL, EMIF16_NANDFCTL_4BIT_ECC_SEL, CSL_EMIF16_NANDFCTL_4BIT_ECC_SEL_RESETVAL);
    
        hEmif16Cfg.maxWait = 0;
        hEmif16Cfg.wait0Polarity = EMIF_LOW_WAIT;
        hEmif16Cfg.wait1Polarity = EMIF_LOW_WAIT;

    1.上述即emif16的定时配置

    2.在while中进行单个16bit写入,应该不存在延迟,你可以参考一下上面的波形图

    以下三个图分别是CE0写,CE1写,CE1读的单个周期长度测量图:

    麻烦了,帮忙分析一下,感谢!

  • 您好

    你能试着增加周转周期数,并检查延迟是否仍然存在吗?

  • 着增加周转周期数,并检查延迟是否仍然存在吗?

    我已经尝试将turnaround cycle 改成最大值3了,仍然存在中断延迟和切换延迟(个人观点:这个问题看起来似乎是写emif时写指令进了一个有固定深度的缓存一样,到了中断触发后,切到另一个CE时,需要把这些数据全部硬件输出后才做另一个CE的写),是否存在指令缓存?写指令可缓存一段类似FIFO相关的机制?

  •     hEmif16Cfg.ceCfg[1] = &hceCfg[1];
        hEmif16Cfg.ceCfg[1]->busWidth = EMIF_BUS_16BIT;
        hEmif16Cfg.ceCfg[1]->nor_pg_Cfg.pageEnable = DISABLE_PAGE_MODE;
        hEmif16Cfg.ceCfg[1]->opMode = NOR_ASRAM_MODE;
        hEmif16Cfg.ceCfg[1]->strobeMode = SS_STROBE;
        hEmif16Cfg.ceCfg[1]->waitMode = EMIF_WAIT_NONE;
    
        hEmif16Cfg.ceCfg[1]->turnAroundCycles = 3;
        hEmif16Cfg.ceCfg[1]->rdSetup = 1;
        hEmif16Cfg.ceCfg[1]->rdStrobe = 10;
        hEmif16Cfg.ceCfg[1]->rdHold = 1;
    
        hEmif16Cfg.ceCfg[1]->wrSetup = 1;
        hEmif16Cfg.ceCfg[1]->wrStrobe = 6;
        hEmif16Cfg.ceCfg[1]->wrHold = 1;
    
        hEmif16Cfg.ceCfg[0] = &hceCfg[0];
        hEmif16Cfg.ceCfg[0]->busWidth = EMIF_BUS_16BIT;
        hEmif16Cfg.ceCfg[0]->nor_pg_Cfg.pageEnable = DISABLE_PAGE_MODE;
        hEmif16Cfg.ceCfg[0]->opMode = NOR_ASRAM_MODE;
        hEmif16Cfg.ceCfg[0]->strobeMode = SS_STROBE;
        hEmif16Cfg.ceCfg[0]->waitMode = EMIF_WAIT_NONE;
    
        hEmif16Cfg.ceCfg[0]->turnAroundCycles = 3;
        hEmif16Cfg.ceCfg[0]->rdSetup = 1;    //10ns
        hEmif16Cfg.ceCfg[0]->rdStrobe = 49;   //40ns
        hEmif16Cfg.ceCfg[0]->rdHold = 1;     //10ns
    
        hEmif16Cfg.ceCfg[0]->wrSetup = 1;    //10ns
        hEmif16Cfg.ceCfg[0]->wrStrobe = 49;   //40ns
        hEmif16Cfg.ceCfg[0]->wrHold = 1;     //10ns
    
        hEmif16Cfg.maxWait = 0;
        hEmif16Cfg.wait0Polarity = EMIF_LOW_WAIT;
        hEmif16Cfg.wait1Polarity = EMIF_LOW_WAIT;

    这是我重新配置的代码,已经把turnaround cycle设置为3,但是从波形上看,turnaround cycle调整后,从波形上看仅有读和读之间时间间隔,读切换到写时的时间间隔才有明显的变化,但是仍然解决不了此问题。

    从图上看,这两个延迟似乎是固定的周期数。

    麻烦再帮忙分析一下,感谢!

  • 您好

    您是否按照 SPRZ381C 芯片勘误表使用手册17中的建议设置 EMIF16隐藏寄存器位?

    Reference Link: https://www.ti.com/lit/er/sprz381c/sprz381c.pdf?ts=1749626162533&ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTMS320C6655

  • 这个配置我已经做过了,也调增了turnaround cycle,从0调到3,对于写来说,上一次异步访问的保持时间后与下一次异步访问的建立时间前的时间间隔并未发生变化,一直都为固定值22-24ns左右,而如果将写换成读,该时间就跟随配置发生了变化,变化时间也跟随配置一致(即生效),但是该时间远大于turnaround cycle的时间,不清楚这个固定值是否是内部调度导致?调整额turnaround cycle,在miam函数循环写CE0(此操作每次都有建立时间和保持时间,不是连续写),在外部中断写CE1时,中断函数执行时刻与片选切换时刻依然存在较大延迟,保持在10CE0写周期和26CE0写周期。这看起来似乎写的操作比较快产生了缓存相似的效果,到了切换片选CE1的时候必须等待CE0的数据全部硬件输出,我不清楚这里面的原子操作是如何的?跟DDR3_MSMC是否有关?写64位进行连续写4个CE0数据时仍然会发生,延迟会更长,接近四倍。以下是我具体配置:

    HMC_S32 drv_emif16_init(void)
    {
        EMIF16_Config hEmif16Cfg;
    EMIF16_CE_Config hceCfg[4];
    hEmif16Cfg.ceCfg[1] = &hceCfg[1];
        hEmif16Cfg.ceCfg[1]->busWidth = EMIF_BUS_16BIT;
        hEmif16Cfg.ceCfg[1]->nor_pg_Cfg.pageEnable = DISABLE_PAGE_MODE;
        hEmif16Cfg.ceCfg[1]->opMode = NOR_ASRAM_MODE;
        hEmif16Cfg.ceCfg[1]->strobeMode = SS_STROBE;
        hEmif16Cfg.ceCfg[1]->waitMode = EMIF_WAIT_NONE;
        hEmif16Cfg.ceCfg[1]->turnAroundCycles = 1;
        hEmif16Cfg.ceCfg[1]->rdSetup = 1;
        hEmif16Cfg.ceCfg[1]->rdStrobe = 10;
        hEmif16Cfg.ceCfg[1]->rdHold = 1;
        hEmif16Cfg.ceCfg[1]->wrSetup = 1;
        hEmif16Cfg.ceCfg[1]->wrStrobe = 6;
        hEmif16Cfg.ceCfg[1]->wrHold = 1;
        hEmif16Cfg.ceCfg[0] = &hceCfg[0];
        hEmif16Cfg.ceCfg[0]->busWidth = EMIF_BUS_16BIT;
        hEmif16Cfg.ceCfg[0]->nor_pg_Cfg.pageEnable = DISABLE_PAGE_MODE;
        hEmif16Cfg.ceCfg[0]->opMode = NOR_ASRAM_MODE;
        hEmif16Cfg.ceCfg[0]->strobeMode = SS_STROBE;
        hEmif16Cfg.ceCfg[0]->waitMode = EMIF_WAIT_NONE;
        hEmif16Cfg.ceCfg[0]->turnAroundCycles = 1;
    hEmif16Cfg.ceCfg[0]->rdSetup = 1; 
    hEmif16Cfg.ceCfg[0]->rdStrobe = 49;
        hEmif16Cfg.ceCfg[0]->rdHold = 1;
    hEmif16Cfg.ceCfg[0]->wrSetup = 1;  
    hEmif16Cfg.ceCfg[0]->wrStrobe = 49;
        hEmif16Cfg.ceCfg[0]->wrHold = 1;
        hEmif16Cfg.maxWait = 0;
        hEmif16Cfg.wait0Polarity = EMIF_LOW_WAIT;
        hEmif16Cfg.wait1Polarity = EMIF_LOW_WAIT;
        emif16_init(&hEmif16Cfg);
        return HMC_OK;
    }
    void emif16_init(EMIF16_Config *pEmif16Cfg)
    {
        int i;
        Uint32 regVal;
        volatile Uint32 *ACR = &EMIF16_Regs->A0CR;
        volatile Uint32 PMCR = 0;
        volatile Uint32 AWCCR = 0;
        volatile Uint32 NANDFCR = 0;
        EMIF16_CE_Config * ceCfg;
        for(i = 0; i < 4; i++)  /*4 CEs*/
        {
            if(NULL == pEmif16Cfg->ceCfg[i])
                continue;
            ceCfg = pEmif16Cfg->ceCfg[i];
            regVal = ((ceCfg->strobeMode << CSL_EMIF16_A0CR_SS_SHIFT) & CSL_EMIF16_A0CR_SS_MASK)
                    | ((ceCfg->wrSetup << CSL_EMIF16_A0CR_WSETUP_SHIFT) & CSL_EMIF16_A0CR_WSETUP_MASK)
                    | ((ceCfg->wrStrobe << CSL_EMIF16_A0CR_WSTROBE_SHIFT) & CSL_EMIF16_A0CR_WSTROBE_MASK)
                    | ((ceCfg->wrHold << CSL_EMIF16_A0CR_WHOLD_SHIFT) & CSL_EMIF16_A0CR_WHOLD_MASK)
                    | ((ceCfg->rdSetup << CSL_EMIF16_A0CR_RSETUP_SHIFT) & CSL_EMIF16_A0CR_RSETUP_MASK)
                    | ((ceCfg->rdStrobe << CSL_EMIF16_A0CR_RSTROBE_SHIFT) & CSL_EMIF16_A0CR_RSTROBE_MASK)
                    | ((ceCfg->rdHold << CSL_EMIF16_A0CR_RHOLD_SHIFT) & CSL_EMIF16_A0CR_RHOLD_MASK)
                    | ((ceCfg->turnAroundCycles << CSL_EMIF16_A0CR_TA_SHIFT) & CSL_EMIF16_A0CR_TA_MASK)
                    | ((ceCfg->busWidth << CSL_EMIF16_A0CR_ASIZE_SHIFT) & CSL_EMIF16_A0CR_ASIZE_MASK);
            if(EMIF_WAIT_NONE != ceCfg->waitMode)
            {
                regVal |= ((1 << CSL_EMIF16_A0CR_EW_SHIFT) & CSL_EMIF16_A0CR_EW_MASK);
                AWCCR |= (((ceCfg->waitMode << CSL_EMIF16_AWCCR_CE0WAIT_SHIFT) & CSL_EMIF16_AWCCR_CE0WAIT_MASK) << (i * 2));
            }
            ACR[i] = regVal;
            if(ceCfg->nor_pg_Cfg.pageEnable != DISABLE_PAGE_MODE)
            {
                regVal = ((ceCfg->nor_pg_Cfg.pageDelay << CSL_EMIF16_PMCR_CE0PGDEL_SHIFT) & CSL_EMIF16_PMCR_CE0PGDEL_MASK)
                    | ((ceCfg->nor_pg_Cfg.pageSize << CSL_EMIF16_PMCR_CE0PGSIZE_SHIFT) & CSL_EMIF16_PMCR_CE0PGSIZE_MASK)
                    | ((1 << CSL_EMIF16_PMCR_CE0PGMDEN_SHIFT) & CSL_EMIF16_PMCR_CE0PGMDEN_MASK);
                PMCR |= (regVal << (i * 8));
            }
            else
            {
                regVal = ((0 << CSL_EMIF16_PMCR_CE0PGMDEN_SHIFT) & CSL_EMIF16_PMCR_CE0PGMDEN_MASK);
                PMCR |= (regVal << (i * 8));
            }
            if(NAND_MODE == ceCfg->opMode)
                NANDFCR |= (((1 << CSL_EMIF16_NANDFCTL_CE0NAND_SHIFT) & CSL_EMIF16_NANDFCTL_CE0NAND_MASK) << i);
        }
        AWCCR |= (((pEmif16Cfg->maxWait << CSL_EMIF16_AWCCR_MAXEXTWAIT_SHIFT) & CSL_EMIF16_AWCCR_MAXEXTWAIT_MASK)
            | ((pEmif16Cfg->wait0Polarity << CSL_EMIF16_AWCCR_WP0_SHIFT) & CSL_EMIF16_AWCCR_WP0_MASK)
            | ((pEmif16Cfg->wait1Polarity << CSL_EMIF16_AWCCR_WP1_SHIFT) & CSL_EMIF16_AWCCR_WP1_MASK));
        EMIF16_Regs->AWCCR = AWCCR;
        EMIF16_Regs->PMCR = PMCR;
        EMIF16_Regs->NANDFCTL = NANDFCR;
        *(Uint32 * ) 0x20C00008 |= 0x80000000; //Disable synchronous mode feature
    },

    我能确定寄存器配置无误,并且应用上配置位ASRAM模式,通过读写内存进行读写emif。

    这个是修改turnaround cycle为3后的时序图:

    0.CE0

    1.CE1

    2.WE

    3.CE

    4.外部io信号

    5.外部中断函数执行

    6.BE0

  • https://www.ti.com/lit/er/sprz381c/sprz381c.pdf?ts=1749626162533&ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTMS320C6655

    你好!从上述文档中刚尝试了Advisory 13 Single MFENCE Issue这一栏,在写入CE0的时候增加了_mfence();进行打断流水线指令,让其等待CPU事务触发完毕再进行循环写一下个,发现能达到与读一样堵塞的效果:

    发现其延时极短,符合目前调度情况,请问增加了这个指令会有什么隐患不?还是说这个就是应这个需求进行开放的?

  • 您好

    在切换之前、尝试添加一个短延迟或从 CE0执行虚拟读取。 这可能有助于清除任何待处理的写入。 请检查之后问题是否仍然存在。

  • 您好
    我在主循环的每个CE0写操作后都增加了两个_mfence(),已经能达到我目前的调度需求了,感谢!