公司待了一个下午,浑浑噩噩的,看了会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.o ledapp.o:ledapp.c $(CC) -c ledapp.c clean : rm ledapp.o
终于搞定了,累死了,还好下雷雨了,天气没有下午那么热了。然后就是板子上去看看效果了。
至于怎么把编译好的led.ko 和ledapp放到板子上,方法很多,我是用SD卡的,具体看以前的blog中。
Ok,注册成功了。
设备文件也创建了
看看,myled这个节点也有了,看来离成功不远了
接着跑跑应用看看
一直在写数据,流水灯也出来了。哈哈哈
然后结束流水灯
搞定,今天有点早,好久没下四国了,趁着周末,玩几局。收工,四国开始。。。。。