和菜鸟一起学linux :第五篇:第一个字符型驱动
第五篇:第一个字符型驱动日期:2009-3-10 驱动板子上的LED,共四个,查原理图,发现教程上的四个GPIO与我板子的GPIO对应不上,教程上是用的GPIO_B7,8,9,10; 而我的板子是 GPIO_F4,5,6,7所以我只替换了管脚的说明,其他一致呵呵 代码如下: #ifndef _KERNEL_#define _KERNEL_#endif
第五篇:第一个字符型驱动
日期:2009-3-10
驱动板子上的LED,共四个,查原理图,发现教程上的四个GPIO与我板子的GPIO对应不上,教程上是用的GPIO_B7,8,9,10; 而我的板子是 GPIO_F4,5,6,7
所以我只替换了管脚的说明,其他一致呵呵
代码如下:
#ifndef _KERNEL_
#define _KERNEL_
#endif
#ifndef MODULE
#define MODULE
#endif
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <asm-arm/arch-s3c2410/hardware.h>
#define DEVICE_NAME "leds"
#define LED_MAJOR 232
static unsigned long led_table[]={GPIO_F4,GPIO_F5,GPIO_F6,GPIO_F7};
static int leds_ioctl(struct inode *inode,struct file *file,unsigned int cmd,
unsigned long arg){
switch(cmd){
case 0:
case 1:
if(arg>4){
return -EINVAL;
}
write_gpio_bit(led_table[arg],!cmd);
default:
return -EINVAL;
}
}
static struct file_operations leds_fops={
owner:THIS_MODULE,
ioctl:leds_ioctl,
};
static int __init leds_init(void){
int ret;
int i;
ret = register_chrdev(LED_MAJOR,DEVICE_NAME,&leds_fops);
if(ret<0)
{
printk(DEVICE_NAME"can't register major number");
return ret;
}
for(i=0;i<4;i++)
{
set_gpio_ctrl(led_table[i]|GPIO_PULLUP_EN|GPIO_MODE_OUT);
write_gpio_bit(led_table[i],1);
}
printk(DEVICE_NAME "initialized/n");
return 0;
}
static void __exit leds_exit(void){
unregister_chrdev(LED_MAJOR,DEVICE_NAME);
}
module_init(leds_init);
module_exit(leds_exit);
按下列方式编译,我的乖乖,这么多警告,错误啊。
[root@localhost sin]# arm-linux-gcc -O2 -c -I/armsys2410/kernel/include/ led.c
In file included from led.c:13:
/armsys2410/kernel/include/asm-arm/arch-s3c2410/hardware.h:70: warning: no semic
olon at end of struct or union
/armsys2410/kernel/include/asm-arm/arch-s3c2410/hardware.h:70: parse error befor
e `offset'
/armsys2410/kernel/include/asm-arm/arch-s3c2410/hardware.h:70: warning: data def
inition has no type or storage class
led.c:19: warning: `struct file' declared inside parameter list
led.c:19: warning: its scope is only this definition or declaration, which is pr
obably not what you want.
led.c:19: warning: `struct inode' declared inside parameter list
led.c: In function `leds_ioctl':
led.c:24: `EINVAL' undeclared (first use in this function)
led.c:24: (Each undeclared identifier is reported only once
led.c:24: for each function it appears in.)
led.c:26: parse error before `)'
led.c:26: parse error before `u32'
led.c:26: `u32' undeclared (first use in this function)
led.c:26: parse error before `)'
led.c:26: parse error before `)'
led.c:26: parse error before `u32'
led.c:26: parse error before `)'
led.c: At top level:
led.c:32: variable `leds_fops' has initializer but incomplete type
led.c:33: unknown field `owner' specified in initializer
led.c:33: warning: excess elements in struct initializer
led.c:33: warning: (near initialization for `leds_fops')
led.c:34: unknown field `ioctl' specified in initializer
led.c:34: warning: excess elements in struct initializer
led.c:34: warning: (near initialization for `leds_fops')
led.c: In function `leds_init':
led.c:41: `LEDMAJOR' undeclared (first use in this function)
led.c:49: parse error before `)'
led.c:49: parse error before `u32'
led.c:49: `u32' undeclared (first use in this function)
led.c:49: parse error before `)'
led.c:49: parse error before `)'
led.c:49: parse error before `u32'
led.c:49: parse error before `)'
led.c:49: parse error before `)'
led.c:49: parse error before `u32'
led.c:49: parse error before `)'
led.c:49: parse error before `)'
led.c:49: parse error before `u32'
led.c:49: parse error before `)'
led.c:50: parse error before `)'
led.c:50: parse error before `u32'
led.c:50: parse error before `)'
led.c:50: parse error before `)'
led.c:50: parse error before `u32'
led.c:50: parse error before `)'
花了一下午时间,在网上搜集资料,但始终也没有解决
在坛上经大家的指点,用kernel/drivers/example-leds.c (发现这个和我的板子的GPIO定义都一样)
但一编译发现错误更多。。。(错误更多,就不列出来了,省的打击信心。。。)
继续找资料。。。
继续搜索资料,发现基于2.6内核的好象多些,胡乱看了一通。。。
有点心恢意冷了
病急乱投医了,开始怀疑内核没有编译会不会影响呢?
(之前把内核一释放,啥操作都没有做)
于是把交叉编译工具,内核都删除,按教程重新弄一边,问题依旧。。。
始终不得法门,郁闷啊,
后来就怀疑编译时,参数错了,换个关键字继续搜索
有人提到编译驱动要加 “-DKERNEL -DMODULE ”
于是
编译写成如下格式
arm-linux-gcc -DKERNEL -DMODULE -I/armsys2410/kernel/include -c led.c
仍旧有问题
没办法,看代码再
发现下面的两句 KERNEL前后的 下划线似乎有点短了,如下:
#ifndef _KERNEL_
#define _KERNEL_
改为:
(下面是两个下划线是两横 嘿嘿)
#ifndef __KERNEL__
#define __KERNEL__
再编译
arm-linux-gcc -DKERNEL -DMODULE -I/armsys2410/kernel/include -c led.c
哈哈 通过了,没有警告也没有错误,兴奋了一把
当前的目录下也多了个 led.o文件 嘿嘿
上传到开发板
修改其权限:
# chmod 777 led.o
挂载:
# insmod ./led.o
查看:
# cat /proc/devices
Character devices:
1 mem
2 pty/m%d
3 pty/s%d
4 vc/0
5 ptmx
7 vcs
10 misc
29 fb
90 mtd
128 ptm
136 pts/%d
162 raw
204 ttyS%d
205 cua%d
232 leds
创建设备文件
# mknod /dev/leds c 243 0
查看
# ls /dev
bon fb misc ptmx shm ttyS2
console full mtd pts touchscreen urandom
cua0 kmem mtdblock pty tty vc
cua1 leds null random ttyS0 vcc
cua2 mem port root ttyS1 zero
#
测试程序
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
int main(int argc,char **argv)
{
int on;
int led_no;
int fd;
if(argc!=3||sscanf(argv[1],"%d",&led_no)!=1|| sscanf(argv[2],"%d",&no)!=1 || on<0 || on>1 ||led_no<0 || led_no>3)
{
fprintf(stderr,"Usage:led led_no 1|0/n");
exit(1);
}
fd = open("/dev/leds", 0);
if (fd < 0) {
perror("open device leds");
exit(1);
}
ioctl(fd, on, led_no);
close(fd);
return 0;
}
[root@localhost sin]# arm-linux-gcc -o ledtest led-test.c
[root@localhost sin]# ls
example-leds.c hh led.o ledss.c led-test.c test.c tt
hello.c led.c leds.c ledtest Makefile test.o
[root@localhost sin]# cp ./ledtest /mnt/hgfs/share
上传到 开发板的 tmp目录
# chmod 777 ledtest
# ls
erase led.o ledtest
# ./ledtest 1 1
open device leds: No such device
# ./ledtest 1 1
open device leds: No such device
# ./ledtest 0 1
open device leds: No such device
居然说没有??真是奇怪了,哪里又出错了呢?
建立接点时出错了,驱动中用的主设备号是:232
而建立时用的是:243, 所以提示“open device leds: No such device”
不知道教程上,怎么出现这么个意外?
我也是网上搜索后,才知道这么个情况(所以啊,基础的东西还是要好好学习学习的)
后修改如下:
# mknod /dev/leds c 232 0
# ls /dev
bon fb misc ptmx shm ttyS2
console full mtd pts touchscreen urandom
cua0 kmem mtdblock pty tty vc
cua1 leds null random ttyS0 vcc
cua2 mem port root ttyS1 zero
# ./ledtest 0 1
# ./ledtest 1 1
# ./ledtest 2 1
# ./ledtest 3 1
OK, 板子上的LED有反应了 呵呵
更多推荐
所有评论(0)