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

 
 
 
Reply to this topicStart new topic
> Zynq, Petalinux, прерывания и заголовочные файлы
Balabes
сообщение Apr 11 2018, 12:47
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
faa
сообщение Apr 11 2018, 15:59
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 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"
Go to the top of the page
 
+Quote Post
Balabes
сообщение Apr 11 2018, 16:51
Сообщение #3


Участник
*

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



За тег спасибо, на панельке его почему то нет.

Вы хотите сказать что в конфигураторе ядра который с петалинуксом идет, нельзя настроить эту функцию?
Go to the top of the page
 
+Quote Post
faa
сообщение Apr 12 2018, 07:20
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 726
Регистрация: 14-09-06
Из: Москва
Пользователь №: 20 394



Цитата(Balabes @ Apr 11 2018, 19:51) *
Вы хотите сказать что в конфигураторе ядра который с петалинуксом идет, нельзя настроить эту функцию?


Конфигуратор ядра идет с ядром.
А какое ядро в петалинухе и есть ли там этот драйвер - хз.
Мы не пользуемся петалинухом, поэтому что там и как - только в общих чертах.

А официальное ядро от Xilinx тут.
Go to the top of the page
 
+Quote Post
sheynmanyu
сообщение Apr 12 2018, 08:34
Сообщение #5


Участник
*

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



Balabes, Вы каким петалинуксом пользуетесь?
Кому-нибудь здесь удавалось настроить Petalinux (любой версии), чтобы он ядро и u-boot грузил с официального git из ветки master? Или он только умеет из соответствующей своей ветки грузить обновления? Подскажите, плиз?

Сообщение отредактировал sheynmanyu - Apr 12 2018, 08:35
Go to the top of the page
 
+Quote Post
Balabes
сообщение Apr 12 2018, 10:37
Сообщение #6


Участник
*

Группа: Участник
Сообщений: 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? знаю что вопрос нубский, но да, я нуб(
Go to the top of the page
 
+Quote Post
sheynmanyu
сообщение Apr 12 2018, 15:12
Сообщение #7


Участник
*

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



Цитата(Balabes @ Apr 12 2018, 13:37) *
А можно прерывания обрабатывать в коде из SDK?

Скорее, подключить соответствующий драйвер (для работы с Вашим блоком). И работать через обращения к этому драйверу. Файлы с описаниями ядра линукса тут
Не могу найти ничего подходящего, что работало бы с axi-устройствами. Может, устройства amba (ttyAM#)?

А для общего понимания можно заглянуть в книжку Jonathan Corbet "Драйверы Устройств Linux" (например, здесь ), в самом начале.
...Я вот тоже сейчас с петалинуксом бодаюсь. Но у меня он даже запускаться не хочет sad.gif((

Сообщение отредактировал sheynmanyu - Apr 12 2018, 15:17
Go to the top of the page
 
+Quote Post
Balabes
сообщение Apr 12 2018, 21:02
Сообщение #8


Участник
*

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



Вы скорее всего встречали этот гайд, но вдруг нет. Файловую систему можно взять и ту что петалинукс сделает, но в убунте и gcc есть и даже apt ссыль
Go to the top of the page
 
+Quote Post
Balabes
сообщение Apr 20 2018, 09:27
Сообщение #9


Участник
*

Группа: Участник
Сообщений: 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");

Go to the top of the page
 
+Quote Post
Balabes
сообщение Apr 25 2018, 07:33
Сообщение #10


Участник
*

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



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

но у меня почему то не получилось. Подскажите, кто что сможет
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 20th July 2025 - 01:10
Рейтинг@Mail.ru


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