您的位置: OpenADSP社区论坛 -> SHARC/TigerSHARC专区 -> 新手上路 -> [求助]ADSP-21369如何利用SPORT实现DMA连续... 
本帖共有1148个阅读者
发表帖子 发表投票 回复主题
[求助]ADSP-21369如何利用SPORT实现DMA连续数据传输
btbt208(论坛新手)
btbt208
头衔:社区公民
帮派:无帮无派
帖数:18
金钱:224
积分:22
注册时间:2013/3/1
楼主信息 | 留言 | Email | 主页 | 编辑 | 管理 | 离线
[求助]ADSP-21369如何利用SPORT实现DMA连续数据传输
//头文件定义
#include <Cdef21369.h>
#include <def21369.h>
#include <sru.h>
#include <signal.h>
#include <stdio.h>
#include <sysreg.h>

#define bufsize 10
#define bufsize1 11

//全局变量,,发送、接收
int tx_buf2a[bufsize】= {1,
                         2,
                         3,
                         4,
                         5,
                         6,
                         7,
                         8,          
                         9,          
                        10};

//ADSP-21369中double和float、int一样也是32位的,和float的区别应该是精度的区别,和int就是浮点和定点的区别了                      
double tx_buf2b[bufsize1]= {10.1,  
                             9.1,
                             8.1,    
                             7.1,      
                             6.1,        
                             5.1,      
                             4.1,      
                             3.1,      
                             2.1,            
                             1.1,          
                             0.1};
int rx_buf3a[bufsize];
int rx_buf3b[bufsize1];

int SP2I_counter = 0;
int SP3I_counter = 0;

//函数原型
void initPLL_SDRAM(void);//这个如示例中那样

void Count_SPORT2_TX_IRQs(int);
void Count_SPORT3_RX_IRQs(int);

void main( void )
{
interrupt(SIG_SP2,Count_SPORT2_TX_IRQs);
interrupt(SIG_SP3,Count_SPORT3_RX_IRQs);
initPLL_SDRAM();//设置时钟和SDRAM
          
//初始化SPORT控制寄存器
*pSPCTL2 = 0;
*pSPCTL3 = 0;
*pSPMCTL2 = 0;
*pSPMCTL3 = 0;    

//设置SPORT2和SPORT3的Internal Loopback
*pSPMCTL2 |= SPL;
*pSPMCTL3 |= SPL;   

//采用A-B双通道数据传输
*pIISP2A = (int) tx_buf2a;    //内部DMA存储地址        
*pIMSP2A = 1;  //内部DMA访问地址修改        
*pCSP2A = sizeof(tx_buf2a);    //DMA传输数据所包含的数据个数          
*pIISP2B = (int) tx_buf2b;            
*pIMSP2B = 1;          
*pCSP2B = sizeof(tx_buf2b);                

*pIISP3A = (int) rx_buf3a;        
*pIMSP3A = 1;        
*pCSP3A = sizeof(rx_buf3a);             

*pIISP3B = (int) rx_buf3b;        
*pIMSP3B = 1;        
*pCSP3B = sizeof(rx_buf3b);

//帧同步和时钟分频操作        
*pDIV2 = 0x001F0000;//0保留,1~15位为CLKDIV时钟分频位,16~31位为帧信号分频位,,,level sensitive,,I2S为edge detection *pSPCTL2 = (SPEN_B|SPEN_A|SLEN32|ICLK|FSR|IFS|SPTRAN|SDEN_A|SDEN_B);//设置SPORT2为发送,自生时钟信号(ICLK),自生帧同步信号(IFS)

*pDIV3 = 0x001F0000;//外部产生时钟和帧同步信号
*pSPCTL3 = (SPEN_B|SPEN_A|SLEN32|FSR|SDEN_A|SDEN_B);//设置SPORT3为接收       
for(;;)      
{}
}

void Count_SPORT2_TX_IRQs(int sig_int) //发送中断
{
SP2I_counter++;
}

void Count_SPORT3_RX_IRQs(int sig_int)//接收中断
{
SP3I_counter++;
}

通过这个程序,

1、采用SPMCTL中的SPL位,使得SPORT2和SPORT3为一对(0-1,2-3,4-5,6-7),即一个发送另一个接收(通过设置SPTRAN位即可),方便测试;

2、采用SPORT双通道A和B进行DMA数据传输,并且通过设置FS_BOTH位(即默认为0),可实现双通道不同个数的数据(A通道10个int型数据,B通道11    个double型数据)传输;

当我想通过该程序,实现数据的一次性发送多次接收/多次发送多次接收等功能,刚了解这个芯片,所以不是太懂,希望大牛能给予指点,如果有代码的话那更好了,,,,谢谢!!


上传的图片
  20138141547020.jpg [ 18.35 KB 479×120 ] (缩略时请点击查看原图)

 



「该帖子被 btbt208 在 2013-08-14 15:47:14 编辑过」

这家伙很懒,什么也没有留下!
等级:论坛新手 参考IP地址:*.*.*.*
2013/8/14 15:27:17
btbt208(论坛新手)
btbt208
头衔:社区公民
帮派:无帮无派
帖数:18
金钱:224
积分:22
注册时间:2013/3/1
1信息 | 留言 | Email | 主页 | 编辑 | 管理 | 离线
这款芯片用的人好少哈,只能自己慢慢瞎琢磨了,为了以后同仁不会犯同样的错误,下面将我自己解决的方法和代码贴出,希望对大家有用!!

改变如下:
1、采用IRQ1中断控制SPORT DMA连续性传输;
2、采用SW1控制IRQ1中断,LED1显示IRQ1中断的状态;
3、双通道变成单通道,采用standard serial标准传输,一次传2个数据,这里定义8个数据,传4次;

用法如下:
1、通过VDSP++ 5.0编译通过,打开View->Debug Windows->Plot,观察所需观察的数据rx_buf3a,设置相关参数;
2、运行,按Sw1,产生IRQ1中断,Led1变暗,暂停,然后就会发现Plot中数据变为1,2,0,0,0,0,0,0,如此循环,观察;

结果如下:
1、可实现外部中断IRQ1控制SPORT DMA传输;
2、数据可循环连续性传输;
3、实验数据证明了代码的正确性;

代码注意如下:
1、initPLL_SDRAM();这个子函数因为example示例代码中有相关代码,就不一一贴出,自己整合一下;
2、因个人水平有限,代码肯定会有有误的情况,希望大家能指出,希望对大家有用;

#include <Cdef21369.h>
#include <def21369.h>
#include <sru.h>
#include <signal.h>
#include <stdio.h>
#include <sysreg.h>

#define bufsize 8

//全局变量,,发送、接收
int tx_buf2a[bufsize]= {1,2,3,4,5,6,7,8};  
int rx_buf3a[bufsize];

int SP2I_counter = 0;//程序测试用,,,
int SP3I_counter = 0;

//函数原型
void initPLL_SDRAM(void);
void Setup_Leds(void);
void TRIG_Init(void);
void IRQ1_Cnt(int sig_int);
void init_SPORT(void);
void Count_SPORT2_TX_IRQs(int);
void Count_SPORT3_RX_IRQs(int);

int main( void )
{

initPLL_SDRAM();//设置时钟和SDRAM
init_SPORT();//初始化SPORT设置

Setup_Leds();
TRIG_Init();
for(;;)
{}
}

void init_SPORT(void)
{
//初始化SPORT控制寄存器
*pSPCTL2 = 0;
*pSPCTL3 = 0;
*pSPMCTL2 = 0;
*pSPMCTL3 = 0;
    
//设置SPORT2和SPORT3的Internal Loopback,,,只是用来测试用,为的是模拟FPGA与DSP相连
*pSPMCTL2 |= SPL;
*pSPMCTL3 |= SPL;
//帧同步和时钟分频操作
        *pDIV2 = 0x001F0000;//0保留,1~15位为CLKDIV时钟分频位,16~31位为帧信号分频位,,,level sensitive,,I2S为edge detection
*pDIV3 = 0x001F0000;//外部产生时钟和帧同步信号
//类似于SIMD中的DM、PM的Ix、Bx、Mx、Lx的操作,,采用A-B双通道数据传输
*pIISP2A = (int) tx_buf2a;    //内部DMA存储地址
        *pIMSP2A = 1;  //内部DMA访问地址修改
        *pCSP2A = 2;    //DMA传输数据所包含的数据大小
    
        *pIISP3A = (int) rx_buf3a;
        *pIMSP3A = 1;
        *pCSP3A = 2;    
}

void Count_SPORT2_TX_IRQs(int sig_int) //发送中断
{
SP2I_counter++;
}

void Count_SPORT3_RX_IRQs(int sig_int)//接收中断
{
SP3I_counter++;
//初始化SPORT控制寄存器
*pSPCTL2 = 0;
*pSPCTL3 = 0;
if(SP3I_counter == 4)//循环传输
{
*pIISP2A = (int) tx_buf2a;
*pIISP3A = (int) rx_buf3a;
SP3I_counter = 0;
}

else
{
*pIISP2A = (int) (tx_buf2a + SP3I_counter*2) ;    //内部DMA存储地址
*pIISP3A = (int) (rx_buf3a + SP3I_counter*2);
}
        *pIMSP2A = 1;  //内部DMA访问地址修改
        *pCSP2A = 2;    //DMA传输数据所包含的数据大小
    
        *pIMSP3A = 1;
        *pCSP3A = 2;  
    
        interrupt(SIG_SP3,SIG_IGN); //则中断屏蔽寄存器IMASK中SPORT3中断对应的位会被清零,即SPORT3 DMA被屏蔽掉了。
}

void Setup_Leds(void)
{
    SRU(FLAG4_O,DPI_PB06_I);    // Connect Flag4 output to DPI_PB06 input (LED1)
    SRU(HIGH,DPI_PBEN06_I);     //enable
    
    sysreg_bit_set(sysreg_FLAGS, (FLG4O));//设置FLAG4和FLAG5为输出
    sysreg_bit_set(sysreg_FLAGS, (FLG4));//对FLAG4和FLAG5置1,,即开始的所有的灯都默认为亮
}

//////////////////////////////////////////////////////////////////////////////
// void TRIG_Ints(void)
//
//////////////////////////////////////////////////////////////////////////////

void TRIG_Init(void)
{

(*pSYSCTL) |= (IRQ1EN); //IRQ0 & IRQ1 are allocated to interrupt request

sysreg_bit_set(sysreg_MODE2, (IRQ1E) ); // edge sens
sysreg_bit_clr(sysreg_IRPTL, (IRQ1I) );
sysreg_bit_set(sysreg_IMASK, (IRQ1I) ); //enable IRQ interrupts
sysreg_bit_set(sysreg_MODE1, IRPTEN );   //enable global interrupts

interrupt(SIG_IRQ1,IRQ1_Cnt); // set the ISR for IRQ1

}

void IRQ1_Cnt(int sig_int)
{
int i;
sysreg_bit_tgl(sysreg_FLAGS, FLG4);//按键sw1点亮或者熄灭第一个led灯
interrupt(SIG_SP3,Count_SPORT3_RX_IRQs);
     //SPORT DMA设置
   *pSPCTL2 = (SPEN_A|SLEN32|ICLK|FSR|IFS|SPTRAN|SDEN_A);//设置SPORT2为发送,自生时钟信号(ICLK),自生帧同步信号(IFS)
   *pSPCTL3 = (SPEN_A|SLEN32|FSR|SDEN_A);//设置SPORT3为接收
   for(i = 0; i < 8; i++)
   {
         printf("i=%d,%d\n",i,rx_buf3a[i]);
        }
}


「该帖子被 btbt208 在 2013-08-21 09:12:49 编辑过」

这家伙很懒,什么也没有留下!
等级:论坛新手 参考IP地址:*.*.*.*
2013/8/21 9:01:36
尊贵身份标志
OpenADSP(管理员)
OpenADSP
头衔:社区公民
帮派:无帮无派
帖数:5187
金钱:34761
积分:6369
注册时间:2011/6/7
2信息 | 留言 | Email | 主页 | 编辑 | 管理 | 离线

谢谢分享


我是OP...
等级:管理员 参考IP地址:*.*.*.*
2013/8/21 9:24:57
btbt208(论坛新手)
btbt208
头衔:社区公民
帮派:无帮无派
帖数:18
金钱:224
积分:22
注册时间:2013/3/1
3信息 | 留言 | Email | 主页 | 编辑 | 管理 | 离线
程序补充:
for(i = 0; i < 8; i++)
    {
         printf("i=%d,%d\n",i,rx_buf3a[i]);
     }
1、经过测试,当上面的这些程序放在void IRQ1_Cnt(int sig_int)子程序中,VisualDSP++下面的output打印端会出现一个奇怪的现象,如下:
    i=0,0
    i=1,2
    i=2,0
    ......
    不难发现,第一个传输的参数值丢失了,如果将参数赋值放在这里面会导致数据丢失问题,第一个参数永远都是初始值0;

2、针对这个问题,不断地进行程序的测试,最后发现赋值程序不能放在这里面,把上面的printf程序放到Count_SPORT3_RX_IRQs程序中,就能正确输出
    i=0,1
    i=1,2
    i=2,0
    ......
    我自己的解释是,当配置完SPCTL2和SPCTL3寄存器之后,会自动产生SPORT DMA接收中断(先),printf(后),产生冲突,因此就会导致第一个数据丢失,
    为了不丢失,只要不冲突就好,因此将printf程序放入Count_SPORT3_RX_IRQs中,发现打印出来的数据就是对的,没有出现数据丢失的问题。

这是我自己的解释,不一定对,但是问题是解决了,希望大家给予批评指正,,,谢谢!!


这家伙很懒,什么也没有留下!
等级:论坛新手 参考IP地址:*.*.*.*
2013/8/23 10:40:47
Powered by OpenADSP Copyright © 2010 www.Openadsp.com. All rights reserved.154160 Call, 1 Queries, Processed in 0.031250 second(s),