当前位置: 首页 > news >正文

课工场网站建设培训免费开发个人小程序的平台

课工场网站建设培训,免费开发个人小程序的平台,dedecms 网站安全,北京app网站建设能够以字节流的形式进行访问的设备是字符设备,编写的对字符设备进行驱动的驱动顺序叫做字符设备驱动 用户层:open(设备文件) 操作方法: open 方法 …

能够以字节流的形式进行访问的设备是字符设备,编写的对字符设备进行驱动的驱动顺序叫做字符设备驱动

用户层:open(设备文件)


操作方法:

open 方法                                                                                                           当字符设备驱动注册到内核时,会从内核申请到一个设备号(32位)一个                                                                                                                        设备有两部分组成主设备号和次设备号主设备号占据高12位次设备号:标识                                                                                                                        一类设备中的一个具体的设备,占据设备号的低20位

read 方法                                                                         

write方法


编写基本的设备驱动需要解决的问题

如何注册字符设备驱动

驱动中的操作方法和管理如何实现

如何创建设备文件

应用程序中的如何回调驱动中的操作方法

如何将硬件的物理内存映射到虚拟内存

用户和内核之间如何进行数据传递 

int register_chdev(unsigned int maior,const char  *name,const struct file_operations *fops )
功能:进行字符设备驱动的注册,申请了256个设备号(0-255)
参数 :
major: >0 手动指定当前驱动的主设备号
==0 由系统内核动态分配的主设备号
name:设备名或驱动名
fops:操作方法对象指针
void unregister_cherdev(unsigned int major,const char *name)功能:进行字符设备的驱动的注销
参数Lmajor 祖册的时候得到的设备号
name :注册填写时候的设备名

字符设备驱动注册的测试案例

填写字符设备的驱动代码

创建一个驱动程序的mycdev.c 在其中的编写如下内容

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
unsigned int major;
int mycdev_open(struct inode *inode ,struct file *file)
{
printk("%s,%s:%d\n",__FILE_,__FUNC_,_LINE_);
return 0;
}
ssize_t mycdev_read(struct file *file,char __user *ubuf,size_t ,loft_t *lft)
{pprintk("%s,%s:%d\n",__FILE_,__FUNC_,_LINE_);
return 0;
}
ssize_t mycdev_write(struct file *file, const char __user *ubunf, size_t size, loff_t *lft)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);return 0;
} 
int mycdev_close(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);return 0;
} 
//定义一个操作方法结构体变量
struct file_operations fops={.open=mycdev_open,.read=mycdev_read,.write=mycdev_write,.release=mycdev_close,
};static int __init mycdev_init(void)
{//进行字符设备驱动的注册major=register_chrdev(0,"mycdev",&fops);if(major<0){printk("字符设备驱动注册失败\n");}printk("字符设备驱动注册成功 major=%d\n",major);return 0;
}
static void __exit mycdev_exit(void)
{//进行字符设备驱动的注销unregister_chrdev(major,"mycdev");}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

安装驱动的镜像,查看/proc/devices文件中,可以发现驱动被注册

为驱动手动创建一个设备文件

创建的命令:

mknod 设备文件路径+名字 设备文件类型(c/b) 主设备号 ,次设备号

编写一个应用程序,在应用程序中操作设备文件,执行查看对应的操作是否被回调

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{int fd=open("/dev/mycdev",O_RDWR);if(fd<0)
{printf("设备文件打开失败");return fd;}char buf[128]={};while(1)
{write(fd,buf,sizeof(buf));sleep(1);
}
close(fd);
return 0;}

4 用户和内核之间的数据传递

内核和用户进行数据传递的api

#include <linux /uaccess.h>
unsigned long copy_to_user(void _user *to,const void *from,unsigned long n)
功能:从内核传递一个数据给用户进程
参数
:to 用户空间保存数据buf的首地址
from: 内核空间保存数据的buf首地址
n :实际传递的数据大小
返回值 :成功返回0,失败返回没有传递成功的数据大小unsigned long copy_from_user(void _user *to,const void *from,unsigned long n)
功能:用户传递数据给内核空间
参数:
to :内核空间保存数据的buf首地址
from:用户空间保存buf的首地址
返回值 :成功返回0,失败返回没有传递成功的数据的大小
ssize_t mycdev_read(struct *file ,char _user *ubuf,size_t size,loft_t *lft)
{
unsigned long ret=copy_to_user(ubuf,kbuf,size);  
if(ret)
{
printk("copy_to_user filad\n" );
return ret;}
return 0;}
ssize_t mycdev_write(struct *file,const char _user*ubuf,size_t size,loff_t*lft)
{
unsigned long ret=copy_from_user(kbuf,ubuf,size);
if(ret)
{
printf("copy_from_user filad\n");
return ret;}
return 0;}
int main(int argc ,char const *argv[])
{
int fd=open("/dev/mycdev",O_RDWR);
if(fd<0)
{printf("设备文件打开失败\n");
return fd;}
char buf[128]="hello world";
write(fd,buf,sizeof(buf));
memset(buf,0,sizeof(buf)));
read(fd,buf,sizeof(buf));
printf("buf:%s\n",buf);
close(fd);}

物理内存的内存映射API

想要完成硬件的控制直接操作硬件的寄存器,硬件的寄存器属于物理内存,我们的驱动程序会加载到虚拟内存中,我们需要寄存器的物理内存映射成虚拟内存才能完成设备的控制

void *ioremap(phys——addr_t paddr,unsigned long size)
功能将指定大小的物理内存映射为虚拟内存
参数:
paddr :要映射的物理内存首地址数值
size :要映射的物理内存的大小
返回值
成功返回映射的虚拟内存的首地址
失败返回NULL;
void ioumap(const void __iomem *addr)
功能:取消物理内存的映射
参数:
addr :物理内存对应的首地址
返回值 :无

LED1 ->PE10

LED2->PF10

LED3->PE8

要对LED1进行控制

将PE10设置为输出模式 GPIOE_MODER[21:20]->01 0X50006000

PE10输出高低电平 GPIOE_ODR[10]  1输出高电平 

rcc_mp_ahb4enster [4]->1 使能GPIOE外设时钟 050000A28

ssize_t myled_write(struct file *file, const char __user *ubuf, size_t size, loff_t *lft)
{//printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);unsigned long ret= copy_from_user(kbuf,ubuf,size);//读取用户写入的数据if(ret){printk("copy from user filad\n");
return ret;}
if(kbuf[0]=='1')
{(*vir_odr)|=(0x1<<10);}
else if(kbuf[0]=='0')
{
(*vir_odr) &=(~(0X1)<<10);}return 0;
static int __init mycdev_init(void)
{major =register_chrdev(0,"myled",&fops);
if(major<0)
{printk("字符设备驱动祖册失败\n");}printk("字符设备驱动注册成功 major=%d\n",major);
vir_moder=ioremap(PHY_GPIOE_MODER,4);
if(vir_moder ==NULL)
{
printk("物理内存映射失败% ")
}}

http://www.dtcms.com/a/480071.html

相关文章:

  • 建筑网站翻译编辑做网站前端用什么
  • 购买网站服务如何做支出广东产品外观结构设计公司官网
  • 高斯隐马尔可夫模型:原理与应用详解
  • 吴恩达d6-DL 选择合适的策略来优化、选择模型
  • 个人做网站报价公司网站怎么维护
  • 网站建设师薪资外国网站怎么进入
  • Trae:颠覆传统开发,AI 赋能下构建新范式--发票管理系统Saas
  • 深圳网站建设培训哪家好国外网站做网上生意哪个好
  • 网站制作视频教程免费手机软件开发的模式
  • 想做网站建设wordpress谷歌字体加载慢
  • 想建立什么网站吗网络营销推广方式怎么收费
  • 公司已有网站 如何自己做推广企点qq是什么
  • 微信做淘宝优惠券但网站是怎么建设但展台设计搭建服务
  • 做网站都需要具备什么地方门户网站建设
  • 东营网站建设推广公司目字形布局结构的网站
  • 织梦企业网站源码初学网站建设
  • MySQL数据库高级特性
  • 化妆品网站建设实施背景域名除了做网站还能做什么
  • Bootstrap 进度条
  • 网站开发竞争对手分析中国建筑有限公司
  • 【Java】分割链表、回文链表、相交链表、环形链表、环形链表II、反转链表、链表的中间节点、返回链表倒数第k个节点的值、合并两个有序链表
  • 公司网站公司简介宣传夸大受处罚网站建设知名
  • 企业做网站的公司有哪些网站cms在线识别
  • 重庆网站seo分析wordpress 底部修改插件
  • 制作手机广告的网站网站推广工作计划
  • 网站策划书背景介绍响应式布局页面
  • 微信小程序怎么做网站链接官方网站英语
  • 哈尔滨哪里有做网站的电子商务官网首页
  • 随身WiFi技术深探:通信芯片/信号增益原理解析+开源方案参考!随身WiFi建议买吗?随身WiFi品牌哪个网速快信号稳定?格行随身WiFi怎么样?
  • 上海市工程信息网站安阳哪里做360网站