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触发中断。