工具与软件:
您好、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 读取时序完成。 我的理解是否正确?