ZYNQ7000-Linux-MIO-LED

ZYNQ7000-Linux-MIO-LED

    • 一、目标
    • 二、寄存器配置
    • 三、代码
    • 四、结果

一、目标

一个通过MIO50引脚点亮LED的驱动。

二、寄存器配置

1、GPIO 基地址:0xE000 A000
2、数据寄存器偏移:0x0000 000C(MASK_DATA_1_MSW)
3、方向寄存器偏移:0x0000 0244 (DIRM_1)
4、使能寄存器偏移:0x0000 0244 (OEN_1)
5、slcr:0xF800 0000
6、时钟:0x0000 012C(APER_CLK_CTRL)
这个寄存器的bit[22]为GPIO_CPU_1XCLKACT需要enable。
7、引脚:0x0000 07C8(MIO_PIN_50)
这个寄存器bit[0]为TRI_ENABLE,需要设置为0(disable)。

三、代码

gpio_led.c,适配linux4.14。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define DEVICE_NAME         "first_gpio"

//MIO 50
#define MY_GPIO_BASE_ADDR          0xE000A000       
#define XGPIOPS_DIRM_OFFSET        0x00000244U      
#define XGPIOPS_OEN_OFFSET         0x00000248U    
#define XGPIOPS_DATA_MSW_OFFSET    0x0000000CU		
#define SLCR_BASE_ADDR             0xF8000000		
#define APER_CLK_OFFSET		   0x0000012C       
#define MIO_PIN_OFFSET		   0x000007C8		

MODULE_AUTHOR("Xilinx XUP");
MODULE_DESCRIPTION("LED moudle dirver");
MODULE_VERSION("v1.0");
MODULE_LICENSE("GPL");

static int gpio_driver_major;
static struct class* gpio_driver_class = NULL;
static struct device* gpio_driver_device = NULL;

volatile unsigned long *Gpio_DIR = NULL;
volatile unsigned long *Gpio_EN = NULL;
volatile unsigned long *Gpio_DATA = NULL;
volatile unsigned long *DATA = NULL;
volatile unsigned long *CLK = NULL;
volatile unsigned long *MIN_PIN_7 = NULL;


static int gpio_open(struct inode * inode, struct file * filp)
{
	printk("first_drv_open\n");
	iowrite32(ioread32(Gpio_DIR) | 0x40000, Gpio_DIR);
	iowrite32(ioread32(Gpio_EN) | 0x40000, Gpio_EN);
	printk("GPIO_DIR_ADDR %x DATA %x \n", Gpio_DIR, ioread32(Gpio_DIR));
	printk("GPIO_EN_ADDR %x DATA %x \n", Gpio_EN, ioread32(Gpio_EN));
	printk("CLK_ADDR %x DATA %x \n", CLK, ioread32(CLK));
	return 0;
}

static ssize_t gpio_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
	int val;
	int state ;
	printk("first_drv_write\n");

	state = copy_from_user(&val, buf, count); //    copy_to_user();
	if(state)
	{

	}

	if (val == 1)
	{
		// 点灯
		iowrite32(0xfffb0004, Gpio_DATA);
		printk("GPIO_DATA_ADDR %x DATA %x \n", Gpio_DATA, ioread32(Gpio_DATA));
	}
	else
	{
		// 灭灯
		*Gpio_DATA = 0xfffb0000;
		printk("GPIO_DATA_ADDR %x DATA %x \n", Gpio_DATA, ioread32(Gpio_DATA));
	}
	return 0;
}

static struct file_operations gpio_drv_fops = {
	.owner = THIS_MODULE,    
	.open = gpio_open,
	.write = gpio_write,
};

int major;
static int __init gpio_drv_init(void)
{
	printk("first_drv_init\n");
	major = register_chrdev(0, "first_gpio", &gpio_drv_fops); 
	if (major < 0) {
		printk("failed to register device.\n");
		return -1;
	}
	gpio_driver_class = class_create(THIS_MODULE, "firstgpio");
	if (IS_ERR(gpio_driver_class)) {
		printk("failed to create pwm moudle class.\n");
		unregister_chrdev(major, "first_gpio");
		return -1;
	}
	gpio_driver_device = device_create(gpio_driver_class, NULL, MKDEV(major, 0), NULL, "first_gpio"); /* /dev/first_gpio */;
	if (IS_ERR(gpio_driver_device)) {
		printk("failed to create device .\n");
		unregister_chrdev(major, "first_gpio");
		return -1;
	}
	Gpio_DIR = (volatile unsigned long *)ioremap(MY_GPIO_BASE_ADDR + XGPIOPS_DIRM_OFFSET, 4);
	Gpio_EN = (volatile unsigned long *)ioremap(MY_GPIO_BASE_ADDR + XGPIOPS_OEN_OFFSET, 4);
	Gpio_DATA = (volatile unsigned long *)ioremap(MY_GPIO_BASE_ADDR + XGPIOPS_DATA_MSW_OFFSET, 4);
	CLK = (volatile unsigned long *)ioremap(SLCR_BASE_ADDR + APER_CLK_OFFSET, 4);
	MIN_PIN_7 = (volatile unsigned long *)ioremap(SLCR_BASE_ADDR + MIO_PIN_OFFSET, 4);
	iowrite32(0x3200, MIN_PIN_7);
	iowrite32(ioread32(CLK) | 0x400000, CLK);//时钟使能 bit[22] GPIO CLK enable
	return 0;
}
static void __exit gpio_drv_exit(void)
{
	printk("Exit gpio module.\n");

	device_destroy(gpio_driver_class, MKDEV(major, 0));
	class_unregister(gpio_driver_class);
	class_destroy(gpio_driver_class);
	unregister_chrdev(major, "first_gpio");
	printk("gpio module exit.\n");

	iounmap(Gpio_DIR);
	iounmap(Gpio_EN);
	iounmap(Gpio_DATA);
	iounmap(CLK);
	iounmap(MIN_PIN_7);

}
module_init(gpio_drv_init);
module_exit(gpio_drv_exit);

程序参考1
测试程序gpio_text.c。

#include 
#include 
#include 
#include 
#include 

int main(int argc, char **argv)
{
    int fd;
    int val = 1;
    fd = open("/dev/first_gpio", O_RDWR);
    if (fd < 0)
    {
        printf("can't open!\n");
    }
    if (argc != 2)
    {
        printf("Usage :\n");
        printf("%s \n", argv[0]);
        return 0;
    }

    if (strcmp(argv[1], "on") == 0)
    {
        val  = 1;
    }
    else
    {
        val = 0;
    }

    write(fd, &val, 4);
    return 0;
}

四、结果

ZYNQ7000-Linux-MIO-LED_第1张图片程序还是有out of tree moudle taints kernel的问题。


  1. https://blog.csdn.net/qq_34322603/article/details/77886912 ↩︎

你可能感兴趣的:(ZYNQ)