• 嵌入式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"	initialized
    ");
    
        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 
    ");
    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

  • 相关阅读:
    hdu 1269 迷宫城堡(强联通分量,基础)
    hdu 2102 A计划(BFS,基础)
    python 变量命名规范
    rpm常用选项
    memcached
    session共享
    Nginx高级使用
    nginx 反向代理
    Nginx基本使用
    github 建立博客
  • 原文地址:https://www.cnblogs.com/pipicold/p/3618818.html
Copyright © 2020-2023  润新知