Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Зависает один процесс
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > scmRTOS
kurtis
Здравствуйте!
Столкнулся с проблемой зависания процесса, который занимается аналоговыми измерениями. Всего в системе 4 процесса, приоритеты распределены следующим образом
Код
#define ANMEAS_PRI  (OS::pr1) /* Аналоговые измерения */
#define UART0_PRI   (OS::pr0) /* Работа с UART */
#define TECHNO_PRI  (OS::pr3) /* Технология (логика работы программы) */
#define PERIPH_PRI  (OS::pr2) /* Работа с периферийными устройствами */

Если я меняю значение приоритета ANMEAS_PRI на максимальный (с OS::pri1 на OS::pri0) то зависания пропадают. Проблема в том что я не могу разобраться почему в одном случае оно работает, а в другом - нет.
Исходный код доступен здесь.
Для поиска неисправностей, я написал небольшой макрос (SET_INFO(x)), который посылает в UART текущий номер, все вызовы макроса расположены в порядке возрастания порядкового номера. Модифицированный вариант исходника лежит здесь.
Таким образом установил, что после зависания процесса, в UART отправляется число 26
Код
104         }
105         SET_INFO(26);
106
107         Sleep(5,5);// 11 mc
108         SET_INFO(27);
109         LED_Out_Str[24] = GREEN_LAMP;
110         SET_INFO(28);
Т.е. прямо перед вызовом функции Sleep(). Далее я перегрузил функцию Sleep() (чтоб вызывалась конкретная функция только для одного процесса), и модифицировал по описанной выше методике, получилось такое
Код
void TBaseProcess::Sleep(TTimeout timeout, uint8_t huita)
{
    {
    TCritSect cs;

    SET_INFO(30);
    Kernel.ProcessTable[Kernel.CurProcPriority]->Timeout = timeout;
    SET_INFO(31);
    Kernel.SetProcessUnready(Kernel.CurProcPriority);
    SET_INFO(32);
    Kernel.Scheduler();
    SET_INFO(33);
    }
    SET_INFO(34);
}
Теперь последнее отправляемое число в UART 32, т.е. прямо перед вызовом Kernel.Scheduler(). Дальше лезть страшно.

В чем может возникать проблема что при смене приоритетов процесс наглухо зависает? Может есть какие-то рекомендации, чего делать не стоит или у меня какие-то существенные ошибки в описании процесса?
Заранее Спасибо!:))

P.S. Версия scmRTOS 3.10, компилятор avr-gcc (4.3.3)
jorikdima
Для начала разберитесь, почему зависает? Зависнуть он может либо в Sleep(), либо ожидая какого-нибудь события (флаг, мютекс) и не дожидается никогда. Проанализируйте, почему шедулер не ставит его в активное состояние.
kurtis
В том то и проблема что я не понимаю почему зависает и зависает он именно в Sleep().
Сергей Борщ
Цитата(kurtis @ Mar 31 2010, 15:32) *
В том то и проблема что я не понимаю почему зависает и зависает он именно в Sleep().
А остальные процессы при этом продолжают работать?
kurtis
да
Сергей Борщ
Я это к чему: Я дописал маленький отладочный кусочек в ядро, который сохраняет адрес сервиса, переведшего процесс в ожидание. И если процесс uart у вас продолжет работать, то в нем можно выводить наружу по запросу адрес такого сервиса. Далее поиском по map-файлу находим, что за сервис и думаем, почему он не отпускает процесс:
Код
в Kernel.h, в TBaseProcess:
        void *waiter() { return Waiter; } // <-----
    protected:
        void *Waiter;                             // <-----
        TStackItem* StackPointer;
        TTimeout Timeout;
        TPriority const Priority;

а в сервисах, в меестах ожидания, вызов Kernel.Scheduler() обрамляем:
    ClrPrioTag(Kernel.ReadyProcessMap, PrioTag);  // remove current process from the ready map
    Kernel.ProcessTable[Kernel.CurProcPriority]->Waiter = this;  // <-----
    Kernel.Scheduler();
    Kernel.ProcessTable[Kernel.CurProcPriority]->Waiter = 0;      // <----

Остается по какому-то событию пройтись по Kernel.ProcessTable и выдать наружу результат waiter().
AHTOXA
Цитата(Сергей Борщ @ Mar 31 2010, 20:19) *
Я это к чему: Я дописал маленький отладочный кусочек в ядро, который сохраняет адрес сервиса, переведшего процесс в ожидание


А если процесс заснул добровольно (и больше не проснулся), как у автора топика, то какой там будет адрес? smile.gif

2 kurtis: Всё выглядит так, что процесс "Работа с UART" занимает всё процессорное время. Но при этом не работали бы и все остальные процессы, а не только TAnalogMeasure... Они точно работают?
Сергей Борщ
Цитата(AHTOXA @ Mar 31 2010, 16:37) *
А если процесс заснул добровольно (и больше не проснулся), как у автора топика, то какой там будет адрес? smile.gif
0
Можно добавить в OS::TBaseProcess:Sleep() занесение туда какого-то другого числа, скажем (void*) -1, чтобы отличить от работающего процесса, у которого более приоритетный отобрал управление насильно.
kurtis
2 Сергей Борщ
Попробовал вашу методику. Поместил ваш код в фунцию TBaseProcess::Sleep(), в переменной Waiter сохраняется адрес зависшего процесса AnalogMeasure.

2 AHTOXA
Остальные работают. В других процессах идет опрос клавиатуры, вывод информации на жки и засветка светодиодов.
dxp
Цитата(kurtis @ Apr 1 2010, 01:15) *
2 Сергей Борщ
Попробовал вашу методику. Поместил ваш код в фунцию TBaseProcess::Sleep(), в переменной Waiter сохраняется адрес зависшего процесса AnalogMeasure.

Значит, это он уснул добровольно. Посмотрите, чему равно значение таймаута этого процесса. При достижении таймаутом нуля процесс должен быть разбужен. Еще посмотрите ReadyProcessMap - точно ли процесс спит или готов к выполнению (соответствующий бит установлен), но по какой-то причине не работает.
BAT
Столкнулся с похожей проблемой. Есть проект, где в паре процессов используется в основном цикле Sleep.
Что-то типа
CODE
for(;;)
{
Sleep(10);

. . .

}


Время от времени (достаточно редко) процессы застревают именно в Sleep.
Timeout процесса при этом равен нулю. Процесс к выполнению в карте процессов не готов.
Порт под STM Cortex-M3. IAR 6.10.
Стек не переполняется с запасом.

Какие, хотя бы приблизительно, могут быть косяки с моей стороны приводящие к такому результату? Не могу понять, где копать.
Некорректное использование переменных с доступом из разных процессов может приводить к такому?
Правда одновременная модификация нигде не используется.
a9d
У меня один раз косяк был, когда я для межпроцессорного обмена использовал глобальную переменную. Избавился от нее и все прошло.
dxp
Цитата(BAT @ Mar 29 2011, 19:31) *
Какие, хотя бы приблизительно, могут быть косяки с моей стороны приводящие к такому результату? Не могу понять, где копать.
Некорректное использование переменных с доступом из разных процессов может приводить к такому?
Правда одновременная модификация нигде не используется.

Сложно сказать удалённо. Возможно, что с вашей стороны косяков и нет. Есть нюанс, связанный с приоритетным многоуровневым аппаратным контроллером и приоритетом прерывания переключения контекстов, который в текущей версии не учитывается (пофиксен в новой версии, которая готовится к выпуску). Не знаю в деталях, как это устроено у кортекса, и как это сконфигурировано в порте, поэтому, возможно, дело не в этом. Но на всякий случай. Добавьте в OS::TKernel::context_switch_hook() (OS_Kernel.h) первой строчкой TCritSect cs; и посмотрите, пропадёт ли зависание.
AHTOXA
Цитата(BAT @ Mar 29 2011, 18:31) *
Стек не переполняется с запасом.

Меня смутила эта фраза. Вы хотели сказать - "стеки"?
BAT
Цитата(AHTOXA @ Mar 30 2011, 08:34) *
Меня смутила эта фраза. Вы хотели сказать - "стеки"?


ну да sm.gif конечно для каждого процесса свой
просто как-то по старой очень привычке называю их одним иногда

Попробую добавить TCritSect cs. Попозже напишу результат.
BAT
CODE
TStackItem* OS::TKernel::ContextSwitchHook(TStackItem* sp)
{
TCritSect cs; <--- здесь

ProcessTable[CurProcPriority]->StackPointer = sp;
sp = ProcessTable[SchedProcPriority]->StackPointer;

#if scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE == 1
ContextSwitchUserHook();
#endif

CurProcPriority = SchedProcPriority;
return sp;
}


Туда я добавил? Если да, то не помогло sad.gif. Все это чаще всего проявляется, когда активно начинает работать высокоприоритетный процес + идет активно связь по компорту, а она реализована в силу особенностей на прерываниях с использованием канала оси. OS::TISRW ISR на обработчиках стоит.
dxp
Цитата(BAT @ Mar 30 2011, 15:18) *
Туда я добавил? Если да, то не помогло sad.gif. Все это чаще всего проявляется, когда активно начинает работать высокоприоритетный процес + идет активно связь по компорту, а она реализована в силу особенностей на прерываниях с использованием канала оси. OS::TISRW ISR на обработчиках стоит.

Да, добавили правильно. Если у вашего порта приоритетный контроллер прерываний и прерывание переключения контекстов может быть прервано (вытеснено) другим прерыванием, то эту критическую секцию надо там оставить (иначе чревато проблемами). В противном случае можно убрать.

Причину найти с ходу тяжело. Если есть возможность, то для начала добиться повторяемости (определить, при каких условиях это происходит). Тогда уже можно экспериментировать с целью локализовать проблему.

По симптомам вообще похоже на переполнение стека, когда данные стека налезают на чужую память. Ну, и вообще, такое поведение характерно для ошибок работы с памятью, когда из-за неправильной адресации портится чужая память. Посмотрите - остальные потроха объекта-процесса не портятся? Только Timeout?

По размерам стеков как определили, что их объём достаточен?

По самой оси кроме вышеописанного косяка с приоритетными контроллерами прерываний, вопросов, вроде, не замечено.
BAT
Остальные данные в объектах-процессах не портятся. Насколько я смог увидеть.
Стек проверяю простой инициализацией его константой и потом просто в отладчике отслеживаю сколько не модифицировалось.
Пока проект в отладке стараюсь выделять с сильным запасом(часто более 2х кратного).
Кстати, в новом релизе не планируется добавить дебагрежима на такие случаи, чтоб были переменные с данными по использованию стеков?

Самое неприятное, что ошибка вылезает нечасто. И пока не могу добиться стабильности в этом.
AHTOXA
Цитата(dxp @ Mar 30 2011, 18:56) *
Да, добавили правильно. Если у вашего порта приоритетный контроллер прерываний и прерывание переключения контекстов может быть прервано (вытеснено) другим прерыванием, то эту критическую секцию надо там оставить (иначе чревато проблемами). В противном случае можно убрать.

В порте(ах) для Cortex-M3 прерывания при вызове OS::TKernel::ContextSwitchHook() и так запрещены:
OS_Target_asm.S:
Код
PendSVC_ISR:
    CPSID   I                 // Prevent interruption during context switch
...
    LDR     R1, =os_context_switch_hook    // os_context_switch_hook();
    BLX     R1

так что эта критическая секция не нужна.
dxp
Цитата(AHTOXA @ Mar 30 2011, 21:15) *
В порте(ах) для Cortex-M3 прерывания при вызове OS::TKernel::ContextSwitchHook() и так запрещены:
OS_Target_asm.S:
Код
PendSVC_ISR:
    CPSID   I                 // Prevent interruption during context switch
...
    LDR     R1, =os_context_switch_hook    // os_context_switch_hook();
    BLX     R1

так что эта критическая секция не нужна.

Ты про свой порт или это у IAR'ного подсмотрел?

Цитата(BAT @ Mar 30 2011, 20:19) *
Кстати, в новом релизе не планируется добавить дебагрежима на такие случаи, чтоб были переменные с данными по использованию стеков?

Да, будет специальный режим отладки (кстати, это уже есть, лежит в репозитории в ветке, которая относится к подготовке релиза, pre-v400), и интерфейс (специальная функция) для получения информации о запасе по стеку. Также, будет возможность засекать адрес сервиса, который ожидает процесс - бывает, что процесс висит, чего-то ждёт, тут полезно бывает узнать, чего он ждёт. Ещё будет профилировка работы процессов (два вида, в виде расширений). Всё это будет подробно описано в документации.

Цитата(BAT @ Mar 30 2011, 20:19) *
Самое неприятное, что ошибка вылезает нечасто. И пока не могу добиться стабильности в этом.

Вот это и есть ключ к решению - если добиться повторяемости, тогда станет понятно, в каких условиях оно проявляется и, меняя условия, можно будет локализовать проблему.
AHTOXA
Цитата(dxp @ Mar 31 2011, 11:04) *
Ты про свой порт или это у IAR'ного подсмотрел?

Это у обоих портов так, изначально.
dxp
Цитата(AHTOXA @ Mar 31 2011, 12:23) *
Это у обоих портов так, изначально.

Гуд, значит для этих портов ничего не надо делать.
kostyan
Аналогично BATу, словил зависание процесса. Вставал высокоприоритетный процесс опроса клавиатуры - когда начиналась в низкоприоритетном процессе активная передача инфы по USART с использованием прерываний (причем сама передача в фоне в задаче, прием коротких команд на чтение данных только в прерывании)! На cortex m3 от атмела sam3u4. Можно сказать "по совету" dxp поигрался с приоритетом прерывания usart-а, выставил ему минимальный приоритет 15-й. И, тьфу тьфу, о чудо - сейчас всё робит! Но в будущих проектах конечно боязно теперь юзать scmRTOS. Как бы и не особо собирался - освоил более менее TNKernel (больше нравится), но факт остается фактом - не у одного меня встают процессы на кортексах на scmRTOS. Похорошему бы перевести проект на TNKernel с изначальными приоритетами прерываний и посмотреть как оно будет. Но проект огромный - времени нет (да и думаю желания у начальства). Вот так вот, может кому поможет - поиграться с приоритетами прерываний.
_Артём_
Цитата(kostyan @ Jun 5 2012, 06:53) *
Аналогично BATу, словил зависание процесса. Вставал высокоприоритетный процесс опроса клавиатуры - когда начиналась в низкоприоритетном процессе активная передача инфы по USART с использованием прерываний (причем сама передача в фоне в задаче, прием коротких команд на чтение данных только в прерывании)! На cortex m3 от атмела sam3u4. Можно сказать "по совету" dxp поигрался с приоритетом прерывания usart-а, выставил ему минимальный приоритет 15-й. И, тьфу тьфу, о чудо - сейчас всё робит! Но в будущих проектах конечно боязно теперь юзать scmRTOS. Как бы и не особо собирался - освоил более менее TNKernel (больше нравится), но факт остается фактом - не у одного меня встают процессы на кортексах на scmRTOS. Похорошему бы перевести проект на TNKernel с изначальными приоритетами прерываний и посмотреть как оно будет. Но проект огромный - времени нет (да и думаю желания у начальства). Вот так вот, может кому поможет - поиграться с приоритетами прерываний.


О какой версии идёт речь? 3 или 4?
kostyan
3.11
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.