基于xilinx平台的lcd pwm背光驱动开发

文章详细描述了一个Linux平台上的PWM驱动程序,包括内核级的模块初始化、中断处理、频率和占空比设置,以及应用层通过字符设备进行控制和测试的示例。同时提到了交叉编译过程。
摘要由CSDN通过智能技术生成

1.驱动层

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <asm/io.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <linux/ioport.h>
#include <linux/of.h>
#include <linux/uaccess.h>
#include <linux/interrupt.h>
#include <asm/irq.h>
#include <linux/irq.h>
#include <asm/uaccess.h>
#include <linux/dma-mapping.h>

//ax_pwm@80000000
#define AX_PWM_ADDR            (0X80000000)

volatile unsigned int  * ax_pwm_freq_addr;
volatile unsigned int  * ax_pwm_duty_addr;


dma_addr_t axidma_handle;
volatile unsigned int * axidma_addr;

int major;

static struct class *pwm_class   = NULL;

static int pwm_open(struct inode *inode,struct file *file);
static ssize_t pwm_write(struct file *file,const char __user *buf, size_t count,loff_t *ppos);
static ssize_t pwm_read(struct file *file,char __user *buf,size_t size,loff_t *ppos);
/*
 *file_operations 结构数据,沟通内核与操作系统桥梁
 *
 * */
static struct file_operations pwm_lops=
{
.owner = THIS_MODULE,
.read  = pwm_read,
.open  = pwm_open,
.write = pwm_write,
};
/*
 * 初始化,用于module init
 *
 * */
static int __init pwm_init(void)
{
    major=register_chrdev(0,"pwm_dev",&pwm_lops);
    pwm_class= class_create(THIS_MODULE,"pwm_dev");
    device_create(pwm_class,NULL,MKDEV(major,0),NULL,"pwm_dev");
    printk("major dev number= %d",major);

    ax_pwm_freq_addr  =  ioremap(AX_PWM_ADDR   + 0x0, 4);
    ax_pwm_duty_addr  =  ioremap(AX_PWM_ADDR   + 0x04, 4);

    printk("ax_pwm_freq_addr=%0x04\n",ax_pwm_freq_addr);
    printk("ax_pwm_duty_addr=%0x04\n",ax_pwm_duty_addr);

    return 0;
}

/*
 *退出 用于 module exit
 *
 * */
static void __exit pwm_exit(void)
{
    unregister_chrdev(major,"pwm_dev");
    
    device_destroy(pwm_class,MKDEV(major,0));
    class_destroy(pwm_class);
    
    iounmap(ax_pwm_duty_addr);
    iounmap(ax_pwm_freq_addr);

}
/*
 *open 接口函数
 *
 * */
static int pwm_open(struct inode *inode,struct file *file)
{
    int err;
    
    printk("pwm open\n");

    return 0;
}
/*
 * write 接口函数
 *
 * */
static ssize_t pwm_write(struct file *file,const char __user *buf, size_t count,loff_t *ppos)
{
    printk("pwm write start !\n");

    char*after;
    unsigned long para = 0;
    para = simple_strtoul(buf,&after,10);

    printk("para=%ld\n",para);
    para = 100 - para;

    unsigned int freq_val = (unsigned int)((4294967296.0 / 100000000) * 500);
    //unsigned int duty     = (unsigned int)(4294967296 * para);//有变量,就不能有小数
    
    unsigned int duty = 4294967296 * para / 100;
    printk("duty=%ld\n",duty);

    //0是最亮,所以是1-percent. add by iverson.deng 2023/9/13
    //unsigned int duty     = (unsigned int)(4294967296 * 0.95);

    iowrite32(freq_val,ax_pwm_freq_addr);
    iowrite32(duty,ax_pwm_duty_addr);

    printk("dma write is over!\n");

    return 0;
}

/*
 * read 接口函数
 *DMA读取数据是按照32bit读取的
 * */
static ssize_t pwm_read(struct file *file,char __user *buf,size_t size,loff_t *ppos)
{
    
    return 0;
}

module_init(pwm_init);
module_exit(pwm_exit);

MODULE_AUTHOR("iverson@pwm");
MODULE_DESCRIPTION("pwm driver");
MODULE_ALIAS("linux axi pwm driver");
MODULE_LICENSE("GPL");

交叉编译 Makefile

modname:=pwm_driver
obj-m:=$(modname).o

PWD :=$(shell pwd)
MAKE :=make
KERNELDIR = /home/iversondeng/workspace/alinx/petalinux/ubootandkernel/linux-xlnx-xilinx-v2020.1
CROSS_COMPILE=aarch64-xilinx-linux-
ARCH=arm64


all:
	$(MAKE) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERNELDIR) M=$(PWD) modules

clean:
	rm -rf $(modname).ko *.o *mod* \.*cmd *odule* .tmp_versions

.PHONY: all clean

2.应用层测试

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

void delay(void)
{
    int i,j;
    for(i=0;i<20000;i++)
        for(j=0;j<10000;j++);
}

unsigned int readarray[128];

int main(int argc , char ** argv)
{
    int fd;
    int i = 0;
    int j = 0;
    
    fd = open("/dev/pwm_dev",O_RDWR);
    if(fd < 0) 
    {
       printf("can not open file\n");
       while(1);
    }
    else
    { 
      printf("open file sucuss\n");
    }
      
    delay();

    if(argc <= 1) return;    

    j = atoi(argv[1]);
    if(!(j >= 0 && j <= 100)) return;

    write(fd,argv[1],1);
    close(fd);


    printf("pwm test over!\n");

    return 0;
}

交叉编译

$CC  pwm_test.c -o pwm_test -O2 -w

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值