上一篇文章我們介紹了字元裝置驅動程式的架構,本篇文章我們將操作真實的硬體---LED。
作者:滄海獵人 出處:http://blog.csdn.net/embedded_hunter 轉載請註明出處 嵌入式技術交流QQ群:179012822
一、實驗環境
開發機環境
作業系統:ubuntu 9.10
交叉編譯環境:arm-linux-gcc 4.2.2 ,安裝位置 /usr/local/arm/4.3.2/
6410板子核心源碼路徑:/work/linux-2.6.36.2-v1.05/
目標板環境:OK6410-A linux2.6.36
二、實驗原理
控制LED是最簡單的一件事情,我們學習LED驅動程式,就相當於學習其他程式設計語言是的“hello world”程式一樣,是一個入門的程式。
學習驅動程式,必須要對硬體有所瞭解,接下來看幾個與硬體相關的材料。
OK6410 LED原理圖
OK6410 LED原理圖
從上面的原理圖可以得知,LED與CPU引腳的串連方法如下,低電平點亮。
LED1 -GPM0
LED2 -GPM1
LED3 -GPM2
LED4 -GPM3
從資料手冊可以找到相應的控制方法。這裡我們以LED1為例,介紹一下LED1的操作方法,其他的類似,請大家自行分析。
通過上面可以得知,需要先將GPM0設定為輸出方式。將相應的寄存器進行配置。
然後將GPMDAT寄存器的第0位置0燈亮,置1燈滅。
三、實驗步驟
1、編寫驅動程式
driver_led.c
#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <asm/uaccess.h> /* copy_to_user,copy_from_user */#include <linux/miscdevice.h> #include <linux/pci.h> #include <mach/map.h> #include <mach/regs-gpio.h> #include <mach/gpio-bank-m.h> #include <plat/gpio-cfg.h>#define LED_MAJOR 240int led_open (struct inode *inode,struct file *filp){unsigned tmp; tmp = readl(S3C64XX_GPMCON); tmp = (tmp & ~(0x7U<<1))|(0x1U); writel(tmp, S3C64XX_GPMCON); printk("#########open######\n");return 0;}ssize_t led_read (struct file *filp, char __user *buf, size_t count,loff_t *f_pos){printk("#########read######\n");return count;}ssize_t led_write (struct file *filp, const char __user *buf, size_t count,loff_t *f_pos){char wbuf[10];unsigned tmp; printk("#########write######\n");copy_from_user(wbuf,buf,count);switch(wbuf[0]){case 0: //offtmp = readl(S3C64XX_GPMDAT); tmp |= (0x1U); writel(tmp, S3C64XX_GPMDAT);break;case 1: //ontmp = readl(S3C64XX_GPMDAT); tmp &= ~(0x1U); writel(tmp, S3C64XX_GPMDAT);break;default :break;}return count;}int led_release (struct inode *inode, struct file *filp){printk("#########release######\n");return 0;}struct file_operations led_fops ={.owner = THIS_MODULE,.open = led_open,.read = led_read,.write = led_write,.release = led_release,};int __init led_init (void){int rc;printk ("Test led dev\n");rc = register_chrdev(LED_MAJOR,"led",&led_fops);if (rc <0){printk ("register %s char dev error\n","led");return -1;}printk ("ok!\n");return 0;}void __exit led_exit (void){unregister_chrdev(LED_MAJOR,"led");printk ("module exit\n");return ;}module_init(led_init);module_exit(led_exit);
Makefile檔案
obj-m := driver_led.oKDIR :=/work/linux-2.6.36.2-v1.05/all:make -C $(KDIR) M=$(shell pwd) modulesinstall:cp driver_led.ko /tftpboot/clean:make -C $(KDIR) M=$(shell pwd) clean
2、編寫測試程式
test.c
#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>int main (void){int fd;char buf[10]={0,1};fd = open("/dev/my_led",O_RDWR);if (fd < 0){printf ("Open /dev/my_led file error\n");return -1;}while(1){write(fd,&buf[0],1);sleep(1);write(fd,&buf[1],1);sleep(1);}close (fd);return 0;}
3、編譯驅動程式與測試程式
編譯驅動程式
#make
將驅動程式放到tftp的工作目錄 /tftpboot
#make install
編譯測試程式
#arm-linux-gcc test.c -o test
將測試程式放到tftp的工作目錄 /tftpboot
#cp test /tftpboot
4、將程式下載到開發板
將開發板的IP地址修改,與主機在同一個網段。確保PC的tftp服務開啟。
下載程式到開發板
SMDK6410# tftp -l /lib/modules/2.6.36.2/driver_led.ko -r driver_led.ko -g 192.168.1.111 192.168.1.111為伺服器IP
SMDK6410# tftp -l test -r test -g 192.168.1.111
5、測試
載入驅動 #insmod /lib/modules/2.6.36.2/driver_led.ko
建立裝置檔案 #mknod /dev/my_led c 240 0
測試 ./test
[root@FORLINX6410]# ./test
此時可以看到OK6410板子上的LED0在閃爍。
卸載驅動 #rmmod driver_led
從上面的結果我們可以看到,當使用者調用相應的檔案操作函數時,驅動程式中的相應的函數也會被調用。
大家可以修改相應程式,測試一下其他的情況。
作者:滄海獵人 出處:http://blog.csdn.net/embedded_hunter 轉載請註明出處 嵌入式技術交流QQ群:179012822
備忘: 本驅動使用了最基本的核心功能,可能操作方法與你看過的其他驅動程式不太一樣,尤其註冊字元裝置的函數。 沒關係,我們會一步一步介紹相關的其他函數。