uclinux简单LED驱动程序
by panasonic.lin@163.com这回还是拿44b0x板上的LED开唰,这是linux2.4的方法,linux2.6有很大区别,相比之下还是2.4的内核比较简单,2.6比较灵活点。
首先声明,此方法是把驱动编译进内核,如果驱动程序比较多的话可能导致内核很冗肿,这时候建议用可加载模块的方式。顶层的简单应用程序放在文件系统中。
1.0
uClinux-dist20050311/linux-2.4.x/drivers/char/{led.h,led.c}
驱动头文件
/************************************************************************************************************/
/*************led.h*************************************************/
/***********************************************************************************************************/
#ifndef __CONFIG_H
#define __CONFIG_H
#include<linux/config.h>
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/fs.h>
#include<linux/errno.h>
#include<asm/uaccess.h>
#include<linux/types.h>
#include<linux/mm.h>
#include<asm/arch/s3c44b0x.h>
#define LED_MAJOR_NR 231
#define DEVICE_NAME "led"
#define PCONC (*(volatile unsigned *)0x01D20010)
#define PDATC (*(volatile unsigned *)0x01D20014)
#define SET_LED_OFF 0
#define SET_LED_ON 1
#define LED0_CON (0x01<<2)
#define LED1_CON (0x01<<4)
#define LED2_CON (0x01<<6)
#define LED0_DAT (0X1<<1)
#define LED1_DAT (0X1<<2)
#define LED2_DAT (0X1<<3)
#endif
驱动程序主体:
/************************************************************************************************************/
/*************led.c*************************************************/
/***********************************************************************************************************/
#include"led.h"
static int led_open(struct inode *inode,struct file *filp);
static int led_release(struct inode *inode,struct file *filp);
static int led_ioctl(struct inode *inode,struct file *filp,unsigned int cmd);
int led_init(void);
void led_cleanup(void);
static struct file_operations LED_fops=
{
owner:THIS_MODULE,
#if 0
llseek:gpio_llseek,
read:gpio_read,
write:gpio_write,
#endif
ioctl:led_ioctl,
open:led_open,
release:led_release,
};
static int led_open(struct inode *inode,struct file *filp)
{
PCONC =(PCONC&(~(0XC)))|LED0_CON;//change led0,not change led1 and led2!
MOD_INC_USE_COUNT;
return 0;
}
static int led_release(struct inode *inode,struct file *filp)
{
MOD_DEC_USE_COUNT;
return 0;
}
static int led_ioctl(struct inode *inode,struct file *filp,unsigned int cmd)
{
switch(cmd)
{
case 0:
PDATC |= LED0_DAT;//LED0=1
break;
case 1:
PDATC &=~(LED0_DAT);//LED0=0
break;
default:
return -1;
break;
}
return 0;
}
int led_init(void){
int result;
result=register_chrdev(231,"led",&LED_fops);
if(result<0)
{
printk(KERN_ERR ":unable to register!\n");
return (result);
}
printk(KERN_DEBUG ":init OK\n");
return 0;
}
void led_cleanup(void)
{
unregister_chrdev(231,"led");
}
2.0
/uClinux-dist20050311/user/ledtest/{ledtest.c,Makefile}
用户空间程序
/************************************************************************************************************/
/*************ledtest.c*********************************************/
/***********************************************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
void delay(int delay){
int i;
for(;delay>0;delay--){
for(i=0;i<5000;i++);
}
}
int main(){
int fd1;
int j;
fd1=open("/dev/led",O_RDWR);
if(fd1== -1){
printf("file can not be open");
return -1;
}
for(j=0;j<10;j++)
{
ioctl(fd1,1);
delay(1000);
ioctl(fd1,0);
delay(1000);
}
close(fd1);
return 0;
}
/************************************************************************************************************/
/*************Makefile*********************************************/
/***********************************************************************************************************/
EXEC = ledtest
OBJS = ledtest.o
all: $(EXEC)
$(EXEC): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS)
romfs:
$(ROMFSINST) /bin/$(EXEC)
clean:
rm -f $(EXEC) *.elf *.gdb *.o
3.0
修改添加驱动配置文件和Makefile
uClinux-dist20050311/linux-2.4.x/drivers/char/{Makefile,config.in,mem.c}
Makefile
obj-$(CONFIG_C5471_WDT) += wdt_c5471.o
#add by panasonic 2009-12-12
obj-$(CONFIG_LED_TEST) += led.o
config.in
if [ "$CONFIG_CPU_S3C44B0X" = "y" ]; then
bool 'Samsung S3C44B0X serial ports support' CONFIG_SERIAL_S3C44B0X
bool 'test led drivers' CONFIG_LED_TEST
if [ "$CONFIG_SERIAL_S3C44B0X" = "y" ]; then
mem.c
int __init chr_dev_init(void)
{
if (devfs_register_chrdev(MEM_MAJOR,"mem",&memory_fops))
printk("unable to get major %d for memory devs\n", MEM_MAJOR);
memory_devfs_register();
rand_initialize();
/*add by panasonic 2009-1-1*/
#ifdef CONFIG_LED_TEST
led_init();
#endif
#ifdef CONFIG_I2C
i2c_init_all();
#endif
uClinux-dist20050311/vendors/Samsung/44B0/Makefile
DEVICES = \
tty,c,5,0 console,c,5,1 cua0,c,5,64 cua1,c,5,65 \
\
mem,c,1,1 kmem,c,1,2 null,c,1,3 \
zero,c,1,5 random,c,1,8 urandom,c,1,9 \
\
ram0,b,1,0 ram1,b,1,1 \
\
ptyp0,c,2,0 ptyp1,c,2,1 ptyp2,c,2,2 ptyp3,c,2,3 \
ptyp4,c,2,4 ptyp5,c,2,5 ptyp6,c,2,6 ptyp7,c,2,7 \
ptyp8,c,2,8 ptyp9,c,2,9 ptypa,c,2,10 ptypb,c,2,11 \
ptypc,c,2,12 ptypd,c,2,13 ptype,c,2,14 ptypf,c,2,15 \
\
rom0,b,31,0 rom1,b,31,1 rom2,b,31,2 rom3,b,31,3 \
rom4,b,31,4 rom5,b,31,5 rom6,b,31,6 rom7,b,31,7 \
rom8,b,31,8 rom9,b,31,9 \
\
tty0,c,4,0 tty1,c,4,1 tty2,c,4,2 tty3,c,4,3 \
ttyS0,c,4,64 ttyS1,c,4,65 \
\
ttyp0,c,3,0 ttyp1,c,3,1 ttyp2,c,3,2 ttyp3,c,3,3 \
ttyp4,c,3,4 ttyp5,c,3,5 ttyp6,c,3,6 ttyp7,c,3,7 \
ttyp8,c,3,8 ttyp9,c,3,9 ttypa,c,3,10 ttypb,c,3,11 \
ttypc,c,3,12 ttypd,c,3,13 ttype,c,3,14 ttypf,c,3,15 \
\
led,c,231,0
4.0
修改添加应用程序的配置和Makefile
uClinux-dist20050311/user/Makefile
dir_$(CONFIG_USER_HELLO) += app
dir_$(CONFIG_USER_LEDTEST) += ledtest
uClinux-dist20050311/config/config.in
#############################################################################
mainmenu_option next_comment
comment 'led driver test'
bool 'LEDtest' CONFIG_USER_LEDTEST
comment "LED_TEST"
endmenu
#############################################################################
5.0
编译连接调试
$make menuconfig
选中customize kernel settings/customize vendor/user settings
然后在kernel setting那里选中test led drivers
最后在vendor/user setting那里选中led drivers test下面的LEDtest应用程序
$make clean
$make dep
$make lib_only
$make user_only
$make romfs
$make image
$make
生成uclinux_rom.bin,uclinux_ram.bin.gz,romfs.img
uclinux_rom.bin拷贝到tftp输出目录。
将根文件系统映像挂载到回环设备,然后拷贝到nfs输出目录:
$mount -o loop romfs.img /mnt
$cp -a /mnt/* /home/panasonic/nfs-root/
在根文件系统的/etc目录新建init.d目录,在init.d目录下新建rcS脚本
#!/bin/sh
mount -t proc proc /proc
hostname 44b0
cat /etc/motd
/bin/msh
$chmod +x rcS添加可执行属性。
重启nfs服务
打开minicom
打开板子
$ping 192.168.0.1
$tftpboot 0xc500000
$bootm 0xc500000
进入shell后首先看看/dev下面有没有led的设备文件
也可以cat /proc/devices查看
好,看看bin目录有没有用户空间应用程序ledtest
运行./ledtest即可看到led一闪一闪的。
文章评论(0条评论)
登录后参与讨论