《嵌入式操作系统》_驱动开发_misc类设备与蜂鸣器_20261008
misc 类设备杂项设备 / Miscellaneous DeviceLinux 把所有无法归入标准大类、功能简单、零散小众的硬件统一收纳到 misc 框架下共用固定主设备号10MISC_MAJOR靠不同次设备号区分每个独立设备。适用场景蜂鸣器、看门狗、按键、LED、温度传感器、实时时钟、调试串口、虚拟控制节点等简单外设。[rootLXY210 misc]# ls CEC binder log_system s3c-jpg HPD cpu_dma_latency network_latency s3c-mfc adc device-mapper network_throughput sec-g2d alarm log_events pmem_gpu1 apm_bios log_main psaux ashmem log_radio rfkill[rootLXY210 dev]# ls buzzer -l crw-rw---- 1 0 0 10, 61 Jan 1 13:18 buzzer [rootLXY210 dev]# ls adc -l crw-rw---- 1 0 0 10, 131 Jan 1 13:18 adc核心底层原理统一主设备号 10内核提前注册主设备号 10 作为 misc 总入口所有 misc 设备共享该主号只分配独立次设备号省去单独申请主设备号的麻烦节约设备号资源。全局链表管理内核维护一条misc_list链表所有注册成功的struct miscdevice都会挂入链表用户层 open 设备时内核通过次设备号遍历链表匹配对应设备再调用其读写 /ioctl 接口。自动创建设备节点调用misc_register()注册时内核内部自动完成创建设备类/sys/class/misc→ 创建设备对象 → 在/dev/下自动生成设备文件不需要手动mknod。极简封装屏蔽 cdev 复杂操作普通字符设备需要手动申请设备号 →cdev_init→cdev_add misc 框架内部封装了全套 cdev 逻辑开发者只需要填充一个miscdevice结构体一行函数完成注册 / 注销。misc 类实例蜂鸣器驱动文件找到文件你怎么知道当前的源码中有没有蜂鸣器的驱动文件vscode在内核源码中直接搜索buzzer如果文件太多你去menuconfig中找buzzer也是可以的编译问题在menuconfig中都没有被选择这个肯定不会被编译。选择它但系统里还是没有buzzer的设备文件这个驱动的配置文件名和kconfig中的文件名不一致修改makefile中的定义文件为成功添加驱动。使用驱动该文件的open和close函数几乎什么也没干我们使用x210_pwm_ioctl去操控硬件static struct file_operations dev_fops { .owner THIS_MODULE, .open x210_pwm_open, .release x210_pwm_close, .ioctl x210_pwm_ioctl, }; static int x210_pwm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { switch (cmd) { case PWM_IOCTL_SET_FREQ: printk(PWM_IOCTL_SET_FREQ:\r\n); if (arg 0) return -EINVAL; PWM_Set_Freq(arg); break; case PWM_IOCTL_STOP: default: printk(PWM_IOCTL_STOP:\r\n); PWM_Stop(); break; } return 0; }程序文件#include stdio.h #include stdlib.h #include fcntl.h #include unistd.h #include sys/ioctl.h #include sys/stat.h #define DEVICE_NAME /dev/buzzer #define PWM_IOCTL_SET_FREQ 1 #define PWM_IOCTL_STOP 0 int main() { int fd; int ret; fd open(DEVICE_NAME, O_RDWR); if (fd 0) { perror(Failed to open buzzer device); return -1; } ret ioctl(fd, PWM_IOCTL_SET_FREQ, 10000); // Example ioctl call sleep(3); // Sleep for 3 seconds to let the buzzer sound ret ioctl(fd, PWM_IOCTL_SET_FREQ, 5000); // Example ioctl call sleep(3); // Sleep for 3 seconds to let the buzzer sound ret ioctl(fd, PWM_IOCTL_STOP); // Example ioctl call close(fd); return 0; }misc 类程序关键点内核部分misc类的创建misc_init#ifdef CONFIG_PROC_FS //是否使用proc文件系统 [rootLXY210 ]# ls /proc/ 1 4 cgroups kmsg softirqs 10 41 cmdline kpagecount stat 11 43 cpu kpageflags sys 12 44 cpuinfo loadavg sysrq-trigger 13 45 crypto locks sysvipc 14 48 devices meminfo timer_list 15 5 diskstats misc tty 16 54 driver modules uptime 17 6 execdomains mounts version 18 7 fb mtd vmallocinfo 19 73 filesystems net vmstat 2 8 fs pagetypeinfo wakelocks 20 9 interrupts partitions yaffs 3 apm iomem pvr yaffs_stats 32 asound ioports sched_debug zoneinfo 33 buddyinfo irq scsi 34 bus kallsyms self [rootLXY210 proc]# cat misc 51 network_throughput 52 network_latency 53 cpu_dma_latency 54 log_system 55 log_radio 56 log_events 57 log_main 58 binder 59 device-mapper 242 CEC 243 HPD 240 sec-g2d 254 s3c-jpg 252 s3c-mfc 60 alarm 1 psaux 0 pmem_gpu1 134 apm_bios 61 buzzer 62 ashmem 131 adc 63 rfkillmisc设备创建misc_registerint misc_register(struct miscdevice * misc) { struct miscdevice *c; dev_t dev; int err 0; //使用链表管理misc类设备 INIT_LIST_HEAD(misc-list); mutex_lock(misc_mtx); //查询次设备号是否被占用 list_for_each_entry(c, misc_list, list) { if (c-minor misc-minor) { mutex_unlock(misc_mtx); return -EBUSY; } } //使用位图的方法自动分配次设备号 if (misc-minor MISC_DYNAMIC_MINOR) { int i find_first_zero_bit(misc_minors, DYNAMIC_MINORS); if (i DYNAMIC_MINORS) { mutex_unlock(misc_mtx); return -EBUSY; } misc-minor DYNAMIC_MINORS - i - 1; set_bit(i, misc_minors); } //合成主、次设备号 dev MKDEV(MISC_MAJOR, misc-minor); //创建设备 misc-this_device device_create(misc_class, misc-parent, dev, misc, %s, misc-name); if (IS_ERR(misc-this_device)) { int i DYNAMIC_MINORS - misc-minor - 1; if (i DYNAMIC_MINORS i 0) clear_bit(i, misc_minors); err PTR_ERR(misc-this_device); goto out; } /* * Add it to the front, so that later devices can override * earlier defaults */ //将设备节点添加到内核misc链表中 list_add(misc-list, misc_list); out: mutex_unlock(misc_mtx); return err; }驱动工程师实现部分设备文件的读写接口//自定义设备文件操作结构体 static struct file_operations dev_fops { .owner THIS_MODULE, .open x210_pwm_open, .release x210_pwm_close, .ioctl x210_pwm_ioctl, }; //建立miscdevice结构体 static struct miscdevice misc { //自动分配次设备号 .minor MISC_DYNAMIC_MINOR, //这里的name只是用来记录 .name DEVICE_NAME, //关键自定义文件操作结构体 .fops dev_fops, }; static int __init dev_init(void) { int ret; //将信号量初始化为1也就成了互斥锁 init_MUTEX(lock); //注册misc设备 ret misc_register(misc); //申请引脚 /* GPD0_2 (PWMTOUT2) */ ret gpio_request(S5PV210_GPD0(2), GPD0); if(ret) printk(buzzer-x210: request gpio GPD0(2) fail); //设置为上拉 s3c_gpio_setpull(S5PV210_GPD0(2), S3C_GPIO_PULL_UP); //特殊模式设置为1也就是输出模式 s3c_gpio_cfgpin(S5PV210_GPD0(2), S3C_GPIO_SFN(1)); //输出值为0 gpio_set_value(S5PV210_GPD0(2), 0); printk (x210 DEVICE_NAME initialized\n); return ret; }硬件操作相关代码// TCFG0在Uboot中设置这里不再重复设置 // Timer0输入频率Finputpclk/(prescaler11)/MUX1 // 66M/16/16 // TCFG0 tcnt (pclk/16/16)/freq; // PWM0输出频率Foutput Finput/TCFG0 freq static void PWM_Set_Freq( unsigned long freq ) { unsigned long tcon; unsigned long tcnt; unsigned long tcfg1; struct clk *clk_p; unsigned long pclk; //unsigned tmp; //设置GPD0_2为PWM输出 s3c_gpio_cfgpin(S5PV210_GPD0(2), S3C_GPIO_SFN(2)); //读寄存器 tcon __raw_readl(S3C2410_TCON); tcfg1 __raw_readl(S3C2410_TCFG1); //mux 1/16 tcfg1 ~(0xf8); tcfg1 | (0x48); __raw_writel(tcfg1, S3C2410_TCFG1); //获取时钟频率pclk clk_p clk_get(NULL, pclk); pclk clk_get_rate(clk_p); tcnt (pclk/16/16)/freq; __raw_writel(tcnt, S3C2410_TCNTB(2)); __raw_writel(tcnt/2, S3C2410_TCMPB(2));//占空比为50% tcon ~(0xf12); tcon | (0xb12); //disable deadzone, auto-reload, inv-off, update TCNTB0TCMPB0, start timer 0 __raw_writel(tcon, S3C2410_TCON); tcon ~(212); //clear manual update bit __raw_writel(tcon, S3C2410_TCON); } void PWM_Stop( void ) { //将GPD0_2设置为input s3c_gpio_cfgpin(S5PV210_GPD0(2), S3C_GPIO_SFN(0)); }内核中的互斥锁另一个进程访问到已经上锁的资源时会在此休眠进入等待序列直到锁被释放解决竞争状态mutex_lock(misc_mtx);mutex_unlock(misc_mtx);int misc_register(struct miscdevice * misc) { struct miscdevice *c; dev_t dev; int err 0; INIT_LIST_HEAD(misc-list); //建立互斥锁防止多线程访问时修改同一资源 mutex_lock(misc_mtx); list_for_each_entry(c, misc_list, list) { if (c-minor misc-minor) { mutex_unlock(misc_mtx); return -EBUSY; } }防止竞争的手段原子访问这次操作一下就能完成不可以被打断自旋锁一种忙等锁线程抢锁失败时不放弃 CPU、不进入休眠原地循环自旋反复查询锁状态直到锁被释放。 底层本质原子操作 CAS 实现靠原子指令保证锁状态修改不冲突。互斥锁只能计数一次只能被打开一次信号量通过计数来避免竞争

相关新闻

Firstmate × Grok 后台通知监督协议:用跟踪后台任务守护待机周期

Firstmate × Grok 后台通知监督协议:用跟踪后台任务守护待机周期

【免费下载链接】firstmate Talk to one agent. Ship with a crew. 项目地址: https://gitcode.com/gh_mirrors/fi/firstmate 点击查看 免费下载 导读 本文讲解 Firstmate 在 Grok 主表面(primary surface)上的监督协议:当 Grok…

2026/10/9 5:54:55 阅读更多 →
AI编程实战:从精准提示词到一键部署全流程

AI编程实战:从精准提示词到一键部署全流程

1. AI编程的真相:你会干的活越多,它才能干得越多最近圈子里有个挺有意思的现象:聊AI编程的人分成两类。一类是刚接触时兴冲冲,觉得有了AI工具自己从此告别写代码;另一类是用了两个月之后,默默把AI生成的代码…

2026/10/9 5:54:55 阅读更多 →
洛谷P5732杨辉三角:二维数组递推、组合数陷阱与DP思维启蒙

洛谷P5732杨辉三角:二维数组递推、组合数陷阱与DP思维启蒙

1. 从一道入门题说起:为什么所有算法新手都绕不开杨辉三角洛谷P5732,题目全称是【深基5.习7】杨辉三角,属于洛谷"深入基础"系列第五章的练习题。这个系列是给刚学完语法、开始接触算法的人准备的,题目本身不难&#xff…

2026/10/9 5:53:55 阅读更多 →

最新新闻

等保2.0数据库测评通关指南:MySQL/Oracle/SQL Server/PostgreSQL/Redis五类数据库加固与自查

等保2.0数据库测评通关指南:MySQL/Oracle/SQL Server/PostgreSQL/Redis五类数据库加固与自查

简介:这份作业指导书面向数据库安全测评人员、等保合规工程师及运维人员,系统梳理了MySQL、Oracle、SQL Server、Postgres、Redis五类主流数据库在等保测评中的实操要点,帮助读者快速定位各数据库的测评项与查询方法。资源包内含1个docx文档&…

2026/10/9 11:09:59 阅读更多 →
基于LoRA微调的中文医疗问答机器人实战:从数据构造到量化部署

基于LoRA微调的中文医疗问答机器人实战:从数据构造到量化部署

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 11:09:59 阅读更多 →
EtherCAT与FSoE协议栈深度解析:从报文结构到安全配置实战

EtherCAT与FSoE协议栈深度解析:从报文结构到安全配置实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 11:09:59 阅读更多 →
pstack-claude:命令行级本地化Claude集成方案

pstack-claude:命令行级本地化Claude集成方案

1. 项目概述:pstack-claude 是什么,它解决的是哪类真实开发痛点?pstack-claude 这个名字乍看像一个工具组合词,但拆开来看,“pstack”是 Linux 系统中一个真实存在的诊断命令,用于打印指定进程的调用栈&…

2026/10/9 11:09:59 阅读更多 →
pstack诊断Claude工具卡死:从调用栈定位Node.js阻塞问题

pstack诊断Claude工具卡死:从调用栈定位Node.js阻塞问题

1. “pstack-claude”不是工具名&#xff0c;而是调试现场的命名习惯你搜“pstack-claude”&#xff0c;大概率是在终端里敲下pstack <pid>后&#xff0c;突然发现进程名里带claude字样——比如claude-code-server、claude-desktop或某个本地部署的codex服务进程。这时候…

2026/10/9 11:09:59 阅读更多 →
力扣模拟题刷题指南:从拆解思路到经典题单与面试策略

力扣模拟题刷题指南:从拆解思路到经典题单与面试策略

做力扣模拟题&#xff0c;最容易被低估&#xff0c;也最容易翻车。我刷了三百多道题之后回头看&#xff0c;真正在面试现场把我救下来的&#xff0c;往往不是那些需要灵光一现的DP难题&#xff0c;而是老老实实按题目要求一步步模拟的“体力活”。今天这篇就把模拟题这件事聊透…

2026/10/9 11:08:57 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题&#xff0c;隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题&#xff0c;排查到最后发现是ZonedDateTime序列化后时区丢了&#xff0c;用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问&#xff1a;办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好&#xff0c;问题是工作场景经常要在几处环境之间来回切换&#xff0c;每次都先登录跳板机再层层代理&#xff0c;实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及&#xff0c;但真正动手搭过一套能跑起来的 Agent 系统的人都知道&#xff0c;从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地&#xff0c;从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 10:11:06 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →