реклама на сайте
подробности

 
 
> PCIe Driver
doom13
сообщение Jul 29 2015, 07:43
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539



Приветствую.
Есть плата с Virtex 7, надо забросить данные в ПК по PCIe. Ранее такого не делал и есь трудности.
В FPGA собрана система: GPIO, Timer, PCIe Bridge (регистры GPIO и таймера смапированы на адресное пространство BAR0). Разбираюсь в написании модулей ядра Linux (использую Ubuntu 15.04).
Пока реализовал управление GPIO при загрузке/выгрузке модуля в Linux. Хочу добавить прерывание. В FPGA линия interrupt от таймера заводится на PCIe-мост, он должен запихнуть его в систему.
Для настройки прерывания в драйвере использую:
Код
irq_handler_t timer_isr(unsigned int irq, void *dev);
struct pci_dev *pdev;
char irq;
...
pci_read_config_byte( pdev, PCI_INTERRUPT_LINE, &irq ); // для моей платы получаю irq = 11
request_irq(irq_num, timer_isr, IRQF_TRIGGER_RISING, "PCIe INT", (void *)pdev);
...


Функция pci_read_config_byte() установит irq = 11.

Далее настраиваю таймер, чтобы генерировал прерывание и стартую его. В syslog вижу следующее сообщение
Цитата
Jul 29 10:57:49 user-pc kernel: [ 797.188154] irq 16: nobody cared (try booting with the "irqpoll" option)
Jul 29 10:57:49 user-pc kernel: [ 797.188158] CPU: 7 PID: 0 Comm: swapper/7 Tainted: G OE 3.19.0-25-generic #26-Ubuntu
Jul 29 10:57:49 user-pc kernel: [ 797.188159] Hardware name: Gigabyte Technology Co., Ltd. To be filled by O.E.M./Z77P-D3, BIOS F7 08/24/2012
Jul 29 10:57:49 user-pc kernel: [ 797.188160] ffff880408dc92a4 ffff88041edc3e28 ffffffff817c4518 0000000000040400
Jul 29 10:57:49 user-pc kernel: [ 797.188162] ffff880408dc9200 ffff88041edc3e58 ffffffff810d0e86 ffff88041edc3e88
Jul 29 10:57:49 user-pc kernel: [ 797.188164] ffff880408dc9200 0000000000000000 0000000000000010 ffff88041edc3e98
Jul 29 10:57:49 user-pc kernel: [ 797.188165] Call Trace:
Jul 29 10:57:49 user-pc kernel: [ 797.188166] <IRQ> [<ffffffff817c4518>] dump_stack+0x45/0x57
Jul 29 10:57:49 user-pc kernel: [ 797.188174] [<ffffffff810d0e86>] __report_bad_irq+0x36/0xd0
Jul 29 10:57:49 user-pc kernel: [ 797.188175] [<ffffffff810d1237>] note_interrupt+0x267/0x2b0
Jul 29 10:57:49 user-pc kernel: [ 797.188177] [<ffffffff810ce8c3>] handle_irq_event_percpu+0x133/0x1a0
Jul 29 10:57:49 user-pc kernel: [ 797.188179] [<ffffffff810ce971>] handle_irq_event+0x41/0x70
Jul 29 10:57:49 user-pc kernel: [ 797.188181] [<ffffffff810d1666>] handle_fasteoi_irq+0x86/0x140
Jul 29 10:57:49 user-pc kernel: [ 797.188182] [<ffffffff81017772>] handle_irq+0x22/0x40
Jul 29 10:57:49 user-pc kernel: [ 797.188184] [<ffffffff817ce55f>] do_IRQ+0x4f/0xf0
Jul 29 10:57:49 user-pc kernel: [ 797.188186] [<ffffffff817cc36d>] common_interrupt+0x6d/0x6d
Jul 29 10:57:49 user-pc kernel: [ 797.188186] <EOI> [<ffffffff816663b5>] ? cpuidle_enter_state+0x65/0x160
Jul 29 10:57:49 user-pc kernel: [ 797.188190] [<ffffffff816663a1>] ? cpuidle_enter_state+0x51/0x160
Jul 29 10:57:49 user-pc kernel: [ 797.188192] [<ffffffff81666597>] cpuidle_enter+0x17/0x20
Jul 29 10:57:49 user-pc kernel: [ 797.188195] [<ffffffff810b7ce1>] cpu_startup_entry+0x311/0x3b0
Jul 29 10:57:49 user-pc kernel: [ 797.188198] [<ffffffff81049107>] start_secondary+0x197/0x1c0
Jul 29 10:57:49 user-pc kernel: [ 797.188199] handlers:
Jul 29 10:57:49 user-pc kernel: [ 797.188202] [<ffffffff815bb130>] usb_hcd_irq
Jul 29 10:57:49 user-pc kernel: [ 797.188204] Disabling IRQ #16


Получается PCIe мост при наличии прерывания от таймера выдаёт его на 16 линию. Для просмотра оборудования в системе установлен System Profiler, для моего устройства он показывает IRQ = 16 (рисунок).
Если пытаюсь использовать 16 линию прерывания в функции request_irq, она выдаёт ошибку.
Код
request_irq(16, timer_isr, IRQF_TRIGGER_RISING, "PCIe INT", (void *)pdev);

Вопрос, что я делаю не так? Почему в конфигурационной области моего устройства записано 11 (Interrupt Line), а прерывание срабатывает на 16 линии?

Код модуля:
CODE

/* Necessary includes for device drivers */
#include <linux/init.h>
//#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/proc_fs.h>
#include <linux/fcntl.h> /* O_ACCMODE */
#include <linux/pci.h>
#include <linux/pci_regs.h>
#include <linux/interrupt.h>
//#include <asm/system.h> /* cli(), *_flags */
#include <asm/uaccess.h> /* copy_from/to_user */

#include "hardware.h"
#include "timer.h"

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Andrei Hres");
MODULE_DESCRIPTION("Driver for /dev/virtex7_pcie");
MODULE_SUPPORTED_DEVICE("virtex7_pcie");

#define __DEBUG_MODE
#define DRV_NAME "virtex7_pcie"

#define BAR0 0
#define BAR1 1
#define BAR2 2
#define BAR3 3
#define BAR4 4
#define BAR5 5

int virtex7_pcie_init(void);
void virtex7_pcie_exit(void);
int virtex7_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
void virtex7_pcie_remove(struct pci_dev *pdev);

irq_handler_t timer_isr(unsigned int irq, void *dev);
int irq_status;
char irq_num;

char *bar0_base;
unsigned long *pio_base;

static struct pci_device_id virtex7_pcie_ids[] = { {PCI_DEVICE(0x10EE, 0x7014)}, {0,} };

MODULE_DEVICE_TABLE(pci, virtex7_pcie_ids);

static struct pci_driver virtex7_pcie_driver = {
.name = DRV_NAME,
.probe = virtex7_pcie_probe,
.remove = virtex7_pcie_remove,
.id_table = virtex7_pcie_ids,
//#ifdef CONFIG_PM
// .suspend = pcie_suspend,
// .resume = pcie_resume,
//#endif /* CONFIG_PM */
};

//static int __init virtex7_pcie_init(void)
int virtex7_pcie_init(void)
{
printk(KERN_ALERT "*****************************************\n");
printk(KERN_ALERT "Inserting PCIe module\n");
return pci_register_driver(&virtex7_pcie_driver);
}

//static void __exit virtex7_pcie_exit(void)
void virtex7_pcie_exit(void)
{
printk(KERN_ALERT "Removing PCIe module\n");
pci_unregister_driver(&virtex7_pcie_driver);
printk(KERN_ALERT "*****************************************\n");
}

int virtex7_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
int status;
int st;
unsigned long data;
char byte2;
unsigned long bar0_start;
unsigned long bar0_end;
unsigned long *pio_reg;

printk(KERN_ALERT "Entering PCIe probe() function\n");

status = pci_enable_device(pdev);

if(status == 0)
{
printk(KERN_ALERT "PCIe device is succesfully enabled\n");
printk(KERN_ALERT "vendor: 0x%.4X\n", pdev->vendor);
printk(KERN_ALERT "device: 0x%.4X\n", pdev->device);

pci_read_config_dword(pdev, 0, &data);
printk(KERN_ALERT "Data from config space: 0x%.8X\n", data);
pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &irq_num);
printk(KERN_ALERT " PCI_INTERRUPT_LINE=%d\n", irq_num);

//irq_num = 16;

pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &byte2);
printk(KERN_ALERT " PCI_INTERRUPT_PIN=%d\n", byte2);

bar0_start = pci_resource_start(pdev, BAR0);
bar0_end = pci_resource_end(pdev, BAR0);
printk(KERN_ALERT "BAR0 start address: 0x%.8X\n", bar0_start);
printk(KERN_ALERT "BAR0 end address: 0x%.8X\n", bar0_end);
printk(KERN_ALERT "BAR0 size: %u bytes = %u kB\n", bar0_end-bar0_start, (bar0_end-bar0_start+1)/1024);

//pio_reg = (unsigned long *) (bar0_start + 0x8000);
//*pio_reg = 0xFFFFFFFF;

//----------------------------------------------------------------

st = pci_request_region(pdev, BAR0, "virtex7_pcie_bar0");
if(st == 0)
{
printk(KERN_ALERT "Request region success\n");
bar0_base = pci_iomap(pdev, BAR0, 0);
printk(KERN_ALERT "bar0_base: 0x%.16X\n", (unsigned int) bar0_base);

pio_base = (unsigned long *) (bar0_base + 32768);
printk(KERN_ALERT "pio_base: 0x%.16X\n", (unsigned int) pio_base);

//*(unsigned long *)(bar0_base + 32768) = 0x1;
*pio_base = 0x1;

Timer_Init(bar0_base + TIMER_0_OFFSET_BYTES);
Timer_IntClear(bar0_base + TIMER_0_OFFSET_BYTES);
data = Timer_DbgRdCSR(bar0_base + TIMER_0_OFFSET_BYTES);
printk(KERN_ALERT "Timer CSR: 0x%.8X\n", (unsigned int) data);

// free_irq(irq_num, (void *)pdev);
irq_status = request_irq(irq_num, timer_isr, IRQF_TRIGGER_RISING/* | IRQF_SHARED*/, "PCIe INT", (void *)pdev);
if(irq_status)
printk(KERN_ALERT "request_irq() error\n");
else
{
printk(KERN_ALERT "request_irq() success\n");
Timer_Start(bar0_base + TIMER_0_OFFSET_BYTES);
}

Timer_IntClear(bar0_base + TIMER_0_OFFSET_BYTES);
data = Timer_DbgRdCSR(bar0_base + TIMER_0_OFFSET_BYTES);
printk(KERN_ALERT "Timer CSR: 0x%.8X\n", (unsigned int) data);
}

//pio_base = (unsigned char *) (addr_bar0 + 0x8000);
//----------------------------------------------------------------
}

return status;
}

void virtex7_pcie_remove(struct pci_dev *pdev)
{
*pio_base = 0;


printk(KERN_ALERT "Disable PCIe device\n");
pci_disable_device(pdev);
pci_release_region(pdev, BAR0);

if(irq_status == 0)
{
free_irq(irq_num, (void *)pdev);
Timer_Stop(bar0_base + TIMER_0_OFFSET_BYTES);
printk(KERN_ALERT "Free PCI interrupt line #%d\n", irq_num);
}
}

module_init(virtex7_pcie_init);
module_exit(virtex7_pcie_exit);

irq_handler_t timer_isr(unsigned int irq, void *dev)
{
static int int_counter = 0;

if(Timer_IntStatus(bar0_base + TIMER_0_OFFSET_BYTES))
{
Timer_IntClear(bar0_base + TIMER_0_OFFSET_BYTES);
}

printk(KERN_ALERT "Interrupt counter %d\n", int_counter);
int_counter++;

return IRQ_NONE;
}


Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- doom13   PCIe Driver   Jul 29 2015, 07:43
- - doom13   Прерывание стало работать со следующими изменениям...   Jul 29 2015, 11:28
- - doom13   Предположил, что раз система видит устройство как ...   Jul 31 2015, 06:47
- - Tarbal   Насколько я понимаю вопрос. PCI имеет механизмы об...   Jul 31 2015, 11:45
|- - doom13   Цитата(Tarbal @ Jul 31 2015, 14:45) Наско...   Jul 31 2015, 14:37
- - doom13   Попробовал поменять местами видеокарту и мою плату...   Aug 4 2015, 06:40
- - doom13   Как правильно со стороны ядра выделить память, что...   Aug 6 2015, 06:12
- - doom13   Последний вопрос снят. Посмотрел старую инфу, где ...   Aug 6 2015, 07:20
- - gerber   Система не может взять и выделить PCI-устройству л...   Aug 6 2015, 09:14
- - doom13   На рисунке Configuration Space для устройства PCIe...   Aug 6 2015, 11:01
|- - gerber   Цитата(doom13 @ Aug 6 2015, 15:01) На рис...   Aug 8 2015, 15:10
||- - doom13   Цитата(gerber @ Aug 8 2015, 18:10) Interr...   Aug 10 2015, 09:43
||- - gerber   Цитата(doom13 @ Aug 10 2015, 13:43) Каким...   Aug 10 2015, 16:22
|- - Tarbal   Цитата(doom13 @ Aug 6 2015, 15:01) Откуда...   Aug 17 2015, 13:08
- - doom13   Хочу ещё спросить по поводу MSI. Добавил в ядро PC...   Aug 6 2015, 13:25
- - doom13   В драйвере есть операции работы с файлом драйвера ...   Aug 13 2015, 11:51
- - doom13   Посмотрел примеры драйверов, все, оказывается, пол...   Aug 13 2015, 13:33
- - gerber   "Нативными" методами работы с драйверами...   Aug 13 2015, 21:15
- - doom13   Ясно, пользуемся open, read, write, close и всё бу...   Aug 14 2015, 06:28
- - doom13   Приветствую! Возник вопрос, какой максимальный...   Sep 30 2015, 11:27
- - doom13   Если использовать alloc_pages, то вообще выделяет ...   Sep 30 2015, 12:33
|- - AVR   Цитата(doom13 @ Sep 30 2015, 15:33) Если ...   Jul 16 2016, 14:39
|- - dm.pogrebnoy   Цитата(AVR @ Jul 16 2016, 17:39) Так это ...   Jul 16 2016, 18:00
|- - AVR   Цитата(dm.pogrebnoy @ Jul 16 2016, 21:00)...   Jul 16 2016, 18:21
|- - dm.pogrebnoy   Цитата(AVR @ Jul 16 2016, 21:21) Я может ...   Jul 16 2016, 19:15
- - doom13   Приветствую. В функции инициализации модуля pcievx...   Dec 15 2015, 19:32
|- - Tarbal   Я бы поле имени pdev->driver->name напечатал...   Dec 16 2015, 02:08
|- - doom13   Цитата(Tarbal @ Dec 16 2015, 05:08) Я бы ...   Dec 16 2015, 07:38
- - doom13   Надо было так: Кодstatic int pcievx7_probe(str...   Dec 16 2015, 11:15


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 24th June 2025 - 08:43
Рейтинг@Mail.ru


Страница сгенерированна за 0.01687 секунд с 7
ELECTRONIX ©2004-2016