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.

[参考译文] AM6421:DMA 配置帮助...

Guru**** 2482225 points


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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1441862/am6421-help-with-dma-configuration

器件型号:AM6421

工具与软件:

你好。

在功能稍有不同的调整示例代码方面需要一些帮助。


我正在尝试使用 DMA 将 DMA 配置为将数据包从 TCM 中的队列传输到 DDR 或 MSRAM。
从 swrigger 示例开始、不同之处在于源/目标队列的可用总空间不同。

下面提供了一些定义(测试值)、以便了解背景信息并简化操作:

- entrySize = 32字节

- chunkSize = 28160字节

- srcSize = 56320字节

- DESTSIZE = 506880

想法是一次通过每个 SW_TRIGGER 事件传输一个块... (因此、chunkSize 的倍数/dest 大小是 src 的倍数、也是 entrySize 的倍数)。 总数据块不是固定的/已知的、而数据将由一个外部驱动事件(GPIO 中断)填充到 src 队列中。

A53在 Linux 下运行、此代码在 R5FSS0_0 (单核模式)下运行。

下面是不起作用的代码:

// TCM (by linker)
volatile BOOL bDMADone                  = TRUE;
uint32_t triggerMask                    = 0;
volatile uint32_t* ch0SwTriggerReg      = NULL;

Udma_EventObject gCh0TrEventObj         __attribute__((section("MSRAM"))) = { 0 };
Udma_EventHandle gCh0TrEventHandle      __attribute__((section("MSRAM"))) = NULL;
volatile Udma_EventPrms gCh0TrEventPrms __attribute__((section("MSRAM"))) = { 0 };
Udma_ChHandle ch0Handle                 __attribute__((section("MSRAM"))) = NULL;

uint8_t gUdmaTestTrpdMem[UDMA_TRPD_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT), section("MSRAM")));

// Debug counters
volatile uint32_t uiEnqueues = 0;
volatile uint32_t uiEnqueueCBs = 0;

void App_udmaEventCb(Udma_EventHandle eventHandle, uint32_t eventType, void* appData)
{
    uiEnqueueCBs++;
    bDMADone = TRUE;
}

static void App_udmaTrpdInit(Udma_ChHandle chHandle, uint32_t chIdx, uint8_t* trpdMem, const void* destBuf, const void* srcBuf, uint32_t destSize, uint32_t srcSize, uint32_t chunkSize, uint32_t entrySize)
{
    CSL_UdmapTR15* pTr;
    uint32_t        cqRingNum = Udma_chGetCqRingNum(chHandle);

    /* Make TRPD with TR15 TR type */
    UdmaUtils_makeTrpdTr15(trpdMem, 1U, cqRingNum);

    /* Setup TR */
    pTr = UdmaUtils_getTrpdTr15Pointer(trpdMem, 0U);
    pTr->flags = CSL_FMK(UDMAP_TR_FLAGS_TYPE, CSL_UDMAP_TR_FLAGS_TYPE_4D_BLOCK_MOVE_REPACKING_INDIRECTION);
    //pTr->flags |= CSL_FMK(UDMAP_TR_FLAGS_WAIT, 1U);
    pTr->flags |= CSL_FMK(UDMAP_TR_FLAGS_STATIC, 0U);
    pTr->flags |= CSL_FMK(UDMAP_TR_FLAGS_EOL, CSL_UDMAP_TR_FLAGS_EOL_ICNT0_ICNT1);
    pTr->flags |= CSL_FMK(UDMAP_TR_FLAGS_EVENT_SIZE, CSL_UDMAP_TR_FLAGS_EVENT_SIZE_ICNT2_DEC);
    pTr->flags |= CSL_FMK(UDMAP_TR_FLAGS_TRIGGER0, CSL_UDMAP_TR_FLAGS_TRIGGER_GLOBAL0);
    pTr->flags |= CSL_FMK(UDMAP_TR_FLAGS_TRIGGER0_TYPE, CSL_UDMAP_TR_FLAGS_TRIGGER_TYPE_ICNT2_DEC);
    pTr->flags |= CSL_FMK(UDMAP_TR_FLAGS_TRIGGER1, CSL_UDMAP_TR_FLAGS_TRIGGER_NONE);
    pTr->flags |= CSL_FMK(UDMAP_TR_FLAGS_TRIGGER1_TYPE, CSL_UDMAP_TR_FLAGS_TRIGGER_TYPE_ALL);
    pTr->flags |= CSL_FMK(UDMAP_TR_FLAGS_CMD_ID, 0x25U);  /* This will come back in TR response */
    pTr->flags |= CSL_FMK(UDMAP_TR_FLAGS_SA_INDIRECT, 0U);
    pTr->flags |= CSL_FMK(UDMAP_TR_FLAGS_DA_INDIRECT, 0U);
    pTr->flags |= CSL_FMK(UDMAP_TR_FLAGS_EOP, 1U);

    pTr->addr = (uint64_t)Udma_defaultVirtToPhyFxn(srcBuf, 0U, NULL);
    pTr->icnt0 = entrySize;                 // 32B
    pTr->icnt1 = chunkSize / entrySize;     // 28160 / 32 = 880
    pTr->icnt2 = srcSize / chunkSize;       // 56320 / 28160 = 2
    pTr->icnt3 = (uint16_t)-1;              // ???? should be infinite ????
    pTr->dim1 = entrySize;                  // 32
    pTr->dim2 = chunkSize;                  // 28160
    pTr->dim3 = 0;

    pTr->daddr = (uint64_t)Udma_defaultVirtToPhyFxn(destBuf, 0U, NULL);
    pTr->dicnt0 = entrySize;                // 32B
    pTr->dicnt1 = chunkSize / entrySize;    // 28160 / 32 = 880
    pTr->dicnt2 = destSize / chunkSize;     // 506880 / 28160 = 18
    pTr->dicnt3 = (uint16_t)-1;             // ???? should be infinite ????
    pTr->ddim1 = entrySize;                 // 32
    pTr->ddim2 = chunkSize;                 // 28160
    pTr->ddim3 = 0;

    pTr->fmtflags = 0x00000000U;    /* Linear addressing, 1 byte per elem */

    /* Perform cache writeback */
    CacheP_wb(trpdMem, UDMA_TRPD_SIZE, CacheP_TYPE_ALLD);

    return;
}

static void App_udmaTriggerInit(void)
{
    int32_t retVal;
    Udma_DrvHandle  drvHandle = &gUdmaDrvObj[CONFIG_UDMA0];

    gCh0TrEventHandle = &gCh0TrEventObj;
    UdmaEventPrms_init((Udma_EventPrms*)& gCh0TrEventPrms);
    gCh0TrEventPrms.eventType = UDMA_EVENT_TYPE_TR;
    gCh0TrEventPrms.eventMode = UDMA_EVENT_MODE_SHARED;
    gCh0TrEventPrms.chHandle = ch0Handle;
    gCh0TrEventPrms.controllerEventHandle = NULL;
    gCh0TrEventPrms.eventCb = App_udmaEventCb;
    gCh0TrEventPrms.appData = NULL;
    retVal = Udma_eventRegister(drvHandle, gCh0TrEventHandle, (Udma_EventPrms*)&gCh0TrEventPrms);
    if (UDMA_SOK != retVal)
        DebugMsg("\nWarning! - Udma_eventRegister ch0 = %d", retVal);

    retVal = Udma_chEnable(ch0Handle);
    if (UDMA_SOK != retVal)
        DebugMsg("\nWarning! - Udma_chEnable ch0 = %d", retVal);

    return;
}

STATUS dma_init(VOID* destBuf, VOID* srcBuf, uint32_t destSize, uint32_t srcSize, uint32_t chunkSize, uint32_t entrySize)
{
    int32_t retVal = UDMA_SOK;
    uint8_t* trpdMem;
    uint64_t trpdMemPhy;

    srcBuf = (VOID*)TCM_ADDR_TO_PHY((uint32_t)srcBuf);

    ch0Handle = gConfigUdma0BlkCopyChHandle[0];  /* Has to be done after driver open */

    App_udmaTrpdInit(ch0Handle, 0, &gUdmaTestTrpdMem[0], destBuf, srcBuf, destSize, srcSize, chunkSize, entrySize);

    App_udmaTriggerInit();

    triggerMask = ((uint32_t)1U << (CSL_UDMAP_TR_FLAGS_TRIGGER_GLOBAL0 - 1U));
    ch0SwTriggerReg = (volatile uint32_t*)Udma_chGetSwTriggerRegister(ch0Handle);

    trpdMem = &gUdmaTestTrpdMem[0];
    trpdMemPhy = (uint64_t)Udma_defaultVirtToPhyFxn(trpdMem, 0U, NULL);
    retVal = Udma_ringQueueRaw(Udma_chGetFqRingHandle(ch0Handle), trpdMemPhy);
    if (UDMA_SOK != retVal)
        DebugMsg("\nWarning! - Udma_ringQueueRaw ch0 = %d", retVal);

    return ERROR_SUCCESS;
}

VOID dma_enqueue(VOID)
{
    // Trigger DMA
    bDMADone = FALSE;
    CSL_REG32_WR(ch0SwTriggerReg, triggerMask);
    CSL_REG32_WR(ch0SwTriggerReg, 0U);
    uiEnqueues++;
}

BOOL dma_done(VOID)
{
    return bDMADone;
}

STATUS dma_end(VOID)
{
    int32_t retVal;
    uint64_t pDesc;

    retVal = Udma_chDisable(ch0Handle, UDMA_DEFAULT_CH_DISABLE_TIMEOUT);
    if (UDMA_SOK != retVal)
        DebugMsg("\nWarning! - Udma_chDisable ch0 = %d", retVal);

    retVal = Udma_ringFlushRaw(Udma_chGetCqRingHandle(ch0Handle), &pDesc);
    if (UDMA_SOK != retVal)
        DebugMsg("\nWarning! - Udma_ringDequeueRaw ch0 = %d", retVal);

    retVal = Udma_eventUnRegister(gCh0TrEventHandle);
    if (UDMA_SOK != retVal)
        DebugMsg("\nWarning! - Udma_eventUnRegister ch0 = %d", retVal);

    return ERROR_SUCCESS;
}

主叫订单将为:

dma_init(xxxxx);
while (not_done) {
    dma_enqueue();
    if (dma_done())
        xxxxxxx; // dequeue src AND enqueue dest
}
dma_end();

任何帮助都将受到赞赏。

谢谢。

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

    已将查询分配给专家。 请在1天或2天内收到回复。

    谢谢!

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

    您好、Carlos Lega、

    您需要将数据从 TCM 存储器传输到 MSRAM 或 DDR。

    因此、此处应在 TCM 存储器中定义源地址。

    TCM 存储器地址应使用 TCM 存储器的全局地址、而不是 R5F 本地视图 TCM 存储器进行 DMA 操作。

    我不确定您是如何在链接器 cmd 文件中定义源存储器的。

    以下示例将指导您 如何定义 TCM 存储器中的源存储器。 如果使用新的 MCU+SDK 版本、用户无法更新链接器 cmd 文件、而是必须更新 syscfg 以在 TCM 中定义源地址。

    接下来、icn3和 dcnt3值应等于1、而不是最大值。  

    请查看以下章节以了解有关 cnt 和 cnt 值的更多详细信息。

    /cfs-file/__key/communityserver-discussions-components-files/791/Testcase_2D00_5-_2800_1_2900_.zip

    如果您希望基于 GPIO 触发 DMA、下面的常见问题解答会帮助您。

    https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1378150/faq-how-to-trigger-dma-with-the-help-of-gpio-on-am64x-am243-and-am62x-devices

    此致、

    Anil。

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

    感谢您发送编修。

    我的问题不是转账本身,而是转账的顺序。 让我来解释一下更多细节:

    1-仔细检查并确认的地址如下:srcBuf = 0x41012280 (由 TCM_ADDR_TO_PHY 宏修改为0x78102280)、destBuf = 0x70100080

    2 -我已经在您的第一个图像(TRM 11.1.3.2.1)中看到并研究了该算法。 根据、在每个周期都有一个 TR_TRIG0_TYPE (也为1)测试、用以继续。 这让我认为、如果未经断言、则算法会暂停、直至再次断言。 对吧? (BTW、我认为算法代码的最后一条可见行错误、并且多遗漏了几行。)

    3-要传输的数据总量未知、但肯定大于:(icnt0*icnt1*icnt2)以及大于:(dicnt0*dicnt1*dicnt3)-假设 icnt3=1、但不知道并需要它运行超过该值、icnt3的逻辑值将是最大值。

    我遇到的问题是、一旦我设置 DMA 传输详细信息并触发它、它不会停止(或暂停)。 不过、它会回调 CB 函数、但不会暂停... 因此它会传输"空数据空间"。


    请参阅以下伪代码以及对我的预期行为的注释:
    注意:为简单起见、我将 srcBuffer 和 destBuffer 定义为具有 chunkSize 大小的单个位置数组。

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

    void* srcBuf = 0x41012280;    // tcm
    void* destBuf = 0x70100080;// MSRAM
    uint32_t entrySize = 32;    //字节
    uint32_t chunkSize = 28160;//字节
    uint32_t srcSize = 56320;    //字节
    uint32_t destSize = 506880;//字节

    typedef struct _chunk_size_T

       uint8_t chunkData[28160];
    } CHUNK_SIZE_T;

    Chuck_size_T srcBuffer[2]_ attribute ((LOCATION (0x41012280)))={0};
    Chuck_size_T destBuffer[3]_attribute ((LOCATION (0x70100080))={0};

    dma_init (destBuf、srcBuf、destSize、srcSize、chunkSize、 entrySize);

    while (NOT_DONE)//手动停止事件

       while (READY_TO_DMA_CHUNK_SIZE)   //手动触发事件
           dma_enqueue();   //请参见下面有关预期数据流的注释
    }
    dma_end();


     
    请查看数组索引!、请记住"数组"大小可能会发生变化(取决于其他因素、而不是固定的)
    预期流程如下:

    NOT_DONE 置为无效
    .
    .一些时间
    .
    READY_TO_DMA_CHUNK_SIZE 置为有效
                                       srcBuffer[0]-> destBuffer[0]        
    .
    .一些时间
    .
    READY_TO_DMA_CHUNK_SIZE 置为有效
                                       srcBuffer[1]-> destBuffer[1]
    .
    .一些时间
    .
    READY_TO_DMA_CHUNK_SIZE 置为有效
                                       srcBuffer[0]-> destBuffer[2]
    .
    .一些时间
    .
    READY_TO_DMA_CHUNK_SIZE 置为有效
                                       srcBuffer[1]-> destBuffer[0]
    .
    .一些时间
    .
    READY_TO_DMA_CHUNK_SIZE 置为有效
                                       srcBuffer[0]-> destBuffer[1]
    .
    .一些时间
    .
    READY_TO_DMA_CHUNK_SIZE 置为有效
                                       srcBuffer[1]-> destBuffer[2]
    .
    .一些时间
    .
    READY_TO_DMA_CHUNK_SIZE 置为有效
                                       srcBuffer[0]-> destBuffer[0]
    .
    .一些时间
    .
    READY_TO_DMA_CHUNK_SIZE 置为有效
                                       srcBuffer[1]-> destBuffer[1]
    .
    .一些时间
    .
    NOT_DONE 置为有效

    P.S.有问题将它嵌入为代码。 DKW

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [报价 userid="525901" url="~/support/processors-group/processors/f/processors-forum/1441862/am6421-help-with-dma-configuration/5532777 #5532777"]

    因此、此处应在 TCM 存储器中定义源地址。

    TCM 存储器地址应使用 TCM 存储器的全局地址、而不是 R5F 本地视图 TCM 存储器进行 DMA 操作。

    [报价]

    您好、Carlos Lega、

    您能否确认您使用的 TCM 地址空间是否为0x4100xxxx、然后尝试使用全局地址空间而不是 R5F TCM 存储器视图?

    如果您查看上面随附的示例、您可以了解到我们将 TCM 全局地址存储器用于 DMA 应用。

    因为、DMA 不知道 R5F 存储器视图。

    要传输的总数据量未知、但肯定大于:(icnt0*icnt1*icnt2)、且大于:(dicnt0*dicnt1*dicnt3)-假设 icnt3=1、但不知道且需要超过该值、则最大的引用值为 icnt3[]。

    实际上、您需要将数据从 TCMB 传输到目标存储器。 在这种情况下、您可以传输最大64KB 的数据、而不能超过无法传输的数据。

    此致、

    Anil。

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

    Anil 您好、再次感谢您的快速回答...

    您能否确认您使用的 TCM 地址空间是否为0x4100xxxx、然后尝试使用全局地址空间而不是 R5F TCM 存储器视图?

    ...我确信我使用的是 TCM 的全局地址,这就是这一行的功能:

    srcBuf =(void*) TCM_ADDR_TO_PHY ((uint32_t) srcBuf);

    实际上、您需要将数据从 TCMB 传输到目标内存。 在这种情况下、您可以传输最大64KB 的数据、但不能超过无法传输的数据。

    我知道单次转移、但我的意图是一次多次转移大约32KB。

    此外、当特定事件发生时、需要传输~32KB 的每个"块"。

    我的确切问题/问题是:

    给定此 TR 配置:

        pTr = UdmaUtils_getTrpdTr15Pointer(trpdMem, 0U);
        pTr->flags = CSL_FMK(UDMAP_TR_FLAGS_TYPE, CSL_UDMAP_TR_FLAGS_TYPE_4D_BLOCK_MOVE_REPACKING_INDIRECTION);
        pTr->flags |= CSL_FMK(UDMAP_TR_FLAGS_STATIC, 0U);
        pTr->flags |= CSL_FMK(UDMAP_TR_FLAGS_EOL, CSL_UDMAP_TR_FLAGS_EOL_ICNT0_ICNT1);
        pTr->flags |= CSL_FMK(UDMAP_TR_FLAGS_EVENT_SIZE, CSL_UDMAP_TR_FLAGS_EVENT_SIZE_ICNT2_DEC);
        pTr->flags |= CSL_FMK(UDMAP_TR_FLAGS_TRIGGER0, CSL_UDMAP_TR_FLAGS_TRIGGER_GLOBAL0);
        pTr->flags |= CSL_FMK(UDMAP_TR_FLAGS_TRIGGER0_TYPE, CSL_UDMAP_TR_FLAGS_TRIGGER_TYPE_ICNT2_DEC);
        pTr->flags |= CSL_FMK(UDMAP_TR_FLAGS_TRIGGER1, CSL_UDMAP_TR_FLAGS_TRIGGER_NONE);
        pTr->flags |= CSL_FMK(UDMAP_TR_FLAGS_TRIGGER1_TYPE, CSL_UDMAP_TR_FLAGS_TRIGGER_TYPE_ALL);
        pTr->flags |= CSL_FMK(UDMAP_TR_FLAGS_CMD_ID, 0x25U);  /* This will come back in TR response */
        pTr->flags |= CSL_FMK(UDMAP_TR_FLAGS_SA_INDIRECT, 0U);
        pTr->flags |= CSL_FMK(UDMAP_TR_FLAGS_DA_INDIRECT, 0U);
        pTr->flags |= CSL_FMK(UDMAP_TR_FLAGS_EOP, 1U);
    

    当已经传输 icont0*icnt1字节时、DMA 算法是否应该暂停传输?

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

    您好、

    是的、现在我已经解决了您的问题。

    您可以告诉我触发 DMA 所需的时间间隔是多少。

    实际上,当你调用 udma_queraw API 时, DMA 只会触发一次。

    完成 DMA 后、DMA 将再次启动、直到您调用 udma_queraw API。

    所以、背后的想法是 如果你希望无限次触发 DMA、那么你需要为每个 DMA 启动调用 udma_queraw API。

    随附的示例对您很有帮助。 在这里、我的用例是将数据从 DDR 传输到 TCM 、以获取 不同 R5F 内核的4KB 数据。

    我已经为每1毫秒创建了一个定时器中断、在1毫秒中断时、我触发了 DMA 启动。 你可以看看 A53示例,你会得到一个想法.

    进入 TR、 只需配置 icnt0 = 32kB、icnt1、icn2和 inct3 = 1、类似地、您可以在应用程序中配置 dicnt 值。

    如果您需要任何帮助、请告诉我。

    e2e.ti.com/.../DMA_5F00_Broadcast_5F00_Periodic.zip

    此致、

    Anil。

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

    Anil、您好、感谢您的最后一个示例。

    您可以告诉我触发 DMA 所需的时间间隔是多少。

    我的具体用例为:

    RF50_0以~1us 的速度接收数据(20~40B 数据包)(如果能够设法将其清除、则速度更快-这就是我最快速地需要它的原因!)。

    这些数据会推入 TCM 队列、最大大小小于32KB。 它位于 TCM 中、以尽可能快地推送(中间有一些计算、因此此处尚无 DMA)。

    然后使用 DMA 与 DDR/MSRAM 中的另一个更大队列(~512KB)进行传输/同步、以便 A53可以访问/使用该队列。

    问题是 R5需要在不到1us 的时间轮询数据、所以任何操作(包括 DMA 队列/触发器)都必须非常快。 这就是我尝试仅使用 SW 触发器来触发它的原因。

    但是、由于许多原因、还需要能够在不完成 DMA 排队 TR 数据的情况下停止它。

    那么我的下一个问题是、我可以将 icnt3设置为无限((uint16_t)-1)吗、这样可以可靠/正确地停止 DMA 传输、并且能够在无需重新启动系统的情况下重复使用 DMA 通道? 如果是、如何实现?

    再次感谢您的帮助。

    此致、Carlos。

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

    卡洛斯、您好!

    我们假设 R5F 内核在 TCM 中每1usec 填充32个字节。 因此、要填充32KB 字节 TCM、R5F 需要大约~1024usec。

    我希望 DMA 能够以1024us 的电流和32KB 的电容传输 DMA。 以便您可以启动下一次传输。

    但是、请确保您需要检查每个事务是否已完成前一个事务。

    否则、TCM 缓冲区可能存在问题。 因为、对于每1Use、R5F 就会填充 TCM 存储器。

    并且、如果配置 icnt3=65535、则一旦启动 DMA、则 DMA 完成事件将在65535 * 32*1024字节传输后完成。

    您无需  在应用程序中无限次地配置 icnt3。 如果前面的 DMA 传输没有完成、那么进行 DMA 通道拆解过程。

    [报价 userid="567653" url="~/support/processors-group/processors/f/processors-forum/1441862/am6421-help-with-dma-configuration/5541243 #5541243"]

    然后使用 DMA 与 DDR/MSRAM 中的另一个更大队列(~512KB)进行传输/同步、以便 A53可以访问/使用该队列。

    [报价]

    您想根据 TCM 事务将 DDR/MSRAM 数据传输到 A53内核?

    我不确定您是否看到了以上示例?

    此致、

    Anil。

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

    Anil、您好!

    我希望 DMA 能够以1024usec 的电压传输32KB 的 DMA。 因此、您可以启动下一次传输。

    是的、它的传输速度确实比 R5F 填充队列更快。

    否则、可能存在 TCM 缓冲区损坏问题。 因为、每1Use R5F 填充一次 TCM 存储器[/报价]

    正确。 这就是我使用乒乓缓冲器的原因(队列满前双 DMA 传输)。

    但是请确保您需要检查每笔交易是否完成了前一笔交易。

    这是问题的一部分。 检查和重新触发新的传输所需的时间比 R5F 所花费的时间更长、并且会破坏 R5F 环路时序。

    [报价 userid="525901" url="~/support/processors-group/processors/f/processors-forum/1441862/am6421-help-with-dma-configuration/5541833 #5541833"]

    并且、如果配置 icnt3=65535、则一旦启动 DMA、则 DMA 完成事件将在65535 * 32*1024字节传输后完成。

    您无需  在应用程序中无限次地配置 icnt3。 如果前面的 DMA 传输没有完成、那么进行 DMA 通道拆解过程。

    [报价]

    问题是要传输的总数据可能会发生变化。 最初、用户将触发(可能)已知数量的数据、但也可能能够停止数据流。 因此、一般流程是:用户启动一个由每1us ~20-40B 数据包组成的数据流、该数据流可在初始阶段与用户需要的时间一样长、也可随时被(用户)停止。

    这意味着:R5F 需要可以自由地按时完全接收每个数据包、对其执行一些 DSP 处理(大约需要900ns)、然后进入 TCM 队列。 这里是当 R5F 没有太多时间来处理 DMA 检查/重新触发/配置时。

    这些数据包需要从 TCM 移动到另一个位置(DDR/MSRAM)的更大队列、然后由 A53进行处理。 这就是 DMA 非常有用的地方、但我也希望此 DMA 配置/触发由 R5F 而非 A53完成。

    请确认在 DMA 完成传输之前是否有暂停/停止/重新配置 DMA 的方法以及如何执行此操作。

    谢谢。 卡洛斯。

    [/quote]
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [报价 userid="567653" url="~/support/processors-group/processors/f/processors-forum/1441862/am6421-help-with-dma-configuration/5542633 #5542633"]

    请确认在 DMA 完成传输之前是否有暂停/停止/重新配置 DMA 的方法以及如何执行此操作。

    [报价]

    卡洛斯、您好!

    如果我们排队等待振铃、我们应该等到振铃操作完成。

    假设 DMA 以10 μ s 的速度以8KB 的速度传输数据。  如果要在 DMA 完成之前以更新的大小触发 DMA、我们需要拆卸通道并使用新的大小更新环。

    此处重新配置 DMA 通道和 TR 配置需要更多的时间。

    如果您可以对 通道进行拆卸并重新配置 TR、则请使用此方法、除此方法外、在 DMA 完成其 DMA 操作之前、没有任何方法可以停止或暂停 DMA。

    此致、

    Anil。

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

    Anil、您好!

    再次感谢您的回答。

    如果我们排队等候振铃、我们应等到振铃操作完成。

    即使队列以软件触发为例也是如此吗?

    此处重新配置 DMA 通道和 TR 配置需要更多时间。

    没关系。 暂停/停止/重新配置 DMA 时、可以花一些时间...

    我现在正在寻找如何拆卸 DMA 通道,而无需等待它传输"垃圾",因为用户已经告诉系统停止(这意味着仍然流动的数据不需要和/或垃圾可能影响后处理)。

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

     卡洛斯、您好!

    [报价 userid="567653" url="~/support/processors-group/processors/f/processors-forum/1441862/am6421-help-with-dma-configuration/5556313 #5556313"]

    即使队列以软件触发为例也是如此吗?

    [报价]

    是的、每个 DMA 通道都应遵循此方法。

    以下代码有助于拆卸 DMA 通道。

        /* Channel disable */
        retVal = Udma_chDisable(chHandle, UDMA_DEFAULT_CH_DISABLE_TIMEOUT);
        DebugP_assert(UDMA_SOK == retVal);
        
        Drivers_udmaClose();

    此致、

    Anil。

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

    Anil、您好!

    查看文档后我们发现环形加速器听起来更像我们需要的,但找不到它的示例。 您能给我们举个例子、说明如何使用 Ring 加速器、将 R5-nortos 作为生产者、将 A53-Linux 作为消费者吗?

    谢谢你。

    卡洛斯。

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

    卡洛斯、您好!

    通过当前的 MCU+SDK 示例修改、我们可以满足您的要求。

    为了达到您的要求、我们可以通过以下方法操作。

    假设两个内核都使用 DDR 存储器。

    然后、在 R5F 内核中从 DDR 分配特定的存储器位置、并从 R5F 内核将数据写入 DDR 存储器中。

    接下来、启动 DMA。

    DMA 完成事件发生后、我们可以将此 DMA 中断路由到两个内核。

    在一个内核中、中断应清除并进行处理、而另一个内核只有 DMA 中断观察功能。

    一旦 A53内核收到中断、就会处理 DDR 数据。

    这可以在 SOC 级别实现。

    但是,我不确定这是可能的或不在软件方面在 Linux 方面. 我需要与 Linux 专家核实、除了这种方法。

    我们不能做任何事情。

    此致、

    Anil。