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.

[参考译文] SK-AM62-LP:在 McASP 中启用第二个串行器

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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1380881/sk-am62-lp-enabling-the-second-serializer-in-mcasp

器件型号:SK-AM62-LP
主题中讨论的其他器件:SysConfig

工具与软件:

您好!

我将使用 McASP 驱动程序来编写一个应用程序。

我成功地配置了 McASP0驱动器实例、以通过单个串行器(AXR0或 AXR1)以48kHz 的速率传输8槽/16位 TDM 帧:

- AXR0:

- AXR1:

问题是、当我启用2个串行器(即 AXR0和 AXR1)并运行非常相同的应用 时、我无法在相应的串行数据引脚上看到任何数据-我只能看到串行位时钟信号:

我想知道如何启用2个串行器、以便它们可以同时为两个引脚上的数据提供服务。

在 SysConfig 中添加第二个串行器是否足够?

我是否需要发送更多数据?

是否有任何实现 TDM 多槽多串行器案例的示例应用可用?

下面是应用代码和 SysConfig 设置示例:

-应用程序:

#include "mcasp_util.h"

#include "ti_drivers_config.h"

#include <FreeRTOS.h>
#include <drivers/mcasp.h>
#include <kernel/dpl/CacheP.h>
#include <kernel/dpl/DebugP.h>
#include <task.h>

#include <stdint.h>
#include <string.h>

#define SLOT_COUNT               (8u)
#define SLOT_SIZE_IN_B           (4u)
#define FRAME_COUNT              (2u)
#define FRAME_SIZE_IN_B          (SLOT_COUNT * SLOT_SIZE_IN_B)
#define DATA_SIZE_IN_B           (FRAME_COUNT * FRAME_SIZE_IN_B)
#define LOOPJOB_BUFFER_SIZE_IN_B (FRAME_SIZE_IN_B)

uint8_t txBuffers[FRAME_COUNT][FRAME_SIZE_IN_B] __attribute__((aligned(256)));

MCASP_Transaction txTransactions[FRAME_COUNT] = {};

uint32_t volatile txCallbackCallCount = 0u;

extern uint8_t txLoopjobBuffer[];

static void fillTxBuffers(uint8_t (* const buffer)[FRAME_COUNT][FRAME_SIZE_IN_B])
{
    for (uint32_t i = 0u; i < FRAME_COUNT; ++i)
    {
        for (uint32_t j = 0u; j < FRAME_SIZE_IN_B; ++j)
        {
            (*buffer)[i][j] = (FRAME_SIZE_IN_B * i + j) % 256u;
        }
    }
}

static void fillLoopjobBuffer(
    uint8_t (* const buffer)[LOOPJOB_BUFFER_SIZE_IN_B],
    uint32_t const value)
{
    for (uint32_t i = 0u; i < LOOPJOB_BUFFER_SIZE_IN_B; i += 4u)
    {
        *((uint32_t*)(&((*buffer)[i]))) = value;
    }
}

static void submitBuffers(
    MCASP_Handle const handle,
    MCASP_Transaction (* const transactions)[FRAME_COUNT],
    uint8_t (* const buffers)[FRAME_COUNT][FRAME_SIZE_IN_B],
    int32_t (* const callback)(MCASP_Handle, MCASP_Transaction*))
{
    for (uint32_t i = 0u; i < FRAME_COUNT; ++i)
    {
        (*transactions)[i].buf = &(*buffers)[i];
        (*transactions)[i].count = FRAME_SIZE_IN_B / SLOT_SIZE_IN_B;
        (*transactions)[i].timeout = 0xFFFFFFFFu;

        callback(handle, &(*transactions)[i]);
    }
}

static void awaitTransferCompletion(void)
{
    vTaskDelay(pdMS_TO_TICKS(100u));
}

static void withdrawBuffers(
    MCASP_Handle const handle,
    MCASP_Transaction* (* const callback)(MCASP_Handle))
{
    while (callback(handle) != NULL)
    {
    }
}

void mcaspMain(void* args)
{
    MCASP_Handle handle;

    fillTxBuffers(&txBuffers);
    CacheP_wb(&txBuffers, DATA_SIZE_IN_B, CacheP_TYPE_ALL);

    fillLoopjobBuffer(&txLoopjobBuffer, 0xFFFFFFFFu);
    CacheP_wb(&txLoopjobBuffer, LOOPJOB_BUFFER_SIZE_IN_B, CacheP_TYPE_ALL);

    handle = MCASP_getHandle(CONFIG_MCASP0);
    DebugP_assert(handle != NULL);

    submitBuffers(
        handle,
        &txTransactions,
        &txBuffers,
        &MCASP_submitTx
    );

    DebugP_assert(MCASP_startTransferTx(handle) == SystemP_SUCCESS);

    awaitTransferCompletion();

    MCASP_stopTransferTx(handle);

    withdrawBuffers(handle, &MCASP_withdrawTx);
}

void runOnTransmittingData(
    MCASP_Handle handle,
    MCASP_Transaction* const transaction)
{
    ++txCallbackCallCount;
}

- SysConfig 设置:

/**
 * These arguments were used when this file was generated. They will be automatically applied on subsequent loads
 * via the GUI or CLI. Run CLI with '--help' for additional information on how to override these arguments.
 * @cliArgs --device "AM62x" --package "AMC" --part "Default" --context "a53ss0-0" --product "MCU_PLUS_SDK_AM62x@09.02.01"
 * @versions {"tool":"1.20.0+3587"}
 */

/**
 * Import the modules used in this configuration.
 */
const mcasp      = scripting.addModule("/drivers/mcasp/mcasp", {}, false);
const mcasp1     = mcasp.addInstance();
const debug_log  = scripting.addModule("/kernel/dpl/debug_log");
const mmu_armv8  = scripting.addModule("/kernel/dpl/mmu_armv8", {}, false);
const mmu_armv81 = mmu_armv8.addInstance();
const mmu_armv82 = mmu_armv8.addInstance();

/**
 * Write custom configuration values to the imported modules.
 */
mcasp1.$name                                   = "CONFIG_MCASP0";
mcasp1.txHclkSourceMux                         = 2;
mcasp1.rxHclkSourceMux                         = 2;
mcasp1.txCallbackFxn                           = "runOnTransmittingData";
mcasp1.rxCallbackFxn                           = "runOnReceivingData";
mcasp1.txLoopjobBuf                            = "txLoopjobBuffer";
mcasp1.rxLoopjobBuf                            = "rxLoopjobBuffer";
mcasp1.rxActiveSlotMask                        = 0x3;
mcasp1.rxDataMask                              = 0xFFFFFFFF;
mcasp1.enableLoopback                          = false;
mcasp1.clkSyncMode                             = "ASYNC";
mcasp1.enableMcaspRx                           = false;
mcasp1.TxMode                                  = "TDM";
mcasp1.NumTxSlots                              = 8;
mcasp1.txAfifoEnable                           = false;
mcasp1.txActiveSlotMask                        = 0xFF;
mcasp1.txFsPolarity                            = 0;
mcasp1.txBitClkPolarity                        = 0;
mcasp1.txDataDelay                             = 0;
mcasp1.TxSlotSize                              = 16;
mcasp1.txDataMask                              = 0xFF000000;
mcasp1.txLoopjobBufLength                      = 16;
mcasp1.MCASP.$assignAllowConflicts             = "MCASP0";
mcasp1.mcaspSer.create(2);
mcasp1.mcaspSer[0].$name                       = "CONFIG_MCASP_SER0";
mcasp1.mcaspSer[0].MCASP.$assignAllowConflicts = "MCASP0";
mcasp1.mcaspSer[1].$name                       = "CONFIG_MCASP_SER1";
mcasp1.mcaspSer[1].serNum                      = 1;
mcasp1.mcaspSer[1].MCASP.$assignAllowConflicts = "MCASP0";
scripting.suppress("Resource conflict,MCASP0 is also in use by @@@.+?@@@, @@@.+?@@@", mcasp1.MCASP, "$assign");
scripting.suppress("Resource conflict,MCASP0 is also in use by @@@.+?@@@, @@@.+?@@@", mcasp1.mcaspSer[0].MCASP, "$assign");
scripting.suppress("Resource conflict,MCASP0 is also in use by @@@.+?@@@, @@@.+?@@@", mcasp1.mcaspSer[1].MCASP, "$assign");

const udma         = scripting.addModule("/drivers/udma/udma", {}, false);
const udma1        = udma.addInstance({}, false);
udma1.$name        = "CONFIG_UDMA0";
mcasp1.bcDmaDriver = udma1;

const udma2         = udma.addInstance({}, false);
udma2.$name         = "CONFIG_UDMA1";
mcasp1.pktDmaDriver = udma2;

debug_log.enableUartLog        = true;
debug_log.uartLog.$name        = "CONFIG_UART_CONSOLE";
debug_log.uartLog.UART.$assign = "USART0";

mmu_armv81.size  = 0x80000000;
mmu_armv81.$name = "SOC_MEM_REGION";

mmu_armv82.vAddr     = 0x80000000;
mmu_armv82.pAddr     = 0x80000000;
mmu_armv82.size      = 0x80000000;
mmu_armv82.attribute = "MAIR7";
mmu_armv82.$name     = "DDR_REGION";

/**
 * Pinmux solution for unlocked pins/peripherals. This ensures that minor changes to the automatic solver in a future
 * version of the tool will not impact the pinmux you originally saw.  These lines can be completely deleted in order to
 * re-solve from scratch.
 */
mcasp1.MCASP.AFSX.$suggestSolution             = "MCASP0_AFSX";
mcasp1.MCASP.ACLKX.$suggestSolution            = "MCASP0_ACLKX";
mcasp1.SYSTEM.$suggestSolution                 = "SYSTEM0";
mcasp1.mcaspSer[0].MCASP.AXR0.$suggestSolution = "MCASP0_AXR0";
mcasp1.mcaspSer[1].MCASP.AXR1.$suggestSolution = "MCASP0_AXR1";
debug_log.uartLog.UART.RXD.$suggestSolution    = "UART0_RXD";
debug_log.uartLog.UART.TXD.$suggestSolution    = "UART0_TXD";

BR、

Maciek

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

    Maciek、您好!

    感谢您的提问。

    我可以看到您随附的 SysConfig 文件。 那么、我将继续向前、假设您在开发中使用 MCU 和 SDK。

    请改正我对同样的理解。

    此致、

    Vaibhav

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

    尊敬的 Vaibhav:

    感谢您的答复。

    是的、我使用的是 MCU-PLUS-SDK AM62X-AM62X。

    供参考、我注意到在 SysConfig 中将传输模式从 DMA 更改为中断后、我可以看到两个串行数据引脚(AXR0和 AXR1)上的数据。

    看起来 McASP v1不支持基于多串行器 DMA 的配置- McASP_DMA.c 不考虑所有可能的音频缓冲器 格式(MCASP_AUDBUFF_FORMAT_MULTISER_MULTIISLOT_SEMI 交错_1和 MCASP_AUDBUFF_FORMAT_MULTIMER_MULTISLOT_SEMI 交错式2)。

    另一方面、McASP V0用于支持它们。

    不幸的是、由于缺少一些依赖项(例如、没有 edma.h 文件)、我无法使用以前的驱动程序版本。

    是否可以将 DMA 与多个 Tx 串行器一起使用?

    BR、

    Maciek

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

    尊敬的 Maciej:

    感谢您的答复。

    让我再为您指派一名有关这方面的专家。

    此致、

    Vaibhav

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

    尊敬的 Vaibhav:

    您是否有机会看到一些使用 McASP 在多个串行器上传输数据的示例应用?

    我对基于 uDMA 的应用感兴趣、而不对基于 EDMA 的应用感兴趣。

    BR、

    Maciek

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

    尊敬的 Maciej:

    感谢您的答复。

    您是否有使用 McASP 通过多个串行器传输数据的范例应用?

    只有 AM62D 中有多个串行器。

    仅供参考、所有其他器件只有一个串行器连接到编解码器。

    此致、

    Vaibhav

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

    尊敬的 Vaibhav:

    我 调整了评估板、以便使用更多串行器。

    无论是哪种方式、我都可以在启用 AFIFO 后通过其中的2种方式传输数据。

    BR、

    Maciek

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

    Maciej、您好!

    无论哪种方式、我都可以在启用 AFIFO 后通过其中的2个节点传输数据。

    听得不错。

    我 调整了评估板以支持使用更多串行器。

    您能否分享这些步骤?

    此致、

    Vaibhav

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

    您好、Vaibhav、

    在修改电路板时、我移除了 R348 (0欧姆)、以留出一些空间、用于连接通过 McASP0实例的导线

    FSYNC 信号来自外部时钟主器件。

    我还移除了 R297 (10k Ω)、以将 AXR1与 VCC3V3_EXP 去耦。

    我花了一段时间才弄清楚、显然需要让 AFIFO 使用一个以上的串行器来发送数据。

    我修补了驱动程序、通过使用有源串行器的信息来提出这一要求:

    diff --git a/source/drivers/mcasp/v1/mcasp_dma.c b/source/drivers/mcasp/v1/mcasp_dma.c
    index e169eda..92a0164 100644
    --- a/source/drivers/mcasp/v1/mcasp_dma.c
    +++ b/source/drivers/mcasp/v1/mcasp_dma.c
    @@ -74,6 +74,8 @@ static void MCASP_udmaTrInit(uint8_t *pTrpd, uint64_t pBuf, uint32_t bufSize);
     static void MCASP_udmaHpdInit(Udma_ChHandle chHandle, uint8_t *pHpdMem,
                                   const void *destBuf, uint32_t length);
     
    +static int32_t configureTxPdmaChannel(MCASP_Object* const driverObject);
    +
     /* ========================================================================== */
     /*                          Function Definitions                              */
     /* ========================================================================== */
    @@ -461,28 +463,9 @@ int32_t MCASP_enableDmaTx(MCASP_Config *config)
     
         if(status == SystemP_SUCCESS)
         {
    -        Udma_ChPdmaPrms pdmaPrms;
             Udma_ChHandle txChHandle = obj->dmaChCfg->txChHandle;
     
    -        /* Config PDMA channel */
    -        UdmaChPdmaPrms_init(&pdmaPrms);
    -        pdmaPrms.elemSize = UDMA_PDMA_ES_32BITS;
    -
    -        /* Number of words received in each transfer */
    -        if(obj->txFifoEnable == 1)
    -        {
    -            pdmaPrms.elemCnt = MCASP_PDMA_ELEM_CNT_WITH_FIFO;
    -        }
    -        else
    -        {
    -            pdmaPrms.elemCnt = 1;
    -        }
    -        pdmaPrms.fifoCnt = 0U;
    -
    -        pdmaPrms.acc32 = 1U;
    -        pdmaPrms.burst = 1U;
    -
    -        status = Udma_chConfigPdma(txChHandle, &pdmaPrms);
    +        status = configureTxPdmaChannel(obj);
             DebugP_assert(SystemP_SUCCESS == status);
     
             status = Udma_chEnable(txChHandle);
    @@ -987,3 +970,48 @@ static void MCASP_udmaIsrRx(Udma_EventHandle eventHandle, uint32_t eventType, vo
             Udma_ringSetDoorBell(Udma_chGetFqRingHandle(rxChHandle), txnPushed);
         }
     }
    +
    +static int32_t configureTxPdmaChannel(MCASP_Object* const driverObject)
    +{
    +    Udma_ChPdmaPrms pdmaParameters;
    +
    +    UdmaChPdmaPrms_init(&pdmaParameters);
    +
    +    // This field specifies how much data is transferred in each write
    +    // which is performed by the DMA.
    +    pdmaParameters.elemSize = UDMA_PDMA_ES_32BITS;
    +
    +    // This field specifies how many elements to transfer each time a trigger
    +    // is received on the channel.
    +    // Its value depends on whether the Write FIFO (WFIFO) is enabled or not.
    +    // The WFIFO is 64-word long (1 word consists of 32 bits).
    +    bool const wfifoEnabled = driverObject->txFifoEnable == 1u;
    +    if (wfifoEnabled)
    +    {
    +        // When it's enabled, each transmit DMA request results in fetching
    +        // 32 words from the DMA so that the WFIFO becomes half full.
    +        // There can be up to 16 serializer in use so loading 32 words means
    +        // queuing 2 samples per each one of them.
    +        pdmaParameters.elemCnt = MCASP_PDMA_ELEM_CNT_WITH_FIFO;
    +    }
    +    else
    +    {
    +        // When it's disabled, the DMA needs to provide data for all
    +        // the active serializers to avoid the transmit underrun error.
    +        uint8_t const serializerCount = driverObject->XmtObj.serCount;
    +        pdmaParameters.elemCnt = serializerCount;
    +    }
    +
    +    // This field is irrelevant to TX and hence set to 0.
    +    pdmaParameters.fifoCnt = 0U;
    +
    +    // This field, when set, enables 32-bit access mode.
    +    // On a 32-bit PDMA, all accesses will have XCNT set to 4
    +    // to support legacy IP that is not fully VBUSP compliant.
    +    pdmaParameters.acc32 = 1U;
    +
    +    // This field, when set, enables VBUSP burst mode on the channel.
    +    pdmaParameters.burst = 1U;
    +
    +    return Udma_chConfigPdma(driverObject->dmaChCfg->txChHandle, &pdmaParameters);
    +}
    

    您是否恰好知道为什么一开始就期望这样?

    使用32字长 WFIFO 背后的原因是什么?

    原因是可用串行器的总数(16个串行器、2个样本/串行器)。

    BR、

    Maciek

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

    Maciej、您好!

    感谢您说明您为实现此目标所做的调整。

    [报价 userid="612160" url="~/support/processors-group/processors/f/processors-forum/1380881/sk-am62-lp-enabling-the-second-serializer-in-mcasp/5299218 #5299218"]

    您是否恰好知道为什么一开始就期望这样?

    使用32字长 WFIFO 背后的原因是什么?

    是因为可用的串行器总数(16个串行器、2个样本/串行器)

    [报价]

    您可以在下周之前获得对未决问题的答复。

    此致、

    Vaibhav