嵌入式linux驱动学习之应用层数据如何和驱动层数据进行交互

嵌入式linux驱动学习<2>



前言

本文介绍应用层数据如何传到内核层


一、应用层数据如何和驱动层数据进行交互

(1)copy_from_user,用来将数据从用户空间复制到内核空间
copy_from_user函数的返回值定义,和常规有点不同。返回值如果成功复制则返回0,如果 不成功复制则返回尚未成功复制剩下的字节数。

/*
 * @description		: 向设备写数据 
 * @param - filp 	: 设备文件,表示打开的文件描述符
 * @param - buf 	: 要写给设备写入的数据
 * @param - cnt 	: 要写入的数据长度
 * @param - offt 	: 相对于文件首地址的偏移
 * @return 			: 写入的字节数,如果为负值,表示写入失败
 */
static ssize_t led_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{
    
    
	int retvalue;
	unsigned char databuf[1];
	unsigned char ledstat;

	retvalue = copy_from_user(databuf, buf, cnt);
	if(retvalue < 0) {
    
    
		printk("kernel write failed!\r\n");
		return -EFAULT;
	}

	ledstat = databuf[0];		/* 获取状态值 */

	if(ledstat == LEDON) {
    
    	
		led_switch(LEDON);		/* 打开LED灯 */
	} else if(ledstat == LEDOFF) {
    
    
		led_switch(LEDOFF);	/* 关闭LED灯 */
	}
	return 0;
}

(2)copy_to_user,用来将数据从用户空间复制到内核空间

/*
 * @description		: 从设备读取数据 
 * @param - filp 	: 要打开的设备文件(文件描述符)
 * @param - buf 	: 返回给用户空间的数据缓冲区
 * @param - cnt 	: 要读取的数据长度
 * @param - offt 	: 相对于文件首地址的偏移
 * @return 			: 读取的字节数,如果为负值,表示读取失败
 */
static ssize_t chrdevbase_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{
    
    
	int retvalue = 0;
	
	/* 向用户空间发送数据 */
	memcpy(readbuf, kerneldata, sizeof(kerneldata));
	retvalue = copy_to_user(buf, readbuf, cnt);
	if(retvalue == 0){
    
    
		printk("kernel senddata ok!\r\n");
	}else{
    
    
		printk("kernel senddata failed!\r\n");
	}
	
	//printk("chrdevbase read!\r\n");
	return 0;
}

二、驱动中如何操控硬件

1.和裸机操控硬件的相同点

(1)硬件物理原理不变
(2)硬件操作接口(寄存器)不变,操作硬件实际上就是操作硬件设计的寄存器
(3)硬件操作代码大体不变

2.和裸机操控硬件的不同点

(1)寄存器地址不同。原来是直接用物理地址,直接通过指针指向设计时规定的物理地址。现在需要用该物理地址在内核虚拟地址空间相对应的虚拟地址。寄存器的物理地址是CPU设计时决定的,从datasheet中查找到的。
(2)编程方法不同。裸机中习惯直接用函数指针操作寄存器地址,而kernel中习惯用封装好的io读写函数来操作寄存器,以实现最大程度可移植性。

3.物理地址和虚拟地址

提到物理地址和虚拟地址就不得提到内核中的虚拟地址映射。

内核中有2套虚拟地址映射方法:动态和静态

(1)静态映射方法的特点:
内核移植时以代码的形式硬编码,如果要更改必须改源代码后重新编译内核
在内核启动时建立静态映射表,到内核关机时销毁,中间一直有效
对于移植好的内核,你用不用他都在那里
(2)动态映射方法的特点:
驱动程序根据需要随时动态的建立映射、使用、销毁映射
映射是短期临时的

猜你喜欢

转载自blog.csdn.net/m0_57730390/article/details/125758529