NXP MCU 技术论坛
直播中

李辉

7年用户 1329经验值
私信 关注
[问答]

具有DMA中断的I2S双缓冲区问题求解

我在 RT600 上有一个使用四个 I2S 端口的新项目。两个用于接收,两个用于发送。我有一个项目正在工作,将音频输入传递到输出(基于示例项目),但需要修改其中一个传递以将数据发送到 DSP 进行处理。我已经查看了文档(存在的很少)和其他示例项目,但似乎缺少有关接收 DMA 中断的关键信息。
我知道我需要两个缓冲区:1 个用于发送到 DSP,而 2 个用于填充传入数据。我可以创建两个缓冲区并将其排队。问题是 I2S DMA 中断在回调中有用户数据,但这个空指针对于特定的 I2S 通道是全局的。它不会根据缓冲区发送或接收数据而改变。所以当中断发生时,不知道刚刚填充或清空了哪个缓冲区。
我认为有一个 DMA 乒乓缓冲区示例项目可以解决问题。但它也只有一个通用用户数据指针。然后中断不指示细节。部分示例代码如下:

static i2s_transfer_t s_rxTransfer[2] = {{
                                             .data     = s_Buffer[0],
                                             .dataSize = DEMO_BUFFER_SIZE,
                                         },
                                         {
                                             .data     = s_Buffer[1],
                                             .dataSize = DEMO_BUFFER_SIZE,
                                         }};
static i2s_transfer_t s_txTransfer[2] = {{
                                             .data     = s_Buffer[1],
                                             .dataSize = DEMO_BUFFER_SIZE,
                                         },
                                         {
                                             .data     = s_Buffer[0],
                                             .dataSize = DEMO_BUFFER_SIZE,

...

    I2S_TxTransferCreateHandleDMA(DEMO_I2S_TX, &s_TxHandle, &s_DmaTxHandle, TxCallback, (void *)&s_txTransfer);
    I2S_RxTransferCreateHandleDMA(DEMO_I2S_RX, &s_RxHandle, &s_DmaRxHandle, RxCallback, (void *)&s_rxTransfer);
    I2S_TransferInstallLoopDMADescriptorMemory(&s_TxHandle, s_txDmaDescriptors, 2U);
    I2S_TransferInstallLoopDMADescriptorMemory(&s_RxHandle, s_rxDmaDescriptors, 2U);

    if (I2S_TransferSendLoopDMA(DEMO_I2S_TX, &s_TxHandle, &s_txTransfer[0], 2U) != kStatus_Success)
    {
        assert(false);
    }

    if (I2S_TransferReceiveLoopDMA(DEMO_I2S_RX, &s_RxHandle, &s_rxTransfer[0], 2U) != kStatus_Success)
    {
        assert(false);
    }

    while (1)
    {
    }
}

static void TxCallback(I2S_Type *base, i2s_dma_handle_t *handle, status_t completionStatus, void *userData)
{
    i2s_transfer_t *transfer = userData;
  
    __NOP();
   
    // Where is the data located?
    if (transfer->data == s_Buffer[0])
    {
      // Code never gets here!!!!
      __NOP();
    }
    else if (transfer->data == s_Buffer[1])
    {
      __NOP();
    }
}

static void RxCallback(I2S_Type *base, i2s_dma_handle_t *handle, status_t completionStatus, void *userData)
{
    i2s_transfer_t *transfer = userData;
  
    __NOP();

    // Where is the data located?
    if (transfer->data == s_Buffer[0])
    {
      __NOP();
    }
    else if (transfer->data == s_Buffer[1])
    {
      // Code never gets here...!!!!!
      __NOP();
    }
}

I2S_TxTransferCreateHandleDMA (Rx) 函数分配用户数据并保持静态,无论哪个缓冲区已填充以生成中断。
是否有我在驱动程序库中没有找到的功能?这应该怎么做?理想情况下,ISR 回调中的用户数据似乎会指向应用程序应该处理的缓冲区。

更多回帖

发帖
×
20
完善资料,
赚取积分