Memory and IO access

Outline

  • LINUX memory management
  • Memory access
  • I/O memory provider
  • Mapping device addresses to user space
  • Static mapping of I/O memory
  • DMA

1 LINUX memory management

  1. User space 0~3GB kernel space
  2. 3~4GB user space of each process is completely independent and irrelevant, and user processes have different page tables.
  3. The kernel space is mapped by the kernel and will not change with the process.
  4. User programs need system calls to access kernel space.
  5. When the physical memory of the system is greater than 4GB, you need to use CPU extended paging (CPU support is required).

2 memory access

2.1 user space memory dynamic application

char *p = (char *)malloc(SIZE);
if(p==NULL)
	return 0;
function(p);
...
free(p);
p=NULL;

2.2 kernel space memory dynamic application

1 void *kmalloc (size_t size,int flags);
flags mainly include:
GFP_ If there are no idle pages available for application, kernel will sleep. Therefore, it cannot be used when interrupting context or holding spin lock.
GFP_ATOMIC returns if there is no free page available for application. It can be used when interrupting the context or holding a spin lock.
Release: kfree(void *p);
2 get_free_pages series, which allocates memory in pages, is rarely used.
3 void *vmalloc(unsigned long size);
Suitable for allocating large memory.
Release: void vfree(void *p);
4 memory pool - used by the operating system itself.

2.3 relationship between virtual address and physical address

1 virtual address to physical address

unsigned long virt_to_phys(volatile void *address);

2 physical address to virtual address

unsigned long phys_to_virt (volatile void *address);

Virtual address usually = physical address - a value + 3GB (in kernel space)

unsigned long l=virt_to_phys((volatile void *)S3C2410_GPBDAT);
unsigned long l=phys_to_virt((volatile void *)0x56000010);

Specifically, any register always traces its virtual address. See mini2440 driver notes_ su .txt_ seven

3 I/O ports and I/O memory providers

3.1 I/O port access function - ARM, PowerPC, etc. do not provide I/O space. Not applicable.
3.2 I/O memory (since 2.6.12, the following two methods are generally used to read and write registers)
Method 1: use the system defined API to access the defined virtual address

 static inline u32 __raw_readl(const volatile void __iomem *addr)
 static inline void __raw_writel(u32 b, volatile void __iomem *addr);

For example:__raw_readl(S3C2410_GPFCON);
       __raw_writel(0x12,S3C2410_GPFDAT);
    (The function is defined in 2.6.32 include/asm-generic/io.h)

Method 2: use the ioremap() function to map the physical address of the device to the virtual address, and then access it directly. as

#define rGPFCON (*((volatile unsigned  *)(ioremap((volatile unsigned *)0x56000050,4))))
regval = rGPFCON;  read
rGPFCON = regval;  write

The virtual address obtained using ioremap() should be released by iounmap().

3.3 check whether the I/O memory to be applied is available.

 void request_mem_region(unsigned start,unsigned long len,char *name);
 void release_mem_region(unsigned start,unsigned long len);

If the application is successful, it is marked as used, and other drivers will fail if they want to apply again.

In fact, the general special registers can be accessed by everyone, so there is no need to check whether the I/O memory to be applied is available. Only space dedicated to resources is needed.

4 map device address to user space

Implement the mmap() function, so that the user space can directly access the physical address of the device---- The device used to display the adapter class.
Function prototype in driver:

Int (*mmap) (struct file *,struct vm_area_struct*);

Implementation mechanism (see code listing 11.8 for more details):
1 create page table
2 fill VM_ area_ VM in struct_ operations_ Struct pointer

Static mapping of I/O memory

Static mapping from physical address to virtual address of peripheral I/O memory. Use map_desc structure.

struct map_desc {
	unsigned long virtual;  //Virtual address
	unsigned long physical;//Physical address
	unsigned long length;//size
	unsigned int type;//type
};

Please refer to / arch/arm/mach-s3c2440/mach-smdk2440.c

DMA

DMA is a hardware mechanism that allows bidirectional data transmission between peripherals and system memory without the participation of CPU.
Cache is the CPU's cache for memory.
When the DMA destination address overlaps with the cache object, it is easy to make the cache data inconsistent with the data in the main memory. Therefore, the cache function within the destination address range of DMA should be prohibited.

1 allocate / release a write merged DMA buffer

 void *dma_alloc_writecombine(struct device *dev,size_t size,dma_addr_t *handle,gfp_t gfp);

Where: the function returns the bus address of DMA buffer through the parameter handle
struct device: used to describe the hierarchical relationship between device related information devices, as well as the relationship between devices, buses and drivers.

gfp Generally GFP_KERNEL
 void *dma_free_writecombine(struct device *dev,size_t size,void *cpuaddr,dma_addr_t *);
For example: fbi->screen_base = dma_alloc_writecombine(sfb->dev, size,						  &map_dma, GFP_KERNEL);

Parameter interpretation

A = dma_alloc_writecombine(B,C,D,GFP_KERNEL);
A: The virtual starting address of memory, which is used by the kernel to operate the allocated memory
B: struct device pointer, which can be specified in platform initialization, mainly DMA_ For mask, refer to framebuffer
C: Actual allocated size, incoming dma_map_size is enough
D: dma can use the returned memory physical address.
Therefore, A and D correspond one-to-one, but A is the virtual address and D is the physical address.
2 apply / release DMA channel

int request_dma(unsigned int dmanr, const char *device_id);
void free_dma(unsigned int dmanr);

For example: err = request_dma(chn, deviceID)

DMA usage process in Linux

Tags: Linux

Posted on Mon, 22 Nov 2021 08:28:20 -0500 by XxDeadmanxX