和菜鳥一起學OK6410之Led字元驅動

來源:互聯網
上載者:User

        公司待了一個下午,渾渾噩噩的,看了會android的wifi架構,還是懵懵懂懂的。都怪昨天熱的睡不著,又不想開空調,唉,夏天,快過去吧。不過也算有點收穫吧。吃了晚飯回到宿舍。想著,上幾個實驗都是看看串口的輸出,沒勁,好歹以前玩51,FPGA什麼的時候,都是做出效果來的,於是覺得,得幹出點實物來啊,好吧,記得51和FPGA是從led燈開始的,那麼就。。。。。。。。。

         還是先上代碼了:

 

#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/miscdevice.h>#include <linux/delay.h>#include <asm/uaccess.h>#include <linux/device.h>#include <linux/cdev.h>#include <asm/irq.h>#include <mach/gpio.h>#include <plat/regs-gpio.h>#include <plat/gpio-cfg.h>#include <mach/hardware.h>#include <linux/io.h> #define LED_MAJOR 240 int led_open(struct inode *inode, struct file *filp){    unsigned int tmp;    tmp = readl(S3C64XX_GPMCON);    tmp = (tmp & ~(0xffff) | (0x1111)); //set the GPIO output mode    writel(tmp, S3C64XX_GPMCON);    printk("$$$$$$$$$$$led_open$$$$$$$$$\n");return 0;} ssize_t led_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos){    printk("$$$$$$$$$$led_read$$$$$$$$$\n");return count;}  ssize_t led_write(struct file *filp, char __user *buf, size_t count, loff_t *f_pos){    char mbuf[10];    unsigned int tmp;    copy_from_user(mbuf,buf,count);        switch(mbuf[0])    {        case 0:            tmp = readl(S3C64XX_GPMDAT);            tmp |= (0x1);            writel(tmp, S3C64XX_GPMDAT);            break;        case 1:            tmp = readl(S3C64XX_GPMDAT);            tmp &= ~(0x1);             writel(tmp, S3C64XX_GPMDAT);            break;        case 2:            tmp = readl(S3C64XX_GPMDAT);            tmp |= (0x2);            writel(tmp, S3C64XX_GPMDAT);            break;        case 3:            tmp = readl(S3C64XX_GPMDAT);            tmp &= ~(0x2);            writel(tmp, S3C64XX_GPMDAT);            break;        case 4:            tmp = readl(S3C64XX_GPMDAT);            tmp |= (0x4);            writel(tmp, S3C64XX_GPMDAT);            break;        case 5:            tmp = readl(S3C64XX_GPMDAT);            tmp &= ~(0x4);            writel(tmp, S3C64XX_GPMDAT);            break;        case 6:            tmp = readl(S3C64XX_GPMDAT);            tmp |= (0x8);            writel(tmp, S3C64XX_GPMDAT);            break;        case 7:            tmp = readl(S3C64XX_GPMDAT);            tmp &= ~(0x8);            writel(tmp, S3C64XX_GPMDAT);            break;        default:            break;    }        printk("$$$$$$$$$$led_write$$$$$$$$$\n");return count;} int led_release(struct inode *inode, struct file *filp){    printk("$$$$$$$$$$led_release$$$$$$$$$\n");return 0;} struct file_operations my_fops = {    .owner = THIS_MODULE,    .open = led_open,    .read = led_read,    .write = led_write,    .release = led_release,}; static int led_init(void){    int rc;    printk("Test led dev\n");    rc = register_chrdev(LED_MAJOR, "led", &my_fops);    if(rc < 0)    {        printk("register %s mychar dev error\n", "led");        return -1;    }    printk("$$$$$$$$$ register led dev OK\n");return 0;} static void led_exit(void){    unregister_chrdev(LED_MAJOR, "led");    printk("Good Bye!\n");} MODULE_LICENSE("GPL");module_init(led_init);module_exit(led_exit);

 

        唉,代碼是越來越長了,為了實現流水燈,寫得搓搓的代碼,其實可以不用那麼複雜的。既然寫複雜了也就懶得改了。其實,流水燈就是控制GPIO口,讓GPIO口輸出高低電平,記得51是直接P1
= 0xFF之類的。而FPGA的話,verilog也是很簡單的led=8’b11111110;嵌入式就是煩,跑系統的東西嘛,總得有個門檻,要不然誰都很容易會了,那麼那些嵌入式工程師不是沒飯吃了?哈哈哈哈。。。

        既然是控制GPIO口,那總得知道是哪個GPIO口吧?看看原理圖吧。

 

        是GPM口,對應的,GPM0-GPM4分別是LED1-LED4。接著看看GPIO的一些寄存器吧,

        控制寄存器GPMCON,主要流水燈只要設定為輸出就好了。所以代碼中有寫著

  

    tmp = readl(S3C64XX_GPMCON);    tmp = (tmp & ~(0xffff) | (0x1111)); //set the GPIO output mode    writel(tmp, S3C64XX_GPMCON);

        先讀取,然後設定,然後再寫進去。

 

        然後就是控制那個GPIO輸出的0、1值了。

        就是這個GPMDAT了,對應的每一位就是每一個GPIO口的輸出值了。這個是低電平點亮,高電平滅掉的,所以值為1是滅,值為0是亮。知道這些,看著代碼,應該很容易理解了。

 

        接著makefile

obj-m :=led.o 

         然後建個makemod,代碼如下

 

make -C /home/eastmoon/work/linux2.6.28/ M=`pwd` modules 

        然後只要source makemod就可以編譯成led.ko了

 

        萬事具備了,那麼為了實現驅動,我們還得寫應用啊,所以說啊,搞驅動的,也得寫應用,要不然,怎麼知道你寫的驅動好不好用。別人來看你的驅動寫應用也太累了。好了,還是上代碼吧:

 

#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h> #define DEVICE "/dev/myled" int main(void){    int fd, i;    char buf[10] = {0, 1, 2, 3, 4, 5, 6, 7};    fd = open(DEVICE, O_RDWR);    if(fd < 0)    {        printf("Open /dev/myled file error\n");        return -1;    }        while(1)    {        for(i = 0; i < 8; i += 2)        {            write(fd, &buf[i], 1);            sleep(1);        }        for(i = 7; i > 0; i -= 2)        {            write(fd, &buf[i], 1);            sleep(1);        }    }    close(fd);return 0;}

 

        看看驅動,然後再看,應該還是很好理解的,就是個水水的流水燈嘛。

 

        然後makefile

CC = /usr/local/arm/4.2.2-eabi/usr/bin/arm-linux-gcc ledapp:ledapp.o       $(CC) -o ledapp ledapp.oledapp.o:ledapp.c        $(CC) -c ledapp.c clean :       rm ledapp.o 

        終於搞定了,累死了,還好下雷雨了,天氣沒有下午那麼熱了。然後就是板子上去看看效果了。

        至於怎麼把編譯好的led.ko
和ledapp放到板子上,方法很多,我是用SD卡的,具體看以前的blog中。

        Ok,註冊成功了。

        裝置檔案也建立了

 

        看看,myled這個節點也有了,看來離成功不遠了

        接著跑跑應用看看

        一直在寫資料,流水燈也出來了。哈哈哈

 

 

        然後結束流水燈

        搞定,今天有點早,好久沒下四國了,趁著周末,玩幾局。收工,四國開始。。。。。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.