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
// 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
#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
#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文件
#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_Hlpc_interrupt.c
#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
/* ============================================================================ 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产生高低电平,触发中断,代码如下
#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也类似
#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触发中断。