0
点赞
收藏
分享

微信扫一扫

和菜鸟一起学OK6410之Led字符驱动


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口吧?看看原理图吧。

 

和菜鸟一起学OK6410之Led字符驱动_c

GPM口,对应的,GPM0-GPM4分别是LED1-LED4。接着看看GPIO的一些寄存器吧,

和菜鸟一起学OK6410之Led字符驱动_c_02

和菜鸟一起学OK6410之Led字符驱动_struct_03

GPMCON,主要流水灯只要设置为输出就好了。所以代码中有写着

  

tmp = readl(S3C64XX_GPMCON);

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

writel(tmp, S3C64XX_GPMCON);

        先读取,然后设置,然后再写进去。

 

GPIO输出的0、1值了。

和菜鸟一起学OK6410之Led字符驱动_struct_04

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中。

和菜鸟一起学OK6410之Led字符驱动_嵌入式_05

        Ok,注册成功了。

和菜鸟一起学OK6410之Led字符驱动_嵌入式_06


        设备文件也创建了


 

和菜鸟一起学OK6410之Led字符驱动_嵌入式_07

myled这个节点也有了,看来离成功不远了

        接着跑跑应用看看

和菜鸟一起学OK6410之Led字符驱动_file_08


        一直在写数据,流水灯也出来了。哈哈哈

 

和菜鸟一起学OK6410之Led字符驱动_struct_09

 

        然后结束流水灯

和菜鸟一起学OK6410之Led字符驱动_struct_10

        搞定,今天有点早,好久没下四国了,趁着周末,玩几局。收工,四国开始。。。。。

举报

相关推荐

0 条评论