|
/**********************************************************/ /* */ /* 中频软件无线电接收机子系统数字信号处理部分主程序 */ /* */ /* dsk_app.c */ /* */ /**********************************************************/
#include "dsk_appcfg.h"
/* * 这些包含文件支持程序中使用的BIOS和CSL模块接口 */ #include <std.h> #include <swi.h> #include <log.h> #include <c6x.h> #include <csl.h> #include <csl_edma.h> #include <csl_irq.h> #include <csl_mcbsp.h>
/* * 该包含文件引入数学函数fastrts67x.lib,其中包括乘方,开方, * 正、余弦,反正切,对数运算,指数运算等汇编函数 */
#include <fastrts67x.h>
/* * TMS320C6713 开发板支持库分为几个模块,每个模块都有各自的包含文件 * 每一个应用程序要使用开发板支持库就必须包含头文件dsk6713.h * 本应用程序中还使用了DIP, LED模块 */ #include "dsk6713.h" #include "dsk6713_led.h" #include "dsk6713_dip.h"
/* 函数原型 */ void initIrq(void);//初始化中断 void initMcbsp(void);//初始化Mcbsp void initEdma(void);//初始化Edma void demodulateAM(INT16 *inBuf,Uint32 *outBuf,INT16 Length)//AM信号解调程序 void processBuffer(void);//处理缓冲区数据 void edmaHwi(void);//Edma中断线程
/* 为ping-pong缓冲传输定义常量 */ #define BUFFSIZE 1024 #define PING 0 #define PONG 1
/* * 数据缓冲区声名 * 程序中使用四个BUFFSIZE大小的逻辑缓冲区 * 一个PING接收缓冲区,一个PONG接收缓冲区 * 一个存储PING缓冲区解调后数据,一个存储PONG缓冲区解调后数据 */ Int16 gBufferRcvPing[BUFFSIZE]; // PING接收缓冲区 Int16 gBufferRcvPong[BUFFSIZE]; // PONG接收缓冲区
Uint32 gBufferXmtPing[BUFFSIZE/2]; // 存储PING缓冲区解调后数据 Uint32 gBufferXmtPong[BUFFSIZE/2]; // 存储PONG缓冲区解调后数据
EDMA_Handle hEdmaRcv;//EDMA句柄 EDMA_Handle hEdmaReloadRcvPing;//EDMA接收PING缓冲区数据自加载句柄 EDMA_Handle hEdmaReloadRcvPong;//EDMA接收PONG缓冲区数据自加载句柄
MCBSP_Handle hMcbsp1; // McBSP1 句柄 Int16 gRcvChan; // EDMA传输结束代码
/* * EDMA 配置数据结构 */ /*接收部分EDMA 配置 */ EDMA_Config gEdmaConfigRcv = { EDMA_FMKS(OPT, PRI, HIGH) | // 优先级高 EDMA_FMKS(OPT, ESIZE, 16BIT) | // 数据单元大小16bit EDMA_FMKS(OPT, 2DS, NO) | // 源地址非两纬传输 EDMA_FMKS(OPT, SUM, NONE) | // 源地址不变 EDMA_FMKS(OPT, 2DD, NO) | // 目的地址非两纬传输 EDMA_FMKS(OPT, DUM, INC) | // 目的地址自动增加 EDMA_FMKS(OPT, TCINT, YES) | // 使能EDMA中断 EDMA_FMKS(OPT, TCC, OF(0)) | // 传输结束代码 EDMA_FMKS(OPT, LINK, YES) | // 使能链接地址 EDMA_FMKS(OPT, FS, NO), // 不使用帧同步 EDMA_FMKS(SRC, SRC, OF(0)), // 源地址 EDMA_FMK (CNT, FRMCNT, NULL) | // 帧计数 EDMA_FMK (CNT, ELECNT, BUFFSIZE), // 数据单元计数 (Uint32)&gBufferRcvPing, // 目的地址 EDMA_FMKS(IDX, FRMIDX, DEFAULT) | // 帧索引值 EDMA_FMKS(IDX, ELEIDX, DEFAULT), // 数据单元索引值
EDMA_FMK (RLD, ELERLD, NULL) | // 重新加载数据单元 EDMA_FMK (RLD, LINK, NULL) // 重新加载链接地址 };
/* McBSP 配置数据结构 */ static MCBSP_Config mcbspCfg1 = { /* 配置McBSP 串行口控制寄存器 */ MCBSP_FMKS(SPCR, FREE, NO) |//禁止串行时钟自由运行模式 MCBSP_FMKS(SPCR, SOFT, NO) |//仿真停止,串行口时钟立即停止 MCBSP_FMKS(SPCR, FRST, YES) |//帧同步发生器复位 MCBSP_FMKS(SPCR, GRST, YES) |//采样率发生器复位 MCBSP_FMKS(SPCR, XINTM, XRDY) |//传输中断由事件XRDY驱动 MCBSP_FMKS(SPCR, XSYNCERR, NO) |//无帧同步发送错误 MCBSP_FMKS(SPCR, XRST, YES) |//使能串行口发送 MCBSP_FMKS(SPCR, DLB, OFF) |//禁止数字链路回馈模式 MCBSP_FMKS(SPCR, RJUST, RZF) |//接收数据无符号扩展,右对其,高位补0 MCBSP_FMKS(SPCR, CLKSTP, DISABLE) |//禁止时钟停止模式 MCBSP_FMKS(SPCR, DXENA, OFF) |//禁止DX管脚使能 MCBSP_FMKS(SPCR, RINTM, RRDY) |//接收中断右事件RRDY驱动 MCBSP_FMKS(SPCR, RSYNCERR, NO) |//无帧同步接收错误 MCBSP_FMKS(SPCR, RRST, YES), //使能串行口接收 /* 配置McBSP接收控制寄存器 */ MCBSP_FMKS(RCR, RPHASE, SINGLE) |//接收一相 MCBSP_FMKS(RCR, RFRLEN2, DEFAULT) |//第二相接收帧长度 MCBSP_FMKS(RCR, RWDLEN2, DEFAULT) |//第二相接收帧中数据单元长度 MCBSP_FMKS(RCR, RCOMPAND, MSB) |//接收时无压缩扩展,由最高位开始传输 MCBSP_FMKS(RCR, RFIG, YES) |//忽略突发接收帧同步信号 MCBSP_FMKS(RCR, RDATDLY, 2BIT) |//接收时数据延迟2位 MCBSP_FMKS(RCR, RFRLEN1, OF(1)) |//第一相接收帧长度每相两个字长 MCBSP_FMKS(RCR, RWDLEN1, 16BIT) |//第一相接收单元长度16bit MCBSP_FMKS(RCR, RWDREVRS, DISABLE), //禁止32bit接收单元位颠倒 /* 配置McBSP 发送控制寄存器 */ MCBSP_FMKS(XCR, XPHASE, DEFAULT) | MCBSP_FMKS(XCR, XFRLEN2, DEFAULT) | MCBSP_FMKS(XCR, XWDLEN2, DEFAULT) | MCBSP_FMKS(XCR, XCOMPAND,DEFAULT) | MCBSP_FMKS(XCR, XFIG, DEFAULT) | MCBSP_FMKS(XCR, XDATDLY, DEFAULT) | MCBSP_FMKS(XCR, XFRLEN1, DEFAULT) | MCBSP_FMKS(XCR, XWDLEN1, DEFAULT) | MCBSP_FMKS(XCR, XWDREVRS, DEFAULT), /* 配置McBSP 采样率产生寄存器 */ MCBSP_FMKS(SRGR, GSYNC, DEFAULT) | MCBSP_FMKS(SRGR, CLKSP, DEFAULT) | MCBSP_FMKS(SRGR, CLKSM, DEFAULT) | MCBSP_FMKS(SRGR, FSGM, DEFAULT) | MCBSP_FMKS(SRGR, FPER, DEFAULT) | MCBSP_FMKS(SRGR, FWID, DEFAULT) | MCBSP_FMKS(SRGR, CLKGDV, DEFAULT), /* 配置McBSP 多通道控制寄存器 */ MCBSP_MCR_DEFAULT, /* 配置McBSP 接收通道使能寄存器 */ MCBSP_RCER_DEFAULT, /* 配置McBSP 发送通道使能寄存器 */ MCBSP_XCER_DEFAULT, /* 配置McBSP引脚控制寄存器 */ MCBSP_FMKS(PCR, XIOEN, SP) |//串行发送模式 MCBSP_FMKS(PCR, RIOEN, SP) |//串行接收模式 MCBSP_FMKS(PCR, FSXM, INTERNAL) |//内部帧同步发送 MCBSP_FMKS(PCR, FSRM, EXTERNAL) |//外部帧同步接收 MCBSP_FMKS(PCR, CLKXM, OUTPUT) |//CLKX输出发送时钟 MCBSP_FMKS(PCR, CLKRM, INPUT) |//CLKR输入接收时钟 MCBSP_FMKS(PCR, CLKSSTAT, DEFAULT) |//CLKS管脚状态 MCBSP_FMKS(PCR, DXSTAT, DEFAULT) |//DX管脚状态 MCBSP_FMKS(PCR, FSXP, ACTIVEHIGH) |//发送帧同步信号高电平有效 MCBSP_FMKS(PCR, FSRP, ACTIVEHIGH) |//接收帧同步信号高电平有效 MCBSP_FMKS(PCR, CLKXP, RISING) |//发送时钟上升沿触发数据发送 MCBSP_FMKS(PCR, CLKRP, FALLING) //接收时钟下降沿触发数据接收 };
/* --------------------------- main() 函数 ------------------------ */ /* * main()函数 - 应用程序主线程 * 应用程序初始化,启动McBSP传输 */ void main() { /* 初始化开发板支持库 */ DSK6713_init();
/* 初始化 LEDs指示灯 和 DIP开关 */ DSK6713_LED_init(); DSK6713_DIP_init(); /* 清除缓冲区 */ memset((void *)gBufferXmtPing, 0, BUFFSIZE * 4 * 2); initMcbsp(); // 初始化 McBSP1 接收AD6620串行输出的数据
IRQ_globalDisable(); // 初始化设置时禁止全局中断
initEdma(); // 初始化 EDMA 控制器 initIrq(); // 初始化中断 DSK6713_rset(6,2); // 设置TMS320C6713 McBSP1连接开发板上外部扩展端口 IRQ_globalEnable(); // 重新使能全局中断 }
/* ------------------------函数代码 ----------------------------- */
/* * initMcbsp() * 使用前面定义的McBSP结构配置初始化McBSP */ void initMcbsp() { /* 打开McBSP1*/ hMcbsp1 = MCBSP_open(MCBSP_DEV1, MCBSP_OPEN_RESET); /* 配置McBSP1 */ MCBSP_config(hMcbsp1, &mcbspCfg1); /* 启动McBSP */ MCBSP_start(hMcbsp1, MCBSP_XMIT_START | MCBSP_RCV_START | MCBSP_SRGR_START | MCBSP_SRGR_FRAMESYNC, 220); MCBSP_start(hMcbsp0, MCBSP_XMIT_START | MCBSP_RCV_START | MCBSP_SRGR_START | MCBSP_SRGR_FRAMESYNC, 220); }
/* * initIrq() * 使用芯片支持库初始化、使能DMA接收中断 * 该中断的中断服务例程是edmaHwi(). */ void initIrq(void) { /* CPU使能 EDMA 中断 */ IRQ_clear(IRQ_EVT_EDMAINT); // 清除挂起的 EDMA 中断 IRQ_enable(IRQ_EVT_EDMAINT); // 使能EDMA中断 }
/* * initEdma() * 初始化EDMA控制器 * 使用连接地址传输,自动在PING、PONG缓冲区间交互传输 */ void initEdma(void) { /* 配置接收通道 */ hEdmaRcv = EDMA_open(EDMA_CHA_REVT1, EDMA_OPEN_RESET); // 获得 hEdmaRcv 句柄、复位通道 hEdmaReloadRcvPing = EDMA_allocTable(-1); // 获得 hEdmaReloadRcvPing 句柄 hEdmaReloadRcvPong = EDMA_allocTable(-1); // 获得 hEdmaReloadRcvPong 句柄 gEdmaConfigRcv.src = MCBSP_getRcvAddr(hMcbsp1); // 设置EDMA传输的源地址是 McBSP1 数据接收寄存器 gRcvChan = EDMA_intAlloc(-1); // 获得一个传输结束代码 gEdmaConfigRcv.opt |= EDMA_FMK(OPT,TCC,gRcvChan); // 设置传输结束代码给 gRcvChan
EDMA_config(hEdmaRcv, &gEdmaConfigRcv); // 配置寄存器 EDMA_config(hEdmaReloadRcvPing, &gEdmaConfigRcv); // Ping重新加载 gEdmaConfigRcv.dst = EDMA_DST_OF(gBufferRcvPong); //改变EDMA配置的目的地址为Pong EDMA_config(hEdmaReloadRcvPong, &gEdmaConfigRcv); // 重新加载Pong EDMA_link(hEdmaRcv,hEdmaReloadRcvPong); // 连接寄存器 Pong EDMA_link(hEdmaReloadRcvPong,hEdmaReloadRcvPing); // 连接地址 Pong 到 Ping EDMA_link(hEdmaReloadRcvPing,hEdmaReloadRcvPong); // 连接地址 Ping 到 Pong /* EDMA 控制器使能中断 */ EDMA_intClear(gRcvChan); // 清除任何可能的伪中断
EDMA_intEnable(gRcvChan); // 使能EDMA 中断 (CIER)
EDMA_enableChannel(hEdmaRcv); // 使能 EDMA 通道 /* 通过Mcbsp写的伪操作产生第一个 McBSP 传输事件 */ MCBSP_write(hMcbsp1, 0);
}
/* ---------------------- 中断服务例程 ----------------------- */
/* * edmaHwi() * EDMA 传输中断服务例程 * 当一个完整的EDMA接收帧传输结束时触发 * 通过在DSP/BIOS中配置 * Scheduling --> HWI --> HWI_INT8. * 在编译时edmaHwi()中断服务例程 插入中断向量表 * edmaHwi() 使用 DSP/BIOS Dispatcher发报机 * 保存寄存器状态、确定中断服务例程和其它DSP/BIOS 函数并存 */ void edmaHwi(void) { static Int16 rcvdone = 0;//定义局部变量rcvdone static Uint32 pingOrPong = PING; // 定义局部变量pingOrPong,指示PING、PONG缓冲区 if (EDMA_intTest(gRcvChan))//通道gRcvChan接收传输完成中断 { EDMA_intClear(gRcvChan);//清楚通道gRcvChan传输完成标志 rcvdone = 1;//传输完成标志变量置1 } /* 如果传输结束, 将处理软件中断 processBufferSwi */ if (rcvdone)//传输完成 { if (pingOrPong==PING)//当前是PING缓冲区 { SWI_or(&processBufferSwi, PING);//启动软件中断processBufferSwi //向mailbox 发送PING=0 pingOrPong = PONG;//缓冲区状态赋值PONG } else { SWI_or(&processBufferSwi, PONG);//启动软件中断processBufferSwi //向mailbox 发送PONG=1 pingOrPong = PING;//缓冲区状态赋值PING } rcvdone = 0;//传输完成标志变量清零 } }
/* ------------------------------- 线程 ------------------------------ */ /* * demodulateAM() * AM信号解调程序 * 将一个缓冲区(inBuf)中的数据(I、Q信号)解调算法处理 * 处理后数据存(outBuf) */
/* * AM解调程序 * 程序中调用了函数库fastrts67x.lib中 * 乘方汇编函数powsp(),开方汇编函数sqrtsp() */ /* inBuf存取I、Q信号缓冲区,16位,缓冲区大小1024 */ /*outBuf存取解调后数据缓冲区,32位,缓冲区大小512*/ void demodulateAM(INT16 *inBuf,Uint32 *outBuf,INT16 Length) { INT16 i; Uint32 TempBuf; for(i=0;i<=Length;i+2) { TempBuf=powsp(inBuf[i],2); TempBuf=+powsp(inBuf[i+1],2); *outBuf[i/2]=sqrtsp(TempBuf); } }
/* * processBuffer() * 软件中断processBufferSwi的线程 * 处理接收缓冲区gBufferRcvPing、gBufferRcvPong数据 */ void processBuffer(void) { Uint32 pingPong; /* 读取mailbox中由edmaHwi()中断发送的内容 */ pingPong = SWI_getmbox();
/*处理接收缓冲区gBufferRcvPing、gBufferRcvPong数据 */ if (pingPong == PING) //处理PING缓冲区中数据 { /* 指示灯LED #3 闪烁 */ DSK6713_LED_toggle(3); /* 处理PING 缓冲区数据 */ demodulateAM(gBufferRcvPing, gBufferXmtPing, BUFFSIZE); } else {//处理PONG缓冲区中数据 /* 指示灯LED #2 闪烁 */ DSK6713_LED_toggle(2); /* 处理POING 缓冲区数据 */ demodulateAM(gBufferRcvPong, gBufferXmtPong, BUFFSIZE); } }
/* * 周期性线程blinkLED() * 当DIP 开关 #0 按下时 ,指示灯LED #0每500毫秒闪亮一次 * 该线程在DSP/BIOS中配置 * Scheduling -->PRD --> PRD_blinkLed. */ void blinkLED(void) { /* 如果DIP 开关 #0 按下,指示灯 LED #0闪亮 */ if (!DSK6713_DIP_get(0)) DSK6713_LED_toggle(0); }
/* * 周期性线程load() * 当DIP开关switch #1按下时,该线程仿真给225MHz 6713 20-25%虚负荷 * 该线程在DSP/BIOS中配置 * Scheduling --> PRD-->PRD_load. * 该线程1毫秒执行一次 */ void load(void) { volatile Uint32 i;
/* 如果DIP 开关 #1 按下,CPU执行一个for循环 */ if (!DSK6713_DIP_get(1)) for (i = 0; i < 30000; i++); }
|