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

Обработка пользовательских прерываний в Nios II

Возникла проблема с реализацией пользовательской обработки прерывания.

Реализован процессор Nios II. Список элементов следующий:

- CPU Ниос 2

- ROM на on_chip_mem

- RAM на on_chip_mem

- Выходной пользовательский интерфейс (выходная от Ниоса шина данных и линия разрешения записи) My_out

- Выходной пользовательский интерфейс (входная линия прерывания irq) My_irq.

 

В IDE написан код программы:

#include "system.h"

#include "sys/alt_irq.h"

 

void My_ISR();

 

int main()

{

volatile unsigned int * out;

out = (unsigned int*) MY_OUT_BASE;

volatile int a = 20;

 

alt_irq_register(MY_IRQ_IRQ ,0,My_ISR);

 

while(1)

{

a = a+5;

if(a > 250) a = 0;

*out = a;

}

 

void My_ISR()

{

volatile unsigned int *qqq;

qqq = (unsigned int*) MY_OUT_BASE;

 

while(1)

{

*qqq = 1;

}

}

Содержимое system.h о My_irq:

#define MY_IRQ_NAME "/dev/My_irq"

#define MY_IRQ_TYPE "altera_avalon_user_defined_interface"

#define MY_IRQ_BASE 0x00002004

#define MY_IRQ_SPAN 4

#define MY_IRQ_IRQ 16

#define MY_IRQ_IMPORTED_WAIT 0

#define MY_IRQ_NIOS_GEN_WAITS 1

#define MY_IRQ_SIMULATE_IMPORTED_HDL 0

#define MY_IRQ_PORT_TYPE "Avalon Slave"

#define MY_IRQ_HDL_IMPORT 0

#define MY_IRQ_TIMING_UNITS "cycles"

#define MY_IRQ_UNIT_MULTIPLIER 12.5

#define MY_IRQ_SETUP_VALUE 0

#define MY_IRQ_HOLD_VALUE 0

#define MY_IRQ_WAIT_VALUE 0

#define MY_IRQ_ADDRESS_WIDTH 32

#define MY_IRQ_MODULE_LIST ""

#define MY_IRQ_SHOW_STREAMING 1

#define MY_IRQ_SHOW_LATENCY 0

#define MY_IRQ_TECHNOLOGY "User Logic"

#define MY_IRQ_FILE_COUNT 0

#define MY_IRQ_PORT_COUNT 1

#define MY_IRQ_COMPONENT_DESC ""

#define MY_IRQ_MODULE_NAME ""

 

Идея: при поступлении прерывания на вход процессора, он проваливается в процедуру обработки прерывания и записывает в бесконечном цикле в выходной регистр число.

 

Программа предназначена только для освоения создания собственных обработчиков прерываний.

 

Проблема: отсутствует реакция на сигнал прерывания, описанная в программе. После поступления сигнала прерывания процессор подвисает (не производя вывода ожидаемой величины = 1) и более не выполняет никаких действий. Основное тело программы выполняется нормально до поступления прерывания.

 

Самостоятельно ошибку найти не смог. Подобную программу писал на Nios, все работало (только использовалась процедура nr_installuserisr(na_My_irq_irq, My_ISR, 0); ).

 

Использовал САПР Quartus II 5.1 и прилагаемые к нему SOPC Builder и IDE (Nios II Evalution). Связь IDE-Board через ByteBlasterII и jtag.

 

Запуск ПО осуществляю через «Run As…». Текст в консоле:

Using cable "ByteBlasterII [LPT1]", device 1, instance 0x00

Pausing target processor: OK

 

Downloading 00010020 ( 0%)

Downloaded 7KB in 0.2s (35.0KB/s)

 

Verifying 00010020 ( 0%)

Verified OK

Leaving target processor paused

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

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


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

main давно не ковырял, не помню, что там уже включено, но основные параметры коротко:

1) у вас должны быть включены прерывания в контрольном регистре №3 с помощью alt_irq_init;

2) ваше прерывание должно быть включено через alt_irq_enable.

 

Посмотрите в alt_irq.h, там описаны основные функции доступа к регистрам, используйте

alt_irq_pending (или NIOS2_READ_IPENDING), alt_irq_enabled, alt_irq_enable, alt_irq_disable и т.д.

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


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

main давно не ковырял, не помню, что там уже включено, но основные параметры коротко:

1) у вас должны быть включены прерывания в контрольном регистре №3 с помощью alt_irq_init;

2) ваше прерывание должно быть включено через alt_irq_enable.

 

Посмотрите в alt_irq.h, там описаны основные функции доступа к регистрам, используйте

alt_irq_pending (или NIOS2_READ_IPENDING), alt_irq_enabled, alt_irq_enable, alt_irq_disable и т.д.

 

Я просмотрел дополнительные рабочие примеры программ. Взял за основу пример count_binary, прилагаемый с IDE и немного изменил код программы:

#include "system.h"

#include "sys/alt_irq.h"

 

volatile int my_context;

volatile unsigned char qqq = 0;

 

void My_ISR(void* context, alt_u32 id);

 

int main (void)

{

alt_irq_init (ALT_IRQ_BASE);

volatile unsigned int *out;

out = (unsigned int*) MY_OUT_BASE;

volatile unsigned char a = 0;

 

volatile unsigned char b = 0;

volatile int i = 1;

void* my_context_ptr = (void*) &my_context;

 

alt_irq_register(MY_IRQ_IRQ , my_context_ptr,My_ISR);

 

while(1)

{

a = a+5;

if (a>240) a=0;

*out = a;

 

for(i=0;i<10000;i++) //просто задержка, чтоб не дергать выходной рег-р

b = i+b;

}

return 0;

}

 

void My_ISR(void* context, alt_u32 id)

{

volatile int* my_context_ptr = (volatile int*) context;

qqq += 1;

while(1);

}

 

Результат следующий: виснуть проект перестал, но ожидаемых действий не наблюдается (вместо того, чтобы остановится внутри обработчика прерывания и прекратить запись на выходные регистры, продолжается вывод на выходную шину чисел, кратных 5)

 

Изучал alt_irq.h, alt_irq_enable как я понял делать не надо тк он выполняется при выходе из alt_irq_register.c.

 

Правда не до конца уверен, что понял, что делает alt_irq_pending и как его можно использовать (не совсем улавливаю смысл), тч если не сложно поясните, пожалуйста.

 

Пробовал использовать alt_irq_init, но хоть и написал строку аналогичную примеру hello_alt_main.c (alt_irq_init (ALT_IRQ_BASE); ), но результат остался тот же :(

 

Возвращаемые значения alt_irq_pending и alt_irq_enable всегда равны 0. alt_irq_enabled возвращает 1.

 

Может кто-нибудь предложит идеи?

Заранее спасибо...

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

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


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

Результат следующий: виснуть проект перестал, но ожидаемых действий не наблюдается (вместо того, чтобы остановится внутри обработчика прерывания и прекратить запись на выходные регистры, продолжается вывод на выходную шину чисел, кратных 5)

А вход в обработчик осуществляется?

 

Правда не до конца уверен, что понял, что делает alt_irq_pending и как его можно использовать (не совсем улавливаю смысл), тч если не сложно поясните, пожалуйста.

Показывает состояние регистра №4, в принципе можно и в отладчике посмотреть на вкладке "регистры". Собственно показывает "активные" прерывания в данный момент.

 

Возвращаемые значения alt_irq_pending и alt_irq_enable всегда равны 0. alt_irq_enabled возвращает 1.

alt_irq_enable возвращает 0 всегда, это в alt_irq.h записано.

alt_irq_enabled - разрешение в регистре №3, объяснен в секции 1 глава 3 раздел "control registers" (как и остальные регистры).

 

Запускайте отладчик и ставьте точку останова в обработчике прерываний. Похоже что прерывание-то у вас и не приходит.

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


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

При необходимости создать свое прерывание процессора от внешнего устройства рабочей оказалась следующая последовательность действий:

1. SOPC builder:

a. Создать компонент PIO назначив его настройки аналогично HW tutorial для Nios (входы, на 1 модуль PIO выделяется одно прерывание, синхронные, захват по фронту)

b. Созданному модулю(ям) распределить адреса и прерывания.

c. Сгенерировать системный модуль (ну сам Ниос в общем)

 

2. В IDE:

a. Произвести инициализацию PIO, например:

static void init_button_pio()

{

/* Переопределение глобального указателя edge_capture

* для соответствия прототипуalt_irq_register()*/

void* edge_capture_ptr = (void*) &edge_capture;

 

/* Разрешение прерывания*/

IOWR_ALTERA_AVALON_PIO_IRQ_MASK(CPU_MY_PIO_IRQ_MODULE_BASE, 0x1);

 

/* Сброс регистра захвата фронта*/

IOWR_ALTERA_AVALON_PIO_EDGE_CAP(CPU_MY_PIO_IRQ_MODULE_BASE, 0x0);

 

 

alt_irq_register( CPU_MY_PIO_IRQ_MODULE_IRQ,

edge_capture_ptr,

handle_button_interrupts );

}

 

В данном случае ISR инициализируется внутри функции инициализации PIO

 

b. Написать функцию обработчик прерывания, например:

static void handle_button_interrupts(void* context, alt_u32 id)

{

/* сопоставление указателя edge_capture_ptr и указателя на контекст*/

volatile int* edge_capture_ptr = (volatile int*) context;

 

/*

* Чтение значения регистра захвата фронта с PIO.

* Сохранение значения.

*/

*edge_capture_ptr =

IORD_ALTERA_AVALON_PIO_EDGE_CAP(CPU_MY_PIO_IRQ_MODULE_BASE);

 

/* Пользовательский код */

 

/* Запись в регистр захвата фронта для сброса его */

IOWR_ALTERA_AVALON_PIO_EDGE_CAP(CPU_MY_PIO_IRQ_MODULE_BASE, 0);

 

/* reset interrupt capability for the PIO. */

IOWR_ALTERA_AVALON_PIO_IRQ_MASK(CPU_MY_PIO_IRQ_MODULE_BASE, 0x1);

}

3. Написать основную программу.

4. Откомпилировать проект.

5. Запустить проект на плате.

 

Использованные материалы: Nios Hardware Development tutorial (для Nios), Nios II Software Developer’s Handbook для QII v7.1 (раздел ISR), Upgrading Nios Processor Systems to the Nios II Processor (для тех, кто не знаком с Nios эта часть не нужна) и Quartus II Version 7.1 Handbook Volume 4: SOPC Builder, alt_irq.h.

 

Данные, пригодившиеся в мануалах:

Nios Hardware Development tutorial – как создать модуль для приема прерывания через PIO.

Nios II Software Developer’s Handbook для QII v7.1 (раздел ISR) – как инициализировать прерывание и написать код для его обработки.

Upgrading Nios Processor Systems to the Nios II Processor – что изменилось в командах для Ниос 2.

Quartus II Version 7.1 Handbook Volume 4: SOPC Builder – как создать компонент и как это делается на примере SDRAM.

Alt_irq.h – какие действия выполняются при регистрации прерывания. (напомню, что эту библиотечку можно найти в папке с библиотечными файлами проекта после генерации системного модуля или открыть ее из IDE также после генерации системного модуля).

 

 

Успеха всем нам, начинающим.

 

PS найдете неточности, пишите и я исправлю ошибки.

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

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


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

Попробовал реализовать Ваш пример....ну и count_binary

(Quartus 2 версия 8.0 , Ядро NIOS2/S, физическая среда-отладочная плата CYCLONE3 )

с кнопочками замечательно работает....

однако, когда я завёл на макете реальное прерывание....проект виснет через какоето время...

а дебаггер вываливается с сообщением Thread [0] (Suspended: Signal 'SIGTRAP' received. Description: Trace/breakpoint trap.)

обратил внимание что время когда вываливается зависит от частоты (количества прерываний) значит какоето переполнение имеет место

пашукал в инете вот что пишут в буржуинствах...

 

"As explained in the spec, it has all to do with the bypassing of the data cache"

 

из http://www.altera.com/literature/hb/nios2/n2sw_nii52007.pdf

"Device drivers typically access control registers associated with their

device. These registers are mapped into the Nios II address space. When

accessing device registers, the data cache must be bypassed to ensure that

accesses are not lost or deferred due to the data cache.

For device drivers, the data cache should be bypassed by using the

ldio/stio family of instructions. On Nios II cores without a data cache,

these instructions behave just like their corresponding ld/st

instructions, and therefore are benign.

For C programmers, note that declaring a pointer as volatile does not

cause accesses using that volatile pointer to bypass the data cache. The

volatile keyword only prevents the compiler from optimizing out

accesses using the pointer.

1 This volatile behavior is different from the methodology for

the first-generation Nios processor."

 

сам я к программирования отношение мало имею...

может кто нибудь прокоментирует как софтину поправить

или примером поделится, реально работоспособным

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


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

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

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

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

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

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

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

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

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

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