📄 tdma55.c
字号:
//test dma
#ifndef _TDMA55_C
#define _TDMA55_C
/*readme.txt
1.如果需要同步触发dma,则ccr的fs比特必须为1(表示中断触发传送1frame),
否则为0(表示中断触发传送1个element)。
2.ti的csl代码和example程序竟然支持8bit操作,何故?
3.auto mode:0表示地址不变;1表示 8比特、16比特、或32比特操作(),取决于CSDP中的
data_type值。
由于dsp不支持8比特,而是16比特操作加1,32比特操作后加2---是否在程序设计
时要考虑这一点?
4.DMA_GSCR的最低比特指示,
DMA destination indexing enhancement: Softwareincompatible control.
0: Destination element index = DMA_CSEI register,destination frame index = DMA_CSFI register
This mode permits software compatibility with previous versions of the DMA controller
hardware.The source indexing registers are also used fordestination indexing. This is the
power1–up default state.
1: Destination element index = DMA_CDEI register,destination frame index = DMA_CDFI register
This mode of operation has separate destination element and frame indexes, which are
configured by the channel destination element index and the channel destination frame index,
respectively.
是否表示,0的时候dma_cdei/dma_cdfi的内容无效,直接使用源地址的设置。
5.检查csei/csfi/cdei/cdfi是否设置
6.csdp中的burst/pack比特是否需要设置?
7.!!!!CSL中关于8bit、16比特、32比特的操作很可能有bug,查看一下dat类的设置。
8.csdp的burst操作在dsp--》emif、arm-》fifo时不同,前者可以用16byte,后者1byte。内部拷贝
可以用16byte,但往外设比如mcbsp,可能只能用1byte。
9.CCR之end_prog比特用来dma的自动reload,步骤:
清repeat比特为0(dma将等待end prog比特=1)--》
清repeat bit比特为0
开始写congfig寄存器
置repeat bit为1
10.cicr用于中断控制(但同步中断触发的控制在ccr中)。设置以下比特为有效:
传送完1frame 或 传送完1block、dma drop中断、time out中断.
在缺省初始化时,设置一下dma drop和time out。
11.注意,往mc bsp等外设通过dma手法数据之src/dst可能是tipb。
12.tipb的控制
cmr:
cpu prio=1时表示cpu总可以抢到tipb总线,应该用‘0’
strb1/strb2比特都设置成0..dsp以最快速度读取寄存器
13.idle控制比特全部设为无效,即不idle。
14.
*/
/*
This testcase is a basic testcase -32-bit , 1d to 1d , SDRAM to SDRAM transfers.
If the value of the variable testResult is 0xFACE, then the test case has passed.
*/
#include "includes.h"
#include "includes_async.h"
#include "dsp_includes.h"
//-******************************************************-//
//设置dma的流程:
//GlobalInitDma
//InitDma
//DmaSetSrcMem
//DmaSetDstMem
//.....
//DmaEndProg(1) ---表示设置完毕
//DmaStart
//-***********************************************************-//
void GlobalInitDma(void)
//dma设置为不支持"空闲时idle"
{
_PREG_SET(_DMA_DMAGCR_ADDR,0x00);
/*GCR比特:
auto_idle: 0设置为free run.1设置为不用时idle。
free=0:emu中断dma的传送;1不中断
mpui_excel:0--mpui有权access dsp内所有的ram
mpui_prio:0--mpui优先级为低
*/
_PREG_SET(_DMA_DMAGTCR_ADDR,0 );//DARAM/SARAM之time out全部disable掉
_PREG_SET(_DMA_DMAGSCR_ADDR,1 );
//1:dma之源地址和目的地址使用各自的地址增加方式csei、csfi、cdei、cdfi
//0:目的地址增长方式与源地址一样的:都是从csei、csfi得到
}
DMA_Handle InitDma(Uint16 dev_no,Uint16 prio,Uint16 sync_int,
Uint16 frm_len,Uint16 elem_len,Uint16 dat_type)
//dev_no表示dma设备号
//auto:表示参数是否自动reload
//prio:1表示此dma在dma循环中为高优先级,0表示低优先级
//sync_int:表示同步触发中断号(eventId).0表示无同步触发中断
//本函数将src、dst地址自动增加方式设置为:src、dst独自依赖于csei/csfi、cdei/cdfi
//dat_type:表示8比特、16比特、还是32比特
//缺省设置仅在1个block传完后才中断
{
DMA_Handle hDma;
Uint16 i=0;
hDma = DMA_open(1, DMA_OPEN_RESET);
if(hDma==INV){
printf("open dma handle err:device no=%d\n",dev_no);
return(NULL);
}
//val=DMA_RGET_H(hDma,DMACFN);
//val=DMA_RGET_H(hDma,DMACEN);
while (DMA_FGET_H(hDma,DMACCR,EN)); /* wait if a previous transfer is pending */
DmaEndProg(hDma,0);
DmaFlushFifo(hDma,1);
for(i=0;i<100;i++); //等待清空dma之fifo
DmaFlushFifo(hDma,0);
DMA_RSET_H(hDma,DMACFN, frm_len);
DMA_RSET_H(hDma,DMACEN,elem_len);
sync_int=sync_int&0x1f;
DMA_RSET_H(hDma,DMACCR,DMA_DMACCR_RMK(
DMA_DMACCR_DSTAMODE_POSTINC, /* Destination address mode is postincrement */
DMA_DMACCR_SRCAMODE_POSTINC, /* Source address mode is postincrement */
DMA_DMACCR_ENDPROG_OFF, /* Registers will not be reloaded after end of current transfer */
DMA_DMACCR_FIFOFLUSH_OFF, /* This is a reserved bit. Must always be 0 */
DMA_DMACCR_REPEAT_OFF, /* Registers will not be reloaded after end of current transfer */
DMA_DMACCR_AUTOINIT_OFF, /* Auto initialisation mode is turned off */
DMA_DMACCR_EN_STOP, /* The channel is disabled */
prio, /* Channel priority is set from the corresponding bit in _CSL_DatChaPriority */
DMA_DMACCR_FS_DISABLE, /* Frame synchronisation is disabled */
sync_int /* DMA transfer does not start on any event */
));
DMA_RSET_H(hDma,DMACICR,DMA_DMACICR_RMK(
DMA_DMACICR_BLOCKIE_OFF, /* Interrupt only on completion of the entire block */
DMA_DMACICR_LASTIE_OFF,
DMA_DMACICR_FRAMEIE_OFF,
DMA_DMACICR_FIRSTHALFIE_OFF,
DMA_DMACICR_DROPIE_OFF,
DMA_DMACICR_TIMEOUTIE_OFF
));
DMA_RSET_H(hDma,DMACSDP,DMA_DMACSDP_RMK(
DMA_DMACSDP_DSTBEN_NOBURST, /* Single access at the destination */
DMA_DMACSDP_DSTPACK_OFF, /* Turn off packing at the destination */
DMA_DMACSDP_DST_DARAM, /* The destination type may be one of SARAM, DARAM or EMIF as computed above */
DMA_DMACSDP_SRCBEN_NOBURST, /* Single access at the source */
DMA_DMACSDP_SRCPACK_OFF, /* Turn off packing at the source */
DMA_DMACSDP_SRC_DARAM, /* The source type may be one of SARAM, DARAM or EMIF as computed above */
dat_type /* One element is 8-bit wide */
));
/*
_DMA_DMACSEI_ADDR(n)
*/
DMA_RSET_H(hDma,DMACFI,0); //这种方式不用,设置成任何值都可以
DMA_RSET_H(hDma,DMACEI,2);
//-***************************************************-//
// DMA_getConfig (hDma, &myconfig);
return(hDma);
}
void DmaSetSrcMem(DMA_Handle hDma,void* src_adr,Uint16 inc_mode,Uint16 burst_on_off)
//inc_mode:0--const;1--加1
//
{
Uint32 lsrc;
Uint16 DatSrcType ;/* whether the source is in SARAM, DARAM or EMIF */
lsrc=((Uint32)src_adr)<<1;
//-***************************************************-//
/* Calculate whether the source and destination lie in SARAM, DARAM or EMIF */
DatSrcType = DMA_DMACSDP_SRC_DARAM;
if (lsrc>=(Uint32)EMIF_START_ADDRESS){
DatSrcType = DMA_DMACSDP_SRC_EMIF;
}
else {
if(lsrc>=(Uint32)SARAM_START_ADDRESS)
DatSrcType = DMA_DMACSDP_SRC_SARAM;
}
printf("DatSrcType =%d\n",DatSrcType);
DMA_RSET_H(hDma,DMACSSAL,(Uint16)((Uint32)lsrc & 0xFFFFu)); /* Extracting lower 16 bits of source address */
DMA_RSET_H(hDma,DMACSSAU,(Uint16)(((Uint32)lsrc >> 16) & 0x00FFu)); /* Extracting upper 8 bits of source address */
//DMA_FSET_H(hDma,DMACCR,SRCAMODE,inc_mode);
DMA_FSET_H(hDma,DMACSDP,SRC,DatSrcType);
DMA_FSET_H(hDma,DMACCR,SRCAMODE,inc_mode);
if(burst_on_off){
//msk=;
DMA_FSET_H(hDma,DMACSDP,SRCBEN,DMA_DMACSDP_SRCBEN_BURST4);
}
}
void DmaSetDstMem(DMA_Handle hDma,void* dst_adr,Uint16 inc_mode,Uint16 burst_on_off)
{
Uint32 ldst;
Uint16 DatDstType;/* whether the source is in SARAM, DARAM or EMIF */
ldst=((Uint32)dst_adr)<<1;
//-***************************************************-//
/* Calculate whether the source and destination lie in SARAM, DARAM or EMIF */
DatDstType = DMA_DMACSDP_DST_DARAM; /* Default source is in DARAM */
if (ldst >= (Uint32)EMIF_START_ADDRESS){ /* Starting address of ASRAM */
DatDstType = DMA_DMACSDP_DST_EMIF;
}
else if (ldst >= (Uint32)SARAM_START_ADDRESS){ /* Starting address of SARAM */
DatDstType = DMA_DMACSDP_DST_SARAM;
}
DMA_RSET_H(hDma,DMACDSAL,(Uint16)((Uint32)ldst & 0xFFFFu)); /* Extracting lower 16 bits of source address */
DMA_RSET_H(hDma,DMACDSAU,(Uint16)(((Uint32)ldst >> 16) & 0x00FFu)); /* Extracting upper 8 bits of source address */
DMA_FSET_H(hDma,DMACCR,DSTAMODE,inc_mode);
DMA_FSET_H(hDma,DMACSDP,DST,DatDstType);
if(burst_on_off)
DMA_FSET_H(hDma,DMACSDP,DSTBEN,DMA_DMACSDP_DSTBEN_BURST4);
}
void DmaFastSetSrcMem(DMA_Handle hDma,void* src_adr)
//不检查地址空间位置,直接设置
{ Uint32 lsrc;
lsrc=((Uint32)src_adr)<<1;
DMA_RSET_H(hDma,DMACSSAL,(Uint16)((Uint32)lsrc & 0xFFFFu));
DMA_RSET_H(hDma,DMACSSAU,(Uint16)(((Uint32)lsrc >> 16) & 0x00FFu));
}
void DmaFastSetDstMem(DMA_Handle hDma,void* dst_adr)
//不检查地址空间位置,直接设置
{ Uint32 ldst;
ldst=((Uint32)dst_adr)<<1;
DMA_RSET_H(hDma,DMACDSAL,(Uint16)((Uint32)ldst & 0xFFFFu));
DMA_RSET_H(hDma,DMACDSAU,(Uint16)(((Uint32)ldst >> 16) & 0x00FFu));
}
void DmaFastSetFrmElemLen(DMA_Handle hDma,Uint16 frm_len,Uint16 elem_len)
//不检查地址空间位置,直接设置
{
DMA_RSET_H(hDma,DMACFN, frm_len);
DMA_RSET_H(hDma,DMACEN,elem_len);
}
void DmaSetSrcMcBsp()
{
}
void DmaSetDstMcBsp()
{
}
void DmaSetSrcMcsi()
{
}
void DmaSetDstMcsi()
{
}
void DmaSetNtxtSrcDstMem(DMA_Handle hDma)
//此时dma应该已经设置为auto init
{
DmaRepeat(hDma,0); //当前dma完成后等待endprog比特=1才开始下一次发送
DmaEndProg(hDma,0);
//-***************************************************-//
//-***************************************************-//
DmaEndProg(hDma,1);
}
void DmaSetNtxtSrcMem(DMA_Handle hDma)
//此时dma应该已经设置为auto init
{
DmaRepeat(hDma,0); //当前dma完成后等待endprog比特=1才开始下一次发送
DmaEndProg(hDma,0);
//-***************************************************-//
//-***************************************************-//
DmaEndProg(hDma,1);
}
void DmaSetNtxtDstMem(DMA_Handle hDma)
//此时dma应该已经设置为auto init
{
DmaRepeat(hDma,0); //当前dma完成后等待endprog比特=1才开始下一次发送
DmaEndProg(hDma,0);
//-***************************************************-//
//-***************************************************-//
DmaEndProg(hDma,1);
}
void DmaSetNtxtDmaParaTipb(void)
{
}
void DmaSetInt(DMA_Handle hdma,Uint16 intmode,void (*func)(void) ,Uint16 prio)
//func:表示中断服务程序入口
//prio:优先级
//intmode表示是blk中断、frame中断,0.5frame中断等,各比特域定义如下.
/*bit5: bit0
block_ie last_ie frame_ie half_ie drop_ie tout_ie
#define DMA_INT_BLOCK (1<<5)
#define DMA_INT_LAST_FRAME (1<<4)
#define DMA_INT_FRAME (1<<3)
#define DMA_INT_HALF_FRAME (1<<2)
#define DMA_INT_DAT_DROP (1<<1) //最后2个选项在初始化时设定
#define DMA_INT_TIME_OUT (1<<0)
*/
{
Uint16 int_no=0;
//intmode=intmode|DMA_INT_DAT_DROP|DMA_INT_TIME_OUT;
DMA_RSET_H(hdma,DMACICR,intmode);
if(intmode==0) //不响应任何中断
return;
int_no=DMA_getEventId(hdma);
DMA_RGET_H(hdma,DMACSR);
IRQ_clear(int_no);
IRQ_plug(int_no,func,prio);
IRQ_enable(int_no);
}
void DmaStart(DMA_Handle hDma)
{
DMA_start(hDma);
}
Uint16 DmaRunning(DMA_Handle hDma)
{//如何知道dma正在传送????
return(DMA_FGET_H(hDma,DMACCR,EN));
}
void DmaRepeat(DMA_Handle hDma,Uint16 on_off)
//on_off=1 on;0 off.
{
DMA_FSET_H(hDma,DMACCR,REPEAT,on_off);
}
void DmaAutoInit(DMA_Handle hDma , Uint16 on_off)
//on_off=1 on;0 off.
{
DMA_FSET_H(hDma,DMACCR,AUTOINIT,on_off);
}
void DmaFlushFifo(DMA_Handle hDma,Uint16 on_off)
//on_off=1 on;0 off
{
DMA_FSET_H(hDma,DMACCR,FIFOFLUSH,on_off);
}
void DmaEndProg(DMA_Handle hDma,Uint16 yes_no)
{
DMA_FSET_H(hDma,DMACCR,ENDPROG,yes_no);
}
void DmaStop(DMA_Handle hDma)
{
DMA_stop(hDma);
DmaFlushFifo(hDma,1);
}
void DmaFs(DMA_Handle hDma,Uint16 fs_mode)
/*fs_mode:
#define FS_FRAME 0 //同步触发时一次读1帧
#define FS_ELEMENT 1 //同步触发时1次读1个element
*/
{
if(fs_mode==FS_FRAME)
DMA_FSET_H(hDma,DMACCR,FS,DMA_DMACCR_FS_ENABLE);
else
DMA_FSET_H(hDma,DMACCR,FS,DMA_DMACCR_FS_DISABLE);
}
extern DMA_Handle hdma;
void DmaIsr(void)
//给dma中断写的一个中断服务程序 查询frame/last frame/block中断
//blk中断后关闭dma并清空fifo。
{
Uint16 i;
i=DMA_RGET_H(hdma,DMACSR);
i=0;
puts("dma interrupt\n");
}
//-*********************************************************-//
#endif //_TDMA55_C
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -