Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: alt_irq_register()?
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Системы на ПЛИС - System on a Programmable Chip (SoPC)
juvf
Не могу разобраться с функцией alt_irq_register(). Нашел в пдф "HAL API Reference" описание.
Цитата
Prototype: int alt_irq_register (alt_u32 id,
void* context,
void (*isr)(void*, alt_u32))

что такое *contex? что туда подставлять и для чего он нужен?
vadimuzzz
обычно там передается указатель на файл устройства, от которого приходит прерывание. если не нужен, можно 0 передавать.
juvf
Цитата(vadimuzzz @ Dec 27 2010, 14:14) *
обычно там передается указатель на файл устройства, от которого приходит прерывание. если не нужен, можно 0 передавать.

что значит "файл устройства"? Это если я использую ос, например linux, то я там должен передать указатель на файл, например, /dev/tty0. А если ос нет? Если я пишу без ос и хочу написать обработчик прерывания от uart-a, что туда передавать?
Цитата
если не нужен
Как определить - нужен он мне или не нужен?

Есть где-нибудь более полное описание этой функции?
vadimuzzz
Цитата
что значит "файл устройства"?

я не совсем корректно выразился. там передается указатель на структуру устройства, имя файла - одно из полей этой стр-ры. например:
Код
/* SGDMA Device Structure */
typedef struct alt_sgdma_dev
{
  alt_llist                 llist;               // Device linked-list entry
  const char                *name;               // Name of SGDMA in SOPC System
  void                      *base;               // Base address of SGDMA
  alt_u32                   *descriptor_base;    // reserved
  alt_u32                   next_index;          // reserved
  alt_u32                   num_descriptors;     // reserved
  alt_sgdma_descriptor      *current_descriptor; // reserved
  alt_sgdma_descriptor      *next_descriptor;    // reserved
  alt_avalon_sgdma_callback callback;            // Callback routine pointer
  void                      *callback_context;   // Callback context pointer
  alt_u32                   chain_control;       // Value OR'd into control reg
} alt_sgdma_dev;

посмотрите, наверное и для UART такая же есть.
Цитата
Если я пишу без ос и хочу написать обработчик прерывания от uart-a, что туда передавать?

вы сами должны решить, нужны вам такие красивости в виде структур. потому что то же самое можно сделать через регистры устройства. а все эти структуры - просто обертки к ним.
Цитата
Есть где-нибудь более полное описание этой функции?

в Software Developer`s Handbook есть описание API HAL, там в конец список функций.
Fynjisx
Цитата(vadimuzzz @ Dec 27 2010, 09:14) *
обычно там передается указатель на файл устройства, от которого приходит прерывание. если не нужен, можно 0 передавать.

Доброго времени!
Никак не получается вызвать свою процедуру по пррыванию. Сделал вроде все как описано, но не получается. В SOPC назначил приоритет, в NIOS SBT, регистрирую таким образом:
CODE

static void ISR_Name();

void Registration(alt_u32 base, alt_u8 irq_number)
{
contx.base = base;
alt_irq_register(irq_number, &contx, ISR_Name);
}

прерывание возникает каждую ms но не вызывается процедура ISR_Name... не заходит у меня туда отладчик...
Как считаете, куда нужно обратить ещё внимание??? Можетчего-то забыл?
Кстати, в руководстве описана функция alt_irq_register, которая располагается в файле <sys/alt_irq.h>, а реально я там не смог её найти, вместо неё описана функция alt_ic_isr_register()... Я сначало подумал, что на этапе компиляции даст ошибку, о том что данной функции нет, но нет...всё прошло нормально...И непоняно откуда он её берет...
barabek
Цитата(Fynjisx @ Feb 18 2012, 14:56) *
Кстати, в руководстве описана функция alt_irq_register, которая располагается в файле <sys/alt_irq.h>, а реально я там не смог её найти, вместо неё описана функция alt_ic_isr_register()... Я сначало подумал, что на этапе компиляции даст ошибку, о том что данной функции нет, но нет...всё прошло нормально...И непоняно откуда он её берет...

alt_irq_register - это сейчас устаревшая функция, вместо нее спользуется alt_ic_isr_register. И функцию alt_irq_register выкинули из sys/alt_irq.h в файл, название которого сейчас не скажу - какой-то набор из слов "приватный" (prev), irq, alt, legacy. Можете все-таки найти функцию поиском.


По существу вашей проблемы сказать что либо трудно. Остальные прерывания работают? Бит, соответствующий прерыванию в регистре ienable выставлен? Вы точно уверены, что флаг прерывания выставляется?

Fynjisx
Цитата(barabek @ Feb 18 2012, 09:50) *
alt_irq_register - это сейчас устаревшая функция, вместо нее спользуется alt_ic_isr_register. И функцию alt_irq_register выкинули из sys/alt_irq.h в файл, название которого сейчас не скажу - какой-то набор из слов "приватный" (prev), irq, alt, legacy. Можете все-таки найти функцию поиском.

понятно, спасибо...
Цитата(barabek @ Feb 18 2012, 09:50) *
Остальные прерывания работают?

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

Цитата(barabek @ Feb 18 2012, 09:50) *
Бит, соответствующий прерыванию в регистре ienable выставлен? Вы точно уверены, что флаг прерывания выставляется?

да, в режиме отладки когда уже зарегил ф-ию, кручусь в бесконечном цикле и жду прерывания, ienable в окне registers при этом равен 1.

Цитата(barabek @ Feb 18 2012, 09:50) *
Вы точно уверены, что флаг прерывания выставляется?

запрос прерывания точно выставляется, смотрел сигналтапом. Кстати это мой собственный компонент... Может чего то не так сделал? но в sopc в принципе только выставляю приоритет, а в sbt при регистрации использую базовый адрес компонента и номер запроса...
грешил на свой компонент, что говорить, но у меня даже от таймера не получается прерваться...
что то я не так пишу, какие еще тонкости могут быть??? может static не надо писать у функции обработчика или в режиме отладки невозможно попасть в обработчик по прерыванию... Если произойдет прерывание от таймера то куда нужно глядеть, на какой регистр?
barabek
Цитата(Fynjisx @ Feb 19 2012, 00:45) *
остальных пока нет, это первое... попробовал от системного таймера прерваться, для этого тоже зарегал функцию подобным образом...но такая же байда - кручусь в бесконечном цикле и ни каких намеков на переброс в функцию-обработчик...
да, в режиме отладки когда уже зарегил ф-ию, кручусь в бесконечном цикле и жду прерывания, ienable в окне registers при этом равен 1.
грешил на свой компонент, что говорить, но у меня даже от таймера не получается прерваться...
что то я не так пишу, какие еще тонкости могут быть??? может static не надо писать у функции обработчика или в режиме отладки невозможно попасть в обработчик по прерыванию... Если произойдет прерывание от таймера то куда нужно глядеть, на какой регистр?


Функции прерывания написаны в таком виде void COM_ISR(void * Context,alt_u32 id) (или при Enhansed void COM_ISR(void * Context) )?


Соответствующий бит разрешения всех прерываний в регистре status выставлен? При возникновении (по сигналтапу или по "ЗубДаюВыставлен") флага прерывания соответствующий бит в ipending (такой же по номеру как и в ienable) возводится? И еще нужно попробовать поставить брекпоинт в обработчике прерываний alt_irq_handler.
UPD А для таймера должен быть выставлен бит ITO и с приходом переполнения выставляется флаг TO. Все это можно посмотреть в memory. Добейтесь сперва работоспособности прерывания от таймера.
Fynjisx
Давайте по порядку.
Цитата(barabek @ Feb 19 2012, 04:08) *
Добейтесь сперва работоспособности прерывания от таймера.

Создаю такой таймер к примеру, рис.1.
Цитата(barabek @ Feb 19 2012, 04:08) *
Функции прерывания написаны в таком виде void COM_ISR(void * Context,alt_u32 id) (или при Enhansed void COM_ISR(void * Context) )?

Пишу так:
CODE

int io = 0;
void COM_ISR(void* context, alt_u32 id)
{
io = io + 1; // здесь я поставил точку прерывания слева
}
...
int main (void)
{
...
alt_irq_register(SYS_TIMER_IRQ, 0, COM_ISR);
...
alt_u16 states;
alt_u16 control;
//ну и чем-то чтобы себя занять, кручусь в цикле ожидая прерывания от таймера
while(1)
{
states = IORD(SYS_TIMER_BASE, 0);
control = IORD(SYS_TIMER_BASE, 1);
i = i + 1;
}
...
}

в модуле system.h то, что касается таймера описано так:
CODE

#define ALT_MODULE_CLASS_sys_timer altera_avalon_timer
#define SYS_TIMER_ALWAYS_RUN 1
#define SYS_TIMER_BASE 0x0
#define SYS_TIMER_COUNTER_SIZE 32
#define SYS_TIMER_FIXED_PERIOD 1
#define SYS_TIMER_FREQ 50000000u
#define SYS_TIMER_IRQ 2
#define SYS_TIMER_IRQ_INTERRUPT_CONTROLLER_ID 0
#define SYS_TIMER_LOAD_VALUE 14ULL
#define SYS_TIMER_MULT 2.0E-8
#define SYS_TIMER_NAME "/dev/sys_timer"
#define SYS_TIMER_PERIOD 15
#define SYS_TIMER_PERIOD_UNITS "clocks"
#define SYS_TIMER_RESET_OUTPUT 0
#define SYS_TIMER_SNAPSHOT 0
#define SYS_TIMER_SPAN 32
#define SYS_TIMER_TICKS_PER_SEC 3333334u
#define SYS_TIMER_TIMEOUT_PULSE_OUTPUT 0
#define SYS_TIMER_TYPE "altera_avalon_timer"

Далее компилирую обновленные файлы, нажимаю на "жучка" и перехожу в режим "debug nios"
В режиме отладки перед тем как зайти в функцию регистрации смотрю, на всплывающую подсказку, которая говорит, что
SYS_TIMER_IRQ = 0, хотя в system.h он определен как SYS_TIMER_IRQ = 2 (рис.2). Ну я думаю это просто глюк..У Вас наверное также...
перед выходом из функции регистрации rc = 0, что говорит, что нормально зарегилась...
Цитата
Соответствующий бит разрешения всех прерываний в регистре status выставлен?

После того, как я начинаю крутиться в цикле, который уже упоминал, дожидаясь события смотрю в окно register (рис.3)
я там выставил двоичный формат, мне так проще смотреть...
Цитата
А для таймера должен быть выставлен бит ITO и с приходом переполнения выставляется флаг TO. Все это можно посмотреть в memory.

долго жму F5, но бит ITO не выставляется... рис.4
тогда иду ва-банк и сам его выставляю ручками рис.5(черт его знает почему он не выставляется автоматом)
Цитата
При возникновении флага прерывания соответствующий бит в ipending (такой же по номеру как и в ienable) возводится?

Далее перехожу на вкладку register и там ipending подтверждается рис.6.
Цитата
И еще нужно попробовать поставить брекпоинт в обработчике прерываний alt_irq_handler.

breakpoint уже сделал в теле COM_ISR (.
вот такая ситуация... Уже неделю на это потратил...Где-то я не то делаю...Но где? не могу понять...
barabek
Цитата(Fynjisx @ Feb 19 2012, 13:30) *
Далее компилирую обновленные файлы, нажимаю на "жучка" и перехожу в режим "debug nios"
В режиме отладки перед тем как зайти в функцию регистрации смотрю, на всплывающую подсказку, которая говорит, что
SYS_TIMER_IRQ = 0, хотя в system.h он определен как SYS_TIMER_IRQ = 2 (рис.2). Ну я думаю это просто глюк..У Вас наверное также...

нет, у меня в nios sbt всплывающее окошко показывает именно то что нужно - в соответствии с system.h
Цитата
перед выходом из функции регистрации rc = 0, что говорит, что нормально зарегилась...

У Вас на третьем рисунке уже вроде как флаг прерывания взведен, если судить по ipending, так же как и на рисунке 6.
Цитата
долго жму F5, но бит ITO не выставляется... рис.4
тогда иду ва-банк и сам его выставляю ручками рис.5(черт его знает почему он не выставляется автоматом)

Флаг этот ITO не должен сам выставляться, его должны Вы выставить.
Цитата
Далее перехожу на вкладку register и там ipending подтверждается рис.6.
breakpoint уже сделал в теле COM_ISR (.
вот такая ситуация... Уже неделю на это потратил...Где-то я не то делаю...Но где? не могу понять...

Непонятно почему на 3-ем рисунке у Вас уже выставился флаг. Ладно потом разберемся sm.gif
А попробуйте дополнительно поставить брекпоинт на одной из строчек бесконечного цикла, но уже после запуска. И после того, как Вы выставите флаг IT0 (програмно или насильно через соответствующее окно) Вполне возможно что в этом случае у Вас остановки не случится, т.к. программа крутится внутри alt_irq_handler.c тщетно ища обработчик (из-за несоответствия по каким-то причинам SYS_TIMER_IRQ тому что нужно). И брекпоинт внутри handler поставьте, забрав его из своего обработчика. А дальше в пошаговом режиме, если все правильно, handler вызовет Ваш обработчик.
Fynjisx
Цитата(barabek @ Feb 19 2012, 08:58) *
И брекпоинт внутри handler поставьте, забрав его из своего обработчика.

из обработчика COM_ISR убрать breakpoint? А где искать этот handler?
barabek
Цитата(Fynjisx @ Feb 19 2012, 16:18) *
из обработчика COM_ISR убрать breakpoint? А где искать этот handler?


Можете и оставить, просто он там не особо нужен. А alt_irq_handler() у меня лежит в PROGECT_bsp->HAL->src->irq_hanler.c


Да Вы его поиском можете найти. Кнопкой с фонариком (или через меню) Search-> file search->containing text = alt_irq_handler, главное поиск настройте, чтобы он и в bsp искал.
Fynjisx
Цитата(barabek @ Feb 19 2012, 09:27) *
Можете и оставить, просто он там не особо нужен. А alt_irq_handler() у меня лежит в PROGECT_bsp->HAL->src->irq_hanler.c


Да Вы его поиском можете найти. Кнопкой с фонариком (или через меню) Search-> file search->containing text = alt_irq_handler, главное поиск настройте, чтобы он и в bsp искал.

разобрался наполовину как это работает: в момент инициализации регистрируется обработчик таймера - alt_avalon_timer_sc_irq. После регистрации в течении инициализации если происходит прерывание по таймеру, то срабатывает alt_irq_handler()(как он срабатывает не увидел); он начинает шарить по всем битам pending в поиске индекса элемента таблицы указателей зарегенных функций и как только находит, обращается по этому индексу...А там указатель обработчика таймера, о котором писал выше...
И всё работает))))...
Но...
Дальше идет ещё какая-то инициализация... Смшная функция _do_ctor работает, в ней прерывания запрещены...потом снова разрешаются иопять всё работает... Но как только я выхожу в main, handler уже больше не вызывается!!!
Должен сказать что я убрал из своего main функцию регистрации прерывания, так как таймер её имееет ещё со времен инициализации и по идее при возникновении прерывания в любом случае должен был вызватсья handler, но он не вызывается если как только я попадаю в main хотя прерывание генерится!!! Вот таккая ситуация... Что может быть???
barabek
А какая у Вас версия? А то у меня при переходе с 9 на 11 тоже возникли проблемы из-за начальной инициализации т.к. Freertos используется и прерывания должны быть запрещены до определенного момента. Не слишком разбираясь записал вместо main alt_main, переопределив стандартную alt_main. Это даже лучше - более предсказуемый код. Функция alt_main есть всегда, и если используется стандартная от алтеры, то она вызывает пользовательскую main.
Fynjisx
Цитата(barabek @ Feb 19 2012, 12:18) *
А какая у Вас версия? А то у меня при переходе с 9 на 11 тоже возникли проблемы из-за начальной инициализации

У меня Eclipse - Version: 3.4.1. Quartus 9.1sp2.
Цитата(barabek @ Feb 19 2012, 12:18) *
Не слишком разбираясь записал вместо main alt_main, переопределив стандартную alt_main. Это даже лучше - более предсказуемый код.

Очень смелый ход)))
Уважаемый barabek!
Нашел я то, что неправильно делаю... Не нужно было жать f5 в ожидании "чуда". Всего то навсего надо было нажать f7, но и ещё куча мелких деталей, типа: всегда снимать irq в обработчике.
Как только у меня стал активизироваться handler из main, я сразу понял что дела пошли в гору) и потом уж написал, знаменитый
COM_ISR, который припервой же попытке не заставил себя долго ждать). Да кстати используйте static function для пользовательских handler's, как в alter'вском коде...

Спасибо за помощь...Здоровски помогли...Спасибо...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.