zynq 使用AXI_dma 传输==pl到ps,linux驱动开发,应用层处理DMA数据(二)

背景

经过上一篇的研究,可以简单使用dma。但是上一篇中重复读取dma存在异常退出问题,因此接下来对其代码进行封装。

dma的fpga工程以及引脚绑定,axi_dma驱动移植,编译等,请看上一篇:

zynq 使用AXI_dma 传输==pl到ps,linux驱动开发,应用层处理DMA数据(一)_zynq linux dma-CSDN博客

1.初始化dma

axidma_dev_t axidma_dev1;
struct dma_transfer gTrans;
    
int initDma()
{
    
    // 初始化AXIDMA设备
    axidma_dev1 = axidma_init();
    if (axidma_dev1 == NULL) 
    {
        printf("Error: Failed to initialize the AXI DMA device.\n");
        return -1;
    }
     printf("Succeed to initialize the AXI DMA device.\n");

        
    return 0;
}

2.初始化通道

const array_t *tx_chans, *rx_chans;
int initInChannel()
{  
    // 如果还没有指定tx和rx通道,则获取收发通道
    tx_chans = axidma_get_dma_tx(axidma_dev1);
    
    
    if (tx_chans->len < 1) {
        printf("Error: No transmit channels were found.\n");
    }
    rx_chans = axidma_get_dma_rx(axidma_dev1);
    
    if (rx_chans->len < 1) {
        printf("Error: No receive channels were found.\n");
    }
    
     /* 如果用户没有指定通道,我们假设发送和接收通道是编号最低的通道。 */
    if (gTrans.input_channel != -1 && gTrans.output_channel != -1) 
    {
        gTrans.input_channel = tx_chans->data[0];
        gTrans.output_channel = rx_chans->data[0];
        printf("user system cfg:\n");
    }
    else
    {
        gTrans.input_channel = 0;
        gTrans.output_channel = 1;
        printf("user custom:\n");
    }

    printf("AXI DMAt File Transfer Info:\n");
    printf("\tTransmit Channel: %d\n", gTrans.input_channel);
    printf("\tReceive Channel: %d\n", gTrans.output_channel);
    printf("\tInput File Size: %d MiB\n", gTrans.input_size);
    printf("\tOutput File Size: %d MiB\n\n", gTrans.output_size);
    
    return 0;
}

3.读取dam数据到内存

/*----------------------------------------------------------------------------
 * DMA File Transfer Functions
 *----------------------------------------------------------------------------*/

static int transfer_file(axidma_dev_t dev, struct dma_transfer *trans, int dataLen)
{
    int rc;

    trans->output_size = dataLen * 8;
    trans->input_size = dataLen * 8;
    
    // Allocate a buffer for the input file, and read it into the buffer
    trans->input_buf = axidma_malloc(dev, trans->input_size);
    if (trans->input_buf == NULL) {
        fprintf(stderr, "Failed to allocate the input buffer.\n");
        rc = -ENOMEM;
        goto ret;
    }

    // Allocate a buffer for the output file
    trans->output_buf = axidma_malloc(dev, trans->output_size);
    if (trans->output_buf == NULL) {
        rc = -ENOMEM;
        goto free_input_buf;
    }

    // Perform the transfer
    // Perform the main transaction
    if(0 != axidma_oneway_transfer(axidma_dev, trans->output_channel, trans->output_buf, trans->output_size, true))
    {
        printf("axidma_oneway_transfer timeout.\n");
    }
    else
    {
        int i = 0;
        for(i = 0; i < dataLen; i++)
        {
            // printf("axidma_oneway_transfer buf[%04d]:%08x %08x %08x %08x %08x %08x %08x %08x .\n", i, \
            // ((char *)trans.output_buf)[i * 8 + 0], ((char *)trans.output_buf)[i * 8 + 1], ((char *)trans.output_buf)[i * 8 + 2], ((char *)trans.output_buf)[i * 8 + 3],\
            // ((char *)trans.output_buf)[i * 8 + 4], ((char *)trans.output_buf)[i * 8 + 5], ((char *)trans.output_buf)[i * 8 + 6], ((char *)trans.output_buf)[i * 8 + 7]);
        
            // u32 data_0 = ((char *)trans->output_buf)[i * 8 + 1] * 256 + ((char *)trans->output_buf)[i * 8 + 0];
            // u32 data_1 = ((char *)trans->output_buf)[i * 8 + 3] * 256 + ((char *)trans->output_buf)[i * 8 + 2];
            // u32 data_2 = ((char *)trans->output_buf)[i * 8 + 5] * 256 + ((char *)trans->output_buf)[i * 8 + 4];
            // u32 data_3 = ((char *)trans->output_buf)[i * 8 + 7] * 256 + ((char *)trans->output_buf)[i * 8 + 6];
            // printf("==> i:%05d  %05d %05d %05d %05d  \n",  i, data_0, data_1, data_2, data_3);
        } 
    }    


    
free_output_buf:
    axidma_free(dev, trans->output_buf, trans->output_size);
free_input_buf:
    axidma_free(dev, trans->input_buf, trans->input_size);
ret:
    return rc;
}

4.释放dma

//释放资源
int destoryDma()
{
    if(axidma_dev1 != NULL)
    {
        printf("destoryDma \n");
        axidma_destroy(axidma_dev1);   
    } 
    
        
    return 0;
}

5.使用流程

1.初始化DMA,

2.初始化DMA通道,

3.循环调用DMA传输函数

4.程序结束释放DMA

6.完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <time.h>
#include <pthread.h>
#include <sys/stat.h>

#include "libaxidma.h"

#define MAXLENGTH 4096
struct dma_transfer {
    int input_fd;           // The file descriptor for the input file
    int input_channel;      // The channel used to send the data
    int input_size;         // The amount of data to send
    void *input_buf;        // The buffer to hold the input data
    int output_fd;          // The file descriptor for the output file
    int output_channel;     // The channel used to receive the data
    int output_size;        // The amount of data to receive
    void *output_buf;       // The buffer to hold the output
};

void get_format_time_ms(char *str_time, int size) {
    struct tm *tm_t;
    struct timeval time;
 
    if (size < 32) {
        printf("input buff len less than 32");
    return;
    }
    gettimeofday(&time,NULL);
    tm_t = localtime(&time.tv_sec);
    if(NULL != tm_t) {
        sprintf(str_time,"%04d_%02d_%02d_%02d_%02d_%02d_%03ld",
            tm_t->tm_year+1900,
            tm_t->tm_mon+1,
            tm_t->tm_mday,
            tm_t->tm_hour,
            tm_t->tm_min,
            tm_t->tm_sec,
            time.tv_usec/1000);
    }
 
    return;

} 

axidma_dev_t axidma_dev1;
struct dma_transfer gTrans;
    
int initDma()
{
    
    // 初始化AXIDMA设备
    axidma_dev1 = axidma_init();
    if (axidma_dev1 == NULL) 
    {
        printf("Error: Failed to initialize the AXI DMA device.\n");
        return -1;
    }
     printf("Succeed to initialize the AXI DMA device.\n");

        
    return 0;
}

//释放资源
int destoryDma()
{
    if(axidma_dev1 != NULL)
    {
        printf("destoryDma \n");
        axidma_destroy(axidma_dev1);   
    } 
    
        
    return 0;
}

const array_t *tx_chans, *rx_chans;
int initInChannel()
{  
    // 如果还没有指定tx和rx通道,则获取收发通道
    tx_chans = axidma_get_dma_tx(axidma_dev1);
    
    
    if (tx_chans->len < 1) {
        printf("Error: No transmit channels were found.\n");
    }
    rx_chans = axidma_get_dma_rx(axidma_dev1);
    
    if (rx_chans->len < 1) {
        printf("Error: No receive channels were found.\n");
    }
    
     /* 如果用户没有指定通道,我们假设发送和接收通道是编号最低的通道。 */
    if (gTrans.input_channel != -1 && gTrans.output_channel != -1) 
    {
        gTrans.input_channel = tx_chans->data[0];
        gTrans.output_channel = rx_chans->data[0];
        printf("user system cfg:\n");
    }
    else
    {
        gTrans.input_channel = 0;
        gTrans.output_channel = 1;
        printf("user custom:\n");
    }

    printf("AXI DMAt File Transfer Info:\n");
    printf("\tTransmit Channel: %d\n", gTrans.input_channel);
    printf("\tReceive Channel: %d\n", gTrans.output_channel);
    printf("\tInput File Size: %d MiB\n", gTrans.input_size);
    printf("\tOutput File Size: %d MiB\n\n", gTrans.output_size);
    
    return 0;
}

/*----------------------------------------------------------------------------
 * DMA File Transfer Functions
 *----------------------------------------------------------------------------*/

static int transfer_file(axidma_dev_t dev, struct dma_transfer *trans, int dataLen)
{
    int rc;

    trans->output_size = dataLen * 8;
    trans->input_size = dataLen * 8;
    
    // Allocate a buffer for the input file, and read it into the buffer
    trans->input_buf = axidma_malloc(dev, trans->input_size);
    if (trans->input_buf == NULL) {
        fprintf(stderr, "Failed to allocate the input buffer.\n");
        rc = -ENOMEM;
        goto ret;
    }

    // Allocate a buffer for the output file
    trans->output_buf = axidma_malloc(dev, trans->output_size);
    if (trans->output_buf == NULL) {
        rc = -ENOMEM;
        goto free_input_buf;
    }

    // Perform the transfer
    // Perform the main transaction
    if(0 != axidma_oneway_transfer(axidma_dev, trans->output_channel, trans->output_buf, trans->output_size, true))
    {
        printf("axidma_oneway_transfer timeout.\n");
    }
    else
    {
        int i = 0;
        for(i = 0; i < dataLen; i++)
        {
            // printf("axidma_oneway_transfer buf[%04d]:%08x %08x %08x %08x %08x %08x %08x %08x .\n", i, \
            // ((char *)trans.output_buf)[i * 8 + 0], ((char *)trans.output_buf)[i * 8 + 1], ((char *)trans.output_buf)[i * 8 + 2], ((char *)trans.output_buf)[i * 8 + 3],\
            // ((char *)trans.output_buf)[i * 8 + 4], ((char *)trans.output_buf)[i * 8 + 5], ((char *)trans.output_buf)[i * 8 + 6], ((char *)trans.output_buf)[i * 8 + 7]);
        
            // u32 data_0 = ((char *)trans->output_buf)[i * 8 + 1] * 256 + ((char *)trans->output_buf)[i * 8 + 0];
            // u32 data_1 = ((char *)trans->output_buf)[i * 8 + 3] * 256 + ((char *)trans->output_buf)[i * 8 + 2];
            // u32 data_2 = ((char *)trans->output_buf)[i * 8 + 5] * 256 + ((char *)trans->output_buf)[i * 8 + 4];
            // u32 data_3 = ((char *)trans->output_buf)[i * 8 + 7] * 256 + ((char *)trans->output_buf)[i * 8 + 6];
            // printf("==> i:%05d  %05d %05d %05d %05d  \n",  i, data_0, data_1, data_2, data_3);
        } 
    }    


    
free_output_buf:
    axidma_free(dev, trans->output_buf, trans->output_size);
free_input_buf:
    axidma_free(dev, trans->input_buf, trans->input_size);
ret:
    return rc;
}

void GetSrcAdcDin()
{
//	u32 rxBufferPtr[1024] = {0};
	int j = 0;
	while(1)
    {
        transfer_file(axidma_dev1,&gTrans,256);
        sleep(1);
	}


}

int main(){

	initDma();
	initInChannel();
    
	GetSrcAdcDin();
    
	destoryDma();
    
	return 0;
}

  • 13
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值