嵌入式linux学习-1

啊啦。。好久没有更新博客了。

恩最近在做毕业设计是和openwrt相关的。

然后自己在学校论坛淘了一块二手的友善之臂mini2440开发板

今天早上成功刷如linux,然后开始学习

PART 1

恩,是开发环境之类的吧。

我是用的ubuntu。恩。

这里是一个前辈的学习计划,我觉得不错的 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

 

posted @ 2014-03-23 11:34  pipi-cold  阅读(258)  评论(0编辑  收藏  举报