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.

[参考译文] MSPM0L1306:早期通道中断阈值设置为传输大小的一半时 DMA 无提前中断触发

Guru**** 2445440 points
Other Parts Discussed in Thread: SYSCONFIG

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1326278/mspm0l1306-no-early-interrupt-firing-for-dma-with-early-channel-interrupt-threshold-set-to-half-point-of-transfer-size

器件型号:MSPM0L1306
主题中讨论的其他器件:SysConfig

您好!

我正在尝试使用 DMA 和早期的中断机制实现某种乒乓缓冲。
但是、我从未得到任何早期 IRQ。
我 SysConfig 为 DMA 通道0生成的初始化代码如下所示:

static const DL_DMA_Config gDMA_CH0Config = {
    .transferMode   = DL_DMA_FULL_CH_REPEAT_SINGLE_TRANSFER_MODE,
    .extendedMode   = DL_DMA_NORMAL_MODE,
    .destIncrement  = DL_DMA_ADDR_UNCHANGED,
    .srcIncrement   = DL_DMA_ADDR_INCREMENT,
    .destWidth      = DL_DMA_WIDTH_BYTE,
    .srcWidth       = DL_DMA_WIDTH_BYTE,
    .trigger        = DMA_CH0_TRIGGER_SEL_FSUB_0,
    .triggerType    = DL_DMA_TRIGGER_TYPE_EXTERNAL,
};

SYSCONFIG_WEAK void SYSCFG_DL_DMA_CH0_init(void)
{
    DL_DMA_clearInterruptStatus(DMA, DL_DMA_INTERRUPT_CHANNEL0);
    DL_DMA_enableInterrupt(DMA, DL_DMA_INTERRUPT_CHANNEL0);
    DL_DMA_clearInterruptStatus(DMA, DL_DMA_FULL_CH_INTERRUPT_EARLY_CHANNEL0);
    DL_DMA_Full_Ch_setEarlyInterruptThreshold(DMA, DMA_CH0_CHAN_ID, DL_DMA_EARLY_INTERRUPT_THRESHOLD_HALF);
    DL_DMA_enableInterrupt(DMA, DL_DMA_FULL_CH_INTERRUPT_EARLY_CHANNEL0);
    DL_DMA_setSrcIncrement(DMA, DMA_CH0_CHAN_ID, DL_DMA_ADDR_INCREMENT);
    DL_DMA_setTransferSize(DMA, DMA_CH0_CHAN_ID, 48);
    DL_DMA_initChannel(DMA, DMA_CH0_CHAN_ID , (DL_DMA_Config *) &gDMA_CH0Config);
}
SYSCONFIG_WEAK void SYSCFG_DL_DMA_init(void){
    DL_DMA_setSubscriberChanID(DMA, DL_DMA_SUBSCRIBER_INDEX_0, 1);
    SYSCFG_DL_DMA_CH0_init();
}

然后、我按如下所示启用和启动 DMA:

    //setting src and dest for dma and then
    DL_DMA_enableChannel(DMA, DMA_CH0_CHAN_ID);
    NVIC_EnableIRQ(DMA_INT_IRQn);

我的中断例程如下所示:

void DMA_IRQHandler(void){
    switch (DL_DMA_getPendingInterrupt(DMA)) {

        case DL_DMA_FULL_CH_EVENT_IIDX_EARLY_IRQ_DMACH0: {
           DL_GPIO_togglePins(GPIO_LEDS_PORT,
                GPIO_LEDS_USER_LED_1_PIN | GPIO_LEDS_USER_TEST_PIN);
        } break;

        case DL_DMA_EVENT_IIDX_DMACH0:
        __NOP();
            break;

        default:
        __NOP();
            break;
    }
}

使用 FSUB_0触发 DMA 的工作原理很有魅力、但不知何故、我无法获得我希望在
传输的前半部分触发、以便我可以重新填充我的乒乓缓冲器中的前24个字节。

此外,它不适用于任何 DL_DMA_EARLY_INTERRUPT_THRESHOLD_*。

但是、DL_DMA_EVENT_IIDX_DMACH0会触发。

谢谢你,至少带我进入正确的方向。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    很抱歉、我以前没有使用过此功能。 但是根据用户的反馈、这个功能应该运转良好。
    首先、您能否检查寄存器值是否正确?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的答复。 这绝对让我走上了正确的方向。
    错误是 DMACTL 中的 DMAPREIRQ 被调用复位

    DL_DMA_initChannel (DMA、DMA_CH0_CHAN_ID、(DL_DMA_Config *)&gDMA_CH0Config);

    大家可以看到:

    __STATIC_INLINE void DL_DMA_configTransfer(DMA_Regs *dma, uint8_t channelNum,
        DL_DMA_TRANSFER_MODE transferMode, DL_DMA_EXTENDED_MODE extendedMode,
        DL_DMA_WIDTH srcWidth, DL_DMA_WIDTH destWidth,
        DL_DMA_INCREMENT srcIncrement, DL_DMA_INCREMENT destIncrement)
    {
        dma->DMACHAN[channelNum].DMACTL =
            ((uint32_t) transferMode | (uint32_t) extendedMode |
                (((uint32_t) destIncrement) << 4) | (uint32_t) srcIncrement |
                ((uint32_t) destWidth << 4) | (uint32_t) srcWidth);
    }

    因此、解决方案只需在 initChannel 调用之后手动设置 DMAPREIRQ。

    恕我直言、SysConfig 工具应注意到这一点、并相应地进行初始化调用。