xilinx|xilinx pl330 DMA驱动访问bram
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define DEVICE_NAME "dma_test"
unsigned char dmatest_major;
static struct class *dmatest_class;
struct dma_chan *chan;
//bus address
dma_addr_t dma_src;
dma_addr_t dma_dst;
//virtual address
char *src = https://www.it610.com/article/NULL;
char *dst = NULL ;
struct dma_device *dev;
struct dma_async_tx_descriptor *tx = NULL;
enum dma_ctrl_flags flags;
dma_cookie_t cookie;
static volatile void __iomem *axi_reg_base = NULL;
#define AXI_REG_BASEADDR
0x43C00000
#define AXI_REG_SIZE
(0x100)
#define READ_LEN
1*1024
//When dma transfer finished,this function will be called.
void dma_callback_func(void)
{
int i;
for (i = 0;
i < READ_LEN;
){
printk("%08x ",*(&dst[i]));
if(i%64 == 0) printk("\r\n");
i+=4;
}
}
int dmatest_open(struct inode *inode, struct file *filp)
{
return 0;
}
int dmatest_release(struct inode *inode, struct file *filp)
{
return 0;
}
static ssize_t dmatest_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
int ret = 0;
//alloc a desc,and set dst_addr,src_addr,data_size.
//tx = dev->device_prep_dma_memcpy(chan, dma_dst, dma_src, READ_LEN, flags);
tx = dmaengine_prep_slave_single(chan, dma_dst, READ_LEN, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!tx){
printk(KERN_INFO "Failed to prepare DMA memcpy");
}
tx->callback = dma_callback_func;
//set call back function
tx->callback_param = NULL;
cookie = tx->tx_submit(tx);
//submit the desc
if (dma_submit_error(cookie)){
printk(KERN_INFO "Failed to do DMA tx_submit");
}
dma_async_issue_pending(chan);
//begin dma transfer
return ret;
}
static ssize_t dmatest_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)
{
int ret = 0;
return ret;
}
static const struct file_operations dmatest_fops = {
.owner = THIS_MODULE,
.read = dmatest_read,
.write = dmatest_write,
.open = dmatest_open,
.release = dmatest_release,
};
int dmatest_init(void)
{
int i;
dma_cap_mask_t mask;
//the first parameter 0 means allocate major device number automatically
dmatest_major = register_chrdev(0,DEVICE_NAME,&dmatest_fops);
if (dmatest_major < 0)
return dmatest_major;
//create a dmatest class
dmatest_class = class_create(THIS_MODULE,DEVICE_NAME);
if (IS_ERR(dmatest_class))
return -1;
//create a dmatest device from this class
device_create(dmatest_class,NULL,MKDEV(dmatest_major,0),NULL,DEVICE_NAME);
axi_reg_base = ioremap(AXI_REG_BASEADDR,AXI_REG_SIZE);
if (axi_reg_base == NULL) {
//release_mem_region(TB0219_START, TB0219_SIZE);
return -ENOMEM;
}
iowrite32(0x1027,axi_reg_base);
udelay(100);
iowrite32(0x1027,axi_reg_base);
//alloc READ_LENB src memory and dst memory
src = https://www.it610.com/article/dma_alloc_coherent(NULL, READ_LEN, &dma_src, GFP_KERNEL);
printk(KERN_INFO "src = https://www.it610.com/article/0x%x, dma_src = 0x%x/n",src, dma_src);
dst = dma_alloc_coherent(NULL, READ_LEN, &dma_dst, GFP_KERNEL);
printk(KERN_INFO "dst = 0x%x, dma_dst = 0x%x\n",dst, dma_dst);
for (i = 0;
i < READ_LEN;
i++){
*(src + i) = i;
}
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
//direction:memory to memory
//dma_cap_set(DMA_MEMCPY, mask);
//direction:memory to memory
chan = dma_request_channel(mask,NULL,NULL);
//request a dma channel
printk(KERN_INFO "dma channel id = %d\n",chan->chan_id);
flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
dev = chan->device;
struct dma_slave_config conf;
int status;
memset(&conf, 0, sizeof(conf));
conf.direction= DMA_DEV_TO_MEM;
conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
conf.src_addr= 0x42000000;
conf.src_maxburst= 8;
status = dmaengine_slave_config(chan, &conf);
if(status)
{
printk("DMA config for rx failed. %d\n", status);
}
dmatest_read(NULL,NULL,0,NULL);
return 0;
}
void dmatest_exit(void)
{
unregister_chrdev(dmatest_major,DEVICE_NAME);
//release major device number
device_destroy(dmatest_class,MKDEV(dmatest_major,0));
//destroy globalmem device
class_destroy(dmatest_class);
//destroy globalmem class
//free memory and dma channel
dma_free_coherent(NULL, READ_LEN, src, &dma_src);
dma_free_coherent(NULL, READ_LEN, dst, &dma_dst);
dma_release_channel(chan);
if(axi_reg_base) iounmap(axi_reg_base);
}
module_init(dmatest_init);
module_exit(dmatest_exit);
MODULE_LICENSE("GPL");
推荐阅读
- 造了一个|造了一个 protoc-gen-fieldmask 插件
- 转换匹配患者记录,看Amazon Lake Formation FindMatches显神通!
- 2022 Android 进阶学习RoadMap!
- Android-例子|初学Android实现打电话的功能-使用Intent和AndroidManifset.xml中加入权限
- STM32CubeMX配置SDIO模式(非DMA方式)
- stm32F4 配置串口+DMA 接收不定长数据 串口空闲中断
- STM32的USART1用DMA方式发送与接收
- STM32F072从零配置工程-串口DMA实现
- STM32F072从零配置工程-基于HAL库的串口UART_DMA配置
- STM32|STM32 USART DMA发送 中断接收