CH32V307使用ETH DMA,发现会频繁进中断

CH32V307使用ETH DMA + 外置100phy,会频繁进DMA中断,发现在phy link完成之前就会进DMA的TBU中断,而且这个中断时持续的在进。除此之外还会进一个异常中断,AIS的ET中断,这两个中断进入后仅做了清标志位的操作,清空中断标志后,还会频繁的进,发生TBU或ET中断后,需要进行其他操作吗?

出现TBU和ET中断,还可以正常通信,当出现RBU中断后,就无法正常通信,进RBU中断后需要什么操作来恢复接收呢?

您好

(1)RBU中断后导致无法正常通信,可在RBU中断下清除DMA描述符指针的缓冲或者复位MAC进行复位操作。

(2)您讲述的这些异常中断的产生可能是时钟配置误差造成的,可参考链接中的程序(官网的新的NET库:/downloads/CH32V307EVT_ZIP.html )的时钟配置进行更改。


您好

    目前使用外置100M PHY的方案,应该不会是时钟配置的问题


    ETH DMA使用Rx Chain的数量是4个,当前找到一个规避方法,当出现RBU中断之后在中断里面

    1、先执行ETH->DMASR = ETH_DMASR_RBUS清空中断标志

    2、然后执行ETH->DMARPDR = 0重新启动DMA的接收流程

    3、最后执行DMARxDescToGet = (ETH_DMADESCTypeDef *)(DMARxDescToGet->Buffer2NextDescAddr)切换DMA描述符,经过这样的操作流程后,可以使通信恢复正常。

            ETH->DMASR = ETH_DMASR_RBUS;

            ETH->DMARPDR = 0;

            DMARxDescToGet = (ETH_DMADESCTypeDef *)(DMARxDescToGet->Buffer2NextDescAddr);


    当发生RBU中断后,立即查看DMARxDescToGet->Status & ETH_DMARxDesc_OWN的值,发现他的值为0x8000 0000,切换DMA描述符后(执行DMARxDescToGet = (ETH_DMADESCTypeDef *)(DMARxDescToGet->Buffer2NextDescAddr))再次查看DMARxDescToGet->Status & ETH_DMARxDesc_OWN的值为0x0000 0000。是否需要再将切换后的DMA描述符的所属权交给DMA控制器(DMARxDescToGet |= ETH_DMARxDesc_OWN)?。出现这样的情况,通过此种方法解决是否合理?正常的处理流程应该是什么样的呢?


    您回复说RBU中断下清除DMA描述符指针的缓冲,DMA描述符指针的缓冲指的是“数据缓冲区”还是“DMA描述符数组”?


这里是中断使能配置

ETH_DMAITConfig(ETH_DMA_IT_NIS | ETH_DMA_IT_AIS | ETH_DMA_IT_R | ETH_DMA_IT_RBU, ENABLE);


以下是ETH中断服务

void ETH_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void ETH_IRQHandler(void)
{
    GET_INT_SP();
    rt_interrupt_enter();

    struct pbuf *frame_in_mail = NULL;
    struct pbuf *frame_in_temp = NULL;
    uint8_t *frame_data_p = NULL;

    uint32_t int_sta = ETH->DMASR;

    if ((int_sta & ETH_DMA_IT_AIS) != RESET)
    {
        // rt_kprintf("AIS <0x%x> <0x%x>\n\n", int_sta, DMARxDescToGet->Status & ETH_DMARxDesc_OWN);
        if ((int_sta & ETH_DMA_IT_RBU) != RESET)
        {
            // 接收缓冲区不可用
            // rt_kprintf("RBU <0x%x>\n", (int_sta & ETH_DMA_IT_RBU));
            ETH->DMASR = ETH_DMASR_RBUS;
            ETH->DMARPDR = 0;
            DMARxDescToGet = (ETH_DMADESCTypeDef *)(DMARxDescToGet->Buffer2NextDescAddr);
        }

        ETH_DMAClearITPendingBit(ETH_DMA_IT_AIS);
    }

    if ((int_sta & ETH_DMA_IT_NIS) != RESET)
    {
        // rt_kprintf("NIS <0x%x>\n", int_sta);

        if ((int_sta & ETH_DMA_IT_R) != RESET)
        {
            while ((rx_eth_len = ETH_HandleRxPkt(rx_eth_buf)) > 16)
            {
                if (eth0_dev.link_status == TRUE)
                {
                    frame_data_p = rx_eth_buf;
                    frame_in_mail = pbuf_alloc(PBUF_RAW, rx_eth_len, PBUF_POOL); //申请存储空间(这里没用PBUF_RAM)
                    if (frame_in_mail != NULL)
                    {
                        // 拷贝数据到PBUF
                        frame_in_temp = frame_in_mail;
                        while (frame_in_temp != NULL)
                        {
                            rt_memcpy(frame_in_temp->payload, frame_data_p, frame_in_temp->len);
                            frame_data_p += frame_in_temp->len;
                            frame_in_temp = frame_in_temp->next;
                        }

                        if (rt_mb_send_wait(frame_in_mb, (rt_ubase_t)frame_in_mail, 0) != RT_EOK)
                        {
                            pbuf_free(frame_in_mail);
                        }
                    }
                    else
                    {
                        ETH_LOGE(MODULE, "pbuf=NULL");
                    }
                }
            }
            ETH_DMAClearITPendingBit(ETH_DMA_IT_R);
        }

        if ((int_sta & ETH_DMA_IT_TBU) != RESET)
        {
            // rt_kprintf("TBU <0x%x>\n", (int_sta & ETH_DMA_IT_TBU));
            ETH->DMASR = ETH_DMASR_TBUS;
            ETH->DMATPDR = 0;
        }

        ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS);
    }

    rt_interrupt_leave();
    FREE_INT_SP();
}



只有登录才能回复,可以选择微信账号登录