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

ucos+nios+isr

Доброго времени суток.

Создаю в 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, и как должен выглядеть обработчик прерываний в моем случае, то есть описанный штатными средствами операционной системы?

Если есть возможность поделитесь простым примером, от которого можно оттолкнутся.

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


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

Обработчик как обработчик. Можете поллингом сделать:

 

while(1)

{

if(BUTTON_PRESSED()) ...

}

 

Будет и просто, и без volatile, и антидребезг заодно.

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


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

Правильно ли я Вас понял, Вы предлагаете не использовать обработчик прерываний, а просто считывать состояние порта PIO?

 

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


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

Тогда я Вас понял, такой вариант тоже возможен, но только меня интересует именно синтаксис описания прерывания штатными средствами OC, может кто-нибудь поделится опытом?

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


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

Тогда я Вас понял, такой вариант тоже возможен, но только меня интересует именно синтаксис описания прерывания штатными средствами 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 в прерываниях.

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


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

Штатные средства ОС такие, что обработчик прерывания вызывается через враппер, который делает всю работу по входу/выходу из прерывания. Если у вас вектор прерываний настроен на работу через этот враппер, то свой обработчик записываете в таблицу обработчиков ОС и он выполнится без дополнительных телодвижений.

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


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

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. в таске, в начале тела ждем семафора, после чего делаем то, что надо, сбрасываем семафор

ну, это примерная модель, а уже для каждого конкретного случая может немного изменяться.

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


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

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

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

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

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

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

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

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

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

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