飞腾D2000 GPIO中断调试

1、背景介绍

模块上采用两片飞腾D2000,两片直接通过PCIE进行连接,通过GPIO方式进行中断触发,连接关系如下:

两个CPU采用GPIO0的A组的2,3,4,5引脚进行中断传输。其中2,3引脚为CPUA给CPUB触发中断,4,5引脚为CPUB给CPUA触发中断。

2、GPIO寄存器说明

D2000 GPIO寄存器描述和FT2000/4芯片完全一样,复用关系也一样,芯片应该用到都是同一个IP。

3、中断驱动

因为寄存器一样,因此驱动也类似,加载gpio-phytium-core.ko和gpio-phytium-platform.ko即可,可参考FT2000/4 GPIO中断调试。https://blog.csdn.net/zhaoxinfan/article/details/152132668

cpp 复制代码
// SPDX-License-Identifier: GPL-2.0
/*
 * Support functions for Phytium GPIO
 *
 * Copyright (c) 2019, Phytium Corporation.
 * Written by Chen Baozi <chenbaozi@phytium.com.cn>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/acpi.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/sched/signal.h>

#include "gpio-phytium-core.h"

#define GPIO_IRQ_PORT_ADDR 0x28004000

#define GpioGetBit(addr, bitpos)    (readl(addr) >> bitpos)&0x1
#define GpioSetBit(addr, bitpos)	writel(readl(addr) | (0x1 << bitpos), addr)
#define GpioClrBit(addr, bitpos)	writel(readl(addr) & (~(0x1 << bitpos)), addr)

#define CMD_SET_PID        0x6B09

#define GPIO_SIGNAL1  40
#define GPIO_SIGNAL2  41
#define GPIO_SIGNAL3  42
#define GPIO_SIGNAL4  43
#define GPIO_SIGNAL5  44

static struct irq_chip phytium_gpio_irqchip = {
	.name		= "phytium_gpio",
	.irq_ack	= phytium_gpio_irq_ack,
	.irq_mask	= phytium_gpio_irq_mask,
	.irq_unmask	= phytium_gpio_irq_unmask,
	.irq_set_type	= phytium_gpio_irq_set_type,
	.irq_enable	= phytium_gpio_irq_enable,
	.irq_disable	= phytium_gpio_irq_disable,
};

static const struct of_device_id phytium_gpio_of_match[] = {
	{ .compatible = "phytium,gpio", },
	{ }
};
MODULE_DEVICE_TABLE(of, phytium_gpio_of_match);

static const struct acpi_device_id phytium_gpio_acpi_match[] = {
	{ "PHYT0001", 0 },
	{ "FTGP0001", 0 },
	{ }
};
MODULE_DEVICE_TABLE(acpi, phytium_gpio_acpi_match);

static int major = 0;
static struct class *gpio_class = NULL;
static struct device *gpio_device = NULL;
static struct task_struct *my_task = NULL;
static DEFINE_SPINLOCK(hc_gpio_lock);

static unsigned int irq_err_times = 0;
long cpld_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	int g_pid = 0;
	void __user *pArg;
	struct pid *pid_struct;
	struct task_struct *task;
	unsigned long flags;
	
	if(cmd == CMD_SET_PID)
	{
		pArg = (void __user *)arg;
		if(copy_from_user((void *)&g_pid, pArg, sizeof(int)))
		{
			printk("copy_from_user failed\n");
		}
			printk("copy_from_user success, g_pid:%d\n", g_pid);

		pid_struct = find_get_pid(g_pid);
		if (!pid_struct)
			return -ESRCH;

		task = get_pid_task(pid_struct, PIDTYPE_PID);
		put_pid(pid_struct);

		spin_lock_irqsave(&hc_gpio_lock, flags);
		if (my_task)
			put_task_struct(my_task);
		my_task = task;
		irq_err_times = 0;
		spin_unlock_irqrestore(&hc_gpio_lock, flags);

		printk("ioctl my_task register success\n");
		return 0;
	}
	return -1;
}

static int cpld_open(struct inode * inode, struct file * filp)
{
	return 0;
}
 
static int cpld_release(struct inode *inode, struct file *file)
{
	return 0;
}


/* File operations struct for character device */
static const struct file_operations gpio_dev_fops = {
	.owner = THIS_MODULE,
	.open = cpld_open,
	.release = cpld_release,
	.unlocked_ioctl = cpld_ioctl,
};

//static unsigned int irq_err_last_times=0;
static irqreturn_t phytium_gpio_irq_handler_example(int irq, void *dev_id)
{
	struct phytium_gpio *gpio = dev_id;
	unsigned long val;
	struct task_struct *task;
	int ret = 1;
	unsigned long flags;

	spin_lock_irqsave(&hc_gpio_lock, flags);
	task = my_task;
	spin_unlock_irqrestore(&hc_gpio_lock, flags);
	
	if (task == NULL || task->exit_state != 0) 
	{
		writel(0xff, gpio->regs + GPIO_PORTA_EOI);
		irq_err_times ++;
		return IRQ_RETVAL(ret);
	}

	val = readl(gpio->regs + GPIO_INTSTATUS);
	if ((val & 0xff) == 0) {
		irq_err_times ++;
		writel(0xff, gpio->regs + GPIO_PORTA_EOI);
		printk("irq_err_times = %d, val=0x%x\n", irq_err_times, val);
		return IRQ_RETVAL(ret);
	}
	
	if (val & (1 << 0)) {
		GpioSetBit(gpio->regs + GPIO_PORTA_EOI, 0);
		printk("gpio0 a0 irq\n");
	}
   
	if (val & (1 << 1)) {
		GpioSetBit(gpio->regs + GPIO_PORTA_EOI, 1);
		printk("gpio0 a1 irq\n");
	}

	if (val & (1 << 2)) {
		GpioSetBit(gpio->regs + GPIO_PORTA_EOI, 2);
		send_sig_info(GPIO_SIGNAL2, SEND_SIG_FORCED, task);
		printk("gpio0 a2 irq\n");
	}
	
	if (val & (1 << 3)) {
		GpioSetBit(gpio->regs + GPIO_PORTA_EOI, 3);
		send_sig_info(GPIO_SIGNAL3, SEND_SIG_FORCED, task);
		printk("gpio0 a3 irq\n");
		
	}
	
	if (val & (1 << 4)) {
		GpioSetBit(gpio->regs + GPIO_PORTA_EOI, 4);
		send_sig_info(GPIO_SIGNAL4, SEND_SIG_FORCED, task);
		printk("gpio0 a4 irq\n");
	}
 
	if (val & (1 << 5)) {
		GpioSetBit(gpio->regs + GPIO_PORTA_EOI, 5);
   	send_sig_info(GPIO_SIGNAL5, SEND_SIG_FORCED, task);
		printk("gpio0 a5 irq\n");
	}
    return IRQ_HANDLED;
}


static int phytium_gpio_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct resource *res;
	struct phytium_gpio *gpio;
	struct fwnode_handle *fwnode;
	int err;
	int irq_port_flags = 0;

	gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
	if (!gpio)
		return -ENOMEM;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	gpio->regs = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(gpio->regs))
		return PTR_ERR(gpio->regs);

	//printk("0313: res->start=0x%lx, res->end=0x%lx\n",res->start,res->end);
	if (res->start == GPIO_IRQ_PORT_ADDR) {
		irq_port_flags = 1;
		printk("0313: irq_port_flags = 1\n");
	} else {
		printk("0313: irq_port_flags = 0\n");
	}
	
	gpio->irq = -ENXIO;
	gpio->irq = platform_get_irq(pdev, 0);
	if (gpio->irq < 0)
		dev_warn(dev, "no irq is found.\n");

	if (!device_get_child_node_count(dev))
		return -ENODEV;

	device_for_each_child_node(dev, fwnode) {
		int idx;

		if (fwnode_property_read_u32(fwnode, "reg", &idx) ||
		    idx >= MAX_NPORTS) {
			dev_err(dev, "missing/invalid port index\n");
			fwnode_handle_put(fwnode);
			return -EINVAL;
		}

		if (fwnode_property_read_u32(fwnode, "nr-gpios",
					     &gpio->ngpio[idx])) {
			dev_info(dev,
				 "failed to get number of gpios for Port%c\n",
				 idx ? 'B' : 'A');
			gpio->ngpio[idx] = NGPIO_DEFAULT;
		}
	}

	/* irq_chip support */
	raw_spin_lock_init(&gpio->lock);

	gpio->gc.base = -1;
	gpio->gc.get_direction = phytium_gpio_get_direction;
	gpio->gc.direction_input = phytium_gpio_direction_input;
	gpio->gc.direction_output = phytium_gpio_direction_output;
	gpio->gc.get = phytium_gpio_get;
	gpio->gc.set = phytium_gpio_set;
	gpio->gc.ngpio = gpio->ngpio[0] + gpio->ngpio[1];
	gpio->gc.label = dev_name(dev);
	gpio->gc.parent = dev;
	gpio->gc.owner = THIS_MODULE;

	err = gpiochip_add_data(&gpio->gc, gpio);
	if (err) {
		dev_err(dev, "failed to register gpiochip\n");
		goto err1;
	}

	err = gpiochip_irqchip_add(&gpio->gc, &phytium_gpio_irqchip,
				   0, handle_bad_irq, IRQ_TYPE_NONE);
	if (err) {
		dev_info(dev, "could not add irqchip\n");
		goto err0;
	}


	platform_set_drvdata(pdev, gpio);
	dev_info(dev, "Phytium GPIO controller @%pa registered\n",
		&res->start);

	if (irq_port_flags) {
		err = devm_request_irq(dev, gpio->irq, phytium_gpio_irq_handler_example,
			0, "phytium_gpio_irq", gpio);
		if (err) {
			dev_err(dev, "failed to request IRQ for GPIO %d, err=%d\n", gpio->irq, err);
			return err;
		}
		
		if ((major = register_chrdev(0, "hc_buttons_dev", &gpio_dev_fops)) < 0)
		{
			printk("failed to create dev entry.\n");
			return (0);
		}
		printk("register_chrdev successfully.\n");
		gpio_class = class_create(THIS_MODULE, "hc_buttondev");
		if (IS_ERR(gpio_class)) {
			printk("Could not create device class");
			unregister_chrdev(200, "gpdiohcdev");
			return EFAULT;
		}
		printk("gpio_class create successfully.\n");
		gpio_device = device_create(gpio_class, NULL, MKDEV(major, 0), NULL, "hc_buttons");
		
		printk("device to create ......%d\n",IS_ERR(gpio_device));
	}


	return 0;

err1:
	gpiochip_remove(&gpio->gc);
err0:
	return err;
}

static void buttons_dev_exit(void)
{
	if (gpio_device)
		device_unregister(gpio_device);
	gpio_device = NULL;

	if (gpio_class)	
		class_destroy(gpio_class);	
	gpio_class = NULL;

	if (major)
		unregister_chrdev(major, "hc_buttons_dev");
	major = 0;
    return;
}

static int phytium_gpio_remove(struct platform_device *pdev)
{
	
	struct phytium_gpio *gpio = platform_get_drvdata(pdev);

	buttons_dev_exit();
	gpiochip_remove(&gpio->gc);

	return 0;
}

#ifdef CONFIG_PM_SLEEP
static int phytium_gpio_suspend(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct phytium_gpio *gpio = platform_get_drvdata(pdev);
	unsigned long flags;

	raw_spin_lock_irqsave(&gpio->lock, flags);

	gpio->ctx.swporta_dr = readl(gpio->regs + GPIO_SWPORTA_DR);
	gpio->ctx.swporta_ddr = readl(gpio->regs + GPIO_SWPORTA_DDR);
	gpio->ctx.ext_porta = readl(gpio->regs + GPIO_EXT_PORTA);
	gpio->ctx.swportb_dr = readl(gpio->regs + GPIO_SWPORTB_DR);
	gpio->ctx.swportb_ddr = readl(gpio->regs + GPIO_SWPORTB_DDR);
	gpio->ctx.ext_portb = readl(gpio->regs + GPIO_EXT_PORTB);

	gpio->ctx.inten = readl(gpio->regs + GPIO_INTEN);
	gpio->ctx.intmask = readl(gpio->regs + GPIO_INTMASK);
	gpio->ctx.inttype_level = readl(gpio->regs + GPIO_INTTYPE_LEVEL);
	gpio->ctx.int_polarity = readl(gpio->regs + GPIO_INT_POLARITY);
	gpio->ctx.debounce = readl(gpio->regs + GPIO_DEBOUNCE);

	raw_spin_unlock_irqrestore(&gpio->lock, flags);

	return 0;
}

static int phytium_gpio_resume(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct phytium_gpio *gpio = platform_get_drvdata(pdev);
	unsigned long flags;

	raw_spin_lock_irqsave(&gpio->lock, flags);

	writel(gpio->ctx.swporta_dr, gpio->regs + GPIO_SWPORTA_DR);
	writel(gpio->ctx.swporta_ddr, gpio->regs + GPIO_SWPORTA_DDR);
	writel(gpio->ctx.ext_porta, gpio->regs + GPIO_EXT_PORTA);
	writel(gpio->ctx.swportb_dr, gpio->regs + GPIO_SWPORTB_DR);
	writel(gpio->ctx.swportb_ddr, gpio->regs + GPIO_SWPORTB_DDR);
	writel(gpio->ctx.ext_portb, gpio->regs + GPIO_EXT_PORTB);

	writel(gpio->ctx.inten, gpio->regs + GPIO_INTEN);
	writel(gpio->ctx.intmask, gpio->regs + GPIO_INTMASK);
	writel(gpio->ctx.inttype_level, gpio->regs + GPIO_INTTYPE_LEVEL);
	writel(gpio->ctx.int_polarity, gpio->regs + GPIO_INT_POLARITY);
	writel(gpio->ctx.debounce, gpio->regs + GPIO_DEBOUNCE);

	writel(0xffffffff, gpio->regs + GPIO_PORTA_EOI);

	raw_spin_unlock_irqrestore(&gpio->lock, flags);

	return 0;
}
#endif

static SIMPLE_DEV_PM_OPS(phytium_gpio_pm_ops, phytium_gpio_suspend,
			 phytium_gpio_resume);

static struct platform_driver phytium_gpio_driver = {
	.driver		= {
		.name	= "gpio-phytium-platform",
		.pm	= &phytium_gpio_pm_ops,
		.of_match_table = of_match_ptr(phytium_gpio_of_match),
		.acpi_match_table = ACPI_PTR(phytium_gpio_acpi_match),
	},
	.probe		= phytium_gpio_probe,
	.remove		= phytium_gpio_remove,
};

module_platform_driver(phytium_gpio_driver);

MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Chen Baozi <chenbaozi@phytium.com.cn>");
MODULE_DESCRIPTION("Phytium GPIO driver");

4、复用配置

引脚复用配置因为CPUA和CPUB不一样,因此不能共用一套代码,代码如下:

CPUA

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/serial.h>
#include <signal.h>

#include "ft20004_gpio.h"


int gpioInit(void)
{
	int ret;
	
	ret = gpio_mem_mmap();
	if (ret != 0) {
		printf("gpio memmap failed!\n");
		return -1;
	}
	//配置复用gpio管脚

	iomux_set_fun(GPIO_A2_MUX_PAD_PIN, FUNC_1);  //gpio0_a2
	iomux_set_fun(GPIO_A3_MUX_PAD_PIN, FUNC_1);  //gpio0_a3
	iomux_set_fun(GPIO_A4_MUX_PAD_PIN, FUNC_1);  //gpio0_a4
	iomux_set_fun(GPIO_A5_MUX_PAD_PIN, FUNC_1);  //gpio0_a5
	

	//set output-CPUA
	gpio_set_dir(GPIO0_A2_PIN, GPIO_DIRECTION_OUTPUT);  //设置gpio0 A2访问输出
	gpio_set_value(GPIO0_A2_PIN, 0); //设置初始值为0
	
	gpio_set_dir(GPIO0_A3_PIN, GPIO_DIRECTION_OUTPUT);  //设置gpio0 A3访问输出
	gpio_set_value(GPIO0_A3_PIN, 0); //设置初始值为0
	
	//中断配置
	//gpio_int_falledge(GPIO_ID_0, GPIO_A2_INT_PIN);  //设置gpio a2为中断信号
	//gpio_int_falledge(GPIO_ID_0, GPIO_A3_INT_PIN);  //设置gpio a3为中断信号
	gpio_int_falledge(GPIO_ID_0, GPIO_A4_INT_PIN);  //设置gpio a4为中断信号
	gpio_int_falledge(GPIO_ID_0, GPIO_A5_INT_PIN);  //设置gpio a5为中断信号
	
	gpio_mem_unmmap();
	return 0;	
	
}

/*
 *GPIO0 a0-a7:pin(0-7)
 *GPIO0 b0-b7:pin(8-15)
 *GPIO1 a0-a7:pin(16-23)
 *GPIO1 b0-b7:pin(24-31)
 */
int main(int argc, char **argv)
{
	int ret;

	ret = gpioInit();
	if (ret != 0) {
		printf("gpio init unsuccessfully!!!\n");
		return -1;
	}
    return 0;
}

CPUB

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/serial.h>
#include <signal.h>

#include "ft20004_gpio.h"


int gpioInit(void)
{
	int ret;
	
	ret = gpio_mem_mmap();
	if (ret != 0) {
		printf("gpio memmap failed!\n");
		return -1;
	}
	//配置复用gpio管脚

	iomux_set_fun(GPIO_A2_MUX_PAD_PIN, FUNC_1);  //gpio0_a2
	iomux_set_fun(GPIO_A3_MUX_PAD_PIN, FUNC_1);  //gpio0_a3
	iomux_set_fun(GPIO_A4_MUX_PAD_PIN, FUNC_1);  //gpio0_a4
	iomux_set_fun(GPIO_A5_MUX_PAD_PIN, FUNC_1);  //gpio0_a5
	

	//set output-CPUA
	gpio_set_dir(GPIO0_A4_PIN, GPIO_DIRECTION_OUTPUT);  //设置gpio0 A2访问输出
	gpio_set_value(GPIO0_A4_PIN, 0); //设置初始值为0
	
	gpio_set_dir(GPIO0_A5_PIN, GPIO_DIRECTION_OUTPUT);  //设置gpio0 A3访问输出
	gpio_set_value(GPIO0_A5_PIN, 0); //设置初始值为0
	
	//中断配置
	gpio_int_falledge(GPIO_ID_0, GPIO_A2_INT_PIN);  //设置gpio a2为中断信号
	gpio_int_falledge(GPIO_ID_0, GPIO_A3_INT_PIN);  //设置gpio a3为中断信号
	//gpio_int_falledge(GPIO_ID_0, GPIO_A4_INT_PIN);  //设置gpio a4为中断信号
	//gpio_int_falledge(GPIO_ID_0, GPIO_A5_INT_PIN);  //设置gpio a5为中断信号
	
	gpio_mem_unmmap();
	return 0;	
	
}

/*
 *GPIO0 a0-a7:pin(0-7)
 *GPIO0 b0-b7:pin(8-15)
 *GPIO1 a0-a7:pin(16-23)
 *GPIO1 b0-b7:pin(24-31)
 */
int main(int argc, char **argv)
{
	int ret;

	ret = gpioInit();
	if (ret != 0) {
		printf("gpio init unsuccessfully!!!\n");
		return -1;
	}
    return 0;
}

5、应用程序

接收中断程序如下,中断程序把GPIO 1-5号引脚都包含了,可以共用,代码如下:

lpc_interrupt.h文件

cpp 复制代码
#ifndef GPIO_IRQ_H
#define GPIO_IRQ_H
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <poll.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <linux/ioctl.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <sys/mman.h>

#undef TRUE
#ifndef TRUE
#define TRUE 1
#endif

#undef FALSE
#ifndef FALSE
#define FALSE 0
#endif

int bslIntDevOpen();
int bslIntDevClose();
int bslIntSetEn(int fd,unsigned int irq,unsigned int enable);
int bslIntRegister(int fd,unsigned int irq, unsigned int prio, void (* isr)(void*), void* data);
int bslIntUnregister(int fd,unsigned int irq);
int bslIntVersion(void);

#endif //GPIO_IRQ_H

lpc_interrupt.c

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/serial.h>
#include <semaphore.h>
#include <signal.h>
#include <pthread.h>
#include "lpc_interrupt.h"



#define LPC_PIDSWITCH_OFFSET 0x6B09uLL

#define LPC_SIGNAL1  40
#define LPC_SIGNAL2  41
#define LPC_SIGNAL3  42
#define LPC_SIGNAL4  43
#define LPC_SIGNAL5  44


int fd;

int g_flag1=0;
int g_flag2=0;
int g_flag3=0;
int g_flag4=0;
int g_flag5=0;


sem_t semGpioInt1;
sem_t semGpioInt2;
sem_t semGpioInt3;
sem_t semGpioInt4;
sem_t semGpioInt5;



#define IRQ_THREAD_NUM (5)
pthread_t gpio_irq_t[IRQ_THREAD_NUM];

void (*MyGpio1RecvFun)(void*) = NULL;
void (*MyGpio2RecvFun)(void*) = NULL;
void (*MyGpio3RecvFun)(void*) = NULL;
void (*MyGpio4RecvFun)(void*) = NULL;
void (*MyGpio5RecvFun)(void*) = NULL;


int bslIntVersion(void)
{
	char *version = "V2.3";
	printf("version:%s\n",version);
	return 0x23;
}

void my_signal_fun(int signum, siginfo_t *info, void *myact)
{
	if (signum == LPC_SIGNAL1 )
	{
		if(g_flag1==1)
		{
			sem_post(&semGpioInt1);
		}
	}
	else if (signum == LPC_SIGNAL2)
	{
		if(g_flag2==1)
		{
			sem_post (&semGpioInt2);
		}
	}
	else if (signum == LPC_SIGNAL3)
	{
		if(g_flag3==1)
		{
			sem_post (&semGpioInt3);
		}
	}
	else if (signum == LPC_SIGNAL4)
	{
		if(g_flag4==1)
		{
			sem_post (&semGpioInt4);
		}
	}
 	else if (signum == LPC_SIGNAL5)
	{
		if(g_flag5==1)
		{
			sem_post (&semGpioInt5);
		}
	}
}

void gpioIntTask1()
{
	while(1)
	{
		sem_wait(&semGpioInt1);
		if(MyGpio1RecvFun != NULL)
		{
			MyGpio1RecvFun(NULL);
		}
		else
		{

		}
	}
}

void gpioIntTask2()
{
	while(1)
	{
		sem_wait(&semGpioInt2);
		if(MyGpio2RecvFun != NULL)
		{
			MyGpio2RecvFun(NULL);
		}
		else
		{

		}
	}
}

void gpioIntTask3()
{
	while(1)
	{
		sem_wait(&semGpioInt3);
		if(MyGpio3RecvFun != NULL)
		{
			MyGpio3RecvFun(NULL);
		}
		else
		{

		}
	}
}

void gpioIntTask4()
{
	while(1)
	{
		sem_wait(&semGpioInt4);
		if(MyGpio4RecvFun != NULL)
		{
			MyGpio4RecvFun(NULL);
		}
		else
		{

		}
	}
}

void gpioIntTask5()
{
	while(1)
	{
		sem_wait(&semGpioInt5);
		if(MyGpio5RecvFun != NULL)
		{
			MyGpio5RecvFun(NULL);
		}
		else
		{

		}
	}
}

int bslIntDevOpen()
{
   int ret = -1;
	int pid = 0;

	struct sigaction sigio_act;
	cpu_set_t cpu_info;
	pthread_attr_t gpio_irq_attr[IRQ_THREAD_NUM];

	fd = open("/dev/hc_buttons", O_RDWR);
	if (fd < 0)
	{
		printf("can't open /dev/hc_buttons device!\n");
		return -1;
	}

	sigemptyset(&sigio_act.sa_mask);
	sigio_act.sa_sigaction = my_signal_fun;
	sigio_act.sa_flags = SA_SIGINFO;
	
	if(sigaction(LPC_SIGNAL1, &sigio_act, NULL) < 0)
	{
		printf("1 error\n");
	}

	if(sigaction(LPC_SIGNAL2, &sigio_act, NULL) < 0)
	{
		printf("2 error\n");
	}

	if(sigaction(LPC_SIGNAL3, &sigio_act, NULL) < 0)
	{
		printf("3 error\n");
	}

	if(sigaction(LPC_SIGNAL4, &sigio_act, NULL) < 0)
	{
		printf("4 error\n");
	}

	if(sigaction(LPC_SIGNAL5, &sigio_act, NULL) < 0)
	{
		printf("5 error\n");
	}
 
	pid = getpid();
	printf("call ioctl. pid = %d \n", pid);
	printf("set fcntl FASYNC ok!\n");
	ret = ioctl(fd, LPC_PIDSWITCH_OFFSET, &pid);

	if(ret == 0)
	{
		printf("<log> Lpc Interrupt sendpid success!\n");
	}
	else
	{
		printf("<err> Lpc Interrupt sendpid failed!\n");
	}

	ret = sem_init(&semGpioInt1, 0, 0);
	if (ret != 0)
	{
		printf("semGpioInt1 sem_init :failed.\n");
		return EXIT_FAILURE;
	}
	ret = sem_init(&semGpioInt2, 0, 0);
	if (ret != 0)
	{
		printf("semGpioInt2 sem_init :failed.\n");
		return EXIT_FAILURE;
	}
	ret = sem_init(&semGpioInt3, 0, 0);
	if (ret != 0)
	{
		printf("semGpioInt3 sem_init :failed.\n");
		return EXIT_FAILURE;
	}
	ret = sem_init(&semGpioInt4, 0, 0);
	if (ret != 0)
	{
		printf("semGpioInt4 sem_init :failed.\n");
		return EXIT_FAILURE;
	}
 
 	ret = sem_init(&semGpioInt5, 0, 0);
	if (ret != 0)
	{
		printf("semGpioInt4 sem_init :failed.\n");
		return EXIT_FAILURE;
	}
	
	pthread_attr_init(&gpio_irq_attr[0]);
	if( 0!= pthread_create(&gpio_irq_t[0],&gpio_irq_attr[0],gpioIntTask1,(void*)0))
	{
		printf("fail to create gpioIntTask1.\n");
		return(EXIT_FAILURE);
	}
	CPU_ZERO(&cpu_info);
	CPU_SET(3,&cpu_info);
	if( 0 != pthread_setaffinity_np(gpio_irq_t[0],sizeof(cpu_set_t),&cpu_info))
	{
		printf("gpioIntTask1:set affinity failed\n");
	}

	pthread_attr_init(&gpio_irq_attr[1]);
	if( 0!= pthread_create(&gpio_irq_t[1],&gpio_irq_attr[1],gpioIntTask2,(void*)0))
	{
		printf("fail to create gpioIntTask2.\n");
		return(EXIT_FAILURE);
	}
	CPU_ZERO(&cpu_info);
	CPU_SET(3,&cpu_info);
	if( 0 != pthread_setaffinity_np(gpio_irq_t[1],sizeof(cpu_set_t),&cpu_info))
	{
		printf("gpioIntTask2:set affinity failed\n");
	}

	pthread_attr_init(&gpio_irq_attr[2]);
	if( 0!= pthread_create(&gpio_irq_t[2],&gpio_irq_attr[2],gpioIntTask3,(void*)0))
	{
		printf("fail to create gpioIntTask3.\n");
		return(EXIT_FAILURE);
	}
	CPU_ZERO(&cpu_info);
	CPU_SET(3,&cpu_info);
	if( 0 != pthread_setaffinity_np(gpio_irq_t[2],sizeof(cpu_set_t),&cpu_info))
	{
		printf("gpioIntTask3:set affinity failed\n");
	}

	pthread_attr_init(&gpio_irq_attr[3]);
	if( 0!= pthread_create(&gpio_irq_t[3],&gpio_irq_attr[3],gpioIntTask4,(void*)0))
	{
		printf("fail to create gpioIntTask4.\n");
		return(EXIT_FAILURE);
	}
	CPU_ZERO(&cpu_info);
	CPU_SET(3,&cpu_info);
	if( 0 != pthread_setaffinity_np(gpio_irq_t[3],sizeof(cpu_set_t),&cpu_info))
	{
		printf("gpioIntTask4:set affinity failed\n");
	}
 
 
 	pthread_attr_init(&gpio_irq_attr[4]);
	if( 0!= pthread_create(&gpio_irq_t[4],&gpio_irq_attr[4],gpioIntTask5,(void*)0))
	{
		printf("fail to create gpioIntTask5.\n");
		return(EXIT_FAILURE);
	}
	CPU_ZERO(&cpu_info);
	CPU_SET(3,&cpu_info);
	if( 0 != pthread_setaffinity_np(gpio_irq_t[4],sizeof(cpu_set_t),&cpu_info))
	{
		printf("gpioIntTask5:set affinity failed\n");
	}
   return fd;
}

int bslIntDevClose()
{
	pthread_join(gpio_irq_t[0],NULL);
	pthread_join(gpio_irq_t[1],NULL);
	pthread_join(gpio_irq_t[2],NULL);
	pthread_join(gpio_irq_t[3],NULL);
 	pthread_join(gpio_irq_t[4],NULL);


	sem_destroy(&semGpioInt1);
	sem_destroy(&semGpioInt2);
	sem_destroy(&semGpioInt3);
	sem_destroy(&semGpioInt4);
 	sem_destroy(&semGpioInt5);

	close(fd);
	return 0;
}

int bslIntRegister(int fd,unsigned int irq, unsigned int prio, void (* isr)(void*), void* data)
{
	switch(irq)
	{
	case 1:
		if(isr != NULL)
		{
			MyGpio1RecvFun = isr;
		}
		break;
	case 2:
		if(isr != NULL)
		{
			MyGpio2RecvFun = isr;
		}
		break;
	case 3:
		if(isr != NULL)
		{
			MyGpio3RecvFun = isr;
		}
		break;
	case 4:
		if(isr != NULL)
		{
			MyGpio4RecvFun = isr;
		}
		break;
 	case 5:
		if(isr != NULL)
		{
			MyGpio5RecvFun = isr;
		}
		break;
	default:
		printf("ERROR! WRONG IRQ NUMBER, IRQ NUMBER VALUE 1-8\n");
		return 0;
	}
	return 1;
}

int bslIntUnregister(int fd,unsigned int irq)
{
	switch(irq)
	{
	case 1:
		MyGpio1RecvFun=NULL;
		break;
	case 2:
		MyGpio2RecvFun=NULL;
		break;
	case 3:
		MyGpio3RecvFun=NULL;
		break;
	case 4:
		MyGpio4RecvFun=NULL;
		break;
 	case 5:
		MyGpio5RecvFun=NULL;
		break;
	default:
		printf("ERROR! WRONG IRQ NUMBER, IRQ NUMBER VALUE 1-8\n");
		return 0;
	}
	return 1;
}

int bslIntSetEn(int fd,unsigned int irq,unsigned int enable)
{
	switch(irq)
	{
	case 1:
		if(enable==TRUE)
		{
			g_flag1=1;
		}
		else
		{
			g_flag1=0;
		}
		break;
	case 2:
		if(enable==TRUE)
		{
			g_flag2=1;
		}
		else
		{
			g_flag2=0;
		}
		break;
	case 3:
		if(enable==TRUE)
		{
			g_flag3=1;
		}
		else
		{
			g_flag3=0;
		}
		break;
	case 4:
		if(enable==TRUE)
		{
			g_flag4=1;
		}
		else
		{
			g_flag4=0;
		}
		break;
 	case 5:
		if(enable==TRUE)
		{
			g_flag5=1;
		}
		else
		{
			g_flag5=0;
		}
		break;
	default:
		printf("ERROR! WRONG IRQ NUMBER, IRQ NUMBER VALUE 1-8\n");
		return 0;
	}
	return 1;
}

hello.c

cpp 复制代码
/*
 ============================================================================
 Name        : hello.c
 Author      : felven
 Version     :
 Copyright   : Your copyright notice
 Description : Hello World in C, Ansi-style
 ============================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "lpc_interrupt.h"

void hello0()
{
 	printf("recv gpio-1 irp\n");
}

void hello1()
{
 	printf("recv gpio-2 irp \n");
}

void hello2()
{
 	printf("recv gpio-3 irp \n");
}

void hello3()
{
 	printf("recv gpio-4 irp\n");
}

void hello4()
{
 	printf("recv gpio-5 irp\n");
}

int main() {
	int fd = 0;
	int ret = 0;
	unsigned long flag = 0;

	fd = bslIntDevOpen();
	if (fd < 0) {
		printf("open device error\n");
		goto error;
	}

	ret = bslIntRegister(fd, 1, 1, hello0, (void*) flag);
	ret = bslIntRegister(fd, 2, 1, hello1, (void*) flag);
	ret = bslIntRegister(fd, 3, 1, hello2, (void*) flag);
	ret = bslIntRegister(fd, 4, 1, hello3, (void*) flag);
 	ret = bslIntRegister(fd, 5, 1, hello4, (void*) flag);
	if (ret < 0) {
		goto error;
	}

	printf("enable irq\n");
	ret = bslIntSetEn(fd, 1, TRUE);
	ret = bslIntSetEn(fd, 2, TRUE);
	ret = bslIntSetEn(fd, 3, TRUE);
	ret = bslIntSetEn(fd, 4, TRUE);
 	ret = bslIntSetEn(fd, 5, TRUE);
	if (ret < 0) {
		goto error;
	}
while(1)
	sleep(100);
	printf("disable irq\n");
	ret = bslIntSetEn(fd, 1, FALSE);
	ret = bslIntSetEn(fd, 2, FALSE);
	ret = bslIntSetEn(fd, 3, FALSE);
	ret = bslIntSetEn(fd, 4, FALSE);
 	ret = bslIntSetEn(fd, 5, FALSE);


	ret = bslIntUnregister(fd, 1);
	ret = bslIntUnregister(fd, 2);
	ret = bslIntUnregister(fd, 3);
	ret = bslIntUnregister(fd, 4);
 	ret = bslIntUnregister(fd, 5);
	if (ret < 0) {
		goto error;
	}

	ret = bslIntDevClose();
	if (ret < 0) {
		goto error;
	}

	error: return 0;
}

6、测试

CPUA通过写GPIO产生高低电平,触发中断,代码如下

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/serial.h>
#include <signal.h>

#include "ft20004_gpio.h"


int gpioInit(void)
{
	int ret;
	
	ret = gpio_mem_mmap();
	if (ret != 0) {
		printf("gpio memmap failed!\n");
		return -1;
	}

	while(1)
	{
		printf("set CPUA GPIO value 1\n");
		//set output-CPUA
		gpio_set_value(GPIO0_A2_PIN, 1); //设置初始值为0
		sleep(1);

		gpio_set_value(GPIO0_A3_PIN, 1); //设置初始值为0
		sleep(1);

		printf("set CPUA GPIO value 0\n");
		//set output-CPUA
		gpio_set_value(GPIO0_A2_PIN, 0); //设置初始值为0
		sleep(1);

		gpio_set_value(GPIO0_A3_PIN, 0); //设置初始值为0
		sleep(1);
	}
	
	
	gpio_mem_unmmap();
	return 0;	
	
}

/*
 *GPIO0 a0-a7:pin(0-7)
 *GPIO0 b0-b7:pin(8-15)
 *GPIO1 a0-a7:pin(16-23)
 *GPIO1 b0-b7:pin(24-31)
 */
int main(int argc, char **argv)
{
	int ret;

	ret = gpioInit();
	if (ret != 0) {
		printf("gpio init unsuccessfully!!!\n");
		return -1;
	}
    return 0;
}

CPUB也类似

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/serial.h>
#include <signal.h>

#include "ft20004_gpio.h"


int gpioInit(void)
{
	int ret;
	
	ret = gpio_mem_mmap();
	if (ret != 0) {
		printf("gpio memmap failed!\n");
		return -1;
	}

	while(1)
	{
		printf("set CPUB GPIO value 1\n");
		//set output-CPUA
		gpio_set_value(GPIO0_A4_PIN, 1); //设置初始值为0
		sleep(1);

		gpio_set_value(GPIO0_A5_PIN, 1); //设置初始值为0
		sleep(1);

		printf("set CPUB GPIO value 0\n");
		//set output-CPUA
		gpio_set_value(GPIO0_A4_PIN, 0); //设置初始值为0
		sleep(1);

		gpio_set_value(GPIO0_A5_PIN, 0); //设置初始值为0
		sleep(1);
	}
	
	
	gpio_mem_unmmap();
	return 0;	
	
}

/*
 *GPIO0 a0-a7:pin(0-7)
 *GPIO0 b0-b7:pin(8-15)
 *GPIO1 a0-a7:pin(16-23)
 *GPIO1 b0-b7:pin(24-31)
 */
int main(int argc, char **argv)
{
	int ret;

	ret = gpioInit();
	if (ret != 0) {
		printf("gpio init unsuccessfully!!!\n");
		return -1;
	}
    return 0;
}

结果如下:

CPUA发送:

CPUB收到中断

CPUB发送

CPUA收到中断

这样可以同时实现CPUA和CPUB触发中断。

相关推荐
喵了meme2 小时前
Linux学习日记21:读写锁
linux·c语言·学习
^乘风破浪^3 小时前
Ubuntu部署Xingrin(星环)企业级漏洞扫描与资产管理平台
linux·运维·ubuntu
Lueeee.3 小时前
内核模块符号的导出
linux·运维·服务器
C语言魔术师3 小时前
【linux】linux进程概念(四)(环境变量)
linux·运维·服务器
松涛和鸣3 小时前
DAY32 Linux Thread Programming
linux·运维·数据库·算法·list
eggrall3 小时前
《gdb 与 cgdb 深度解析:命令行调试的效率革命》
linux
晨曦夜月4 小时前
头文件与目标文件的关系
linux·开发语言·c++
白仑色4 小时前
java中的anyMatch和allMatch方法
java·linux·windows·anymatch·allmatch
yimengsama4 小时前
VMWare虚拟机如何连接U盘
linux·运维·服务器·网络·windows·经验分享·远程工作