嵌入式linux學習-1

啊啦。。很久沒有更新博客了。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

相關文章
相關標籤/搜索