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