新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > OK6410A學習筆記三:嵌入式Linux驅動之LED驅動

        OK6410A學習筆記三:嵌入式Linux驅動之LED驅動

        作者: 時間:2016-11-21 來源:網絡 收藏
        開發環境:
        Windows7 + vmware workstation 6.5 + Ubuntu9.10
        Linux Source Code: FORLINX_linux-3.0.1.tar.gz
        ARM CROSS GCC: arm-linux-gcc v4.3.2

        源碼:
        //s3c6410_led.c – driver file
        #include
        #include
        #include
        #include
        #include

        #define DEV_MAJOR 176
        #define DEV_NAME "s3c6410_leds"


        #define GPMCON 0x7F008820
        #define GPMDAT 0x7F008824
        #define GPMPUD 0x7F008828


        volatile unsigned long *gpmcon = NULL;
        volatile unsigned long *gpmdat = NULL;
        volatile unsigned long *gpmpud = NULL;


        static int s3c6410_led_open(struct inode *inode, struct file *filp)
        {
        //int ret;

        printk(KERN_ALERT "This is open function of s3c6410 led driver.n");

        *gpmpud &= 0xffffffaa; //set GPM0~3 as pull up enabled
        *gpmcon &= 0xffff1111; //set GPM0~3 as output
        *gpmdat &= 0xfffffff0; //set GPM0~3 to low level, which turn on leds

        return 0;

        }

        static ssize_t s3c6410_led_write(struct file *filp,const char __user *buf,size_t count,loff_t *ppos)
        {
        int val;

        //copy_from_user(&val,buf,count);

        printk(KERN_ALERT "This is write function of s3c6410 led driver.n");

        return count;
        }


        struct file_operations s3c6410_led_flops = {
        .owner = THIS_MODULE,
        .open = s3c6410_led_open,
        .write = s3c6410_led_write,
        };

        static int __init s3c6410_led_init(void)
        {
        int ret;

        //register led device driver into kernel
        ret = register_chrdev(DEV_MAJOR,DEV_NAME,&s3c6410_led_flops);

        //retriver the vritual address by ioremap
        gpmcon = (volatile unsigned long *)ioremap(GPMCON,4); //32-bit reg
        gpmdat = gpmcon + 1;
        gpmpud = gpmcon + 2;

        return 0;
        }

        static void __exit s3c6410_led_exit(void)
        {
        //unregister led device dirver from kernel
        unregister_chrdev(DEV_MAJOR,DEV_NAME);

        //iounmap
        iounmap(gpmcon);
        }

        module_init(s3c6410_led_init);
        module_exit(s3c6410_led_exit);

        MODULE_DESCRIPTION("This is led driver sample for OK6410A board.");
        MODULE_VERSION("1.0");
        MODULE_AUTHOR("");
        MODULE_LICENSE("Dual BSD/GPL");

        //s3c6410_led_test.c – test file
        #include
        #include

        int main(int argc,char* argv[])
        {
        int fd;

        fd = open("/dev/s3c6410_led",0);

        if(!fd){
        printf("open s3c6410 led failed.n");
        }else{
        printf("open s3c6410 led succeed.n");
        }
        return 0;
        }

        解析:
        1. 查看OK6410A開發板原理圖,4個LED燈接在GPM0~3四個GPIO上。
        2. 查看Samsung S3C6410X User’s Manual.pdf ,查看GPm端口操作說明,包括GPMCON,GPMDAT,GPMPUD三個寄存器的基地址以及配置信息,從而確定點亮LED燈和熄滅LED燈的操作。
        3. 編寫源代碼,包括驅動源碼和測試源碼。這里比較重要的地方是,Linux驅動是工作在保護模式下,無法直接操作寄存器,因此必須將步驟二中找到的寄存器基地址通過IO地址重映射,從而得到虛擬地址進行操作,在驅動程序入口函數中使用ioremap()函數進行地址重映射,在退出函數中使用iounmap()結束地址重映射。另外,如果想在加載驅動的同時,讓系統自動新建設備節點,則要將設備信息提供給系統內核,Linux系統支持的mdev機制會根據驅動程序提供的信息新建設備節點。在上述源碼中并沒有實現這一功能。
        4. 編譯源碼
        驅動程序Makefile如下:
        obj-m:=s3c6410_led.o
        KERNELDIR?=/usr/src/linux-3.0.1

        default:
        $(MAKE) -C $(KERNELDIR) M=$(shell pwd) modules

        clean:
        rm -rf *.o *~ *.ko *.mod.c *.order *.symvers

        在終端下執行如下命令:
        #make //編譯驅動程序,得到s3c6410_led.ko文件
        #arm-linux-gcc s3c6410_led_test.c –o s3c6410_led_test //編譯測試源碼

        5. 拷貝s3c6410_led.ko和s3c6410_led_test到SD卡中,給開發板上電




        評論


        技術專區

        關閉
        主站蜘蛛池模板: 青海省| 湄潭县| 绥芬河市| 昆山市| 汉源县| 塔河县| 射洪县| 读书| 分宜县| 昭平县| 库尔勒市| 顺义区| 东光县| 澜沧| 光泽县| 宜章县| 龙门县| 安吉县| 龙岩市| 平定县| 外汇| 边坝县| 鹤山市| 黄浦区| 独山县| 石棉县| 鹰潭市| 昆明市| 龙口市| 柞水县| 武城县| 河间市| 界首市| 屯门区| 扎兰屯市| 兴仁县| 凉山| 赣州市| 禹城市| 宁德市| 佳木斯市|