我正在尝试编写一个内核驱动程序来管理物理上连续和可DMA的内存的一些内存块(我正在使用,kmalloc()因为这些只是DMA流).要将某些功能提取到用户空间,这个内存将mmap()使用自己的实现来编辑mmap().我一直在使用Linux设备驱动程序以及在Google中显示的不良示例作为我的主要信息来源.
我mmap()(my_mmap()现在称之为)需要在内核中注册.它似乎是使用a执行此操作的唯一有效方法struct file_operations,但这需要为其创建字符设备和物理位置.我不想那样做.我只想为用户空间应用程序创建一个虚拟地址来访问内存缓冲区,而不是创建任何文件来映射内存缓冲区.这可能吗?
我确实发现帧缓冲区也有一个与mmap()实现相同的结构,但这太过分了.这和它增加了更多的未知数.
据我所知,只要我对失去的灵活性感到满意,my_mmap()就可以完成繁重的工作remap_pfn_range().否则我将不得不实现一个本地nopages()并使用a注册它struct vm_operations_struct.它是否正确?
我想知道从dma写入数据的内存中读取是否安全?
我有一个带有adc设置的stm32F1,可以连续执行转换并使用dma将数据传输到ram缓冲区.我知道我可以使用adc中断安全地访问缓冲区,但是如何从非中断上下文访问缓冲区呢?如果我尝试从dma写的相同位置读取数据,数据是否会被破坏?
我尝试使用来自自定义内核驱动程序的 DMAengine API 来执行分散-聚集操作。我有一个连续的存储区域作为源极和我想要通过在几个分布式缓冲器以复制其数据散布表结构。DMA 控制器是支持 DMAengine API 的PL330 控制器(请参阅PL330 DMA 控制器)。
我的测试代码如下:
在我的驱动程序头文件 ( test_driver.h) 中:
#ifndef __TEST_DRIVER_H__
#define __TEST_DRIVER_H__
#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/scatterlist.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/of_dma.h>
#define SG_ENTRIES 3
#define BUF_SIZE 16
#define DEV_BUF 0x10000000
struct dma_block {
void * data;
int size;
};
struct dma_private_info {
struct sg_table sgt;
struct dma_block * blocks;
int nblocks;
int dma_started;
struct dma_chan * dma_chan;
struct dma_slave_config dma_config; …Run Code Online (Sandbox Code Playgroud) 我使用的是 stm32f40x 微控制器 (UC),我必须使用其内部闪存来存储一些数据。写操作,如你所知,非常慢,占用UC很长时间。所以我想到了 DMA,这里是问题:
是否可以使用DMA将数据从SRAM传输到FLASH?
感谢您的时间。
在 PCIe 配置中,设备具有专用地址,并且它们以对等模式相互发送数据 - 每个设备都可以在需要时写入,并且交换机会注意正确地转发数据。不需要有一个“总线主控”来决定数据何时以及如何传输。
DMA 在这样的配置中如何发挥作用?对我来说,DMA 似乎是一个过时的功能,在 PCIe 配置中不需要它。每个设备都可以将数据发送到主存储器,或从中读取数据 - 显然主存储器在此类操作中始终是“从属设备”。
或者 DMA 是否还有其他一些我所缺少的功能?
先感谢您!
我想问一下,在以下情况下,STM32 中的 DMA SPI rx 将如何表现。我有一个名为 A 的指定(例如)96 字节数组,用于存储从 SPI 接收到的数据。我打开对每个字节进行操作的循环 SPI DMA,配置为 96 字节。是否有可能,当 DMA 将填充我的 96 字节数组时,传输完成中断将关闭,以快速将 96 字节数组复制到另一个 - B,然后循环 DMA 将开始写入 A(并破坏保存在 B 中的数据) ? 我想通过 USB 将数据从 B 快速传输(每次我从 B 中的 A 获取新数据时)到 PC。
我只是在想如何通过 USB 将 STM32 的连续数据流 SPI 传输到 PC,因为我认为每隔一定时间通过 USB 传输的 96 字节数据块比通过 STM32 将实时 SPI 流传输到 USB 更容易?我不知道这甚至可能
我已经开始阅读有关内存映射IO的内容,而且我在理解这些概念时遇到了一些困难
这是我到目前为止所理解的:
每个进程都有一个虚拟地址空间.内存映射文件在虚拟地址空间中分配一个特定的地址范围,映射到物理内存上的相同地址.这样,磁盘控制器在
内存上完成的所有写操作(通过DMA)都将反映到进程中,无需任何额外的复制.(在非内存映射文件的情况下,CPU必须将内容复制到进程的缓冲区).
我怀疑:
我的理解是否正确?
如果有多个进程试图对文件进行mmap并且没有可用于直接映射的连续内存块,会发生什么?
我正在尝试使用DMA将数据发送到SPI1.然后SPI1将控制DAC以进行电压更新.
使用的芯片是STM32F407.因此,相应的频道/流是:channel3/stream5,如参考手册中所示.但是,当DMA使能时,SPI1-> DR中不显示任何数据,示波器中没有显示结果.
当SPI1-> DR由软件写入时,SPI工作正常.谁能帮忙看看发生了什么?代码如下:
uint16_t DACData[1];
void InitDMA(void)
{
DMA_InitTypeDef DMA_InitStructure;
DMA_Cmd(DMA2_Stream2, DISABLE);
while (DMA2_Stream2->CR & DMA_SxCR_EN);
//SPI1 Tx DMA
DMA_DeInit(DMA2_Stream5);
DMA_StructInit(&DMA_InitStructure);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); //Init DMA clock
DMA_InitStructure.DMA_Channel = DMA_Channel_3;//SPI1 Tx
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->DR); //Set the SPI1 Tx
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&DACData; //Set the memory location
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; //
DMA_InitStructure.DMA_BufferSize = 1; //Define the number of bytes to send
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //Normal mode (not circular)
DMA_InitStructure.DMA_Priority …Run Code Online (Sandbox Code Playgroud) 正如我们所知,分散列表收集了物理上分散在内存中的内存,但实际上是连续的.当与DMA通信时,它为DMA提供了一个抽象的内存视图,因为这是物理上连续的内存.
怎么scatterlist处理这个?它是一种保持在内的链表scatterlist吗?
例如,如果要使用DMA传输4000字节的数据,因为数据在物理上是连续的,分散列表如何使其连续?scatterlist实现将使用分配4000字节的数据Kmalloc来确保它获得物理上连续的内存?还是会创建一个链表?
注意:这里我的查询不是关于SG表,而是关于单个分散列表
让我们说我们想要保存4000字节物理上不连续的内存的数据
struct scatterlist sg,
sg_init_one(&sg,data,4000)
Run Code Online (Sandbox Code Playgroud)
现在,这个sg如何解决这个问题?
memory-management linux-device-driver linux-kernel dma iommu