最近一直在做DSP与FPGA之间的视频传输工作,使用的通信方式是EDMA,为了系统的介绍通过EDMA方式在DSP与FPGA之间实现数据传输。
首先介绍一下DSP-C6455中的GPIO与中断系统。以后再介绍DSP强大的EDMA模块,以及具体的数据传输实现。
(注: 其实EDMA是C6455芯片中的一个模块,可以认为其是芯片内部的一个”协处理器”)
---------------------------华丽分割----------------------------------
背景
使用DSP+FPGA搭建的嵌入式系统进行视频采集,编解码,传输无疑是一个不错的选择。使用FPGA系统进行视频采集,DSP进行视频处理需要了解一下知识:
- 1. DSP-C6000系列的中断与GPIO系统
- 2. DSP-C6000系列的EDMA模块
- 3. FPGA的乒乓RAM
- 4. 一种视频格式(例如VGA,PAL等)
- 5. 视频处理算法
本文将介绍DSP C6000系列的GPIO系统(针对C6455)
--------------------------- 华丽分割 ----------------------------------
C6455的GPIO
TMS320C6455中共有16个通用输入输出管脚。每一个管脚都可以单独进行配置成如下功能之一:
- 通用输入管脚Input
- 通用输出管脚Output
- 中断&EDMA事件 管脚
首先看一下GPIO的框图:
![](https://img-my.csdn.net/uploads/201205/04/1336121675_5031.png)
- DIR寄存器控制GPIO管脚是输入还是输出,其中,对应bit置0表示该管脚配置为输出管脚;对应bit置1表示该管脚配置为输入管脚。
- 若一个GPIO管脚配置为Output,给SET_DATA寄存器对应位置1,将使该管脚输出高电平,给CLR_DATA寄存器对应位置1,将使该管脚输出低电平。需要注意的是:向SET_DATA和CLR_DATA中写入0无作用。
- 若一个GPIO管脚配置为Input,可以通过读取IN_DATA寄存器中的对应位来获得管脚的状态。且向SET_DATA和CLR_DATA中写入0无作用。
- 若一个GPIO管脚配置为中断&EDMA事件模式,此时可以忽略该管脚的Input/Output配置。可以通过置位SET_RIS_TRIG和SET_FAL_TRIG寄存器的相应bit把GPIO管脚配置为中断/事件触发方式。如下图所示:
![](https://img-my.csdn.net/uploads/201205/04/1336121678_8741.png)
![](https://img-my.csdn.net/uploads/201205/04/1336121681_6384.png)
查看官方文档:
![](https://img-my.csdn.net/uploads/201205/04/1336121686_3795.png)
此外,使用GPIO时,还需要考虑到对应芯片的管脚复用问题,以6455为例,GPIO管脚复用情况如下图示:
可见,16个GPIO管脚中有大半是可以复用的。可以通过配置6455的外设配置寄存器来使能GPIO模块。即把6455中的PERCFG0寄存器中GPIO对应位置1,如下图示:
![](https://img-my.csdn.net/uploads/201205/04/1336121689_1977.png)
![](https://img-my.csdn.net/uploads/201205/04/1336121693_6828.png)
使用CSL库的API函数配置DSP显然比逐一配置寄存器方面且容易理解。下面介绍一下如何使用CSL库把DSP的GPIO4配置成中断模式。
- 第一步:使能GPIO模块
使能之前,首先要解除锁,即向PERLOCK寄存器写入0x0F0A0B00,然后把PERCFG0寄存器中GPIO对应位置1。代码如下:
- <SPAN style="FONT-FAMILY: 'Microsoft YaHei'">Bool gpioEn;
- CSL_FINST(((CSL_DevRegs*)CSL_DEV_REGS)->PERLOCK,DEV_PERLOCK_LOCKVAL, UNLOCK);
- CSL_FINST(((CSL_DevRegs*)CSL_DEV_REGS)->PERCFG0, DEV_PERCFG0_GPIOCTL, ENABLE);
- do {
- gpioEn = (Bool)CSL_FEXT(((CSL_DevRegs*)CSL_DEV_REGS)->PERSTAT0,
- DEV_PERSTAT0_GPIOSTAT);
- } while (gpioEn != TRUE);
- </SPAN>
Bool gpioEn;
CSL_FINST(((CSL_DevRegs*)CSL_DEV_REGS)->PERLOCK,DEV_PERLOCK_LOCKVAL, UNLOCK);
CSL_FINST(((CSL_DevRegs*)CSL_DEV_REGS)->PERCFG0, DEV_PERCFG0_GPIOCTL, ENABLE);
do {
gpioEn = (Bool)CSL_FEXT(((CSL_DevRegs*)CSL_DEV_REGS)->PERSTAT0,
DEV_PERSTAT0_GPIOSTAT);
} while (gpioEn != TRUE);
- 第二步:初始化GPIO模块
- <SPAN style="FONT-FAMILY: 'Microsoft YaHei'">CSL_Status status;
- CSL_GpioContext pContext;
- status = CSL_gpioInit(&pContext);</SPAN>
CSL_Status status;
CSL_GpioContext pContext;
status = CSL_gpioInit(&pContext);
- 第三步:打开GPIO模块
- 第四步:使能GPIO管脚作为中断源的功能
- 第五步:配置GPIO-PIN4的属性:方向,中断触发方式
---------------------------华丽分割----------------------------------
完整的配置代码如下所示:
- <SPAN style="FONT-FAMILY: 'Microsoft YaHei'">/*-----------------------------------------------------------------------------------
- *
- * 初始化GPIO
- *
- -----------------------------------------------------------------------------------*/
- void Init_GPIO()
- {
- Bool gpioEn;
- CSL_Status status;
- CSL_GpioContext pContext;
- CSL_GpioHandle hGpio;
- CSL_GpioObj gpioObj;
- CSL_GpioHwSetup hwSetup;
- CSL_GpioPinConfig config;
- // CSL_GpioPinNum pinNum;
- /* Unlock the control register */
- CSL_FINST(((CSL_DevRegs*)CSL_DEV_REGS)->PERLOCK, DEV_PERLOCK_LOCKVAL,
- UNLOCK);
- /* Enable the GPIO */
- CSL_FINST(((CSL_DevRegs*)CSL_DEV_REGS)->PERCFG0, DEV_PERCFG0_GPIOCTL,
- ENABLE);
- do {
- gpioEn = (Bool) CSL_FEXT(((CSL_DevRegs*)CSL_DEV_REGS)->PERSTAT0,
- DEV_PERSTAT0_GPIOSTAT);
- } while (gpioEn != TRUE);
- /* Initialize the GPIO CSL module */
- status = CSL_gpioInit(&pContext);
- #ifdef SHOW_PRINTF
- if (status != CSL_SOK) {
- printf("GPIO: Initialization error.\n");
- return;
- }
- else {
- printf("GPIO: Module Initialized.\n");
- }
- #endif
- /* Open the CSL module */
- hGpio = CSL_gpioOpen(&gpioObj, CSL_GPIO, NULL, &status);
- #ifdef SHOW_PRINTF
- if ((hGpio == NULL) || (status != CSL_SOK)) {
- printf("GPIO: Error opening the instance.\n");
- return;
- }
- else {
- printf("GPIO: Module instance opened.\n");
- }
- #endif
- /* Setup hardware parameters */
- hwSetup.extendSetup = NULL;
- /* Setup the General Purpose IO */
- status = CSL_gpioHwSetup(hGpio, &hwSetup);
- /* Enable the bank interrupt */
- status = CSL_gpioHwControl(hGpio, CSL_GPIO_CMD_BANK_INT_ENABLE, NULL);
- #ifdef SHOW_PRINTF
- if (status != CSL_SOK) {
- printf("GPIO: Command to enable bank interrupt... Failed.\n");
- }
- else {
- printf("GPIO: Command to enable bank interrupt... successful.\n");
- }
- #endif
- /* Configure pin 4 to generate an interrupt on Rising Edge, and
- * configure it as an input, then set the data High (Low->High).
- * Set Trigger:
- */
- config.pinNum = CSL_GPIO_PIN4;
- config.trigger = CSL_GPIO_TRIG_RISING_EDGE;
- config.direction = CSL_GPIO_DIR_INPUT;
- /* configure the gpio pin 4 */
- status = CSL_gpioHwControl(hGpio, CSL_GPIO_CMD_CONFIG_BIT, &config);
- #ifdef SHOW_PRINTF
- if (status != CSL_SOK) {
- printf("GPIO: GPIO pin configuration error.\n");
- return;
- }
- else {
- printf("GPIO: GPIO pin configuration successful.\n");
- }
- #endif
- }</SPAN>
/*-----------------------------------------------------------------------------------
*
* 初始化GPIO
*
-----------------------------------------------------------------------------------*/
void Init_GPIO()
{
Bool gpioEn;
CSL_Status status;
CSL_GpioContext pContext;
CSL_GpioHandle hGpio;
CSL_GpioObj gpioObj;
CSL_GpioHwSetup hwSetup;
CSL_GpioPinConfig config;
// CSL_GpioPinNum pinNum;
/* Unlock the control register */
CSL_FINST(((CSL_DevRegs*)CSL_DEV_REGS)->PERLOCK, DEV_PERLOCK_LOCKVAL,
UNLOCK);
/* Enable the GPIO */
CSL_FINST(((CSL_DevRegs*)CSL_DEV_REGS)->PERCFG0, DEV_PERCFG0_GPIOCTL,
ENABLE);
do {
gpioEn = (Bool) CSL_FEXT(((CSL_DevRegs*)CSL_DEV_REGS)->PERSTAT0,
DEV_PERSTAT0_GPIOSTAT);
} while (gpioEn != TRUE);
/* Initialize the GPIO CSL module */
status = CSL_gpioInit(&pContext);
#ifdef SHOW_PRINTF
if (status != CSL_SOK) {
printf("GPIO: Initialization error.\n");
return;
}
else {
printf("GPIO: Module Initialized.\n");
}
#endif
/* Open the CSL module */
hGpio = CSL_gpioOpen(&gpioObj, CSL_GPIO, NULL, &status);
#ifdef SHOW_PRINTF
if ((hGpio == NULL) || (status != CSL_SOK)) {
printf("GPIO: Error opening the instance.\n");
return;
}
else {
printf("GPIO: Module instance opened.\n");
}
#endif
/* Setup hardware parameters */
hwSetup.extendSetup = NULL;
/* Setup the General Purpose IO */
status = CSL_gpioHwSetup(hGpio, &hwSetup);
/* Enable the bank interrupt */
status = CSL_gpioHwControl(hGpio, CSL_GPIO_CMD_BANK_INT_ENABLE, NULL);
#ifdef SHOW_PRINTF
if (status != CSL_SOK) {
printf("GPIO: Command to enable bank interrupt... Failed.\n");
}
else {
printf("GPIO: Command to enable bank interrupt... successful.\n");
}
#endif
/* Configure pin 4 to generate an interrupt on Rising Edge, and
* configure it as an input, then set the data High (Low->High).
* Set Trigger:
*/
config.pinNum = CSL_GPIO_PIN4;
config.trigger = CSL_GPIO_TRIG_RISING_EDGE;
config.direction = CSL_GPIO_DIR_INPUT;
/* configure the gpio pin 4 */
status = CSL_gpioHwControl(hGpio, CSL_GPIO_CMD_CONFIG_BIT, &config);
#ifdef SHOW_PRINTF
if (status != CSL_SOK) {
printf("GPIO: GPIO pin configuration error.\n");
return;
}
else {
printf("GPIO: GPIO pin configuration successful.\n");
}
#endif
}