Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Помогите! Не работают OS*Post из прерываний
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > uC/OS-II
vitek101
Пишу для XMega128, IAR 5.20. Не работают вызовы OSMboxPost, OSSemPost и OSQPost из обработчика прерывания. Между задачами вызовы работают прекрасно, сами прерывания тоже работают (диоды моргают, байты в UART бегают). Что делать ума не приложу 07.gif
nemo777
Цитата(vitek101 @ Aug 25 2009, 15:09) *
Пишу для XMega128, IAR 5.20. Не работают вызовы OSMboxPost, OSSemPost и OSQPost из обработчика прерывания. Между задачами вызовы работают прекрасно, сами прерывания тоже работают (диоды моргают, байты в UART бегают). Что делать ума не приложу 07.gif


как используются функции OSIntEnter(), OSIntExit() ?
Vladimir_T
Непосредственно из прерывания сервисы ОС вызывать нельзя. Можно находясь в прерывании вызвать вспомогательную функцию в которой и устанавливается, например, семафор:
OSSemPost (Sem_LCD); // установить семафор для прорисовки дисплея
В отладчике можно проследить за переменной-семафором.
vitek101
Цитата(nemo777 @ Aug 25 2009, 18:10) *
как используются функции 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



Цитата(Vladimir_T @ Aug 25 2009, 20:25) *
Непосредственно из прерывания сервисы ОС вызывать нельзя. Можно находясь в прерывании вызвать вспомогательную функцию в которой и устанавливается, например, семафор:
OSSemPost (Sem_LCD); // установить семафор для прорисовки дисплея
В отладчике можно проследить за переменной-семафором.



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

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);
}
Andy Mozzhevilov
Цитата(Vladimir_T @ Aug 25 2009, 20:25) *
Непосредственно из прерывания сервисы ОС вызывать нельзя.

Почему?

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

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


Цитата(vitek101 @ Aug 26 2009, 08:42) *
Сейчас попробовал - не работает. Смотрю в отладчике, при вызове OSSemPost параметр pevent равен нулю и в жирном месте процедура вылетает. Если вызываю из задачи, то все нормально. Сам этот параметр при вызове располагается в регистрах R24-R25. Не может система при вызове прерывания как-нибудь кривить их? 05.gif

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

Я думаю успевает, т.к. прерывание от УАРТа, а оно происходит по нажатию клавиши на клавиатуре (ну если конечно ему не 5 минут на инициализацию надо).
Вот код. В BSP_Init настраиваю УАРТ, разрешаю его прерывания, настраиваю таймер и порт для светодиода. Задача просто ждет семафора и моргает диодом (должна моргать, но не моргает huh.gif ). Приоритет задачи 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.gif
Andy Mozzhevilov
Во-первых, пользуйтесь тегом code для вставки исходных текстов.
Во-вторых, вы не показали здесь функцию прерывания, в которой делается OSSemPost.
Попытаюсь проявить телепатические способности:
Вызов OSSemPost у вас происходит в другом модуле, а App_Sem в приведенном вами тексте объявлен как static, то есть его область видимости ограничена этим модулем (единицей компиляции).
Соответственно, переменная App_Sem, которую вы используете в OSSemPost - это другая переменная в другой области видимости, которая у вас не инициализируется.
Покажите свой код, как вы объявляете и импользуете App_Sem в другом модуле.
Проследите в отладчике, по каким адресам у вас лежат эти переменные, чем и когда они инициализируются.
vitek101
Цитата(Andy Mozzhevilov @ Aug 26 2009, 13:49) *
Во-первых, пользуйтесь тегом code для вставки исходных текстов.
Во-вторых, вы не показали здесь функцию прерывания, в которой делается OSSemPost.
Попытаюсь проявить телепатические способности:
Вызов OSSemPost у вас происходит в другом модуле, а App_Sem в приведенном вами тексте объявлен как static, то есть его область видимости ограничена этим модулем (единицей компиляции).
Соответственно, переменная App_Sem, которую вы используете в OSSemPost - это другая переменная в другой области видимости, которая у вас не инициализируется.
Покажите свой код, как вы объявляете и импользуетет App_Sem в другом модуле.
Проследите в отладчике, по каким адресам у вас лежат эти переменные, чем и когда они инициализируются.


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

Цитата(Andy Mozzhevilov @ Aug 26 2009, 13:49) *
Во-первых, пользуйтесь тегом code для вставки исходных текстов.
Во-вторых, вы не показали здесь функцию прерывания, в которой делается OSSemPost.
Попытаюсь проявить телепатические способности:
Вызов OSSemPost у вас происходит в другом модуле, а App_Sem в приведенном вами тексте объявлен как static, то есть его область видимости ограничена этим модулем (единицей компиляции).
Соответственно, переменная App_Sem, которую вы используете в OSSemPost - это другая переменная в другой области видимости, которая у вас не инициализируется.
Покажите свой код, как вы объявляете и импользуете App_Sem в другом модуле.
Проследите в отладчике, по каким адресам у вас лежат эти переменные, чем и когда они инициализируются.


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

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

  OSSemPost(App_Sem);
  BSP_LED_Toggle(8);
}
Andy Mozzhevilov
Цитата(vitek101 @ Aug 26 2009, 14:21) *
Вот обработчик, вызываемый из приведенного выше асмового обработчика. Эта процедура находится в файле bsp.c. App_Sem и задача объявляются в App.c. А не подскажете, как надо правильно объявлять App_Sem чтобы он всюду был виден? blush.gif

Говорю же, у вас проблемы с Си, а вы сразу за ОС.
Читайте о ключевом слове extern.
vitek101
Цитата(Andy Mozzhevilov @ Aug 26 2009, 14:31) *
Говорю же, у вас проблемы с Си, а вы сразу за ОС.
Читайте о ключевом слове extern.


Заработало! Спасибо!!! 08.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.