Xilinx公司SP605开发板移植Linux系统LED的驱动程序

时间:2021-08-25 16:33:05
/*********************************************************
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;
}