Chinaunix

标题: arm linux下驱动开发 [打印本页]

作者: hoursjl    时间: 2014-05-24 11:16
标题: arm linux下驱动开发
请教大家个问题:

      我有个给arm linux 下一个字符设备写好的驱动程序,这个驱动程序编译成模块形式之后,用insmod手动加载,并且手动建立/dev下的设备节点后,工作正常。
      但是我希望使用静态加载的方式,我将它编译进内核(修改Kconfig,Makefile),引导系统后,始终找不相应的设备或驱动信息。
      /proc/devices 里没有相关项, /dev下也没有设备节点。


      我想知道如何来确定我的驱动已成功编译进内核了?  要使用静态加载方式,在写驱动的时候有没有要注意的地方?  什么导致了我的静态加载失败?
作者: arm-linux-gcc    时间: 2014-05-24 13:16
要自动创建结点,需要使用device_create
把代码贴出来
作者: fairy795    时间: 2014-05-24 16:41
看下模块编译产生的临时文件。回复 1# hoursjl


   
作者: hoursjl    时间: 2014-05-26 14:52
本帖最后由 hoursjl 于 2014-05-26 14:58 编辑

回复 2# arm-linux-gcc

确实没用你说的函数。   我刚接触嵌入式linux驱动,有没有什么资料推荐我看一下啊? 谢谢!



/*
* blink.c - Create an input/output character device
*/
#include <linux/kernel.h> /* We're doing kernel work */
#include <linux/module.h> /* Specifically, a module */
#include <linux/fs.h>
#include <asm/uaccess.h> /* for get_user and put_user */
#include <asm/io.h>
#include "blink.h"
#define SUCCESS 0
#define DEVICE_NAME "/dev/blink_Dev"


#define BLINK_CTRL_REG         0x7C600000
static void *mmio;
static int major_num;

/*
* Is the device open right now? Used to prevent
* concurent access into the same device
*/
static int Device_Open = 0;


static void set_blink_ctrl(void)
{
        printk("KERNEL PRINT : set_blink_ctrl \n\r");
        *(unsigned int *)mmio = 0x1;
}



static void reset_blink_ctrl(void)
{

        printk("KERNEL PRINT : reset_blink_ctrl \n\r");
        *(unsigned int *)mmio = 0x0;
}
/*
* This is called whenever a process attempts to open the device file
*/
static int device_open(struct inode *inode, struct file *file)
{
        #ifdef DEBUG
                printk(KERN_INFO "device_open(%p)\n", file);
        #endif
        /*
        * We don't want to talk to two processes at the same time
        */
        if (Device_Open)
                return -EBUSY;
        Device_Open++;
        /*
        * Initialize the message
        */
//        Message_Ptr = Message;
        try_module_get(THIS_MODULE);
        return SUCCESS;
}
static int device_release(struct inode *inode, struct file *file)
{
        #ifdef DEBUG
                printk(KERN_INFO "device_release(%p,%p)\n", inode, file);
        #endif
        /*
        * We're now ready for our next caller
        */
        Device_Open--;
        module_put(THIS_MODULE);
        return SUCCESS;
}
/*
* This function is called whenever a process which has already opened the
* device file attempts to read from it.
*/
static ssize_t device_read(        struct file *file, /* see include/linux/fs.h */
                                                        char __user * buffer, /* buffer to be filled with data */
                                                        size_t length, /* length of the buffer */
                                                        loff_t * offset)
{
        return SUCCESS;
}
/*
* This function is called when somebody tries to
* write into our device file.
*/
static ssize_t device_write(struct file *file,
                                                        const char __user * buffer,
                                                        size_t length,
                                                        loff_t * offset)
{
        return SUCCESS;
}
/*
* This function is called whenever a process tries to do an ioctl on our
* device file. We get two extra parameters (additional to the inode and file
* structures, which all device functions get): the number of the ioctl called
* and the parameter given to the ioctl function.
*
* If the ioctl is write or read/write (meaning output is returned to the
* calling process), the ioctl call returns the output of this function.
*
*/
int device_ioctl(                        struct file *file, /* ditto */
                                        unsigned int ioctl_num, /* number and param for ioctl */
                                        unsigned long ioctl_param)
{
//        int i;
        char *temp;
//        char ch;
        /*
        * Switch according to the ioctl called
        */
        switch (ioctl_num)
        {
        case IOCTL_ON_LED:
               
                temp = (char *)ioctl_param;
                set_blink_ctrl();
        break;
        case IOCTL_STOP_LED:
                temp = (char *)ioctl_param;
                reset_blink_ctrl();
        break;
       
        }
        return SUCCESS;
}
/* Module Declarations */
/*
* This structure will hold the functions to be called
* when a process does something to the device we
* created. Since a pointer to this structure is kept in
* the devices table, it can't be local to
* init_module. NULL is for unimplemented functions.
*/
struct file_operations Fops = {
                                                                .read = device_read,
                                                                .write = device_write,
                                                                .unlocked_ioctl = device_ioctl,
                                                                .open = device_open,
                                                                .release = device_release, /*close */                                                                };
/*
* Initialize the module - Register the character device
*/
int init_module()
{
        int ret_val;
       
        /*
        * Register the character device (atleast try)
        */
        major_num = register_chrdev(0,DEVICE_NAME, &Fops);
        /*
        * Negative values signify an error
        */
        if (major_num < 0)
        {
                printk(KERN_ALERT "%s failed with %d\n","Sorry, registering the character device ", ret_val);
                return ret_val;
        }
        printk(KERN_INFO "%s The major device number is %d.\n",
        "Registeration is a success", major_num);
        printk(KERN_INFO "If you want to talk to the device driver,\n");
        printk(KERN_INFO "Than create a device file by following command. \n");
        printk(KERN_INFO "mknod %s c %d 0\n", DEVICE_FILE_NAME, major_num);
        printk(KERN_INFO "The device file name is important, because\n");
        printk(KERN_INFO "the ioctl program assumes that's the\n");
        printk(KERN_INFO "file you'll use.\n");

        mmio = ioremap(BLINK_CTRL_REG,0x100);

        return 0;
}
/*
* Cleanup - unregister the appropriate file from /proc
*/
void cleanup_module()
{
        /*
        * Unregister the device
        */
        iounmap(mmio);
        unregister_chrdev(major_num,DEVICE_NAME);
}

作者: hoursjl    时间: 2014-05-26 14:55
中间结果都是有的



回复 3# fairy795


   

无标题.png (1.65 KB, 下载次数: 28)

无标题.png

作者: arm-linux-gcc    时间: 2014-05-26 20:10
本帖最后由 arm-linux-gcc 于 2014-05-26 20:28 编辑

你的写法还是很古老的写法,没有使用设备模型这一套东西,没把设备、驱动、总线分开

建议参考platform_device_register和platform_driver_register的用法


作者: hoursjl    时间: 2014-05-26 20:36
回复 6# arm-linux-gcc


用了device_create()现在可以了。 马上去学习platform_device_register和platform_driver_register,多谢你的指点啊!   




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2