slaveeen 0 15 сентября, 2014 Опубликовано 15 сентября, 2014 · Жалоба Доброго времени суток. Создаю в eclipse проект на основе примера hello usoc. В нем есть две задачи, которые попеременно выводят в консоль сообщения, все вроде бы просто и понятно. В моей процессорной системе (Nios) есть порт (input) PIO. Он настроен на генерацию прерываний по нажатию на кнопку на моем борде. Если говорить о "чистом " C коде, то как зарегистрировать прерывания и описать их обработчик мне известно (через ф-ию alt_irq_register() и т.д.). В примере hello usoc я так и сделал, вот пример кода: #include <stdio.h> #include "includes.h" #include "system.h" #include "altera_avalon_pio_regs.h" //#include "altera_avalon_pio_regs.h" /* Definition of Task Stacks */ #define TASK_STACKSIZE 2048 OS_STK task1_stk[TASK_STACKSIZE]; OS_STK task2_stk[TASK_STACKSIZE]; /* Definition of Task Priorities */ #define TASK1_PRIORITY 1 #define TASK2_PRIORITY 8 volatile int buttons=0; int led=0; static void button_isr( void * base, alt_u32 id ) { buttons = IORD_ALTERA_AVALON_PIO_EDGE_CAP(base); IOWR_ALTERA_AVALON_PIO_EDGE_CAP(base,0x3); } void task1(void* pdata) { while (1) { if (buttons != 0) { switch (buttons) { case 1: alt_printf("Нажата кнопка pb_left\n "); if (led == 0x80||led==0x00 ) led = 0x01; else led = led << 1; buttons = 0; break; case 2: alt_printf("Нажата кнопка pb_right\n "); if (led == 0x01 ||led==0x00 ) led = 0x80; else led = led >> 1; buttons = 0; break; default: buttons = 0; break; } IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE,led); } printf("Hello from task1\n"); //OSTimeDlyHMSM(0, 0, 1, 0); } } void task2(void* pdata) { while (1) { alt_irq_register(BUTTONS_IRQ, (void*)BUTTONS_BASE, button_isr); printf("Hello from task2\n"); //OSTimeDlyHMSM(0, 0, 1, 0); } } /* The main function creates two task and starts multi-tasking */ int main(void) { IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE,0x00); IOWR_ALTERA_AVALON_PIO_IRQ_MASK(BUTTONS_BASE, 0x3); IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTONS_BASE, 0x3); alt_irq_register(BUTTONS_IRQ, (void*)BUTTONS_BASE, button_isr); OSTaskCreateExt(task1, NULL, (void *)&task1_stk[TASK_STACKSIZE-1], TASK1_PRIORITY, TASK1_PRIORITY, task1_stk, TASK_STACKSIZE, NULL, 0); OSTaskCreateExt(task2, NULL, (void *)&task2_stk[TASK_STACKSIZE-1], TASK2_PRIORITY, TASK2_PRIORITY, task2_stk, TASK_STACKSIZE, NULL, 0); OSStart(); return 0; } Но я чувствую, что в ucos такая работа с прерываниями некорректна. Подскажите пожалуйста, какова идеология работы с прерываниями под ucos, и как должен выглядеть обработчик прерываний в моем случае, то есть описанный штатными средствами операционной системы? Если есть возможность поделитесь простым примером, от которого можно оттолкнутся. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrewlekar 0 16 сентября, 2014 Опубликовано 16 сентября, 2014 · Жалоба Обработчик как обработчик. Можете поллингом сделать: while(1) { if(BUTTON_PRESSED()) ... } Будет и просто, и без volatile, и антидребезг заодно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
slaveeen 0 16 сентября, 2014 Опубликовано 16 сентября, 2014 · Жалоба Правильно ли я Вас понял, Вы предлагаете не использовать обработчик прерываний, а просто считывать состояние порта PIO? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrewlekar 0 17 сентября, 2014 Опубликовано 17 сентября, 2014 · Жалоба Да. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
slaveeen 0 17 сентября, 2014 Опубликовано 17 сентября, 2014 · Жалоба Тогда я Вас понял, такой вариант тоже возможен, но только меня интересует именно синтаксис описания прерывания штатными средствами OC, может кто-нибудь поделится опытом? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Lagman 1 18 сентября, 2014 Опубликовано 18 сентября, 2014 · Жалоба Тогда я Вас понял, такой вариант тоже возможен, но только меня интересует именно синтаксис описания прерывания штатными средствами OC, может кто-нибудь поделится опытом? Использовал на другом процессоре. Нет там никаких штатных средств описания прерывания, есть только общие слова (ucos-ii) YourISR: Save all CPU registers; Call OSIntEnter() or, increment OSIntNesting directly; Execute user code to service ISR; Call OSIntExit(); Restore all CPU registers; Execute a return from interrupt instruction; Остальное происходит как описано в даташите на процессор, единственное нельзя ожидать событий от RTOS в прерываниях. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrewlekar 0 19 сентября, 2014 Опубликовано 19 сентября, 2014 · Жалоба Штатные средства ОС такие, что обработчик прерывания вызывается через враппер, который делает всю работу по входу/выходу из прерывания. Если у вас вектор прерываний настроен на работу через этот враппер, то свой обработчик записываете в таблицу обработчиков ОС и он выполнится без дополнительных телодвижений. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
billidean 0 11 октября, 2014 Опубликовано 11 октября, 2014 · Жалоба void task2(void* pdata) { while (1) { alt_irq_register(BUTTONS_IRQ, (void*)BUTTONS_BASE, button_isr); printf("Hello from task2\n"); //OSTimeDlyHMSM(0, 0, 1, 0); } } Это вообще ... какая-то, в бесконечном цикле регить обработчик.... А вообще, более правильный механизм выглядит так: 1. регим обработчик прерывания 2. заводим семафор 3. заводим таск, которому нужно это прерывание 4. в обработчике прерывания взводим семафор 5. в таске, в начале тела ждем семафора, после чего делаем то, что надо, сбрасываем семафор ну, это примерная модель, а уже для каждого конкретного случая может немного изменяться. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться