百篇博客系列篇.本篇为:
v67.xx 鸿蒙内核源码分析(字符设备篇) | 字节为单位读写的设备 | 51 .c .h .o
/
上的文件系统 | 51 .c .h .o设备(device): 是提供输入或输出功能的一种载体,其包括物理设备(对实际存在的物理硬件的抽象)例如,键盘是一种输入设备,硬盘是输入和输出设备。也包括虚拟设备(不依赖于特定的物理硬件,仅是内核自身提供的模拟/虚拟功能). 例如:虚拟控制台是输入和输出设备。每个设备都对应一个文件(设备文件),这些设备文件统一放在一个公共位置/dev
下,通过设备文件(或称设备节点)来使用驱动程序操作设备。
设备按照存取方式的不同,分为两类:
字符设备: 字符设备按字符处理。最明显的例子是键盘,其中每个键在设备上生成一个字符。还有鼠标,每一个动作或按钮点击都会发送一个字符到 /dev/mouse 设备。字符设备可理解为商品零售商,可以一件一件的卖,卖的细自然就卖的少.
块设备:以更大的块读取数据的存储设备,如IDE硬盘也叫机械硬盘(/dev/hd)、SCSI硬盘也叫固态硬盘(/dev/sd) 和 CD-ROM (/dev/cdrom) 是块设备。输入输出与块设备的交互处理数据块,允许大量数据来回移动提高效率。块设备可理解为商品批发商,必须一箱一箱的卖,卖的粗但吞吐量大.
字符设备还是块设备的定义属于内核设备访问层,与实际物理设备的特性无必然联系。设备访问层下面是驱动程序,存取方式取决于驱动程序是否支持,也可以同时支持两种方式访问物理设备,是块设备还是字符设备由使用者(往往是内核)决定。
鸿蒙系统中常见的字符设备如下:
/dev/mem 物理内存的全镜像。可以用来直接存取物理内存。 /dev/kmem 内核看到的虚拟内存的全镜像。其访问的是虚拟内存而不是物理内存。 /dev/null 空设备。也叫黑洞设备,任何写入都将被直接丢弃(但返回"成功");任何读取都将得到EOF(文件结束标志)。 /dev/port 存取I/O端口 /dev/zero 零流源。任何写入都将被直接丢弃(但返回"成功");任何读取都将得到无限多的二进制零流。 /dev/full 满设备。任何写入都将失败,并把errno设为ENOSPC(没有剩余空间);任何读取都将得到无限多的二进制零流。 这个设备通常被用来测试程序在遇到磁盘无剩余空间错误时的行为。 /dev/random 真随机数发生器。以背景噪声数据或硬件随机数发生器作为熵池,读取时会返回小于熵池噪声总数的随机字节。 若熵池空了,读操作将会被阻塞,直到收集到了足够的环境噪声为止。建议用于需要生成高强度密钥的场合。 [注意]虽然允许写入,但企图通过写入此文件来"预存"随机数是徒劳的,因为写入的数据对输出并无影响。 /dev/urandom 伪随机数发生器。更快,但是不够安全。仅用于对安全性要求不高的场合。 即使熵池空了,读操作也不会被阻塞,而是把已经产生的随机数做为种子来产生新的随机数。 [注意]虽然允许写入,但企图通过写入此文件来"预存"随机数是徒劳的,因为写入的数据对输出并无影响。 /dev/aio 异步I/O通知接口 /dev/kmsg 任何对该文件的写入都将作为printk的输出;而读取则得到printk的输出缓冲区内容。
/dev/mem
是一个字符设备, 源文件是 kernel/drivers/char/mem/src/mem.c, 这个设备文件是专门用来读写物理地址用的。里面的内容是所有物理内存的地址以及内容信息。通常只有root用户对其有读写权限。利用 mmap
和/dev/mem
建立起直接读写系统物理内存的渠道。利用/dev/mem
和mmap
导出系统物理地址,免去了用户虚拟地址到内核逻辑地址的繁琐拷贝,提升效率。 //文件和线性区的映射关系 static ssize_t MemMap(struct file *filep, LosVmMapRegion *region) { #ifdef LOSCFG_KERNEL_VM size_t size = region->range.size; PADDR_T paddr = region->pgOff << PAGE_SHIFT; VADDR_T vaddr = region->range.base; LosVmSpace *space = LOS_SpaceGet(vaddr); if ((paddr >= SYS_MEM_BASE) && (paddr < SYS_MEM_END)) { return -EINVAL; } /* Peripheral register memory adds strongly ordered attributes */ region->regionFlags |= VM_MAP_REGION_FLAG_STRONGLY_ORDERED; if (space == NULL) { return -EAGAIN; }//映射 if (LOS_ArchMmuMap(&space->archMmu, vaddr, paddr, size >> PAGE_SHIFT, region->regionFlags) <= 0) { return -EAGAIN; } #else UNUSED(filep); UNUSED(region); #endif return 0; } // vfs 接口实现 static const struct file_operations_vfs g_memDevOps = { MemOpen, /* open */ MemClose, /* close */ MemRead, /* read */ MemWrite, /* write */ NULL, /* seek */ NULL, /* ioctl */ MemMap, /* mmap */ #ifndef CONFIG_DISABLE_POLL NULL, /* poll */ #endif NULL, /* unlink */ }; // 注册/dev/mem 的驱动程序 int DevMemRegister(void) { return register_driver("/dev/mem", &g_memDevOps, 0666, 0); /* 0666: file mode */ }
TTY 是 Teletype 或 Teletypewriter 的缩写,原来是指电传打字机,后来这种设备逐渐键盘和显示器取代。不管是电传打字机还是键盘显示器,都是作为计算机的终端设备存在的,所以 TTY 也泛指计算机的终端(terminal)设备,一般分成以下几种
/dev/rtc 实时时钟(Real Time Clock)
RtcOpen 获取RTC设备驱动句柄 RtcClose 释放RTC设备驱动句柄 RtcReadTime 读RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒 RtcWriteTime 写RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒 RtcReadAlarm 读RTC报警时间信息 RtcWriteAlarm 写RTC报警时间信息 RtcRegisterAlarmCallback 注册报警超时回调函数 RtcAlarmInterruptEnable 使能/去使能RTC报警中断 RtcGetFreq 读RTC外接晶振频率 RtcSetFreq 配置RTC外接晶振频率 RtcReset RTC复位 RtcReadReg 读用户自定义寄存器 RtcWriteReg 写用户自定义寄存器
/dev/i2c-0 第1个 I2C 适配器 ... /dev/i2c-n 第n-1个 I2C 适配器
I2cOpen 打开I2C控制器 I2cClose 关闭I2C控制器 I2cTransfer 自定义传输,I2c消息传输接口
SpiOpen 获取SPI设备句柄 SpiClose 释放SPI设备句柄 SpiRead 读取指定长度的数据 SpiWrite 写入指定长度的数据 SpiTransfer SPI数据传输接口 SpiSetCfg 根据指定参数,配置SPI设备 SpiGetCfg 获取SPI设备配置参数
/dev/ttyS0 第1个UART串口(Serial port) ... /dev/ttyS200 第199个UART串口
串口设备是终端设备的一种,采用 /dev/ttySn 或 /dev/tts/n 来表示,分别对应于windows系统下的COM1、COM2等。若要向一个端口发送数据,可以在命令行上把标准输出重定向到这些特殊文件名上即可,例如,在命令行提示符下键入:echo test > /dev/ttyS1会把单词”test”发送到连接在ttyS1(COM2)端口的设备上。
UART(Universal Asynchronous Receiver/Transmitter)通用异步收发传输器,UART 作为异步串口通信协议的一种,工作原理是将传输数据的每个字符一位接一位地传输。是在应用程序开发过程中使用频率最高的数据总线。
UART应用比较广泛,常用于输出打印信息,也可以外接各种模块,如GPS、蓝牙等。
UART 串口的特点是将数据一位一位地顺序传送,只要 2 根传输线就可以实现双向通信,一根线发送数据的同时用另一根线接收数据。UART 串口通信有几个重要的参数,分别是波特率、起始位、数据位、停止位和奇偶检验位,对于两个使用 UART 串口通信的端口,这些参数必须匹配,否则通信将无法正常完成。UART 串口传输的数据格式如下图所示:
UART接口定义了操作UART端口的通用方法集合,包括获取、释放设备句柄、读写数据、获取和设置波特率、获取和设置设备属性。
鸿蒙UART驱动API接口功能介绍
UartOpen UART获取设备句柄 UartClose UART释放设备句柄 UartRead 从UART设备中读取指定长度的数据 UartWrite 向UART设备中写入指定长度的数据 UartGetBaud UART获取波特率 UartSetBaud UART设置波特率 UartGetAttribute UART获取设备属性 UartSetAttribute UART设置设备属性 UartSetTransMode UART设置传输模式
/dev/lcd 液晶(LCD)显示屏
Touch(触摸芯片)是 UI 设计中进行人机交互重要的一部分,一个完整的 UI 设计应该包括输入信息和输出信息,LCD 等屏幕设备负责显示输出,那么 Touch 设备就负责触点信息采集作为信息输入。
Touch 设备与主机通讯一般都是采用 I2C 总线协议来进行数据交互,所以一个 Touch 设备,就是一个标准的 I2C 从设备,而且为了提高接收 Touch 数据的实时性,触摸芯片都会提供中断支持,当有触摸事件(抬起,按下,移动)发生时,会触发中断通知 MCU 有触摸事件。主机可以通过中断回调函数去读取触摸点信息。
Touchscreen器件的硬件接口相对简单,根据PIN脚的属性,可以简单分为如下三类:
Touchscreen驱动用于驱动触摸屏使其正常工作,该驱动主要完成如下工作:对触摸屏驱动IC进行上电、配置硬件管脚并初始化其状态、注册中断、配置通信接口(I2C或SPI)、设定input相关配置、下载及更新固件等操作。
鸿蒙基于input驱动模型开发touchscreen器件驱动。Input驱动模型基于HDF驱动框架、PLATFORM接口、OSAL接口进行开发,向上对接规范化的驱动接口HDI(Hardware Driver Interface)层,通过Input-HDI层对外提供硬件能力,即上层input service可以通过HDI接口层获取相应的驱动能力,进而操控touchscreen等输入设备。
基于HDF驱动框架的input驱动模型
/dev/biometric/sensor0/fingerprint 第1个设备的第1个指纹传感器 /dev/biometric/sensor0/iris 第1个设备的第1个虹膜传感器 /dev/biometric/sensor0/retina 第1个设备的第1个视网膜传感器 /dev/biometric/sensor0/voiceprint 第1个设备的第1个声波传感器 /dev/biometric/sensor0/facial 第1个设备的第1个面部传感器 /dev/biometric/sensor0/hand 第1个设备的第1个手掌传感器 /dev/biometric/sensor1/fingerprint 第2个设备的第1个指纹传感器 /dev/biometric/sensor2/fingerprint 第3个设备的第1个指纹传感器
Sensor(传感器)是物联网重要的一部分,Sensor 之于物联网”就相当于“眼睛之于人类"。人类如果没有了眼睛就看不到这大千的花花世界,对于物联网来说也是一样。
如今随着物联网的发展,已经有大量的 Sensor 被开发出来供开发者选择了,如:加速度计(Accelerometer)、磁力计(Magnetometer)、陀螺仪(Gyroscope)、气压计(Barometer/pressure)、湿度计(Humidometer)等。这些传感器,世界上的各大半导体厂商都有生产,虽然增加了市场的可选择性,同时也加大了应用程序开发的难度。因为不同的传感器厂商、不同的传感器都需要配套自己独有的驱动才能运转起来,这样在开发应用程序的时候就需要针对不同的传感器做适配,自然加大了开发难度。
为了降低应用开发的难度,增加传感器驱动的可复用性, 鸿蒙Sensor(传感器)驱动模块为上层Sensor服务系统提供稳定的Sensor基础能力API,包括Sensor列表查询、Sensor启停、Sensor订阅及去订阅,Sensor参数配置等功能;基于HDF(Hardware Driver Foundation)驱动框架开发的Sensor驱动模型,实现跨操作系统迁移,器件差异配置等功能。
鸿蒙Sensor驱动模型图
/dev/watchdog 看门狗(CONFIG_WATCHDOG) /dev/watchdogs/0 第一只看门狗 ... /dev/watchdogs/n 第n-1只看门狗
硬件看门狗(watchdog timer)是一个定时器,其定时输出连接到电路的复位端。在产品化的嵌入式系统中,为了使系统在异常情况下能自动复位,一般都需要引入看门狗。
当看门狗启动后,计数器开始自动计数,在计数器溢出前如果没有被复位,计数器溢出就会对 CPU 产生一个复位信号使系统重启(俗称 “被狗咬”)。系统正常运行时,需要在看门狗允许的时间间隔内对看门狗计数器清零(俗称“喂狗“),不让复位信号产生。如果系统不出问题,程序能够按时“喂狗”。一旦程序跑飞,没有“喂狗”,系统“被咬” 复位。
鸿蒙看门狗 API接口功能介绍
WatchdogOpen 打开看门狗设备 WatchdogClose 关闭看门狗设备 WatchdogStart 启动看门狗 WatchdogStop 停止看门狗 WatchdogSetTimeout 设置看门狗超时时间 WatchdogGetTimeout 获取看门狗超时时间 WatchdogGetStatus 获取看门狗状态 WatchdogFeed 清除看门狗定时器(喂狗)
v08.xx 鸿蒙内核源码分析(总目录) | 百万汉字注解 百篇博客分析 | 51 .c .h .o
百万汉字注解 >> 精读鸿蒙源码,中文注解分析, 深挖地基工程,大脑永久记忆,四大码仓每日同步更新< gitee | github | csdn | coding >
百篇博客分析 >> 故事说内核,问答式导读,生活式比喻,表格化说明,图形化展示,主流站点定期更新中< 51cto | csdn | harmony | osc >
QQ群:790015635 | 入群请填: 666
原创不易,欢迎转载,但请注明出处.
|