简单的LED驱动

编译模块的Makefile文件
ifeq ($(KERNELRELEASE),)
# set your object kernel dir
KERNELDIR ?= /source/kernel/linux-2.6.22.6-farsight
PWD := $(shell pwd)
modules:
 $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
 $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
clean:
 rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.symvers
.PHONY: modules modules_install clean
else
    obj-m := led_drv.o
endif

编译模块的Makefile文件、
注:如果一个模块由多个*.c文件编译而成,那么应该如下编写Makefile文件:
obj-m := led_drv.o
module-objs := file1.o file2.o

驱动程序详细设计:

#include <linux/cdev.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/fcntl.h>
#include <linux/slab.h>
#include <asm/io.h>

MODULE_LICENSE("GPL");

#define rGPFDAT 0x56000054   //实际IO的物理地址
#define rGPFCON 0x56000050

#define LED_ON  0x1
#define LED_OFF 0x2

//static dev_t my_led_id;
static int led_major = 257;  //主设备号

struct __my_led
{
 struct cdev dev;
 unsigned char *vrGPFDAT;
 unsigned short int *vrGPFCON;
}my_led;

static int my_led_open(struct inode *inode, struct file *filp)
{
 struct __my_led *p = container_of(inode->i_cdev, struct __my_led, dev);
 filp->private_data = p;
 //实际物理地址映射到内核虚拟地址
 p->vrGPFDAT = (unsigned char *)ioremap(rGPFDAT, 0x1);
 p->vrGPFCON = (unsigned short int *)ioremap(rGPFCON, 0x2);
 *p->vrGPFCON = (*p->vrGPFCON) & 0x00ff |(0x55<<8);
// *p->vrGPFDAT = 0x30;
// printk("open my_led, p->vrGPFDAT = 0x%x, p->vrGPFCON = 0x%x\n", p->vrGPFDAT, p->vrGPFCON);
  
 return 0;
}

static int  my_led_release(struct inode *inode, struct file *filp)
{
 printk("close my_led\n");
 filp->private_data = NULL;
 //解除映射
 iounmap(my_led.vrGPFDAT);
 iounmap(my_led.vrGPFCON);

 return 0;
}

static int my_led_ioctl(struct inode *inode, struct file *filp,
   unsigned int cmd, unsigned long arg)
{
 struct __my_led *p = filp->private_data;
 int ret = 0;
// printk("in ioctl_dri func , cmd = %d, p->vrGPFDAT = 0x%x\n", cmd, p->vrGPFDAT);
 switch (cmd)
 {
  case LED_ON:
   *p->vrGPFDAT &= 0x0f; //GPF4,5,6,7 置为低电平
   break;
  case LED_OFF:
   *p->vrGPFDAT |= 0xf0;//GPF4,5,6,7 置为高电平
   break;
  default:
   ret = EINVAL;
   break;
 }

 return ret;
}

static const struct file_operations my_led_fops =
{
 .owner = THIS_MODULE,
  .open = my_led_open,
 .release = my_led_release,
 .ioctl = my_led_ioctl,
};

static void my_led_setup_cdev(void)
{
 int err;
 int devno=MKDEV(led_major, 0);
 
 //是字符设备关联一个my_led_fops
 cdev_init(&my_led.dev, &my_led_fops);
 my_led.dev.owner = THIS_MODULE;
 //添加字符设备
 err = cdev_add(&my_led.dev, devno, 1);
 if (err)
 {
  printk("add my_led device error, err = %d \n", err);
  return ;
 }

 return;
}

int __init my_led_init(void)
{
 int ret;
 dev_t dev = MKDEV(led_major,0);

 //注册设备号
 memset(&my_led, 0, sizeof(my_led));
 ret = alloc_chrdev_region(&dev, 0, 1, "my_led");
 if (ret < 0)
 {
  printk("alloc led device id error \n");
  return ret;
 }
 my_led_setup_cdev();
 printk("add my_led device ok!\n");
 printk(KERN_NOTICE"[DEBUG] adc device major is %d\n",led_major);

 return 0;
}

void __exit my_led_exit(void)
{
  //注意顺序不能颠倒,要和加载设备时步骤相反
 cdev_del(&my_led);
 unregister_chrdev_region(MKDEV(led_major,0) ,1);
 printk("my-adc device uninstalled\n");
}
module_init(my_led_init);
module_exit(my_led_exit);

内容概要:本文详细介绍了基于FPGA的144输出通道可切换电压源系统的设计与实现,涵盖系统总体架构、FPGA硬件设计、上位机软件设计以及系统集成方案。系统由上位机控制软件(PC端)、FPGA控制核心和高压输出模块(144通道)三部分组成。FPGA硬件设计部分详细描述了Verilog代码实现,包括PWM生成模块、UART通信模块和温度监控模块。硬件设计说明中提及了FPGA选型、PWM生成方式、通信接口、高压输出模块和保护电路的设计要点。上位机软件采用Python编写,实现了设备连接、命令发送、序列控制等功能,并提供了一个图形用户界面(GUI)用于方便的操作和配置。 适合人群:具备一定硬件设计和编程基础的电子工程师、FPGA开发者及科研人员。 使用场景及目标:①适用于需要精确控制多通道电压输出的实验环境或工业应用场景;②帮助用户理解和掌握FPGA在复杂控制系统中的应用,包括PWM控制、UART通信及多通道信号处理;③为研究人员提供一个可扩展的平台,用于测试和验证不同的电压源控制算法和策略。 阅读建议:由于涉及硬件和软件两方面的内容,建议读者先熟悉FPGA基础知识和Verilog语言,同时具备一定的Python编程经验。在阅读过程中,应结合硬件电路图和代码注释,逐步理解系统的各个组成部分及其相互关系。此外,实际动手搭建和调试该系统将有助于加深对整个设计的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值