📄 dma.c
字号:
/* * ApOS (Another Project software for s3c2410) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Copyright caiyuqing * * this file define the functions of the DMA block * 本文件实现了对DMA模块进行操作的函数 */#include "../include/s3c2410/s3c2410.h"#include "../include/s3c2410/dma.h"#include "../include/kernel/irq.h"extern irq_ptr irq_rotunie[32];/* * DMA global object,any functions of the dma control is base it. * DMA全局对象,整个系统的DMA操作(初始化,设置等等)都是基于这个对象的 */struct dma_ctrl_object dma_ctrl_object;/* * system can get the status of a dma opteration througth * thease four global variable * 四个全局变量,通过他们系统可以知道dma操作是否已经完成 */char sys_dma0_done;char sys_dma1_done;char sys_dma2_done;char sys_dma3_done;/* * irq for chanel0 * 0号通道dma中断服务例程 */void dma0_irq(struct cpu_registers *regs);/* * initialize the DMA object * 初始化 dma_ctrl_object 对象 */void dma_ctrl_obj_init(struct dma_ctrl_object *dco){ //0通道对象初始化 dco->chanel0.disrc =&rDISRC0; dco->chanel0.disrcc =&rDISRCC0; dco->chanel0.didst =&rDIDST0; dco->chanel0.didstc =&rDIDSTC0; dco->chanel0.dcon =&rDCON0; dco->chanel0.dstat =&rDSTAT0; dco->chanel0.dcsrc =&rDCSRC0; dco->chanel0.dcdst =&rDCDST0; dco->chanel0.dmasktrig =&rDMASKTRIG0; dco->chanel0.tc_opt =1; //1通道对象初始化 dco->chanel1.disrc =&rDISRC1; dco->chanel1.disrcc =&rDISRCC1; dco->chanel1.didst =&rDIDST1; dco->chanel1.didstc =&rDIDSTC1; dco->chanel1.dcon =&rDCON1; dco->chanel1.dstat =&rDSTAT1; dco->chanel1.dcsrc =&rDCSRC1; dco->chanel1.dcdst =&rDCDST1; dco->chanel1.dmasktrig =&rDMASKTRIG1; dco->chanel1.tc_opt =1; //2通道对象初始化 dco->chanel2.disrc =&rDISRC2; dco->chanel2.disrcc =&rDISRCC2; dco->chanel2.didst =&rDIDST2; dco->chanel2.didstc =&rDIDSTC2; dco->chanel2.dcon =&rDCON2; dco->chanel2.dstat =&rDSTAT2; dco->chanel2.dcsrc =&rDCSRC2; dco->chanel2.dcdst =&rDCDST2; dco->chanel2.dmasktrig =&rDMASKTRIG2; dco->chanel2.tc_opt =1; //3通道对象初始化 dco->chanel3.disrc =&rDISRC3; dco->chanel3.disrcc =&rDISRCC3; dco->chanel3.didst =&rDIDST3; dco->chanel3.didstc =&rDIDSTC3; dco->chanel3.dcon =&rDCON3; dco->chanel3.dstat =&rDSTAT3; dco->chanel3.dcsrc =&rDCSRC3; dco->chanel3.dcdst =&rDCDST3; dco->chanel3.dmasktrig =&rDMASKTRIG3; dco->chanel3.tc_opt =1; irq_rotunie[INT_DMA0] =&dma0_irq;}/* * we use chanel0 to perform the data transfer between memory and memory * 本函数使用DMA的0号通道对内存间的数据传送 * src_addr: source address 源地址 * dest_addr: destination address 目标地址 * len: data length(byts) 数据长度(字节) */int dma_mem_copy(unsigned int* src_addr,unsigned int* dest_addr,int len){ struct dma_ctrl_object *dma_obj =&dma_ctrl_object; struct dma_chanel *dma_chanel =((struct dma_chanel *)dma_obj)+0; unsigned int tc=(len); irq_mask(INT_DMA0,IRQ_UNMASK); sys_dma0_done=0; //必须清除DCache,否则数据会出错 invalidate_DCache(); /* * LOC: 0 address increment * INC: 0 AHB */ *dma_chanel->disrc=src_addr; *dma_chanel->disrcc=(0<<LOC_OFFSET)|(0<<INC_OFFSET); *dma_chanel->didst=dest_addr; *dma_chanel->didstc=(0<<LOC_OFFSET)|(0<<INC_OFFSET); /* * DMD_HS: 1 Handshake mode. * * SYNC: 1 DREQ and DACK are synchronized to HCLK. * 由于是内存间的数据传递,数据源设备是内存,应该同步于HCLK * 所以将SYNC位设置为1 * 若数据源设备是属于外部总线的,则必须同步于PCLK,必须将该 * 位设置为0 * * INT: 1 interrupt request is generated when all the transfer is done. * 当该位为1时,则DMA完成(既CURR_TC变为0)之后相应的DMA中断将被触发 * * TSZ: 0 an union transfer is performed. * DMA设备每次占用总线时传递数据的次数,0是传递1次后释放总线, * 1是传递4次后再释放总线 * * SERVMODE:1 Whole service mode. * * SWHW_SEL:0 S/W request mode. * DMA触发方式的选择,0软件触发,1为硬件触发。 * 当设置为硬件触发之后我们必须设置HWSRCSEL位 * 为4个通道配置触发源 * * RELOAD: 1 DMA channel (DMA REQ) is turned off when a current value of * transfer count becomes 0. * 当设置为1时,则一旦某通道完成了DMA操作(既CURR_TC变为0),该通道 * 将被马上关闭。(既DMASKTRIG寄存器的ON_OFF位被置0) * 若设置为0时,则完成DMA操作之后的通道并不关闭(既DMASKTRIG寄存器 * 的ON_OFF位还是1),它会紧接着处理新的请求(如果有的话) * * DSZ: 00 BYTE. * DMA每次传送数据的字节数 * * TC: tc 当前DMA请求总共需要传递多少次数据(必须占用多少次总线) * 一个DMA操作传递的数据字节数实际上是 DSZ*TSZ*TC * */ *dma_chanel->dcon=(1<<DMD_HS_OFFSET)|(1<<SYNC_OFFSET)| (1<<INT_OFFSET)|(0<<TSZ_OFFSET)|(1<<SERVMODE_OFFSET)| (0<<SWHW_SEL_OFFSET)|(1<<RELOAD_OFFSET)|(BYTE<<DSZ_OFFSET)| (tc); //ready? //while((*dma_chanel->dstat)&0xfffff!=0); while(((*dma_chanel->dstat)>>20)&0x3!=0);//DMA is busy /* * DMA on, SW_TRIG * 开启DMA通道,触发一个DMA信号 */ *dma_chanel->dmasktrig=(1<<ON_OFF_OFFSET)|(1<<SW_TRIG_OFFSET); return tc;}void dma_stop(int chanel){ struct dma_ctrl_object *dma_obj =&dma_ctrl_object; struct dma_chanel *dma_chanel =((struct dma_chanel *)dma_obj)+chanel; *dma_chanel->dmasktrig=(1<<STOP_OFFSET);}/* * irq for dam chanel0 * dma chanel0 中断服务例程 */void dma0_irq(struct cpu_registers *regs){ /* * clean the interrupt pin and mask the interrupt,set * the sys_dmaX_done to 1,indecate that the DMA opteration * is complete. * * 清除中断信号并屏蔽该中断,将sys_dmaX_done * 设置为0表示一个DMA操作已经完成 */ clean_src_pnd(INT_DMA0); clean_int_pnd(INT_DMA0); irq_mask(INT_DMA0,IRQ_MASK); sys_dma0_done=1;}int dma_copy_done(){ return sys_dma0_done;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -