Wolfsoul 0 15 мая, 2007 Опубликовано 15 мая, 2007 (изменено) · Жалоба Возникла проблема с реализацией пользовательской обработки прерывания. Реализован процессор 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 Изменено 15 мая, 2007 пользователем CrazyFern Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
id_gene 0 15 мая, 2007 Опубликовано 15 мая, 2007 · Жалоба 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 и т.д. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Wolfsoul 0 16 мая, 2007 Опубликовано 16 мая, 2007 (изменено) · Жалоба 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. Может кто-нибудь предложит идеи? Заранее спасибо... Изменено 16 мая, 2007 пользователем CrazyFern Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
id_gene 0 16 мая, 2007 Опубликовано 16 мая, 2007 · Жалоба Результат следующий: виснуть проект перестал, но ожидаемых действий не наблюдается (вместо того, чтобы остановится внутри обработчика прерывания и прекратить запись на выходные регистры, продолжается вывод на выходную шину чисел, кратных 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" (как и остальные регистры). Запускайте отладчик и ставьте точку останова в обработчике прерываний. Похоже что прерывание-то у вас и не приходит. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Wolfsoul 0 24 мая, 2007 Опубликовано 24 мая, 2007 (изменено) · Жалоба При необходимости создать свое прерывание процессора от внешнего устройства рабочей оказалась следующая последовательность действий: 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 найдете неточности, пишите и я исправлю ошибки. Изменено 24 мая, 2007 пользователем CrazyFern Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
slonok 1 20 февраля, 2009 Опубликовано 20 февраля, 2009 · Жалоба Попробовал реализовать Ваш пример....ну и 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." сам я к программирования отношение мало имею... может кто нибудь прокоментирует как софтину поправить или примером поделится, реально работоспособным Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться