File Name: han_led.c
Author: Han Yu-Long
Version: v0.1 2013-04-02
Description: Driver of han_led peripheral.
*********************************************************/
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/ioport.h>
#include <linux/of.h>
#include <linux/fs.h>
#include <asm/io.h>
/********************************************************************************
/*宏定义
********************************************************************************/
#define DEVICE_NAME "han_led" /*The name of this driver, which is shown in the terminal by typing "ls /dev" after insmod operation*/
#define MY_LED_PHY_ADDR 0x40020000 /*The physical address of 4-Leds*/
#define MY_LED_REG_NUM 1 /*Number of Led regs*/
#define MY_LED_REG_WIDTH 32 /*Width of Led regs (not used in this file)*/
/********************************************************************************
/*配置寄存器定义
*描述: 从名称中可以直接看出寄存器名称,具体配置请查询XPS中的PDF文档
********************************************************************************/
static void __iomem *LED_Regs;
/********************************************************************************
/*han_led设备文件打开
*描述: 在用户应用软件中调用open()函数时调用该函数
*@ inode: 文件节点
*@ filp: 文件指针
********************************************************************************/
static int han_led_open(struct inode * inode , struct file * filp)
{
return 0;
}
/********************************************************************************
/*han_led设备文件关闭
*描述: 在用户应用软件中调用close()函数时调用该函数
*@ inode: 文件节点
*@ filp: 文件指针
********************************************************************************/
static int han_led_release(struct inode * inode, struct file *filp)
{
return 0;
}
/********************************************************************************
/*han_led设备文件读取
*描述: 在用户应用软件中调用read()函数时调用该函数
********************************************************************************/
static int han_led_read(struct file *filp, char *buffer, size_t length, loff_t * offset)
{
return 0;
}
/********************************************************************************
/*han_led设备文件写入
*描述: 在用户应用软件中调用write()函数时调用该函数,实际这个函数不会调用因为按键是输入设备
********************************************************************************/
static int han_led_write(struct file *filp, const char *buffer, size_t length, loff_t * offset)
{
return 0;
}
/********************************************************************************
/*han_led设备文件控制
*描述: 在用户应用软件中调用ioctl()函数时调用该函数
********************************************************************************/
static int han_led_ioctl(struct file *filp, unsigned int reg_num, unsigned long arg)
{
if(reg_num>=0 && reg_num<MY_LED_REG_NUM)
{
iowrite32(arg, LED_Regs+reg_num*4);
printk("han_led: Write 0x%x to 0x%x!\n", arg, LED_Regs+reg_num*4);
}
else
{
printk("han_led:[ERROR] Wrong register number!\n");
return -EINVAL;
}
return 0;
}
/********************************************************************************
/*file_operations结构体
*描述: 衔接用户程序和驱动程序的关键
********************************************************************************/
static const struct file_operations han_led_fops =
{
.owner = THIS_MODULE,
.open = han_led_open,
.release = han_led_release,
.read = han_led_read,
.write = han_led_write,
.unlocked_ioctl = han_led_ioctl,
};
/********************************************************************************
/*miscdevice结构体
********************************************************************************/
static struct miscdevice han_led_dev =
{
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &han_led_fops,
};
/********************************************************************************
/*han_led模块加载函数
********************************************************************************/
int __init han_led_init(void)
{
int ret, val;
val=0x0;
//Map device to the virtual address of kernel
LED_Regs = ioremap(MY_LED_PHY_ADDR, MY_LED_REG_NUM); /* Verify it's non-null! */
printk("han_led: Access address to device is:0x%x\n", (unsigned int)LED_Regs);
if(LED_Regs == NULL)
{
printk("han_led:[ERROR] Access address is NULL!\n");
return -EIO;
}
ret = misc_register(&han_led_dev);
if (ret)
{
printk("han_led:[ERROR] Misc device register failed\n");
return ret;
}
printk("han_led: Tata! Module init complete\n");
iowrite32(val, LED_Regs);
printk("OK!\n");
return 0; /* Success */
}
/********************************************************************************
/*han_led模块卸载函数
********************************************************************************/
void __exit han_led_exit(void)
{
iounmap(LED_Regs);
misc_deregister(&han_led_dev);
printk("han_led: Module exit\n");
}
/********************************************************************************
/*指明模块加载卸载函数
********************************************************************************/
module_init(han_led_init);
module_exit(han_led_exit);
/********************************************************************************
/*指明模块描述加载卸载函数
********************************************************************************/
MODULE_AUTHOR("Han Yu-Long");
MODULE_ALIAS("han_led");
MODULE_DESCRIPTION("han_led module");
MODULE_LICENSE("GPL");
/*********************************************************
File Name: led_main.c
Author: Han Yu-Long
Version: v0.1 2013-04-03
Description: led testing samples
*********************************************************/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#define MAX_TIME 32
int count=0;
/*****************************************************************
/*定时器中断处理函数*/
/*alarm(1) means the next interrupt will be come 1 seconds later
*****************************************************************/
void sigalrm_fn(int sig)
{
count++;
alarm(1);
return;
}
/*****************************************************************
/*主函数
*****************************************************************/
int main(int argc, char* argv[])
{
int fd;
fd = open("/dev/han_led",0);
if(fd<0)
{
printf("Led open failed\n");
}
signal(SIGALRM, sigalrm_fn);
alarm(1);
while(count<MAX_TIME)
{
ioctl(fd, 0, count);
pause();
}
close(fd);
return 0;
}
测试程序如下:
/*********************************************************
File Name: led_main.c
Author: Han Yu-Long
Version: v0.1 2013-04-03
Description: led testing samples
*********************************************************/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#define MAX_TIME 32
int count=0;
/*****************************************************************
/*定时器中断处理函数*/
/*alarm(1) means the next interrupt will be come 1 seconds later
*****************************************************************/
void sigalrm_fn(int sig)
{
count++;
alarm(1);
return;
}
/*****************************************************************
/*主函数
*****************************************************************/
int main(int argc, char* argv[])
{
int fd;
fd = open("/dev/han_led",0);
if(fd<0)
{
printf("Led open failed\n");
}
signal(SIGALRM, sigalrm_fn);
alarm(1);
while(count<MAX_TIME)
{
ioctl(fd, 0, count);
pause();
}
close(fd);
return 0;
}