啊啦。。很久沒有更新博客了。node
恩最近在作畢業設計是和openwrt相關的。linux
而後本身在學校論壇淘了一塊二手的友善之臂mini2440開發板ubuntu
今天早上成功刷如linux,而後開始學習數組
PART 1markdown
恩,是開發環境之類的吧。數據結構
我是用的ubuntu。恩。app
這裏是一個前輩的學習計劃,我以爲不錯的 http://blog.csdn.net/yaozhenguo2006/article/details/6909410框架
安裝環境的搭建http://blog.csdn.net/yaozhenguo2006/article/details/6766458函數
在加上友善之臂給的資料,很容易就跑起來linux。學習
PART 2
恩。因而
而後進入驅動調用和驅動開發學習
把交叉編譯好的文件放入開發板中:http://blog.163.com/lihom_1987@126/blog/static/114844863201182594144423/
這裏是led驅動程序的源代碼
/* 源碼:友善之臂 註釋:pipicold */ //////////////////////////////// /* miscdivice.h: 在Linux驅動中把沒法歸類的五花八門的設備定義爲混雜設備(用miscdevice結構體表述)。 miscdevice共享一個主設備號MISC_MAJOR(即10),但次設備號不一樣。 全部的miscdevice設備造成了一個鏈表,對設備訪問時內核根據次設備號查找對應的miscdevice設備, 而後調用其file_operations結構中註冊的文件操做接口進行操做。 在內核中用struct miscdevice表示miscdevice設備, 而後調用其file_operations結構中註冊的文件操做接口進行操做。 miscdevice的API實如今drivers/char/misc.c中。 */ #include <linux/miscdevice.h>//這裏是複雜設備的頭文件 #include <linux/delay.h>//延遲 #include <asm/irq.h>//中斷 #include <mach/regs-gpio.h> //機器相關的gpio頭文件 #include <mach/hardware.h> //應該也是機器相關文件 #include <linux/kernel.h> //linux內核頭文件 #include <linux/module.h> //驅動模塊必須要加的個頭文件 #include <linux/init.h> #include <linux/mm.h> #include <linux/fs.h>//文件系統 #include <linux/types.h> #include <linux/delay.h> #include <linux/moduleparam.h>//模塊頭文件 #include <linux/slab.h> #include <linux/errno.h> #include <linux/ioctl.h> //io控制。。I/O control #include <linux/cdev.h> #include <linux/string.h> #include <linux/list.h> #include <linux/pci.h> #include <linux/gpio.h> #include <asm/uaccess.h> #include <asm/atomic.h> /*unistd.h 是 C 和 C++ 程序設計語言中提供對 POSIX 操做系統 API 的訪問功能的頭文件的名稱。(from 百度百科) 對於類 Unix 系統,unistd.h 中所定義的接口一般都是大量針對系統調用的封裝(英語:wrapper functions), 如 fork、pipe 以及各類 I/O 原語(read、write、close 等等)。 */ #include <asm/unistd.h> #define DEVICE_NAME "leds" //自定義的設備名字「leds」 static unsigned long led_table [] = { S3C2410_GPB(5), //S3C2410_GPB定義在regs-gpio.h中,regs-gpio.h應該是與平臺相關的各類寄存器的定義 S3C2410_GPB(6), S3C2410_GPB(7), S3C2410_GPB(8), }; static unsigned int led_cfg_table [] = { S3C2410_GPIO_OUTPUT, //也是定義在regs-gpio.h中,吧gpio設置爲輸出模式 S3C2410_GPIO_OUTPUT, S3C2410_GPIO_OUTPUT, S3C2410_GPIO_OUTPUT, }; static int sbc2440_leds_ioctl( struct inode *inode, //爲何會多一個inode的緣由在這裏:http://blog.csdn.net/freechao/article/details/8439681, struct file *file, //他們同屬於一個指針大概是這麼個意思 /* file、inode在應用層和驅動層之間的聯繫 在: http://blog.csdn.net/dreaming_my_dreams/article/details/8272586 另外這個設備由於是miscdevice設備(複雜設備),因此主設備號一直都是10。 關於查看設備號的命令:ls -l | grep leds 在本來是大小的那一欄就會顯示主,從設備號,用逗號分割。 */ unsigned int cmd, unsigned long arg) { switch(cmd) { case 0: case 1: if (arg > 4) { return -EINVAL; } s3c2410_gpio_setpin(led_table[arg], !cmd); return 0; default: return -EINVAL; } } /* 這裏是文件的數據結構,恩liunx把全部設備看成一個文件來看 */ static struct file_operations dev_fops = { .owner = THIS_MODULE, .ioctl = sbc2440_leds_ioctl, }; //miscdevice的數據結構 static struct miscdevice misc = { .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .fops = &dev_fops, }; static int __init dev_init(void) { int ret; int i; for (i = 0; i < 4; i++) { //這裏就是用來設置gpio口的 s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]); //這句話是把這三個gpio口都清爲低電平? s3c2410_gpio_setpin(led_table[i], 0); } //註冊一個miscdevice ret = misc_register(&misc); //關於printk的用法問題之後再說 printk (DEVICE_NAME"\tinitialized\n"); return ret; } static void __exit dev_exit(void) { 註銷設備 misc_deregister(&misc); } //註冊module和註銷module時用的函數 module_init(dev_init); module_exit(dev_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("FriendlyARM Inc.");
加上了本身的註釋這個程序的設備是在負責設備之下的。試着寫一個本身的主設備
1 /* 2 write by pipicold 3 4 */ 5 #include <stidio.h> //linux內核部分 6 #include <linux/kernel.h> 7 #include <linux/module.h>//模塊 8 #include <linux/init.h> 9 #include <linux/fs.h>//文件系統 10 #include <linux/moduleparam.h> 11 #include <linux/types.h> 12 #include <linux/errno.h> 13 #include <linux/ioctl.h> 14 #include <linux/cdev.h> 15 #include <linux/string.h> 16 #include <linux/gpio.h> 17 #include <linux/gfp.h>//分配內存空間用 18 //平臺相關部分 19 #include <mach/regs-gpio.h> 20 #include <mach/hardware.h> 21 22 //彙編相關 23 #include <asm/unistd.h> 24 25 26 27 //定義驅動設備名字 28 #define DEVICE_NAME "pipicoldled" 29 #define DEVICE_MAJOR 97 30 #define DEVICE_MINOR 0 31 32 33 struct cdev cdev;//字符設備驅動結構體 34 35 36 37 //定義led的設置數組 38 static unsigned long led_table[]={ 39 S3C2410_GPB(5); 40 S3C2410_GPB(6); 41 S3C2410_GPB(7); 42 S3C2410_GPB(8); 43 } 44 45 static unsigned int led_config[]={ 46 S3C2410_GPIO_OUTPUT; 47 S3C2410_GPIO_OUTPUT; 48 S3C2410_GPIO_OUTPUT; 49 S3C2410_GPIO_OUTPUT; 50 } 51 //控制函數,這個led只須要控制就行了不須要打開什麼的 52 ssize_t pipicoldled_ioctl( 53 struct inode *inode, 54 struct file * file, 55 unsigned int cmd, 56 unsigned long arg 57 ) 58 { 59 switch(cmd){ 60 61 case 0://do nothing, 62 case 1: 63 if (arg>4){ 64 65 printk ("I only have 3 leds..T_T"); 66 return 0; 67 } 68 s3c2410_gpio_setpin(led_table[arg],!cmd); 69 default : 70 printk("what do you say?"); 71 return 0; 72 73 } 74 } 75 //爲了框架完整我把open,close,read,write都寫出來 76 ssize_t pipicoldled_open( 77 struct inode * inode, 78 struct file * file 79 ) 80 { 81 //open函數只須要寫文件命令就好 82 printk("you open mydriver"); 83 84 } 85 86 ssize_t pipicoldled_close( 87 struct inode * inode, 88 struct file * file 89 ) 90 { 91 //close函數只須要寫文件命令就好 92 printk("you close mydriver"); 93 94 } 95 96 ssize_t pipicoldled_close( 97 struct inode * inode, 98 struct file * file 99 ) 100 { 101 //close函數只須要寫文件命令就好 102 printk("you close mydriver"); 103 104 } 105 106 ssize_t pipicoldled_read( 107 struct file * file, 108 char *buf, 109 size_t count 110 ) 111 { 112 //http://blog.csdn.net/hjhcs121/article/details/7460738 113 printk("you pipicoldled_read"); 114 115 } 116 117 ssize_t pipicoldled_write( 118 struct file * file, 119 char *buf, 120 size_t count 121 ) 122 { 123 //http://blog.csdn.net/hjhcs121/article/details/7460738 124 printk("you pipicoldled_write"); 125 126 } 127 128 struct file_operations pipiocld_fops={ 129 owner:THIS_MODULE, 130 open:pipicoldled_open, 131 read:pipicoldled_read, 132 write:pipicoldled_write, 133 ioctl:pipicoldled_ioctl, 134 close:pipicoldled_close, 135 }; 136 137 static int __int pipicold_int(void){ 138 139 int ret= -ENODEV; 140 int delay; 141 int i; 142 143 144 145 dev_t dev;//初始化設備,設備號由MKDEV()函數生成 146 /* 147 a) 分配並註冊主設備號和次設備號 148 b) 初始化表明設備的struct結構體:scull_dev 149 c) 初始化互斥體init_MUTEX(本筆記不整理) 150 d) 初始化在內核中表明設備的cdev結構體,最主要是將該設備與file_operations結構體聯繫起來。 151 */ 152 153 154 for (i = 0; i < 4; i++) { 155 //這裏就是用來設置gpio口的 156 s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]); 157 //這句話是把這三個gpio口都清爲低電平? 158 s3c2410_gpio_setpin(led_table[i], 0); 159 } 160 /* 161 對於手動給定一個主次設備號,使用如下函數: 162 int register_chrdev_region(dev_t first, unsigned int count, char *name) 163 164 對於動態分配設備號,使用如下函數: 165 int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name) 166 */ 167 dev=MKDEV(DEVICE_MAJOR,DEVICE_MINOR); 168 169 /*獲取一個或多個設備編號來使用 170 若是分配成功進行, register_chrdev_region 的返回值是 0. 171 出錯的狀況下, 返回一個負的錯誤碼, 你不能存取請求的區域. 172 */ 173 ret=register_chrdev_region(dev,1,DEVICE_NAME); 174 if (ret<0){ 175 176 printk("can't get major \n"); 177 return ret; 178 179 } 180 181 //爲自定義的設備結構申請空間 182 /*在linux/gfp.h中定義的一個宏,是分配內核空間的內存時的一個標誌位。 183 這個標誌位分配內存的一個選項,GFP_KERNEL是內核內存分配時最經常使用的,無內存可用時可引發休眠。 184 */ 185 cdev=kmalloc(sizeof(struct cdev),GFP_KERNEL); 186 187 if(!cdev){ 188 189 ret=-ENOMEM//沒有內存空間 190 return ret; 191 192 } 193 //將新申請的空間清零 194 memset(cdev,0,sizeof(struct cdev)); 195 //初始化一個字符驅動 結構 196 197 /* 198 void cdev_init(struct cdev *cdev, const struct file_operations *fops) 199 { 200 memset(cdev, 0, sizeof *cdev); 201 INIT_LIST_HEAD(&cdev->list); 202 kobject_init(&cdev->kobj, &ktype_cdev_default); 203 cdev->ops = fops; 204 } 205 */ 206 cdev_init(&cdev,&pipiocld_fops); 207 cdev.owner=THIS_MODULE; 208 //在內核中添加字符驅動 209 //int cdev_add(struct cdev* dev,dev_t num,unsigned int count) 210 //count是應該和該設備關聯的設備編號的數量.count常常取1,可是在某些狀況下,會有多個設備編號對應於一個特定的設備. 211 ret=cdev_add(&cdev,dev,1); 212 if (ret) 213 { 214 215 printk("error while adding device"); 216 return ret; 217 218 219 } 220 221 } 222 223 static int __exit pipicold_exit() 224 { 225 dev_t dev=MKDEV(DEVICE_MAJOR,DEVICE_MINOR); 226 cdev_del(&cdev) 227 kfree(cdev); 228 unregister_chrdev_region(dev,1); 229 230 231 232 } 233 234 module_init(pipicold_int); 235 module_exit(pipicold_exit);
恩。。。關於怎麼加載驅動的問題。。。我明天再查吧。。。不想弄了額先,先去學學markdown