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.

[参考译文] AM2434:AM2434 GPMC 读取/写入函数问题

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1407001/am2434-am2434-gpmc-read-write-function-question

器件型号:AM2434

工具与软件:

您好、TI 专家:

我尝试在定制 AM2434硬件上使用 GPMC 与 FPGA 通信、采用地址/数据多路复用、同步突发读取/写入模式。 在实际使用期间、会出现一些时序问题、例如只读取2个字节而不是64个字节的数据。 下面是我的一些寄存器配置:

/* GPMC attributes */
static GPMC_HwAttrs gGpmcAttrs[CONFIG_GPMC_NUM_INSTANCES] =
{ 
    {
        .gpmcConfig1 =
        {
            .wrapBurst                  = CSL_GPMC_CONFIG1_WRAPBURST_WRAPNOTSUPP,
            .readMultipleFlag           = CSL_GPMC_CONFIG1_READMULTIPLE_RDMULTIPLE,
            .writeMultipleFlag          = CSL_GPMC_CONFIG1_WRITEMULTIPLE_WRMULTIPLE,
            .readType                   = CSL_GPMC_CONFIG1_READTYPE_RDSYNC,
            .writeType                  = CSL_GPMC_CONFIG1_WRITETYPE_WRSYNC,
            .attachedDevicePageLength   = CSL_GPMC_CONFIG1_ATTACHEDDEVICEPAGELENGTH_THIRTYTWO,
            .waitReadMonitoring         = CSL_GPMC_CONFIG1_WAITREADMONITORING_WMONIT,
            .waitWriteMonitoring        = CSL_GPMC_CONFIG1_WAITWRITEMONITORING_WMONIT,
            .waitMonitoringTime         = CSL_GPMC_CONFIG1_WAITMONITORINGTIME_ATVALID,
            .waitPinSelect              = CSL_GPMC_CONFIG1_WAITPINSELECT_W0,
            .deviceSize                 = CSL_GPMC_CONFIG1_DEVICESIZE_SIXTEENBITS,
            .deviceType                 = CSL_GPMC_CONFIG1_DEVICETYPE_NORLIKE,
            .muxAddrData                = CSL_GPMC_CONFIG1_MUXADDDATA_MUX,
            .timeParGranuLarity         = CSL_GPMC_CONFIG1_TIMEPARAGRANULARITY_X1,
            .fclkDivider                = CSL_GPMC_CONFIG1_GPMCFCLKDIVIDER_DIVBY1,
            .clkActivationTime          = CSL_GPMC_CONFIG1_CLKACTIVATIONTIME_ONECLKB4,
        },
        .timingParams =
        {
            .csOnTime               =   0,             
            .csRdOffTime            =   11,            
            .csWrOffTime            =   11,            
            .advOnTime              =   1,             
            .advRdOffTime           =   2,             
            .advWrOffTime           =   2,             
            .advAadMuxOnTime        =   0,             
            .advAadMuxRdOffTime     =   0,             
            .advAadMuxWrOffTime     =   0,             
            .weOnTime               =   3,             
            .weOffTime              =   11,            
            .oeOnTime               =   3,             
            .oeOffTime              =   11,            
            .oeAadMuxOnTime         =   0,             
            .oeAadMuxOffTime        =   0,             
            .pageBurstAccess        =   1,             
            .rdAccessTime           =   10,            
            .wrAccessTime           =   10,            
            .rdCycleTime            =   11,                 
            .wrCycleTime            =   11,                 
            .wrDataOnMuxBusTime     =   2,                  
            .cycle2CycleDelay       =   2,                  
            .cycleDelaySameChipSel  =   CSL_GPMC_CONFIG6_CYCLE2CYCLESAMECSEN_C2CDELAY,
            .cycleDelayDiffChipSel  =   CSL_GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN_C2CDELAY,
            .busTurnAroundTime      =   1,                
        },
        .gpmcBaseAddr           =   CSL_GPMC0_CFG_BASE,
        .dataBaseAddr           =   CSL_GPMC0_DATA_BASE,
        .elmBaseAddr            =   CSL_ELM0_BASE,
        .inputClkFreq           =   100000000U,
        .intrNum                =   CSLR_R5FSS0_CORE0_INTR_GPMC0_GPMC_SINTERRUPT_0,
        .intrPriority           =   4U,
        .chipSelBaseAddr        =   0x50000000U,
        .chipSelAddrSize        =   GPMC_CS_MASK_ADDR_SIZE_128MB, 
        .waitPinPol             =   CSL_GPMC_CONFIG_WAIT0PINPOLARITY_W0ACTIVEL,
        .eccAlgo                =   GPMC_NAND_ECC_ALGO_BCH_16BIT,
        .csExtraDelay           =   CSL_GPMC_CONFIG2_CSEXTRADELAY_NOTDELAYED,
        .advExtraDelay          =   CSL_GPMC_CONFIG3_ADVEXTRADELAY_NOTDELAYED,
        .weExtraDelay           =   CSL_GPMC_CONFIG4_WEEXTRADELAY_NOTDELAYED,
        .oeExtraDelay           =   CSL_GPMC_CONFIG4_OEEXTRADELAY_NOTDELAYED,
        .dmaRestrictedRegions   =   gGpmcDmaRestrictRegions,
    },
};

关于 GPMC、没有什么问题:

1. 我要实现16位* 32字的突发读取/写入操作。 我的寄存器配置有什么问题吗?

2.  wrapBurst 的具体功能是什么? 我查看了参考手册的描述、但不明白。 是否有更多特定资源可用、以及此功能是否仅支持某些芯片?

3. 由于我将 deviceType 配置为16位、并将 attcachedDevicePageLength 配置为32个字、我认为一次 GPMC 操作的数据传输量是16位* 32个字= 64字节。 以下是我的 GPMC 读取/写入函数:

typedef struct
{
    uint8_t data[64];
} DataStruct64;

int32_t GPMC_NormalRead(GPMC_Handle handle, GPMC_Transaction *trans)
{
    DataStruct64 data64;
    int32_t status = SystemP_SUCCESS;
    if (handle == NULL && trans == NULL) {
        status = SystemP_FAILURE;
        return status;
    }

    GPMC_Object *object = ((GPMC_Config*)handle)->object;
    const GPMC_HwAttrs *attrs = ((GPMC_Config*)handle)->attrs;
    uint32_t byteCount = trans->count;

    if (object->operMode == GPMC_OPERATING_MODE_POLLING) {
        if (trans->transType == GPMC_TRANSACTION_TYPE_READ) {
            uint32_t baseAddress = GPMC_DATA_BASE_ADDRESS;
            volatile DataStruct64 *pDst = (volatile DataStruct64 *)trans->Buf;
            volatile DataStruct64 *pSrc = (volatile DataStruct64 *)(trans->offset + baseAddress);
            while (byteCount != 0U) {
                *pDst = *pSrc;
                pSrc++;
                pDst++;
                if (byteCount < 64) {
                    byteCount = 0;
                } else {
                    byteCount -= 64;
                }
            }
        }
    }
    return status;
}

int32_t GPMC_NormalWrite(GPMC_Handle handle, GPMC_Transaction *trans)
{
    int32_t status = SystemP_SUCCESS;
    if (handle == NULL && trans == NULL) {
        status = SystemP_FAILURE;
        return status;
    }

    GPMC_Object *object = ((GPMC_Config*)handle)->object;
    uint32_t byteCount = trans->count;

    if (object->operMode == GPMC_OPERATING_MODE_POLLING) {
        if (trans->transType == GPMC_TRANSACTION_TYPE_WRITE) {
            uint32_t baseAddress = GPMC_DATA_BASE_ADDRESS;
            volatile DataStruct64 *pDst = (volatile DataStruct64 *)(trans->offset + baseAddress); 
            volatile DataStruct64 *pSrc = (volatile DataStruct64 *)trans->Buf;
            uint32_t remain = byteCount % 64;
            if (remain != 0U) {
                byteCount = byteCount - remain + 64U;
            }
            while (byteCount != 0U) {
                *pDst = *pSrc;
                pSrc++;
                pDst++;
                byteCount -= 64;
            }
        }
    }

    return status;
}

根据 *pDst = *pSrc、可以看出我以64字节为增量执行读/写操作。 我的实现是否正确? 此外、如果我使用执行指针赋值操作 uint16_t*、这是否意味着 GPMC 一次只传输2个字节?

4. 关于写操作、我认为将数据复制到 CSL_GPMC0_DATA_BASE 地址后、GPMC 数据传输会自动触发。 但是、对于读取操作、当我从 CSL_GPMC0_DATA_BASE 地址执行复制操作时、该复制操作会被阻止、直到 GPMC 读取时序完成。 我的理解是否正确?

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

    与 GPMC 相关的时序问题已解决。