led.h
#ifndef _HEAD_H #define _HEAD_H #define MAGIC 'h' #define LED_ON _IOW(MAGIC,1,int) #define LED_OFF _IOW(MAGIC,0,int) struct led_device{ dev_t devno; unsigned int led_major; struct cdev *led_cdev; struct class *led_class; struct device *led_device; }; #endif
平臺設(shè)備
dev_led.c
#include <linux/init.h> #include#include #include 'led.h' static void led_release(struct device *dev){ } static struct platform_device s5pv210_led_device_lhy = { .name = 's5pv210_led_lhy', .id = 1, .dev = { .release = led_release, //開發(fā)模式下,這個(gè)真不能少! }, }; static int __init dev_led_init(void){ platform_device_register(&s5pv210_led_device_lhy); return 0; } static void __exit dev_led_exit(void){ platform_device_unregister(&s5pv210_led_device_lhy); } module_init(dev_led_init); module_exit(dev_led_exit); MODULE_LICENSE('GPL');
平臺驅(qū)動
led_drv.c
#include#include #include //register_chrled #include //class_create/ledice_create #include //kmalloc #include //copy_to_user/copy_from_user #include //ioremap #include gpio.h> //gpio_request #include //s3c_gpio_cfgpin #include //cdev_alloc #include #include'led.h' static struct led_device *led_drv; static int led_open(struct inode *inode, struct file *file) { printk(KERN_INFO'%s()-%dn', __func__, __LINE__); s3c_gpio_cfgpin(S5PV210_GPC0(3),S3C_GPIO_OUTPUT); s3c_gpio_cfgpin(S5PV210_GPC0(4),S3C_GPIO_OUTPUT); return 0; } static ssize_t led_read(struct file *file, char __user *buf, size_t count, loff_t *offset) { printk(KERN_INFO'%s()-%dn', __func__, __LINE__); return count; } ssize_t led_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) { printk(KERN_INFO'%s()-%dn', __func__, __LINE__); return 0; } static long led_ioctl(struct file *file, unsigned int cmd, unsigned long val) { printk(KERN_INFO'%s()-%dn', __func__, __LINE__); printk(KERN_INFO'cmd=%d arg=%ldn', cmd, val); switch(cmd) { case LED_ON: gpio_set_value(S5PV210_GPC0(val),1); break; case LED_OFF: gpio_set_value(S5PV210_GPC0(val),0); break; default: break; } return 0; } //硬件操作方法 static struct file_operations led_fops={ .owner = THIS_MODULE, .open = led_open, .write = led_write, .read = led_read, .unlocked_ioctl = led_ioctl, }; static int s5pv210_led_probe(struct platform_device *pdrv){ int ret; led_drv = kmalloc(sizeof(struct led_device),GFP_KERNEL); if(led_drv==NULL){ printk(KERN_ERR'no memory malloc for fs210_ledn'); return -ENOMEM; } /*1. 動態(tài)注冊/申請主設(shè)備*/ ret=alloc_chrdev_region(&led_drv->devno,0,1,'dev_module'); if (ret < 0) { printk(KERN_ERR 'unable to get majorn'); return -EFAULT; goto out_err_1; } //從設(shè)備號中分離出主設(shè)備號 led_drv->led_major = MAJOR(led_drv->devno); /*為cdev分配空間*/ led_drv->led_cdev = cdev_alloc(); /*注冊硬件操作方法/初始化cdev*/ cdev_init(led_drv->led_cdev,&led_fops); /*注冊字符設(shè)備*/ cdev_add(led_drv->led_cdev,led_drv->devno,1); /*2. 創(chuàng)建設(shè)備類*/ led_drv->led_class=class_create(THIS_MODULE,'led_class'); if (IS_ERR(led_drv->led_class)) { printk(KERN_ERR 'class_create() failed for led_classn'); ret = -ENODATA; goto out_err_2; } /*3. 創(chuàng)建設(shè)備文件*/ led_drv->led_device=device_create(led_drv->led_class,NULL,MKDEV(led_drv->led_major,0),NULL,'led'); // /led/xxx if (IS_ERR(led_drv->led_device)) { printk(KERN_ERR 'device_create failed for led_devicen'); ret = -ENODEV; goto out_err_3; } /*申請GPC0_3,4引腳資源*/ gpio_request(S5PV210_GPC0(3),'LED1'); gpio_request(S5PV210_GPC0(4),'LED2'); return 0; out_err_3: class_destroy(led_drv->led_class); out_err_2: unregister_chrdev(led_drv->led_major,'led_module'); out_err_1: kfree(led_drv); return ret; } static int s5pv210_led_remove(struct platform_device *pdrv){ unregister_chrdev(led_drv->led_major,'led_module'); device_destroy(led_drv->led_class,MKDEV(led_drv->led_major,0)); class_destroy(led_drv->led_class); gpio_free(S5PV210_GPC0(3)); gpio_free(S5PV210_GPC0(4)); kfree(led_drv); return 0; } struct platform_device_id led_ids[]={ [0]={ .name = 's5pv210_led_lhy', .driver_data = 0, }, }; static struct platform_driver s5pv210_led_driver = { .probe = s5pv210_led_probe, .remove = s5pv210_led_remove, .driver = { .name = 's5pv210_led_lhy', .owner = THIS_MODULE, }, .id_table = led_ids, }; static int __init led_init(void) { platform_driver_register(&s5pv210_led_driver); return 0; } static void __exit led_exit(void) { platform_driver_unregister(&s5pv210_led_driver); } module_init(led_init); module_exit(led_exit); MODULE_LICENSE('GPL');
測試程序:
#include#include #include #include #include #include #include #include #include 'led.h' /* ** ./led_test on num 點(diǎn)亮LED1/2 ** ./led_test off num 熄滅LED1/2 */ int main(int argc, char *argv[]) { if (argc != 3) printf('input:< %s on led_num >or< %s off led_num>n',argv[0],argv[0]); int fd; unsigned int cmd=0; unsigned long val=0; fd=open('/dev/led', O_RDWR); if(fd<0){ perror('open failed!n'); exit(1); } if(strcmp(argv[1],'on')==0){ cmd=LED_ON; }else if(strcmp(argv[1],'off')==0){ cmd=LED_OFF; }else{ printf('err input!n'); } val = atoi(argv[2]); if(ioctl(fd,cmd,val)<0){ perror('ioctl failed!n'); exit(1); } close(fd); return 0; }
Makefile
ifeq ($(KERNELRELEASE),) KERNELDIR =/home/farsight/work/kernel/linux-3.0.8 PWD =$(shell pwd) modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules arm-none-linux-gnueabi-gcc led_test.c -o led_test cp led_drv.ko dev_led.ko led_test /opt/filesystem/s5pv210 modules_install: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install clean: rm -rf *.so *.o *.ko *test .tmp_versions *.mod.c *.order *.symvers else obj-m :=led_drv.o dev_led.o endif
上一篇:linux驅(qū)動(七)gpiolib庫詳解
下一篇:tiny210裸機(jī)第1課(啟動原理)
推薦閱讀最新更新時(shí)間:2025-05-22 12:02




設(shè)計(jì)資源 培訓(xùn) 開發(fā)板 精華推薦
- Microchip 升級數(shù)字信號控制器(DSC)產(chǎn)品線 推出PWM 分辨率和 ADC 速度業(yè)界領(lǐng)先的新器件
- 意法半導(dǎo)體STM32MP23x:突破成本限制的工業(yè)AI應(yīng)用核心
- 意法半導(dǎo)體推出用于匹配遠(yuǎn)距離無線微控制器STM32WL33的集成的匹配濾波芯片
- ESP32開發(fā)板連接TFT顯示屏ST7789跳坑記
- 如何讓ESP32支持analogWrite函數(shù)
- LGVL配合FreeType為可變字體設(shè)置字重-ESP32篇
- 使用樹莓派進(jìn)行 ESP32 Jtag 調(diào)試
- ESP32怎么在SPIFFS里面存儲html,css,js文件,以及網(wǎng)頁和arduino的通訊
- ESP32 freeRTOS使用測試
- MCP3905EV,用于計(jì)量客戶的 MCP3905 電能計(jì)量 IC 的評估板
- AS3930 演示系統(tǒng),AS3930 喚醒接收器的演示板包括一維喚醒模式檢測、虛假喚醒讀出
- 使用 ROHM Semiconductor 的 BD45291 的參考設(shè)計(jì)
- ONS321A5VGEVB:5 Vgs MOSFET 評估板
- 2022電子設(shè)計(jì)競賽省賽F題跟隨小車設(shè)計(jì)
- LTC2635-LMX10 四通道、10 位數(shù)模轉(zhuǎn)換器的典型應(yīng)用
- NCP5104SYNCBUCKGEVB:可變直流輸入、開環(huán)同步降壓評估板
- 用LED替代低效率的MR16鹵素?zé)?/a>
- DC2296A DC2209和DC2210數(shù)字溫度測量系統(tǒng)
- 【訓(xùn)練營】一條狗腿子
- 納祥科技2W 24位數(shù)字功放NX4920,可用于AI語音播報(bào)、WIFI播放器
- 常用解調(diào)器的定義和工作原理
- 從性能與網(wǎng)絡(luò)傳輸出發(fā),講講鐵威馬MAX系列為什么一騎絕塵
- 惠普選中Hailo下一代人工智能加速器,革新零售業(yè)與酒店業(yè)運(yùn)營模式
- 跨國商務(wù)溝通困局破解之道:時(shí)空壺 W4Pro 全場景應(yīng)用解析
- 從矢量降噪到雙向同傳,時(shí)空壺 W4Pro 如何重構(gòu) AI 同傳技術(shù)標(biāo)準(zhǔn)?
- LoRa+NB-IoT雙模融合,地下車庫信號盲區(qū)電梯場景等的冗余通信
- LoRa與UWB的“定位之戰(zhàn)”,成本敏感場景高精度需求的場景切割
- 時(shí)空壺X1再升級:引領(lǐng)AI同傳新時(shí)代,革新演講翻譯體驗(yàn)
- ARXML 規(guī)則下 ECU 總線通訊與 ADTF 測試方案
- 外媒提前上手三星Note9:S Pen應(yīng)用更有趣
- 聚焦四大行業(yè) 一窺華南智造
- 自動駕駛當(dāng)“貨郎” 機(jī)器人走街串巷還需跨溝邁坎
- 中國芯片發(fā)展需要"萬眾用芯" 而非“萬眾創(chuàng)芯”
- 韋爾股份“再續(xù)前緣” 擬收購北京豪威1.98%股權(quán)
- 使用ST-Link Utility去除STM32芯片讀寫保護(hù)
- STM32學(xué)習(xí)筆記:SysTick時(shí)鐘
- stm32F103的systick時(shí)間不準(zhǔn)終于找到原因了
- SysTick_Config配置systic中斷間隔時(shí)間
- STM32L0 SysTick無法進(jìn)入中斷怎么處理