首页 > 其他分享 >DMA(三) - DMA控制器接口函数

DMA(三) - DMA控制器接口函数

时间:2022-10-31 17:38:33浏览次数:108  
标签:DMA 控制器 dma int dev s3c2410 s3c 接口函数


DMA控制器接口函数

主要作用是配置DMA控制器并启动相应传输
s3c2440中关于公共DMA控制器的函数提供有:
s3c2410_dma_config()
s3c2410_dma_ctrl()
s3c2410_dma_enqueue()
s3c2410_dma_devconfig()
s3c2410_dma_set_buffdone_fn()
s3c2410_dma_request()
s3c2410_dma_free()
一般使用的顺序如下:
request =>set_buffdone_fn=> devconfig => config => enqueue => ctrl => free
1、int s3c2410_dma_request(unsigned int channel, struct s3c2410_dma_client *client, void *dev)

2、static inline void s3c2410_dma_buffdone(struct s3c2410_dma_chan *chan, struct s3c2410_dma_buf *buf, enum s3c2410_dma_buffresult result)
设置相应的dma通道完成一次dma传输后的回调函数

3、int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source, unsigned long devaddr)
source: S3C2410_DMASRC_HW: source is hardware
S3C2410_DMASRC_MEM: source is memory
devaddr: physical addr of source

4、int s3c2410_dma_config(unsigned int channel, int xferunit)
根据xferunit设置通道的控制寄存器DCONx
xferunit为每次传输的数据大小:0:byte 1:half word 2:word

5、dma_alloc_coherent
DMA要求使用non-cached, 物理地址连续的内存。
将对应的内核虚拟地址转化为物理地址,供给后面的s3c2410_dma_enqueue函数使用。

6、int s3c2410_dma_enqueue(unsigned int channel, void *id, dma_addr_t data, int size)

7、int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op)
8、int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *client)

参考文章:
1. ​​​ s3c2410的dma操作的一般步骤​


DMA控制器接口函数使用实例

s3c2440 DMA datasheet

s3c2440 DMA控制器支持4种情况的DMA传输:
a. source and destination are in the system bus
b. source in the system bus while destination in the peripheral bus
c. source in the peripheral bus while destination in the system bus
d. source and destination are in the peripheral bus
但是在arch/arm/plat-s3c24xx/dma.c的函数s3c2410_dma_devconfig中却只实现了b和c两种情况。

s3c2440有4个DMA channel,每个channel都有DISC/DISCC/DIDST/DIDSTC寄存器,DISC和DIST可以填入不同source类型(具体参考S3c2440 Datasheet Table 8-1),除此之外还能填入内存的物理地址作为source或destination。

和传输相关的3个参数:
TSZ:DCON[28],0:unit模式:一次transfer1个data size,burst模式:一次transfer4个data size
DSZ:DCON[21:20],0:data size is BYTE,1:data size is Half WORLD,0:data size is WORLD
TC:DCON[19:0],transfer count
传输的数据量=TC * (DSZ * 8) * TSZ

request source: DCON[23]
0:S/W request mode, DMA is triggered by setting SW_TRIG bit of DMASKTRIG control register
1:DMA source selected by bit[26:24] triggers the DMA operation

service mode:DCON[27]
0:single service mode,一次DMA请求完成一次原子操作,等待下一次请求
1:whole service mode,一次DMA请求完成一批原子操作,当TC=0表示完成一次whole service

参考文章:
1. ​​​ S3C2410:DMA介紹​


使用cpu搬运内存与使用DMA搬运内存

下面这个例子我使用了s3c2440的公共DMA控制器,直接去配置寄存器并没有使用内核提供的arch/arm/plat-s3c24xx/dma.c文件中的DMA控制器接口函数,虽然效果是一样的,但最好应调用DMA控制器接口函数。
完整代码位置:​​dma_operation.c​​

static ssize_t s3c_mem_copy_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int i;
unsigned long time_s = 0, time_e = 0;

if (!buf && count < 1)
return -1;

printk("buf is: %s", buf);

memset(s3c_dma_dev->src, 0xaa, BUF_SIZE);
memset(s3c_dma_dev->dst, 0x55, BUF_SIZE);

switch (buf[0]) {
case MEM_CPY_NO_DMA:
time_s = jiffies;
for(i = 0;i < BUF_SIZE;i++)
s3c_dma_dev->dst[i] = s3c_dma_dev->src[i];
time_e = jiffies;

if (memcmp(s3c_dma_dev->src, s3c_dma_dev->dst, BUF_SIZE) == 0)
printk("MEM_CPY_NO_DMA OK\n");
else
printk("MEM_CPY_NO_DMA ERROR\n");
break;
case MEM_CPY_DMA:
s3c_dma_dev->dma_regs->disrc = s3c_dma_dev->src_phy; //src physical addr
s3c_dma_dev->dma_regs->disrcc = (0 << 1) | (0 << 0); //src in the AHB bus, addr INC
s3c_dma_dev->dma_regs->didst = s3c_dma_dev->dst_phy; //dst physical addr
s3c_dma_dev->dma_regs->didstc = (0 << 2) | (0 << 1) | (0 << 0); //intr when TC=0, dst in AHB bus, addr INC
s3c_dma_dev->dma_regs->dcon = (1 << 30) | (1 << 29) | (0 << 28) | (1 << 27) \
| (0 << 23) | (0 << 20) | (BUF_SIZE << 0); // enable intr, unit mode, soft trig

/* start DMA transfer */
time_s = jiffies;
s3c_dma_dev->dma_regs->dmasktrig = (1 << 1) | (1 << 0);
wait_for_completion(&s3c_dma_dev->comp);
time_e = jiffies;

if (memcmp(s3c_dma_dev->src, s3c_dma_dev->dst, BUF_SIZE) == 0)
printk("MEM_CPY_DMA OK\n");
else
printk("MEM_CPY_DMA ERROR\n");

break;

default:
break;
}

printk("use time: %ld\n", time_e - time_s);
return count;
}
static DEVICE_ATTR(oper, 0666, NULL, s3c_mem_copy_store);

static irqreturn_t s3c_dma_irq(int irq, void *devid)
{
complete(&s3c_dma_dev->comp);

return IRQ_HANDLED;
}

参考文章:
1. ​​​ S3C实现DMA驱动程序编写​


标签:DMA,控制器,dma,int,dev,s3c2410,s3c,接口函数
From: https://blog.51cto.com/u_15854579/5810522

相关文章

  • DMA(二) - DMA接口函数
    DMA接口函数arch/arm/mm/dma-mapping.c主要的作用是将虚拟地址映射到物理地址。一致性DMA映射,分配指定大小的内存,并将物理地址映射到虚拟地址dma_alloc_coherentdma_mma......
  • 内网安全之:黄金&白银票据传递域控制器权限维持
    内网安全之:黄金&白银票据传递域控制器权限维持目录内网安全之:黄金&白银票据传递域控制器权限维持1GoldenTicket1.1导出krbtgt的NTLMHash1.2获取基本信息1.3Kerbe......
  • 实验6:开源控制器实践——RYU
    实验6:开源控制器实践——RYU一、实验目的能够独立部署RYU控制器;能够理解RYU控制器实现软件定义的集线器原理;能够理解RYU控制器实现软件定义的交换机原理。二、实验......
  • 实验6:开源控制器实践——RYU
    a)搭建下图所示SDN拓扑,协议使用OpenFlow1.0,并连接Ryu控制器,通过Ryu的图形界面查看网络拓扑。b)运行当中的L2Switch,h1pingh2或h3,在目标主机使用tcpdump验证L2Switch......
  • 实验6:开源控制器实践——RYU
    基本要求a)搭建下图所示SDN拓扑,协议使用OpenFlow1.0,并连接Ryu控制器,通过Ryu的图形界面查看网络拓扑。b)运行当中的L2Switch,h1pingh2或h3,在目标主机使用tcpdump验......
  • 实验6:开源控制器实践——RYU
    一、实验目的1、能够独立部署RYU控制器;2、能够理解RYU控制器实现软件定义的集线器原理;3、能够理解RYU控制器实现软件定义的交换机原理。二、实验环境Ubuntu20.04Desktop......
  • 实验6:开源控制器实践——RYU
    (一)基本要求1.搭建SDN拓扑,协议使用OpenFlow1.0,并连接Ryu控制器,通过Ryu的图形界面查看网络拓扑。(通过命令实现搭建拓扑)命令:sudomn--topo=single,3--mac--controller......
  • 开源控制器-ryu
    实验6:开源控制器实践——RYU一、实验目的能够独立部署RYU控制器;能够理解RYU控制器实现软件定义的集线器原理;能够理解RYU控制器实现软件定义的交换机原理。二、实验......
  • 实验6:开源控制器实践——RYU
    1.搭建下图所示SDN拓扑,协议使用OpenFlow1.0,并连接Ryu控制器,通过Ryu的图形界面查看网络拓扑。sudomn--topo=single,3--mac--controller=remote,ip=127.0.0.1,port=66......
  • 实验6:开源控制器实践——RYU
    实验6:开源控制器实践——RYU一、实验目的能够独立部署RYU控制器;能够理解RYU控制器实现软件定义的集线器原理;能够理解RYU控制器实现软件定义的交换机原理。二、实验......