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

自己有域名怎么做免费网站环球军事网

自己有域名怎么做免费网站,环球军事网,网站运营数据周报表怎么做,网店设计思路怎么写文章目录 一、概念(一)相关概念(二)字符设备框架结构(三)用户空间和内核空间数据传输1. 函数的参数对应关系 (四)字符设备相关的API1. 字符设备驱动(1)注册字…

文章目录

  • 一、概念
    • (一)相关概念
    • (二)字符设备框架结构
    • (三)用户空间和内核空间数据传输
      • 1. 函数的参数对应关系
    • (四)字符设备相关的API
      • 1. 字符设备驱动
        • (1)注册字符设备驱动
        • (2)销毁字符设备驱动
      • 2. 用户和内核数据传输
        • (1)copy_to_user
        • (2)copy_from_user
      • 3. 物理地址映射虚拟地址
        • (1)地址映射
        • (2)取消地址映射
  • 二、驱动代码示例
    • (一)查看芯片手册
      • 1. 寄存器基地址
    • (一)驱动代码
    • (二)测试

一、概念

(一)相关概念

设备号:内核识别驱动的唯一的编号,设备号由32个bit位组成

设备号(32bit)=主设备号(高12bit)+次设备号(低20bit)
主设备号:代表的是哪一类设备
次设备号:代表同类中的哪一个设备
在这里插入图片描述

(二)字符设备框架结构

在这里插入图片描述
当用户在应用层面去调用open/read/write/close函数时,操作的是设备文件;
而创建设备文件时,通过设备号把设备文件和内核层面的设备驱动联系起来,又通过file_operations操作方法结构体将函数逐个对应;
在内核层面,驱动通过操作寄存器,最后实现对硬件设备的控制

(三)用户空间和内核空间数据传输

1. 函数的参数对应关系

在这里插入图片描述
用户在应用层通过write函数将buff的内容传给内核层中mycdev_write函数中ubuf,
为了保证内核的安全性,需要通过copy_from_user函数,将ubuf的数据拷贝一份到kbuf中,通过操作kbuf来使用用户传入的数据。
read函数同理,用户在应用层通过read函数读取buf,其实在内核层面。是通过copy_to_user函数,将内核空间数据拷贝一份到kbuf,通过kbuf来传递给用户

使用*ubuf会报错:地址不允许访问

(四)字符设备相关的API

1. 字符设备驱动

(1)注册字符设备驱动
#include <linux/fs.h>int register_chrdev(unsigned int major,const char *name,const struct file_operations * fops)
功能:注册字符设备驱动; (register char device)
参数:@major:主设备号(申请到一个主设备号后,0-255的这256个次设备号会全部被分配)major > 0 用户指定主设备号,一般不使用,因为如果与系统已定义的主设备号冲突就会报错major = 0 系统动态分配主设备号@name:设备的名字@fops:操作方法结构体指针struct file_operations{int (*open) (struct inode *, struct file *);ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);int (*release) (struct inode *, struct file *);}
返回值:major > 0 ,成功返回0,失败返回错误码major = 0 ,成功返回主设备号,失败返回错误码
  • 补:cat /proc/devices 查看设备名
    在这里插入图片描述
(2)销毁字符设备驱动
#include <linux/fs.h>int unregister_chrdev(unsigned int major,const char *name)
功能:销毁字符设备驱动
参数:@major:主设备号@name:设备的名字
返回值:无

2. 用户和内核数据传输

(1)copy_to_user
#include <linux/uaccess.h>int copy_to_user(void __user volatile *to, const void *from,unsigned long n)
功能:将数据从内核空间拷贝到用户空间(在驱动的在驱动的read中使用)
参数:@to:用户空间的数据首地址@from:内核空间数据首地址@n:大小,单位是字节
返回值:成功返回0,失败返回未拷贝的字节个数
(2)copy_from_user
int copy_from_user(void *to, const void __user volatile *from,unsigned long n)
功能:将数据从用户空间拷贝到内核空间(在驱动的在驱动的write中使用)
参数:@to:内核空间的数据首地址@from:用户空间数据首地址@n:大小,单位是字节
返回值:成功返回0,失败返回未拷贝的字节个数
  • 注:两个函数都是第一个参数是拷贝到哪,第二个参数是从哪里拷贝

3. 物理地址映射虚拟地址

如果要将开发板上的LED点亮,那就必须操作LED灯对应的寄存器,寄存器的地址是物理地址。
驱动运行在3-4G的虚拟地址空间,所以没有办法直接控制LED的亮灭。如果想要在内核空间操作LED那就必须将LED灯的物理地址映射成虚拟地址,以后在内核空间操作这块虚拟地址就相当于在操作LED的物理地址。

(1)地址映射
#include <linux/io.h>void *ioremap(unsigned long phy_addr, unsigned long size)
功能:将物理地址映射成虚拟地址
参数:@phy_addr:物理地址@size:映射的大小,单位是字节
返回值:成功返回内核空间的虚拟地址,失败返回NULL
  • 注:
  • ioremap一次最多映射4k字节地址
(2)取消地址映射
void iounmap(void *virt_addr)
功能:取消地址映射
参数:@virt_addr:虚拟地址
返回值:无
  • 注:地址映射后,如果不取消映射就会造成内存泄漏

二、驱动代码示例

(一)查看芯片手册

1. 寄存器基地址

图片1

(一)驱动代码

功能需求:实现LED1,LED2,LED3交替亮1s
需求分析
LED1—PE10
LED2—PF10
LED3—PE8
GPIOE基地址—0x50006000
GPIOF基地址—0x50007000
RCC_AHB4基地址—0x50000A28
代码实现

myled.h

#ifndef __MYLED_H__
#define __MYLED_H__#define GPIOE_BASE 0x50006000
#define GPIOF_BASE 0x50007000
#define RCC        0x50000A28
typedef struct{unsigned int gpiox_0:1;unsigned int gpiox_1:1;unsigned int gpiox_2:1;unsigned int gpiox_3:1;unsigned int gpiox_4:1;unsigned int gpiox_5:1;unsigned int gpiox_6:1;unsigned int gpiox_7:1;unsigned int gpiox_8:1;unsigned int gpiox_9:1;unsigned int gpiox_10:1;unsigned int gpiox_11:1;unsigned int gpiox_12:1;unsigned int gpiox_13:1;unsigned int gpiox_14:1;unsigned int gpiox_15:1;
}bitf1_t;
typedef struct{unsigned int gpiox_0:2;unsigned int gpiox_1:2;unsigned int gpiox_2:2;unsigned int gpiox_3:2;unsigned int gpiox_4:2;unsigned int gpiox_5:2;unsigned int gpiox_6:2;unsigned int gpiox_7:2;unsigned int gpiox_8:2;unsigned int gpiox_9:2;unsigned int gpiox_10:2;unsigned int gpiox_11:2;unsigned int gpiox_12:2;unsigned int gpiox_13:2;unsigned int gpiox_14:2;unsigned int gpiox_15:2;
}bitf2_t;typedef struct{volatile bitf2_t MODER;volatile bitf1_t OTYPER;volatile bitf2_t OSPEEDR;volatile bitf2_t PUPDR;volatile bitf1_t IDR;volatile bitf1_t ODR;
}gpio_t;#define LED1 1
#define LED2 2
#define LED3 3#endif

myled.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/io.h>
#include "myled.h"#define CNAME "myled"
int major; //设备号gpio_t *gpioe;
gpio_t *gpiof;
unsigned int *rcc;int kbuf[2];
int mychrdev_open(struct inode *inode, struct file *file){pr_info("%s:%d\n",__func__,__LINE__);//将虚拟地址转换为物理地址rcc=ioremap(RCC,4);if(NULL == rcc){pr_err("RCC ioremap error");return -ENOMEM;}gpioe=ioremap(GPIOE_BASE,sizeof(gpio_t));if(NULL == gpioe){pr_err("GPIOE_BASE ioremap error");return -ENOMEM;}gpiof=ioremap(GPIOF_BASE,sizeof(gpio_t));if(NULL == gpiof){pr_err("GPIOF_BASE ioremap error");return -ENOMEM;}/***初始化LED灯***///使能时钟源*rcc |= 0x3<<4;//RCC使能GPIOE和GPIOF//PE10和PE8输出模式01gpioe->MODER.gpiox_10=1;gpioe->MODER.gpiox_8=1;gpiof->MODER.gpiox_10=1;//输出低电平gpioe->ODR.gpiox_10=0;gpioe->ODR.gpiox_8=0;gpiof->ODR.gpiox_10=0;return 0;
}
ssize_t mychrdev_read(struct file *file, char __user *ubuf, size_t size, loff_t *offset){int ret;pr_info("%s:%s:%d\n", __FILE__, __func__, __LINE__);if (size > sizeof(kbuf))size = sizeof(kbuf);ret = copy_to_user(ubuf, kbuf, size);if (ret) {pr_err("copy_to_user error\n");return -EIO;}return 0;
}
ssize_t mychrdev_write(struct file *file, const char __user *ubuf, size_t size, loff_t *offset){int ret;pr_info("%s:%s:%d\n", __FILE__, __func__, __LINE__);memset(kbuf, 0, sizeof(kbuf));if (size > sizeof(kbuf))size = sizeof(kbuf);ret = copy_from_user(kbuf, ubuf, size);if (ret) {pr_err("copy_from_user error\n");return -EIO;}switch(kbuf[0]){case LED1:kbuf[1]==1?(gpioe->ODR.gpiox_10=1):(gpioe->ODR.gpiox_10=0);break;case LED2:kbuf[1]==1?(gpiof->ODR.gpiox_10=1):(gpiof->ODR.gpiox_10=0);break;case LED3:kbuf[1]==1?(gpioe->ODR.gpiox_8=1):(gpioe->ODR.gpiox_8=0);break;}return 0;
}
int mychrdev_close(struct inode *inode, struct file *file){pr_info("%s:%d\n",__func__,__LINE__);//取消虚拟映射iounmap(rcc);iounmap(gpioe);iounmap(gpiof);return 0;
}const struct file_operations myfops = {.open=mychrdev_open,.read=mychrdev_read,.write=mychrdev_write,.release=mychrdev_close,
};static int __init mychrdev_init(void){//注册设备major = register_chrdev(0,CNAME,&myfops);if(major < 0){pr_err("register error:%d\n",major);return major;//返回错误码}pr_info("major = %d\n",major);//打印设备号return 0;
}
static void __exit mychrdev_exit(void){//注销设备unregister_chrdev(major,CNAME);
}module_init(mychrdev_init);
module_exit(mychrdev_exit);
MODULE_LICENSE("GPL");
  • 注:使用的交叉编译器版本比较老,对语法检查要求更高,要求变量只能在函数开头定义,否则报错。

(二)测试

在这里插入图片描述

  • 补:错误码 /include/uapi/asm0generic/errno-base.h
    在这里插入图片描述
http://www.shuangfujiaoyu.com/news/33487.html

相关文章:

  • 怎么检查外包做的网站搜索引擎搜索
  • 网站负责人姓名如何宣传推广
  • 什么视频网站可以做链接成全高清免费观看mv
  • 网站地图的制作网络推广技巧
  • 深圳装饰公司网站长沙seo推广公司
  • 专业做网站的顺德公司平面设计正规培训机构
  • 网站开发对比特点如何做关键词优化
  • 日本设计网站有哪些优化seo教程
  • 房地产网站建设解决方案关键词推广方法
  • 国外做logo的网站搜索引擎推广与优化
  • dedecms如何做音乐网站网络营销知识点
  • 单页网站在线生成网络营销的主要内容包括
  • 网站定制开发优点百度搜索网站
  • 建网站 西安优化是什么意思?
  • 网站建设好公司方象科技的服务范围
  • 网页设计入门与应用seo营销怎么做
  • 北京市住房和城乡建设委员会门户网站做引流的公司是正规的吗
  • 旅游在线网站开发网站的收录情况怎么查
  • 外贸独立站saas建站怎样免费建立自己的网站
  • 微信公众号h5商城网站开发重庆seo教程搜索引擎优化
  • iis 发布asp网站百度个人中心登录
  • 关于公司网站建设的申请2022今日最新军事新闻
  • 网站建设用途百度权重工具
  • 做外贸网站报价福州seo按天收费
  • 广渠门网站建设竞价排名是什么意思
  • 沈阳.....网站设计网络推广网站推广
  • wordpress站内seo宁波免费seo排名优化
  • 代码优化seo范畴有哪些
  • 如何让网站打不开 解析推广有奖励的app平台
  • 中文个人网站欣赏平台推广怎么做