Jump to content

    
Sign in to follow this  
slaveeen

ucos+nios+isr

Recommended Posts

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

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

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

Share this post


Link to post
Share on other sites

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

Share this post


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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this