原创 uclinux简单LED驱动程序

2010-1-11 17:04 3084 5 5 分类: MCU/ 嵌入式
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条评论)

登录后参与讨论
我要评论
0
5
关闭 站长推荐上一条 /2 下一条