[资料分享] 使用 CSL 配置 EMIFA 模块时的主要步骤

火辣西米秀   2019-12-8 21:03 楼主

1. 使能设备 EMIFA 模块
2. 配置 CEnCFG 寄存器
3. 初始化 EMIFA 模块
4. 打开 EMIFA 模块
5. 把 2 中配置的参数设置到打开的 EMIFA 模块中
完整配置代码:(把 EMIFA 的 CE2 配置为以 FPGA 作为外部存储器,64 位数据线,2 个周期的读延时)
/*-----------------------------------------------------------------------------------

*

* 初始化EMIFA

*

-----------------------------------------------------------------------------------*/

#define EMIFA_MEMTYPE_ASYNC 0                 //都是用宏定义

#define EMIFA_MEMTYPE_SYNC 1

 

#define EMIFA_CE2_BASE_ADDR (0xA0000000)//地址空间基地址

#define CSL_EMIFA_SYNCCFG_RLTNCY_PARAMETER 2//读延时2周期

#define CSL_EMIFA_SYNCCFG_SBSIZE_PARAMETER 3//64位数据总线

#define CSL_EMIFA_SYNCCFG_READEN_PARAMETER 1//SRE

//CEnCFG寄存器参数宏

#define CSL_EMIFA_SYNCCFG_PARAMETER {\

(Uint8)CSL_EMIFA_SYNCCFG_READBYTEEN_DEFAULT, \

(Uint8)CSL_EMIFA_SYNCCFG_CHIPENEXT_DEFAULT, \

(Uint8)CSL_EMIFA_SYNCCFG_READEN_PARAMETER,\ (Uint8)CSL_EMIFA_SYNCCFG_WLTNCY_DEFAULT, \

(Uint8)CSL_EMIFA_SYNCCFG_RLTNCY_PARAMETER, \

(Uint8)CSL_EMIFA_SYNCCFG_SBSIZE_PARAMETER \

}

void Init_EMIF()

{

CSL_EmifaObj         emifaObj;

CSL_Status               status;

CSL_EmifaHwSetup               hwSetup;

CSL_EmifaHandle               hEmifa;             //EMIF的句柄

CSL_EmifaMemType               syncVal;             //不同的类型对应相应的CE空间

CSL_EmifaSync               syncMem =CSL_EMIFA_SYNCCFG_PARAMETER;

/* Clear local data structures */

memset(&emifaObj, 0, sizeof(CSL_EmifaObj));

memset(&hwSetup, 0, sizeof(CSL_EmifaHwSetup));

//步骤1: 使能设备的EMIFA功能(不用先解锁外设寄存器)

CSL_FINST(((CSL_DevRegs*)CSL_DEV_REGS)->PERCFG1,

DEV_PERCFG1_EMIFACTL, ENABLE);

//步骤2:配置CE2CFG寄存器

syncVal.ssel = EMIFA_MEMTYPE_SYNC;

syncVal.async = NULL;

syncVal.sync = &syncMem;

 

hwSetup.ceCfg[0] = &syncVal; //CE2

hwSetup.ceCfg[1] = NULL;

hwSetup.ceCfg[2] = NULL;

hwSetup.ceCfg[3] = NULL;

 

//步骤3:初始化EMIFA模块

status = CSL_emifaInit(NULL);

 

#ifdef SHOW_PRINTF

if (status != CSL_SOK)

{

printf("EMIFA: Initialization error.\n");

printf("\tReason: CSL_emifaInit [status = 0x%x].\n", status);

return;

}

else

{printf("EMIFA: Module Initialized.\n"); }

#endif

 

//步骤4:打开EMIFA模块

hEmifa = CSL_emifaOpen(&emifaObj,CSL_EMIFA,NULL,&status);

 

#ifdef SHOW_PRINTF

if ((status != CSL_SOK) || (hEmifa == NULL))

{printf("EMIFA: Error opening the instance. [status = 0x%x, hEmifa \

= 0x%x]\n", status, hEmifa);

return;

}

Else

{printf("EMIFA: Module instance opened.\n"); }

#endif

 

//步骤5:把步骤2中配置的参数设置到打开的EMIFA模块中

status = CSL_emifaHwSetup(hEmifa,&hwSetup);

#ifdef SHOW_PRINTF

if (status != CSL_SOK) {

printf("EMIFA: Error in HW Setup.\n");

printf("Read write operation fails\n");

return;

}

else

{printf("EMIFA: Module Hardware setup is successful.\n"); }

#endif

}

EMIFA的CSL API
EMIFA的CSL API做得相当的规整,主要有以下的函数,

image.png

而这些函都是CSL中每一个外设都会实现的,它们做得事情的相似的。

image.png

上面的图是从API文档中截取下来的,其大概的描述了每一个函数所完成的事情。下面我以CSL中提供的example为例,说明一下其用法。

CSL中EMFIA的example
CSL中对每一个外设至少包含了一个example以帮助开发者快速的掌握其用法。

初始化并打开EMFIA
在Emifa_ReadWrite_example.c文件中有两个函数,在main函数中只有一句代码

CSL_FINST(((CSL_DevRegs*)CSL_DEV_REGS)->PERCFG1, DEV_PERCFG1_EMIFACTL, \

ENABLE);

要看懂这句话要一定的时间,但是我们知道其做的事情就是配置PERCFG1打开EMIFA外设(PERCFG1(Peripheral Configuration Register 1)The Peripheral Configuration Register (PERCFG1) is used to enable the EMIFA and DDR2 Memory Controller.对于一般的外设,我们需要先往PERLOCK中写入一个特定的UNLOCK值后才能打开,但是对于DDR2和EMIFA是可以直接打开的,详细的解释可以看相应的文档)。打开EMIFA后,main函数直接调用emifaReadWrite()函数了。

在emifaReadWrite()中,

第一个被调用的函数就是CSL_emifaInit(NULL),从上面的解释中可以看出,这个函数是optional的,查看了其源代码以后,会发现其什么也没有做,只是单纯的返回了一个CSL_OK。

第二个被调用的函数是

hEmifa = CSL_emifaOpen(&emifaObj, CSL_EMIFA, NULL, &status);

其函数原型为

CSL_EmifaHandle CSL_emifaOpen (

CSL_EmifaObj *hEmifaObj,

CSL_InstNum emifaNum,

CSL_EmifaParam *pEmifaParam,

CSL_Status *status

);

这个函数必须详细得看一看,其第一个参数是CSL_EmifaObj*类型的,这个类型里面其实有两个域

typedef struct CSL_EmifaObj {

/* This is a pointer to the registers of the instance of EMIFA

* referred to by this object

*/

CSL_EmifaRegsOvly regs;

 

/** This is the instance of EMIFA being referred to by this object */

CSL_InstNum perNum;

} CSL_EmifaObj;

CSL_EmifaRegsOvly中包含EMIF这个模块的所有寄存器,CSL_InstNum表示这是第几个EMIF模块(C6455中只有一个EMIF模块,所以这个值只能是0)。

CSL_EMIFA是一个宏,其真实的值为

/** @brief Peripheral Instance for EMIFA */

#define CSL_EMIFA (0)

也就是表示只有一个EMIF模块。

第三个参数是留着以后用的

typedef struct {

/** Bit mask to be used for module specific parameters. The below

* declaration is just a place-holder for future implementation. Passed as

* an argument to CSL_emifaOpen().

*/

CSL_BitMask16 flags;

 

} CSL_EmifaParam;

所以总是传入NULL。

第四个参数是CSL_Status*,这个参数实际上是同时作为输入和输出参数的。

这个函数在时间运行时,首先检查status是不是NULL,如果是NULL的话,它就返回一个NULL给hEmifa ,所以我们一定要保证传入的值不是NULL,如果我们总是用CSL_emifaInit(NULL)返回的值传入的话,这个条件就总是满足了,所以我们先调用CSL_emifaInit(NULL)函数,然后再调用CSL_emifaOpen。

该函数返回值为一个handler,其实际类型是一个指针

/** @brief This is a pointer to @a CSL_EmifaObj and is passed as the first

* parameter to all EMIFA CSL APIs

*/

typedef struct CSL_EmifaObj *CSL_EmifaHandle;

如果不太能够理解的话也没有关系,其他的API函数都会以这个handler作为其第一个参数。

配置EMIFA的硬件
成功的初始化并打开硬件后,就需要安装自己的要求配置硬件了

status = CSL_emifaHwSetup(hEmifa, &hwSetup);

主要开看二个参数,hwSetup是CSL_emifaHwSetup的一个变量,这儿要特别注意,这个函数的名字叫CSL_emifaHwSetup,而其参数的类型也是CSL_emifaHwSetup的指针,CSL_emifaHwSetup的定义如下

typedefstruct {

/** Pointer to structure for configuring the Asynchronous Wait Cycle

* Configuration register

*/

CSL_EmifaAsyncWait *asyncWait;

/** Array of CSL_EmifaMemType* for configuring the Chip enables

* as Async or Sync memory type.

*/

CSL_EmifaMemType *ceCfg[NUMCHIPENABLE];

} CSL_EmifaHwSetup;

要注意的是,不同的外设,他们的HwSetup类型的定义是不一样的,因为这个结构体是与硬件(Hw->Hardward) 相关的,其实在调用这个函数之前,hwSetup各个域已经被设置为我们想要的值了,相应的设置代码我就不copy下来了。

  • image.png

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复