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

Помогите! Не работают OS*Post из прерываний

Пишу для XMega128, IAR 5.20. Не работают вызовы OSMboxPost, OSSemPost и OSQPost из обработчика прерывания. Между задачами вызовы работают прекрасно, сами прерывания тоже работают (диоды моргают, байты в UART бегают). Что делать ума не приложу :07:

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


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

Пишу для XMega128, IAR 5.20. Не работают вызовы OSMboxPost, OSSemPost и OSQPost из обработчика прерывания. Между задачами вызовы работают прекрасно, сами прерывания тоже работают (диоды моргают, байты в UART бегают). Что делать ума не приложу :07:

 

как используются функции OSIntEnter(), OSIntExit() ?

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


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

Непосредственно из прерывания сервисы ОС вызывать нельзя. Можно находясь в прерывании вызвать вспомогательную функцию в которой и устанавливается, например, семафор:

OSSemPost (Sem_LCD); // установить семафор для прорисовки дисплея

В отладчике можно проследить за переменной-семафором.

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


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

как используются функции OSIntEnter(), OSIntExit() ?

 

Вот обработчик из отдельного асмового файла. BSP_USARTC0_RXC_IRQ_Hndlr - мой обработчик прерывания. Изначально взят из порта, скачанного с Micriuma, изменил только ссылку на свой обработчик.

 

BSP_USARTC0_RXC_IRQ_vect:

CLI ; Disable Global Interrupts to avoid breaking context save

PUSH_ALL ; Save all registers and status register

PUSH_SREG_INT ; Save the SREG but with interrupts enabled

PUSH_SP ; Save the task's hardware stack pointer onto task's stack

LDS R16,OSIntNesting ; Notify uC/OS-II of ISR

INC R16 ;

STS OSIntNesting,R16 ;

CPI R16,1 ; if (OSIntNesting == 1) {

BRNE BSP_USARTC0_RXC_IRQ_vect_1

LDS R30,OSTCBCur ; OSTCBCur->OSTCBStkPtr = Y

LDS R31,OSTCBCur+1

ST Z+,R28

ST Z+,R29 ; }

BSP_USARTC0_RXC_IRQ_vect_1:

CALL BSP_USARTC0_RXC_IRQ_Hndlr ; Call Handler written in C

CALL OSIntExit ; Notify uC/OS-II about end of ISR

POP_SP ; Restore the hardware stack pointer from task's stack

POP_SREG_INT ; Restore status register (DISABLE interrupts)

POP_ALL ; Restore all registers

SEI ; Enable interrupts, since RETI does not on Xmega

RETI

 

 

 

Непосредственно из прерывания сервисы ОС вызывать нельзя. Можно находясь в прерывании вызвать вспомогательную функцию в которой и устанавливается, например, семафор:

OSSemPost (Sem_LCD); // установить семафор для прорисовки дисплея

В отладчике можно проследить за переменной-семафором.

 

 

Сейчас попробовал - не работает. Смотрю в отладчике, при вызове OSSemPost параметр pevent равен нулю и в жирном месте процедура вылетает. Если вызываю из задачи, то все нормально. Сам этот параметр при вызове располагается в регистрах R24-R25. Не может система при вызове прерывания как-нибудь кривить их? :05:

 

INT8U OSSemPost (OS_EVENT *pevent)

{

#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */

OS_CPU_SR cpu_sr = 0;

#endif

 

 

 

#if OS_ARG_CHK_EN > 0

if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */

return (OS_ERR_PEVENT_NULL);

}

#endif

if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */

return (OS_ERR_EVENT_TYPE);

}

OS_ENTER_CRITICAL();

if (pevent->OSEventGrp != 0) { /* See if any task waiting for semaphore */

/* Ready HPT waiting on event */

(void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_OK);

OS_EXIT_CRITICAL();

OS_Sched(); /* Find HPT ready to run */

return (OS_ERR_NONE);

}

if (pevent->OSEventCnt < 65535u) { /* Make sure semaphore will not overflow */

pevent->OSEventCnt++; /* Increment semaphore count to register event */

OS_EXIT_CRITICAL();

return (OS_ERR_NONE);

}

OS_EXIT_CRITICAL(); /* Semaphore value has reached its maximum */

return (OS_ERR_SEM_OVF);

}

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


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

Непосредственно из прерывания сервисы ОС вызывать нельзя.

Почему?

 

Можно находясь в прерывании вызвать вспомогательную функцию в которой и устанавливается, например, семафор:

Чем прямой вызов OSSemPost будет принципиально отличаться от его вызова через промежуточную функцию?

 

 

Сейчас попробовал - не работает. Смотрю в отладчике, при вызове OSSemPost параметр pevent равен нулю и в жирном месте процедура вылетает. Если вызываю из задачи, то все нормально. Сам этот параметр при вызове располагается в регистрах R24-R25. Не может система при вызове прерывания как-нибудь кривить их? :05:

По моему у вас проблемы не с ОС, а с Си. Код покажите. Как вы семафор объявляете, как инициализируете. Вы уверены, что он успевает инициализироваться до первого прерывания?

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


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

По моему у вас проблемы не с ОС, а с Си. Код покажите. Как вы семафор объявляете, как инициализируете. Вы уверены, что он успевает инициализироваться до первого прерывания?

 

Я думаю успевает, т.к. прерывание от УАРТа, а оно происходит по нажатию клавиши на клавиатуре (ну если конечно ему не 5 минут на инициализацию надо).

Вот код. В BSP_Init настраиваю УАРТ, разрешаю его прерывания, настраиваю таймер и порт для светодиода. Задача просто ждет семафора и моргает диодом (должна моргать, но не моргает :huh: ). Приоритет задачи 5, таймера 63.

 

#define APP_CFG_TASK1_STK_SIZE 360

 

static void App_Task1 (void *p_arg);

 

static OS_STK App_Task1Stk[APP_CFG_TASK1_STK_SIZE];

 

static OS_EVENT *App_Sem;

 

void main (void)

{

BSP_IntDisAll(); /* Disable all interrupts until we are ready to accept them */

/* IMPORTANT: MUST be setup before calling 'OSInit()' */

OSTaskStkSize = OS_TASK_IDLE_STK_SIZE; /* Setup the default stack size */

OSTaskStkSizeHard = OS_TASK_STK_SIZE_HARD; /* Setup the default hardware stack size */

 

OSInit(); /* Initialize "uC/OS-II, The Real-Time Kernel" */

 

BSP_Init(); /* Initialize the BSP */

 

App_TaskCreate(); /* Create the application tasks */

App_EventCreate(); /* Create the application events */

 

OSStart(); /* Start multitasking (i.e. give control to uC/OS-II) */

}

 

static void App_TaskCreate (void)

{

#if (OS_TASK_NAME_SIZE > 13)

CPU_INT08U os_err;

#endif

 

OSTaskCreateExt((void (*)(void *)) App_Task1,

(void *) 0,

(OS_STK *)&App_Task1Stk[APP_CFG_TASK1_STK_SIZE - 1],

(INT8U ) APP_CFG_TASK1_PRIO,

(INT16U ) APP_CFG_TASK1_PRIO,

(OS_STK *)&App_Task1Stk[0],

(INT32U ) APP_CFG_TASK1_STK_SIZE,

(void *) 0,

(INT16U )(OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR));

#if (OS_TASK_NAME_SIZE > 13)

OSTaskNameSet(APP_CFG_TASK1_PRIO, "Task1", &os_err);

#endif

}

 

static void App_EventCreate (void)

{

CPU_INT08U os_err;

 

App_Sem = OSSemCreate(1);

 

 

#if (OS_EVENT_NAME_SIZE > 8)

OSEventNameSet(App_Sem, "Semafor", &os_err);

#else

void(os_err);

#endif

 

}

 

 

static void App_Task1 (void *p_arg)

{

(void)p_arg;

 

while (DEF_TRUE) {

OSSemPend(App_Sem);

 

BSP_LED_Toggle(1);

}

}

 

 

 

Может у кого есть рабочий проект хотя бы для ATmega128. Если не жалко поделитесь. :help:

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


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

Во-первых, пользуйтесь тегом code для вставки исходных текстов.

Во-вторых, вы не показали здесь функцию прерывания, в которой делается OSSemPost.

Попытаюсь проявить телепатические способности:

Вызов OSSemPost у вас происходит в другом модуле, а App_Sem в приведенном вами тексте объявлен как static, то есть его область видимости ограничена этим модулем (единицей компиляции).

Соответственно, переменная App_Sem, которую вы используете в OSSemPost - это другая переменная в другой области видимости, которая у вас не инициализируется.

Покажите свой код, как вы объявляете и импользуете App_Sem в другом модуле.

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

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


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

Во-первых, пользуйтесь тегом code для вставки исходных текстов.

Во-вторых, вы не показали здесь функцию прерывания, в которой делается OSSemPost.

Попытаюсь проявить телепатические способности:

Вызов OSSemPost у вас происходит в другом модуле, а App_Sem в приведенном вами тексте объявлен как static, то есть его область видимости ограничена этим модулем (единицей компиляции).

Соответственно, переменная App_Sem, которую вы используете в OSSemPost - это другая переменная в другой области видимости, которая у вас не инициализируется.

Покажите свой код, как вы объявляете и импользуетет App_Sem в другом модуле.

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

 

Спасибо за наводку. Сейчас попробую :rolleyes:

 

Во-первых, пользуйтесь тегом code для вставки исходных текстов.

Во-вторых, вы не показали здесь функцию прерывания, в которой делается OSSemPost.

Попытаюсь проявить телепатические способности:

Вызов OSSemPost у вас происходит в другом модуле, а App_Sem в приведенном вами тексте объявлен как static, то есть его область видимости ограничена этим модулем (единицей компиляции).

Соответственно, переменная App_Sem, которую вы используете в OSSemPost - это другая переменная в другой области видимости, которая у вас не инициализируется.

Покажите свой код, как вы объявляете и импользуете App_Sem в другом модуле.

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

 

Вот обработчик, вызываемый из приведенного выше асмового обработчика. Эта процедура находится в файле bsp.c. App_Sem и задача объявляются в App.c. А не подскажете, как надо правильно объявлять App_Sem чтобы он всюду был виден? :blush:

 

void  BSP_USARTC0_RXC_IRQ_Hndlr (void)
{
  CPU_INT08U temp;
  temp = USARTC0.DATA;

  OSSemPost(App_Sem);
  BSP_LED_Toggle(8);
}

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


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

Вот обработчик, вызываемый из приведенного выше асмового обработчика. Эта процедура находится в файле bsp.c. App_Sem и задача объявляются в App.c. А не подскажете, как надо правильно объявлять App_Sem чтобы он всюду был виден? :blush:

Говорю же, у вас проблемы с Си, а вы сразу за ОС.

Читайте о ключевом слове extern.

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


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

Говорю же, у вас проблемы с Си, а вы сразу за ОС.

Читайте о ключевом слове extern.

 

Заработало! Спасибо!!! :08:

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


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

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

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

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

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

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

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

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

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

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