Tool/software:
Hi, TI expert,
I am trying to communicate with an FPGA using GPMC on custom AM2434 hardware, employing address/data multiplexed, synchronous burst read/write mode. During actual use, there are some timing issues, such as being able to read only 2 bytes of data instead of 64 bytes. Below are some of my register configurations:
/* 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,
},
};
there is few question about GPMC:
1. I want to achieve a burst read/write operation of 16bit * 32word. Are there any issues with my register configurations?
2. What is the specific function of wrapBurst? I checked the reference manual's description, but I didn't understand it. Are there more specific resources available, and does this function only support certain chips?
3. Since I configured deviceType to 16bit and attachedDevicePageLength to 32words, I believe the data transfer amount for one GPMC operation is 16bit * 32words = 64bytes. Here is my GPMC read/write function:
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; }
Based on *pDst = *pSrc
, it can be seen that I am performing read/write operations in increments of 64 bytes. Is my implementation correct? Additionally, if I perform a pointer assignment operation using uint16_t*
, does this mean that the GPMC only transfers 2 bytes at a time?
4. Regarding write operations, I believe that after copying data to the CSL_GPMC0_DATA_BASE address, the GPMC data transmission will be triggered automatically. However, for read operations, when I perform a copy operation from the CSL_GPMC0_DATA_BASE address, this copy operation gets blocked until the GPMC read timing is complete. Is my understanding correct?