|
|
  |
Zynq, Petalinux, прерывания и заголовочные файлы |
|
|
|
Apr 11 2018, 12:47
|
Участник

Группа: Участник
Сообщений: 66
Регистрация: 8-07-13
Пользователь №: 77 442

|
Здравствуйте! Хочу обработать прерывания от AXI Timer в линуксе. На сайте xilinx нарыл пример. CODE #include <linux/kernel.h> #include <linux/module.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <asm/io.h>
MODULE_LICENSE("GPL");
#define DEVICE_NAME "xilaxitimer"
#define IRQ_NUM 91
#define XIL_AXI_TIMER_BASEADDR 0x41C00000 #define XIL_AXI_TIMER_HIGHADDR 0x41C0FFFF
#define XIL_AXI_TIMER_TCSR_OFFSET 0x0 #define XIL_AXI_TIMER_TLR_OFFSET 0x4 #define XIL_AXI_TIMER_TCR_OFFSET 0x8 #define XIL_AXI_TIMER_CSR_INT_OCCURED_MASK 0x00000100
#define XIL_AXI_TIMER_CSR_CASC_MASK 0x00000800 #define XIL_AXI_TIMER_CSR_ENABLE_ALL_MASK 0x00000400 #define XIL_AXI_TIMER_CSR_ENABLE_PWM_MASK 0x00000200 #define XIL_AXI_TIMER_CSR_INT_OCCURED_MASK 0x00000100 #define XIL_AXI_TIMER_CSR_ENABLE_TMR_MASK 0x00000080 #define XIL_AXI_TIMER_CSR_ENABLE_INT_MASK 0x00000040 #define XIL_AXI_TIMER_CSR_LOAD_MASK 0x00000020 #define XIL_AXI_TIMER_CSR_AUTO_RELOAD_MASK 0x00000010 #define XIL_AXI_TIMER_CSR_EXT_CAPTURE_MASK 0x00000008 #define XIL_AXI_TIMER_CSR_EXT_GENERATE_MASK 0x00000004 #define XIL_AXI_TIMER_CSR_DOWN_COUNT_MASK 0x00000002 #define XIL_AXI_TIMER_CSR_CAPTURE_MODE_MASK 0x00000001
#define TIMER_CNT 0xF8000000
static struct platform_device *pdev; void *dev_virtaddr; static int int_cnt;
static irqreturn_t xilaxitimer_isr(int irq,void*dev_id) { unsigned int data; /* * Check Timer Counter Value */ data = ioread32(dev_virtaddr + XIL_AXI_TIMER_TCR_OFFSET); printk("xilaxitimer_isr: Interrupt Occurred ! Timer Count = 0x%08X\n",data); /* * Clear Interrupt */ data = ioread32(dev_virtaddr + XIL_AXI_TIMER_TCSR_OFFSET); iowrite32(data | XIL_AXI_TIMER_CSR_INT_OCCURED_MASK, dev_virtaddr + XIL_AXI_TIMER_TCSR_OFFSET); /* * Disable Timer after 100 Interrupts */ int_cnt++; if (int_cnt>=100) { printk("xilaxitimer_isr: 100 interrupts have been occurred. Disabling timer"); data = ioread32(dev_virtaddr + XIL_AXI_TIMER_TCSR_OFFSET); iowrite32(data & ~(XIL_AXI_TIMER_CSR_ENABLE_TMR_MASK), dev_virtaddr + XIL_AXI_TIMER_TCSR_OFFSET); } return IRQ_HANDLED; }
static int __init xilaxitimer_init(void) { unsigned int data; int_cnt = 0; printk(KERN_INFO "xilaxitimer_init: Initialize Module \"%s\"\n", DEVICE_NAME); /* * Register ISR */ if (request_irq(IRQ_NUM, xilaxitimer_isr, 0, DEVICE_NAME, NULL)) { printk(KERN_ERR "xilaxitimer_init: Cannot register IRQ %d\n", IRQ_NUM); return -EIO; } else { printk(KERN_INFO "xilaxitimer_init: Registered IRQ %d\n", IRQ_NUM); } /* * Map Physical address to Virtual address */ dev_virtaddr = ioremap_nocache(XIL_AXI_TIMER_BASEADDR, XIL_AXI_TIMER_HIGHADDR - XIL_AXI_TIMER_BASEADDR + 1); /* * Set Timer Counter */ iowrite32(TIMER_CNT, dev_virtaddr + XIL_AXI_TIMER_TLR_OFFSET); data = ioread32(dev_virtaddr + XIL_AXI_TIMER_TLR_OFFSET); printk("xilaxitimer_init: Set timer count 0x%08X\n",data); /* * Set Timer mode and enable interrupt */ iowrite32(XIL_AXI_TIMER_CSR_LOAD_MASK, dev_virtaddr + XIL_AXI_TIMER_TCSR_OFFSET); iowrite32(XIL_AXI_TIMER_CSR_ENABLE_INT_MASK | XIL_AXI_TIMER_CSR_AUTO_RELOAD_MASK, dev_virtaddr + XIL_AXI_TIMER_TCSR_OFFSET);
/* * Register Device Module */ pdev = platform_device_register_simple(DEVICE_NAME, 0, NULL, 0); if (pdev == NULL) { printk(KERN_WARNING "xilaxitimer_init: Adding platform device \"%s\" failed\n", DEVICE_NAME); kfree(pdev); return -ENODEV; } /* * Start Timer */ data = ioread32(dev_virtaddr + XIL_AXI_TIMER_TCSR_OFFSET); iowrite32(data | XIL_AXI_TIMER_CSR_ENABLE_TMR_MASK, dev_virtaddr + XIL_AXI_TIMER_TCSR_OFFSET);
return 0; }
static void __exit xilaxitimer_edit(void) { /* * Exit Device Module */ iounmap(dev_virtaddr); free_irq(IRQ_NUM, NULL); platform_device_unregister(pdev); printk(KERN_INFO "xilaxitimer_edit: Exit Device Module \"%s\".\n", DEVICE_NAME); }
module_init(xilaxitimer_init); module_exit(xilaxitimer_edit);
MODULE_AUTHOR ("Xilinx"); MODULE_DESCRIPTION("Test Driver for Zynq PL AXI Timer."); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("custom:xilaxitimer"); собираю образ и файловую систему. загружается. все отлично. но в /usr/include/linux нет <linux/interrupt.h> и других. понимаю что нужно в конфиге ядра или файловой системе что-то сделать. Кто опытен в линуксах на цинке подскажите как быть. т.к. опыта особого ни в цинке ни в линуксе не имею.
Сообщение отредактировал Balabes - Apr 11 2018, 16:48
|
|
|
|
|
Apr 11 2018, 15:59
|
Знающий
   
Группа: Свой
Сообщений: 726
Регистрация: 14-09-06
Из: Москва
Пользователь №: 20 394

|
Цитата(Balabes @ Apr 11 2018, 15:47)  Здравствуйте! Хочу обработать прерывания от AXI Timer в линуксе. На сайте xilinx нарыл пример. Код #include <linux/kernel.h> #include <linux/module.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <asm/io.h>
MODULE_LICENSE("GPL");
#define DEVICE_NAME "xilaxitimer" ...... module_init(xilaxitimer_init); module_exit(xilaxitimer_edit);
MODULE_AUTHOR ("Xilinx"); MODULE_DESCRIPTION("Test Driver for Zynq PL AXI Timer."); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("custom:xilaxitimer"); собираю образ и файловую систему. загружается. все отлично. но в /usr/include/linux нет <linux/interrupt.h> и других. понимаю что нужно в конфиге ядра или файловой системе что-то сделать. Кто опытен в линуксах на цинке подскажите как быть. т.к. опыта особого ни в цинке ни в линуксе не имею. Копать документацию в сторону ядра, модулей, кросс-компиляции и т.д. - но, похоже, тут ликбез нужен. И, видимо, с 0. ЗЫ: для длинных исходных текстов на этом форуме есть отдельный "codebox"
|
|
|
|
|
Apr 11 2018, 16:51
|
Участник

Группа: Участник
Сообщений: 66
Регистрация: 8-07-13
Пользователь №: 77 442

|
За тег спасибо, на панельке его почему то нет.
Вы хотите сказать что в конфигураторе ядра который с петалинуксом идет, нельзя настроить эту функцию?
|
|
|
|
|
Apr 12 2018, 07:20
|
Знающий
   
Группа: Свой
Сообщений: 726
Регистрация: 14-09-06
Из: Москва
Пользователь №: 20 394

|
Цитата(Balabes @ Apr 11 2018, 19:51)  Вы хотите сказать что в конфигураторе ядра который с петалинуксом идет, нельзя настроить эту функцию? Конфигуратор ядра идет с ядром. А какое ядро в петалинухе и есть ли там этот драйвер - хз. Мы не пользуемся петалинухом, поэтому что там и как - только в общих чертах. А официальное ядро от Xilinx тут.
|
|
|
|
|
Apr 12 2018, 08:34
|
Участник

Группа: Участник
Сообщений: 66
Регистрация: 5-07-17
Пользователь №: 97 975

|
Balabes, Вы каким петалинуксом пользуетесь? Кому-нибудь здесь удавалось настроить Petalinux (любой версии), чтобы он ядро и u-boot грузил с официального git из ветки master? Или он только умеет из соответствующей своей ветки грузить обновления? Подскажите, плиз?
Сообщение отредактировал sheynmanyu - Apr 12 2018, 08:35
|
|
|
|
|
Apr 12 2018, 10:37
|
Участник

Группа: Участник
Сообщений: 66
Регистрация: 8-07-13
Пользователь №: 77 442

|
sheynmanyu использую последний петалинукс, долго искал указание на то из какой ветки исходники, вот лучшее что нашел Код [core] repositoryformatversion = 0 filemode = true bare = true [remote "origin"] url = https://github.com/Xilinx/linux-xlnx.git fetch = +refs/*:refs/* mirror = true надеюсь будет полезна эта ссылка, если такой же дурачок как и я вдруг этим займется тыкfaa, если я все правильно понял, мне нужно добавить модуль в ядро, содержащий обработчик прерывания. А можно прерывания обрабатывать в коде из SDK? знаю что вопрос нубский, но да, я нуб(
|
|
|
|
|
Apr 12 2018, 15:12
|
Участник

Группа: Участник
Сообщений: 66
Регистрация: 5-07-17
Пользователь №: 97 975

|
Цитата(Balabes @ Apr 12 2018, 13:37)  А можно прерывания обрабатывать в коде из SDK? Скорее, подключить соответствующий драйвер (для работы с Вашим блоком). И работать через обращения к этому драйверу. Файлы с описаниями ядра линукса тутНе могу найти ничего подходящего, что работало бы с axi-устройствами. Может, устройства amba (ttyAM#)? А для общего понимания можно заглянуть в книжку Jonathan Corbet "Драйверы Устройств Linux" (например, здесь ), в самом начале. ...Я вот тоже сейчас с петалинуксом бодаюсь. Но у меня он даже запускаться не хочет  ((
Сообщение отредактировал sheynmanyu - Apr 12 2018, 15:17
|
|
|
|
|
Apr 12 2018, 21:02
|
Участник

Группа: Участник
Сообщений: 66
Регистрация: 8-07-13
Пользователь №: 77 442

|
Вы скорее всего встречали этот гайд, но вдруг нет. Файловую систему можно взять и ту что петалинукс сделает, но в убунте и gcc есть и даже apt ссыль
|
|
|
|
|
Apr 20 2018, 09:27
|
Участник

Группа: Участник
Сообщений: 66
Регистрация: 8-07-13
Пользователь №: 77 442

|
Снова здравствуйте! Модуль собрал, через insmod запускаю, таймер настраивается, тикает, судя по регистру состояния прерывание срабатывает (8 бит равен 1), но вот обработчик не вызывается. Есть у знающих идеи что я делаю не так?  CODE #include <linux/kernel.h> #include <linux/module.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <asm/io.h>
MODULE_LICENSE("GPL");
#define DEVICE_NAME "xilaxitimer"
#define IRQ_NUM 61
#define XIL_AXI_TIMER_BASEADDR 0x42800000 #define XIL_AXI_TIMER_HIGHADDR 0x4280FFFF
#define XIL_AXI_TIMER_TCSR_OFFSET 0x0 #define XIL_AXI_TIMER_TLR_OFFSET 0x4 #define XIL_AXI_TIMER_TCR_OFFSET 0x8 #define XIL_AXI_TIMER_CSR_INT_OCCURED_MASK 0x00000100
#define XIL_AXI_TIMER_CSR_CASC_MASK 0x00000800 #define XIL_AXI_TIMER_CSR_ENABLE_ALL_MASK 0x00000400 #define XIL_AXI_TIMER_CSR_ENABLE_PWM_MASK 0x00000200 #define XIL_AXI_TIMER_CSR_INT_OCCURED_MASK 0x00000100 #define XIL_AXI_TIMER_CSR_ENABLE_TMR_MASK 0x00000080 #define XIL_AXI_TIMER_CSR_ENABLE_INT_MASK 0x00000040 #define XIL_AXI_TIMER_CSR_LOAD_MASK 0x00000020 #define XIL_AXI_TIMER_CSR_AUTO_RELOAD_MASK 0x00000010 #define XIL_AXI_TIMER_CSR_EXT_CAPTURE_MASK 0x00000008 #define XIL_AXI_TIMER_CSR_EXT_GENERATE_MASK 0x00000004 #define XIL_AXI_TIMER_CSR_DOWN_COUNT_MASK 0x00000002 #define XIL_AXI_TIMER_CSR_CAPTURE_MODE_MASK 0x00000001
#define TIMER_CNT 0x0000FFFF
static struct platform_device *pdev; void *dev_virtaddr; static int int_cnt;
static irqreturn_t xilaxitimer_isr(int irq,void*dev_id) { unsigned int data; /* * Check Timer Counter Value */ data = ioread32(dev_virtaddr + XIL_AXI_TIMER_TCR_OFFSET); printk("xilaxitimer_isr: Interrupt Occurred ! Timer Count = 0x%08X\n",data); /* * Clear Interrupt */ data = ioread32(dev_virtaddr + XIL_AXI_TIMER_TCSR_OFFSET); iowrite32(data | XIL_AXI_TIMER_CSR_INT_OCCURED_MASK, dev_virtaddr + XIL_AXI_TIMER_TCSR_OFFSET); /* * Disable Timer after 100 Interrupts */ int_cnt++; if (int_cnt>=100) { printk("xilaxitimer_isr: 100 interrupts have been occurred. Disabling timer"); data = ioread32(dev_virtaddr + XIL_AXI_TIMER_TCSR_OFFSET); iowrite32(data & ~(XIL_AXI_TIMER_CSR_ENABLE_TMR_MASK), dev_virtaddr + XIL_AXI_TIMER_TCSR_OFFSET); } return IRQ_HANDLED; }
static int __init xilaxitimer_init(void) { unsigned int data; int_cnt = 0; printk(KERN_INFO "xilaxitimer_init: Initialize Module \"%s\"\n", DEVICE_NAME); /* * Register ISR */ if (request_irq(IRQ_NUM, xilaxitimer_isr, 0, DEVICE_NAME, NULL)) { printk(KERN_ERR "xilaxitimer_init: Cannot register IRQ %d\n", IRQ_NUM); return -EIO; } else { printk(KERN_INFO "xilaxitimer_init: Registered IRQ %d\n", IRQ_NUM); } /* * Map Physical address to Virtual address */ dev_virtaddr = ioremap_nocache(XIL_AXI_TIMER_BASEADDR, XIL_AXI_TIMER_HIGHADDR - XIL_AXI_TIMER_BASEADDR + 1); /* * Set Timer Counter */ iowrite32(TIMER_CNT, dev_virtaddr + XIL_AXI_TIMER_TLR_OFFSET); data = ioread32(dev_virtaddr + XIL_AXI_TIMER_TLR_OFFSET); printk("xilaxitimer_init: TLR 0x%08X\n",data); /* * Set Timer mode and enable interrupt */ data = ioread32(dev_virtaddr + XIL_AXI_TIMER_TCSR_OFFSET); iowrite32(data | XIL_AXI_TIMER_CSR_INT_OCCURED_MASK, dev_virtaddr + XIL_AXI_TIMER_TCSR_OFFSET);
data = ioread32(dev_virtaddr + XIL_AXI_TIMER_TCSR_OFFSET); printk("xilaxitimer_init: empty TCSR 0x%08X\n",data);
iowrite32(XIL_AXI_TIMER_CSR_LOAD_MASK, dev_virtaddr + XIL_AXI_TIMER_TCSR_OFFSET);
iowrite32(XIL_AXI_TIMER_CSR_ENABLE_INT_MASK | XIL_AXI_TIMER_CSR_AUTO_RELOAD_MASK, dev_virtaddr + XIL_AXI_TIMER_TCSR_OFFSET);
iowrite32(XIL_AXI_TIMER_CSR_DOWN_COUNT_MASK, dev_virtaddr + XIL_AXI_TIMER_TCSR_OFFSET);
data = ioread32(dev_virtaddr + XIL_AXI_TIMER_TCSR_OFFSET); printk("xilaxitimer_init: full TCSR 0x%08X\n",data);
/* * Register Device Module */ pdev = platform_device_register_simple(DEVICE_NAME, 0, NULL, 0); if (pdev == NULL) { printk(KERN_WARNING "xilaxitimer_init: Adding platform device \"%s\" failed\n", DEVICE_NAME); kfree(pdev); return -ENODEV; } /* * Start Timer */ data = ioread32(dev_virtaddr + XIL_AXI_TIMER_TCSR_OFFSET); iowrite32(data | XIL_AXI_TIMER_CSR_ENABLE_TMR_MASK, dev_virtaddr + XIL_AXI_TIMER_TCSR_OFFSET);
data = ioread32(dev_virtaddr + XIL_AXI_TIMER_TCSR_OFFSET); printk("xilaxitimer_init: TCSR 0x%08X\n",data);
printk("xilaxitimer_init: timer started\n");
/*int i = 0; for (i; i < 50; i++) { data = ioread32(dev_virtaddr + XIL_AXI_TIMER_TCR_OFFSET); printk("xilaxitimer_init: XIL_AXI_TIMER_TCR_OFFSET 0x%08X\n",data);
data = ioread32(dev_virtaddr + XIL_AXI_TIMER_TCSR_OFFSET); printk("xilaxitimer_init: XIL_AXI_TIMER_TCSR_OFFSET 0x%08X\n",data); }*/
return 0; }
static void __exit xilaxitimer_edit(void) { /* * Exit Device Module */ iounmap(dev_virtaddr); free_irq(IRQ_NUM, NULL); platform_device_unregister(pdev); printk(KERN_INFO "xilaxitimer_edit: Exit Device Module \"%s\".\n", DEVICE_NAME); }
module_init(xilaxitimer_init); module_exit(xilaxitimer_edit);
MODULE_AUTHOR ("Xilinx"); MODULE_DESCRIPTION("Test Driver for Zynq PL AXI Timer."); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("custom:xilaxitimer");
|
|
|
|
|
Apr 25 2018, 07:33
|
Участник

Группа: Участник
Сообщений: 66
Регистрация: 8-07-13
Пользователь №: 77 442

|
здравствуйте. Проблему локализовал, требуется помощь в устранении. как видно на скрине сверху что мой таймер зарегистрирован как прерывание номер 61, но мне нужно прерывание №61 в GIC а не в системе. Как я понял до какой-то версии ядра, это было одно и тоже. Теперь нет. Как найти нужный номер прерывания, я не могу понять. Люди писали что через res = platform_get_resource(ofdev, IORESOURCE_IRQ, 0); или platform_get_irq(pdev, 0);
но у меня почему то не получилось. Подскажите, кто что сможет
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|