代码示例_ioctl
2025-02-07 来源:cnblogs
//头文件
#include #include #include #include #include #include #include #include #define LED_NUM_ON _IOW('L',0x1122,int) #define LED_NUM_OFF _IOW('L',0x3344,int) #define LED_ALL_ON _IO('L',0x1234) #define LED_ALL_OFF _IO('L',0x5678) //面向对象编程----设计设备的类型 struct s5pv210_led{ unsigned int major; struct class * cls; struct device * dev; int data; }; struct s5pv210_led *led_dev; volatile unsigned long *gpco_conf; volatile unsigned long *gpco_data; //实现设备操作接口 int led_open(struct inode *inode, struct file *filp) { printk('--------^_^ %s------------n',__FUNCTION__); //将对应的管脚设置为输出 *gpco_conf &= ~(0xff<<12); //19--12清0 *gpco_conf |= 0x11<<12; //19---12赋值:00010001 return 0; } ssize_t led_write(struct file *filp, const char __user *buf, size_t size, loff_t *flags) { int ret; printk('--------^_^ %s------------n',__FUNCTION__); //应用空间数据转换为内核空间数据 ret = copy_from_user(&led_dev->data,buf,size); if(ret != 0){ printk('copy_from_user error!n'); return -EFAULT; } if(led_dev->data){ //点灯 *gpco_data |= 0x3<<3; }else{ //灭灯 *gpco_data &= ~(0x3<<3); } return size; } long led_ioctl(struct file *filp, unsigned int cmd , unsigned long args) { int num = args+2; printk('--------^_^ %s------------n',__FUNCTION__); switch(cmd){ case LED_NUM_ON: //将某个灯点亮 if(num != 3 && num != 4) return -EINVAL; else *gpco_data |= 0x1 << num; break; case LED_NUM_OFF: //将某个灯点灭掉 if(num != 3 && num != 4) return -EINVAL; else *gpco_data &= ~(0x1 << num); break; case LED_ALL_ON: //两个灯同时亮 *gpco_data |= 0x3<<3; break; case LED_ALL_OFF: //两个灯同时灭 *gpco_data &= ~(0x3<<3); break; default: printk('unknow cmd!n'); } return 0; } int led_close(struct inode *inode, struct file *filp) { printk('--------^_^ %s------------n',__FUNCTION__); //灭灯 *gpco_data &= ~(0x3<<3); return 0; } static struct file_operations fops = { .open = led_open, .write = led_write, .unlocked_ioctl = led_ioctl, .release = led_close, }; //加载函数和卸载函数 static int __init led_init(void) //加载函数-----在驱动被加载时执行 { int ret; printk('--------^_^ %s------------n',__FUNCTION__); //0,实例化设备对象 //参数1 ---- 要申请的空间的大小 //参数2 ---- 申请的空间的标识 led_dev = kzalloc(sizeof(struct s5pv210_led),GFP_KERNEL); if(IS_ERR(led_dev)){ printk('kzalloc error!n'); ret = PTR_ERR(led_dev); return -ENOMEM; } //1,申请设备号 #if 0 //静态申请主设备号 led_dev->major = 256; ret = register_chrdev(led_dev->major,'led_drv',&fops); if(ret < 0){ printk('register_chrdev error!n'); return -EINVAL; } #else //动态申请主设备号 led_dev->major = register_chrdev(0,'led_drv',&fops); if(led_dev->major < 0){ printk('register_chrdev error!n'); ret = -EINVAL; goto err_kfree; } #endif //2,创建设备文件-----/dev/led1 led_dev->cls = class_create(THIS_MODULE,'led_cls'); if(IS_ERR(led_dev->cls)){ printk('class_create error!n'); ret = PTR_ERR(led_dev->cls); goto err_unregister; } led_dev->dev = device_create(led_dev->cls,NULL,MKDEV(led_dev->major,0),NULL,'led'); if(IS_ERR(led_dev->dev)){ printk('device_create error!n'); ret = PTR_ERR(led_dev->dev); goto err_class; } //3,硬件初始化----地址映射 gpco_conf = ioremap(0xE0200060,8); gpco_data = gpco_conf+1; return 0; err_class: class_destroy(led_dev->cls); err_unregister: unregister_chrdev(led_dev->major,'led_drv'); err_kfree: kfree(led_dev); return ret; } static void __exit led_exit(void) //卸载函数-----在驱动被卸载时执行 { printk('--------^_^ %s------------n',__FUNCTION__); device_destroy(led_dev->cls,MKDEV(led_dev->major,0)); class_destroy(led_dev->cls); unregister_chrdev(led_dev->major,'led_drv'); kfree(led_dev); } //声明和认证 module_init(led_init); module_exit(led_exit); MODULE_LICENSE('GPL'); #include #include #include #include #include #include #include #define LED_NUM_ON _IOW('L',0x1122,int) #define LED_NUM_OFF _IOW('L',0x3344,int) #define LED_ALL_ON _IO('L',0x1234) #define LED_ALL_OFF _IO('L',0x5678) int main(void) { int fd; fd = open('/dev/led',O_RDWR); if(fd < 0){ perror('open'); exit(1); } //闪灯 while(1){ //第一个灯闪 ioctl(fd,LED_NUM_ON,1); sleep(1); ioctl(fd,LED_NUM_OFF,1); sleep(1); //第二个灯闪 ioctl(fd,LED_NUM_ON,2); sleep(1); ioctl(fd,LED_NUM_OFF,2); sleep(1); //两个灯同时闪 ioctl(fd,LED_ALL_ON); sleep(1); ioctl(fd,LED_ALL_OFF); sleep(1); } close(fd); return 0; } #指定内核源码路径 KERNEL_DIR = /home/farsight/s5pv210/kernel/linux-3.0.8 CUR_DIR = $(shell pwd) MYAPP = test all: #让make进入内核源码编译,同时将当前目录中的c程序作为内核模块一起编译 make -C $(KERNEL_DIR) M=$(CUR_DIR) modules arm-none-linux-gnueabi-gcc -o $(MYAPP) $(MYAPP).c clean: #删除上面编译生成的文件 make -C $(KERNEL_DIR) M=$(CUR_DIR) clean rm -rf $(MYAPP) install: cp *.ko $(MYAPP) /opt/rootfs/drv_module #指定当前目录下哪个文件作为内核模块编 obj-m = led_drv.o
上一篇:代码示例_数据传递
下一篇:代码示例_中断下半部
- s5pv210启动debian出错提示bash: cannot set terminal process group (-1): Inappropriate ioctl for device
- ioctl和unlock_ioctl的区别
- Linux2.6.32驱动笔记(4)ioctl方法解析及mini2440-led驱动实现
- ARM驱动开发之ioctl函数的使用
- 2416开发记录四: ioctl与unlocked_ioctl区别
- 基于μClinux的触摸屏软硬件关键技术分析
- 支持实时流媒体协议的MPEG-4 IP摄像机方案
- 基于μClinux的触摸屏设计与关键技术分析
- C语言高级第一节杂谈
- ARM启动流程
- 六大全新产品系列推出,MCX A微控制器家族迎来创新
- 意法半导体全新STM32C5系列,重新定义入门级微控制器性能与价值,赋能万千智能设备
- 模组复用与整机重测在SRRC、CCC、CTA/NAL认证中的实践操作指南
- 有源晶振与无源晶振的六大区别详解
- 英飞凌持续巩固全球微控制器市场领导地位
- 使用 Keil Studio for Visual Studio Code开发 STM32 设备
- 从控制到系统:TI利用边缘AI重塑嵌入式MCU的边界
- 蓝牙信道探测技术原理与开发套件实践
- Microchip 推出生产就绪型全栈边缘 AI 解决方案,赋能MCU和MPU实现 智能实时决策
- LoRa、LoRaWAN、NB-IoT与4G DTU技术对比及工业无线方案选型分析




