C6455 CSL_EMIF详解

原网址http://www.61ic.com/Article/C6000/C64X/201303/47507.html C6455CSL详解

和DSP6455的EMIFA模块http://blog.csdn.net/ruby97/article/details/7539151

将两篇文章整理一下,一起来看就清楚多了。

看这篇文章之前,还以为C6000 CSL是可以给全系列的C6000DSP使用呢。下次文档一定要找对,代码和文档对应不上的时候一定要看看是不是文档找错了。

ABSTRACT

开发C6455的应用程序,一定会使用TI 提供的CSL(Chip Support Library),CSL 提供的API已经将底层的实现细节给我包装好了,我们只需要直接调用这些API就可以了。但是为了更好的使用这些API,我们很有必要仔细的分析这些API函数是怎样实现的。

这篇文章中我以EMIFA接口为例子,分析CSL 的相应API函数和结构体定义。

在CCS中添加CSL的头文件和库文件

CCS(Code Composer Studio)是TI公司开发的用于其公司的DSP,MSP等芯片的综合开发工具,CCS5.x的版本是基于Eclipse开发的,而CCS4.x以及其前面的版本的开发平台我不太清楚。

我使用的是CCS5.2,在CCS5.x中,CSL的库并不是默认被包含的该CCS中的,在http://www.ti.com/tool/sprc234中可以下载到最新的CSL库,下载下来的CSL库如下,里面包含了这个库实现的源代码和我们需要的库文件和头文件,以及一个PDF格式的API Reference。

从上面的图我们可以看到,这个版本的CSL已经把INTC(中断管理)做出一个单独的模块了,而其他的外设放在了另外一个模块中。

使用的时候,我们必须在工程中加入头文件我库文件所在的路径以及库文件的名字,这样在编译器编译和链接的时候才能找到它们,不然会提示找不到的错误。

EMIF

C6455的EMIF模块

EMIF 是 External Memory Interface 的简称。个人认为它是 DSP 比较强大

的地方之一。通过 EMIF 接口,使得 DSP 可以和 FPGA 很方便地进行大数据量的数据传输。

C6455 的 EMIFA 可以访问多种外部存储器,比如:SRAM,ROM,FLASH 等等。当然,也包括 FPGA。本文的重点就是介绍使用 EMIFA 接口与 FPGA 建立无缝连接。

这是官方文档给出的 EMIFA 模块的接口示意图,乍一看,复杂的很。好多

引脚而且还有好多复用。没关系,我们再贴一张,你就会感觉轻松很多了。 这一张图首先是把 EMIFA 模块的接口分了类,然和呢,我把在与 FPGA 通信场合下所需要使用的管脚使用红色框框标注了出来。是不是少了很多呢。归纳一下标注的管脚,如下:

AED[63:0]     64 位数据总线

AEA[19:0]     20 位地址总线(Optional)

ACE2          片选信号(低有效)

AECLKOUT     时钟信号

ASWE          写使能(低有效)

ASRE          读使能(低有效)

(注:应用场合是 DSP 读 FPGA 内部 RAM 中的图像数据,其他场合续根据情况调整)

由于 FPGA 的可编程性,使得一切从 DSP 看来简单了许多。因为 DSP 面对的"存储器"显得格外智能。甚至连地址线都可以不需要。

下面,我们来一一分析上述的信号。

首先,应该是片选信号 CE。这里不得不提到 DSP 的地址空间。下图是

DSP6455 的 EMIFA 映射情况

从图中可以看出

EMIFA 共支持 4 个外部存储器,比如可以把 CE2 分配给 FPGA,CE3 分

配给 SRAM,CE4 分配给 FLASH 等。

每个外部存储器的寻址空间大小是 8MB。20 根地址线即 2 的 20 次方,

也就是 1MB,此外由于数据总线是 64 位的,故对应的寻址空间是 8MB

由于FPGA内部时序逻辑可以产生地址,所以我们可以不使用地址线。这样,下面的事情就简单了。只要把 CE2 管脚和 FPGA 的某一个通用 IO 口连上即可。在读取 FPGA 内部 RAM 数据时告诉 EDMA 要读取的数据的基地址是

0xA0000000,以及读取的数据的长度即可。

第二个信号,ECLKOUT,即时钟信号的。因为 FPGA 工作是需要时钟激励的,没有时钟信号怎么产生地址逻辑呢?此外,时钟频率不能过高,要考虑到 FPGA 芯片的能力。OK,因为有了同步时钟,所以 EMIFA 模块的工作模式

也就确定了,即同步工作模式。

第三个信号,包括 2 个,即 ASRE,ASWE。更熟悉的叫法是 RE,WE。读使能

和写使能。这个就不赘述了。

第四个信号,数据总线&地址总线。也不赘述了。

经过上面的分析,我们可以简要的画出 FPGA 与 DSP 的连接图:

配置EMIFA寄存器

在连接的思路清晰之后,我们可以开始配置 EMIFA 的寄存器了。

其实也就 1 个比较重要的寄存器,即 CEnCFG。该寄存器有两套完全不同的配置。分别对应于同步存储器模式和异步存储器模式。由于 FPGA 内部 RAM 工作于同步模式,故我们来看一下同步模式下该寄存器的配置。

SSEL 设置为 1 时,表示该 CE 对应同步模式的外部存储器。在与 FPGA 连接时,主要考虑以下四个参数:

R_ENABLE :设置 SRE/SADS 管脚的功能      为 1 时:SRE      为 0 时:SADS

    W_LTNCY 写延时(0,1,2,3)

00    :0 周期延时

01    :1 周期延时

02    :2 周期延时

03    :3 周期延时

    R_LTNCY 读延时(1,2,3)

(读延时即:当 CE 和 RE 同时为低电平后,表示 DSP 开始读 FPGA 的 RAM,经过 R_LTNCY 个 ECLKOUT 周期后第一个数据出现在数据总线上)

01     :1 周期延时

02     :2 周期延时

03     :3 周期延时

 SBSIZE     数据位宽(8,16,32,64)

00     :8 位数据总线

01    :16 位数据总线

02    :32 位数据总线

03    :64 位数据总线

使用 CSL 配置 EMIFA 模块时,主要的步骤如下:

  • 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做得相当的规整,主要有以下的函数,

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

上面的图是从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下来了。

C6455 CSL_EMIF详解的更多相关文章

  1. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  2. 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)

    一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...

  3. EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解

    前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...

  4. Java 字符串格式化详解

    Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...

  5. Android Notification 详解(一)——基本操作

    Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...

  6. Android Notification 详解——基本操作

    Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...

  7. Git初探--笔记整理和Git命令详解

    几个重要的概念 首先先明确几个概念: WorkPlace : 工作区 Index: 暂存区 Repository: 本地仓库/版本库 Remote: 远程仓库 当在Remote(如Github)上面c ...

  8. Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)

    Android XML shape 标签使用详解   一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...

  9. Node.js npm 详解

    一.npm简介 安装npm请阅读我之前的文章Hello Node中npm安装那一部分,不过只介绍了linux平台,如果是其它平台,有前辈写了更加详细的介绍. npm的全称:Node Package M ...

随机推荐

  1. luogu P1194 买礼物

    题目描述 又到了一年一度的明明生日了,明明想要买B样东西,巧的是,这B样东西价格都是A元. 但是,商店老板说最近有促销活动,也就是: 如果你买了第I样东西,再买第J样,那么就可以只花K[I,J]元,更 ...

  2. [xsy2363]树

    设$f_{i,j}$表示$i$个点的树,权值为$j$且可以不选根的方案数,$g_{i,j}$表示$i$个点的树,权值为$j$且必选根的方案数 首先$g_{1,1}=0$ 我们可以把原树连上一个新的子树 ...

  3. [UOJ164]V

    线段树真是好东西... 每个线段树节点维护四个标记:$a,b,maxa,maxb$,$(a,b)$表示对子树内的所有数执行$x'=\max(x+a,b)$,$maxa,maxb$是历史最大标记,初始时 ...

  4. 【点分治】【哈希表】bzoj2599 [IOI2011]Race

    给nlog2n随便过的跪了,不得已弄了个哈希表伪装成nlogn(当然随便卡,好孩子不要学)…… 不过为啥哈希表的大小开小点就RE啊……?必须得超过数据范围一大截才行……谜 #include<cs ...

  5. 【Treap模板详细注释】BZOJ3224-普通平衡树

    模板题:D错因见注释 #include<iostream> #include<cstdio> #include<cstring> #include<algor ...

  6. 将html文档转成pdf

    (1)使用场景:在项目中使用到了合同,只有在合同的头部,是不相同的.在合同的主体部分都是相同的,因此就把他放到了模板(html文件)里面. 在用户线上签约完成之后,可以将pdf版的合同下载. (2)需 ...

  7. MySQL第三方客户端工具

    如前所述,MySQL是一个基于客户机--服务器的DBMS,因此,为了使用MySQl,你需要有一个客户机软件给MySQL提供要执行的命令.即你需要一个编写和测试MySQL脚本的工具. 1.MySQL命令 ...

  8. 7zip File: How to Uncompress 7z files on Ubuntu, Debian, Fedora

    转:http://www.thegeekstuff.com/2010/04/7z-7zip-7za-file-compression/ Question: How do I uncompress a ...

  9. nginx做反向代理时获取真实IP

    原文:http://blog.csdn.net/aquester/article/details/48657395 1. 编译 对于client -> nginx reverse proxy - ...

  10. 如何用路由器改成WiFi Pineapple系统镜像网络流量

    本文主要介绍利用自己现有的设备,如何制作和使用WiFi Pineapple镜像网络流量,利用DWall模块分析用户数据,然后根据自己的需求,给DWall加入了日志记录功能.最后介绍了如何防范wifi ...