用不用DMAengine

  星辉资讯     |      2023-04-21 09:16

使用DMAengine

DMAengine是Linux下一套通用的DMA驱动框架,用于通用的DMA,就是UART、SPI他们这些相对低速的接口使用的DMA,这些接口使用一个或两个DMA控制器。通过这个DMA控制器的不同端口共同使用这个控制器,控制器可以仲裁各个端口分时使用。

使用步骤如下:

1)申请一个DMA channel。

2)根据设备(slave)的特性,配置DMA channel的参数。

3)要进行DMA传输的时候,获取一个用于识别本次传输(transaction)的描述符(descriptor)。

4)将本次传输(transaction)提交给dma engine并启动传输。

5)等待传输(transaction)结束。

然后,重复3~5即可。

之所以有这个框架是因为这一个控制器就管理着好多的端口,可以应用的设备比较多。

不使用DMAengine

像以太网之类的外设有自己的专用DMA控制器,就没必要使用这个驱动框架了。比如上一步的第一步和第二部就是不适合用于那个框架。如果非要用,就比如第四部,启动传输由于连个DMA控制器的具体用法不一样,还得单独写一个DMAengine的中间层。

static void macb_configure_dma(struct macb *bp)

{

u32 dmacfg;

if (macb_is_gem(bp)) {

dmacfg=gem_readl(bp, DMACFG) & ~GEM_BF(RXBS, -1L);

dmacfg |=GEM_BF(RXBS, bp->rx_buffer_size / RX_BUFFER_MULTIPLE);

if (bp->dma_burst_length)

dmacfg=GEM_BFINS(FBLDO, bp->dma_burst_length, dmacfg);

dmacfg |=GEM_BIT(TXPBMS) | GEM_BF(RXBMS, -1L);

dmacfg &=~GEM_BIT(ENDIA_PKT);

...

比如这是一段dma控制器的初始化,就是随设备一起初始化。发送的时候也是直接写寄存器。如下所示

if (i==queue->tx_head) {

ctrl |=MACB_BF(TX_LSO, lso_ctrl);

ctrl |=MACB_BF(TX_TCP_SEQ_SRC, seq_ctrl);

} else

ctrl |=MACB_BF(MSS_MFS, mss_mfs);

macb_set_addr(bp, desc, tx_skb->mapping);