Перейти к содержанию
    

Zynq, Petalinux, прерывания и заголовочные файлы

Здравствуйте!

Хочу обработать прерывания от 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"

#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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Здравствуйте!

Хочу обработать прерывания от 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"

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Вы хотите сказать что в конфигураторе ядра который с петалинуксом идет, нельзя настроить эту функцию?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы хотите сказать что в конфигураторе ядра который с петалинуксом идет, нельзя настроить эту функцию?

 

Конфигуратор ядра идет с ядром.

А какое ядро в петалинухе и есть ли там этот драйвер - хз.

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

 

А официальное ядро от Xilinx тут.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Balabes, Вы каким петалинуксом пользуетесь?

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

Изменено пользователем sheynmanyu

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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? знаю что вопрос нубский, но да, я нуб(

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А можно прерывания обрабатывать в коде из SDK?

Скорее, подключить соответствующий драйвер (для работы с Вашим блоком). И работать через обращения к этому драйверу. Файлы с описаниями ядра линукса тут

Не могу найти ничего подходящего, что работало бы с axi-устройствами. Может, устройства amba (ttyAM#)?

 

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

...Я вот тоже сейчас с петалинуксом бодаюсь. Но у меня он даже запускаться не хочет :(((

Изменено пользователем sheynmanyu

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Снова здравствуйте!

Модуль собрал, через insmod запускаю, таймер настраивается, тикает, судя по регистру состояния прерывание срабатывает (8 бит равен 1), но вот обработчик не вызывается. Есть у знающих идеи что я делаю не так?

123.png

#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");

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

здравствуйте.

Проблему локализовал, требуется помощь в устранении.

как видно на скрине сверху что мой таймер зарегистрирован как прерывание номер 61, но мне нужно прерывание №61 в GIC а не в системе.

Как я понял до какой-то версии ядра, это было одно и тоже. Теперь нет. Как найти нужный номер прерывания, я не могу понять. Люди писали что через

res = platform_get_resource(ofdev, IORESOURCE_IRQ, 0);

или

platform_get_irq(pdev, 0);

 

но у меня почему то не получилось. Подскажите, кто что сможет

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...