先贴出源代码:
led源程序:
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/cdev.h>
#include <linux/ioctl.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <linux/gpio.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
//自己定义的头文件
#include "led.h"
#define DEVICE_NAME "led_lwm" //设备名称
#define LED_MAJOR 106 // 主设备号
#define GPBCON (unsigned long) (0x56000010)
#define GPBDAT (unsigned long) (0x56000014)
#define GPBUP (unsigned long) (0x56000018)
unsigned long _IO_GPBCON;
unsigned long _IO_GPBDAT;
unsigned long _IO_GPBUP;
#define GPB5_0 ~(1<<5)
#define GPB6_0 ~(1<<6)
#define GPB7_0 ~(1<<7)
#define GPB8_0 ~(1<<8)
#define GPB5_1 (1<<5)
#define GPB6_1 (1<<6)
#define GPB7_1 (1<<7)
#define GPB8_1 (1<<8)
void ledinit(void)
{
_IO_GPBCON = (unsigned long)ioremap(GPBCON,0x4);
_IO_GPBDAT = (unsigned long)ioremap(GPBDAT,0x4);
_IO_GPBUP = (unsigned long)ioremap(GPBUP,0x4);
*(volatile unsigned long *)_IO_GPBCON = 0x154FD;
*(volatile unsigned long *)_IO_GPBUP = 0x7FF;
}
static int leds_open(struct inode *inode, struct file *file)
{
return 0;
}
static int leds_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
//检测命令的有效性
if (_IOC_TYPE(cmd) != LED_MAGIC)
return -EINVAL;
if (_IOC_NR(cmd) > LED_MAXNR)
return -EINVAL;
//根据命令,点亮或熄灭相应的LED灯
switch(cmd)
{
case LED1_ON:
{
*(volatile unsigned long *)_IO_GPBDAT &= GPB5_0;
break;
}
case LED1_OFF:
{
*(volatile unsigned long *)_IO_GPBDAT |= GPB5_1;
break;
}
case LED2_ON:
{
*(volatile unsigned long *)_IO_GPBDAT &= GPB6_0;
break;
}
case LED2_OFF:
{
*(volatile unsigned long *)_IO_GPBDAT |= GPB6_1;
break;
}
case LED3_ON:
{
*(volatile unsigned long *)_IO_GPBDAT &= GPB7_0;
break;
}
case LED3_OFF:
{
*(volatile unsigned long *)_IO_GPBDAT |= GPB7_1;
break;
}
case LED4_ON:
{
*(volatile unsigned long *)_IO_GPBDAT &= GPB8_0;
break;
}
case LED4_OFF:
{
*(volatile unsigned long *)_IO_GPBDAT |= GPB8_1;
break;
}
default:
{
return -EINVAL;
}
}
return 0;
}
static struct file_operations leds_fops =
{
.owner = THIS_MODULE,
.open = leds_open,
.ioctl = leds_ioctl,
};
static int __init led_init(void)
{
int ret;
//初始化各IO口为输出模式,这里初始化为1,不让LED点亮
ledinit();
*(volatile unsigned long *)_IO_GPBDAT = 0x1E0;
//注册LED设备为字符设备
ret = register_chrdev(LED_MAJOR, DEVICE_NAME, &leds_fops);
if(ret < 0)
{
printk(DEVICE_NAME " register falid!\n");
return ret;
}
return 0;
}
static void __exit led_exit(void)
{
//注销设备
unregister_chrdev(LED_MAJOR, DEVICE_NAME);
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("li wei meng");
MODULE_DESCRIPTION("led driver of li wei meng");
|
测试程序:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include "led.h"
int main(void)
{
int val,fd;
//打开LED设备
fd = open("/dev/led_lwm", 0);
if(fd < 0)
{
printf("Open Led Device Faild!\n");
exit(1);
}
//IO控制
else
{
input: printf("please input 10/11/20/21/30/31/40/41:\n");
printf("if you want to exit,please input 886\n");
scanf("%d",&val);
switch (val)
{
case 10:
ioctl(fd,LED1_ON,0);
break;
case 11:
ioctl(fd,LED1_OFF,0);
break;
case 20:
ioctl(fd,LED2_ON,0);
break;
case 21:
ioctl(fd,LED2_OFF,0);
break;
case 30:
ioctl(fd,LED3_ON,0);
break;
case 31:
ioctl(fd,LED3_OFF,0);
break;
case 40:
ioctl(fd,LED4_ON,0);
break;
case 41:
ioctl(fd,LED4_OFF,0);
break;
default:
break;
}
if(val != 886)
goto input;
else
return 0;
}
}
|
头文件:led。h
#ifndef _LED_H
#define _LED_H
#include <linux/ioctl.h>
//定义幻数
#define LED_MAGIC 'l'
//定义命令
#define LED1_ON _IO(LED_MAGIC,1)
#define LED1_OFF _IO(LED_MAGIC,2)
#define LED2_ON _IO(LED_MAGIC,3)
#define LED2_OFF _IO(LED_MAGIC,4)
#define LED3_ON _IO(LED_MAGIC,5)
#define LED3_OFF _IO(LED_MAGIC,6)
#define LED4_ON _IO(LED_MAGIC,7)
#define LED4_OFF _IO(LED_MAGIC,8)
#define LED_MAXNR 8
#endif
|
刚开始实现的时候,ioctrl的命令直接用的是0,1,2,3,4,5,6,7结果LED2那盏灯死活不亮。
后来经过师兄的帮忙,从这个过程才第一次领会到怎么去调试,怎么去发现问题,怎么去排除问题。后来发现时ioctl的命令冲突的原因。得到这个原因是一步一步排除错误的原因,最终确定只有这么一个原因。后来又学习ioctl的命令码应该怎么定义,才不会冲突。最后就出现了上面的程序。
makefile:
KERNELDIR = /home/linux/linux-2.6.32.2
PWD := $(shell pwd)
CROSS_COMPILE = /usr/local/arm/4.3.2/bin/arm-linux-
CC = $(CROSS_COMPILE)gcc
obj-m := led.o
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.ko *.o *.mod.o *.mod.c *.symvers *.order
.PHONY: modules modules_install clean
|
通过FTP下到板子上之后,首先要在/dev目录下创建节点
mknod /dev/led_lwm c 106 0
然后insmod /lib/modules/2.6.32.2/led.ko
最后去执行测试程序。
这个上传图片怎么这么麻烦?
阅读(1059) | 评论(0) | 转发(1) |