mini2440烧录进自己配置的内核镜像,commandlines,文件系统,superboot,启动开发板后led一直在按照顺序闪灭,怀疑是led的程序自启动了。
[root@FriendlyARM bin]# cat /etc/init.d/rcS
打开脚本后发现有段代码启动led脚本
sleep 1
/etc/rc.d/init.d/leds start
echo " " > /dev/tty1
echo "Starting leds service..." > /dev/tty1
echo " "
sleep 1
打开led的sh脚本:
[root@FriendlyARM bin]# cat /etc/rc.d/init.d/leds
#!/bin/sh
base=led-player
# See how we were called.
case "$1" in
start)
/usr/bin/$base &
;;
stop)
pid=`/bin/pidof $base`
if [ -n "$pid" ]; then
kill -9 $pid
fi
;;
esac
exit 0
led-player这个文件是二进制文件。我并不想让LED开机就走跑马灯,所以在/etc/init.d/rcS 中leds start那句注释掉,重新启动开发板就可以了。
测试例程:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#define IOCTL_LED_ON 0
#define IOCTL_LED_OFF 1
void usage(char* exename)
{
printf("Usage:\n");
printf(" %s <led_no> <on/off>\n",exename);
printf(" led_no = 1,2,3,4\n ");
}
int main(int argc,char** argv)
{
unsigned int led_no;
int fd = -1;
if(argc != 3)
{
goto err;
}
fd = open("/dev/leds",0);
if(fd<0)
{
printf("can't open /dev/leds\n");
return -1;
}
led_no = strtoul(argv[1],0,0)-1;
if(led_no > 3)
{
goto err;
}
if(strcmp(argv[2],"on"))
{
ioctl(fd,IOCTL_LED_ON,led_no);
}else if(strcmp(argv[2],"off")){
ioctl(fd,IOCTL_LED_OFF,led_no);
}else{
goto err;
}
close(fd);
return 0;
err:
if(fd > 0)
{
close(fd);
}
usage(argv[0]);
return -1;
}
LED驱动代码:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
#define DEVICE_NAME "leds"
#define LED_MAJOR 231
#define IOCTL_LED_ON 0
#define IOCTL_LED_OFF 1
static unsigned long led_table[] = {
S3C2410_GPB5,
S3C2410_GPB6,
S3C2410_GPB7,
S3C2410_GPB8,
};
static unsigned int led_cfg_table[] = {
S3C2410_GPB5_OUTP,
S3C2410_GPB6_OUTP,
S3C2410_GPB7_OUTP,
S3C2410_GPB8_OUTP,
};
static int s3c24xx_leds_open(struct inode* inode,
struct file* file)
{
int i;
for(i=0;i<4;i++)
{
s3c2410_gpio_cfgpin(led_table[i],led_cfg_table[i]);
}
return 0;
}
static int s3c24xx_leds_ioctl(
struct inode* inode,
struct file* file,
unsigned int cmd,
unsigned long arg)
{
if(arg > 4)
{
return -EINVAL;
}
switch(cmd)
{
case IOCTL_LED_ON:
s3c2410_gpio_setpin(led_table[arg],0);
case IOCTL_LED_OFF:
s3c2410_gpio_setpin(led_table[arg],1);
default:
return -EINVAL;
}
}
static struct file_operations s3c24xx_led_fops ={
.owner=THIS_MODULE,
.open = s3c24xx_leds_open,
.ioctl = s3c4xx_leds_ioctl;
};
static int __init s3c24xx_leds_init(void)
{
int ret;
ret = register_chrdev(LED_MAJOR,DEVICE_NAME,&s3c24xx_leds_fops);
if(ret < 0)
{
printk(DEVICE_NAME "can't register major number\n");
}
printk(DEVICE_NAME " initilizaed\n");
return 0;
}
static void __exit s3c24xx_leds_exit(void)
{
unregister_chrdev(LED_MAJOR, DEVICE_NAME);
}
module_init(s3c24xx_leds_init);
module_exit(s3c24xx_leds_exit);
MODULE_AUTHOR("Nobody");
MODULE_DESCRIPTION("S3C2440 LED Driver");
MODULE_LISCENSE("GPL");
LED属于字符设备,下一篇博文准备总结下字符驱动代码的编写。
PS:在sourceinsight下相应内核源代码建立的工程中编写驱动可能会好点,还因为源码下有s3c2440的led源码驱动,值得参考上述代码为嵌入式完全应用手册中的代码修改可用。
PS1:我的方法是在sourceinsight下编写完成后放入共享文件夹中,我的是D:\SharedDir,在虚拟机中进入/mnt/hgfs/SharedDir中将代码复制到ubuntu目录中,比如我内核源码放在.opt/kernel下,所以讲s3c24xx_leds.c放到kernel下/drivers/char/下,修改此目录下的Makefile(加句 obj+= s3c24xx_leds.o),回到源码目录make modules即可生成相应模块文件,将例程文件和makefile放到/usr/bin中,make后生成二进制可执行文件,打开设备节点文件,传递相关参数实现驱动的调用。