RK3399 DMA控制程序
时间: 2023-11-07 13:04:46 浏览: 179
RK3399是一款基于ARM架构的处理器,它提供了DMA控制器来优化数据传输速度。下面是一个简单的RK3399 DMA控制程序的示例代码:
```c
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#define DMA_TX_CHANNEL 0
#define DMA_RX_CHANNEL 1
#define BUFFER_SIZE 1024
// 定义DMA设备和通道
static struct dma_device *dma_dev;
static struct dma_chan *dma_tx_chan;
static struct dma_chan *dma_rx_chan;
// 定义DMA缓冲区
static dma_addr_t tx_dma_handle;
static dma_addr_t rx_dma_handle;
static char *tx_buffer;
static char *rx_buffer;
// 初始化DMA设备和通道
static int dma_init(void) {
dma_dev = dmaengine_get_device("ffaa0000.dma");
if (!dma_dev) {
printk(KERN_ERR "Failed to get DMA device\n");
return -ENODEV;
}
dma_tx_chan = dma_request_chan(dma_dev, "tx");
if (!dma_tx_chan) {
printk(KERN_ERR "Failed to get TX DMA channel\n");
return -ENODEV;
}
dma_rx_chan = dma_request_chan(dma_dev, "rx");
if (!dma_rx_chan) {
printk(KERN_ERR "Failed to get RX DMA channel\n");
return -ENODEV;
}
// 分配DMA缓冲区
tx_buffer = dma_alloc_coherent(&dma_dev->dev, BUFFER_SIZE, &tx_dma_handle, GFP_KERNEL);
if (!tx_buffer) {
printk(KERN_ERR "Failed to allocate TX buffer\n");
return -ENOMEM;
}
rx_buffer = dma_alloc_coherent(&dma_dev->dev, BUFFER_SIZE, &rx_dma_handle, GFP_KERNEL);
if (!rx_buffer) {
printk(KERN_ERR "Failed to allocate RX buffer\n");
dma_free_coherent(&dma_dev->dev, BUFFER_SIZE, tx_buffer, tx_dma_handle);
return -ENOMEM;
}
return 0;
}
// 发送数据
static int dma_send_data(char *data, size_t len) {
struct dma_async_tx_descriptor *desc;
struct dma_slave_config config = {
.direction = DMA_MEM_TO_DEV,
.src_addr = tx_dma_handle,
.dst_addr = DMA_TX_CHANNEL,
.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
.src_maxburst = 1,
.dst_maxburst = 1,
};
// 设置DMA配置
dmaengine_slave_config(dma_tx_chan, &config);
// 创建DMA事务
desc = dmaengine_prep_slave_single(dma_tx_chan, data, len, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
if (!desc) {
printk(KERN_ERR "Failed to prepare TX DMA descriptor\n");
return -EIO;
}
// 提交DMA事务
dmaengine_submit(desc);
dma_async_issue_pending(dma_tx_chan);
return 0;
}
// 接收数据
static int dma_recv_data(char *data, size_t len) {
struct dma_async_tx_descriptor *desc;
struct dma_slave_config config = {
.direction = DMA_DEV_TO_MEM,
.src_addr = DMA_RX_CHANNEL,
.dst_addr = rx_dma_handle,
.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
.src_maxburst = 1,
.dst_maxburst = 1,
};
// 设置DMA配置
dmaengine_slave_config(dma_rx_chan, &config);
// 创建DMA事务
desc = dmaengine_prep_slave_single(dma_rx_chan, data, len, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
if (!desc) {
printk(KERN_ERR "Failed to prepare RX DMA descriptor\n");
return -EIO;
}
// 提交DMA事务
dmaengine_submit(desc);
dma_async_issue_pending(dma_rx_chan);
return 0;
}
// 释放DMA缓冲区和通道
static void dma_cleanup(void) {
dmaengine_terminate_all(dma_tx_chan);
dmaengine_terminate_all(dma_rx_chan);
dma_release_channel(dma_tx_chan);
dma_release_channel(dma_rx_chan);
dma_free_coherent(&dma_dev->dev, BUFFER_SIZE, tx_buffer, tx_dma_handle);
dma_free_coherent(&dma_dev->dev, BUFFER_SIZE, rx_buffer, rx_dma_handle);
}
// 模块加载函数
static int __init dma_test_init(void) {
int ret;
printk(KERN_INFO "RK3399 DMA test module loaded\n");
// 初始化DMA设备和通道
ret = dma_init();
if (ret) {
return ret;
}
// 发送和接收数据
ret = dma_send_data("Hello, world!", 13);
if (ret) {
dma_cleanup();
return ret;
}
ret = dma_recv_data(rx_buffer, BUFFER_SIZE);
if (ret) {
dma_cleanup();
return ret;
}
printk(KERN_INFO "Received data: %s\n", rx_buffer);
return 0;
}
// 模块卸载函数
static void __exit dma_test_exit(void) {
printk(KERN_INFO "RK3399 DMA test module unloaded\n");
// 释放DMA缓冲区和通道
dma_cleanup();
}
module_init(dma_test_init);
module_exit(dma_test_exit);
MODULE_LICENSE("GPL");
```
这个程序使用了DMA发送和接收数据,通过DMA传输数据可以减少CPU的负担,提高系统性能。在程序中,我们首先通过`dmaengine_get_device`函数获取DMA设备,然后通过`dma_request_chan`函数获取DMA通道。接着,我们使用`dma_alloc_coherent`函数分配DMA缓冲区,这个函数会返回一个物理地址,我们需要将这个地址传给DMA控制器。在发送和接收数据时,我们需要设置DMA配置,并使用`dmaengine_prep_slave_single`函数创建DMA事务,最后通过`dmaengine_submit`和`dma_async_issue_pending`函数提交事务。在模块卸载时,我们需要使用`dma_release_channel`和`dma_free_coherent`函数释放DMA通道和缓冲区。
阅读全文