公司待了一個下午,渾渾噩噩的,看了會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這個節點也有了,看來離成功不遠了
接著跑跑應用看看
一直在寫資料,流水燈也出來了。哈哈哈
然後結束流水燈
搞定,今天有點早,好久沒下四國了,趁著周末,玩幾局。收工,四國開始。。。。。