kurtis 0 31 марта, 2010 Опубликовано 31 марта, 2010 · Жалоба Здравствуйте! Столкнулся с проблемой зависания процесса, который занимается аналоговыми измерениями. Всего в системе 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 0 31 марта, 2010 Опубликовано 31 марта, 2010 · Жалоба Для начала разберитесь, почему зависает? Зависнуть он может либо в Sleep(), либо ожидая какого-нибудь события (флаг, мютекс) и не дожидается никогда. Проанализируйте, почему шедулер не ставит его в активное состояние. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kurtis 0 31 марта, 2010 Опубликовано 31 марта, 2010 · Жалоба В том то и проблема что я не понимаю почему зависает и зависает он именно в Sleep(). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 31 марта, 2010 Опубликовано 31 марта, 2010 · Жалоба В том то и проблема что я не понимаю почему зависает и зависает он именно в Sleep().А остальные процессы при этом продолжают работать? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kurtis 0 31 марта, 2010 Опубликовано 31 марта, 2010 · Жалоба да Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 31 марта, 2010 Опубликовано 31 марта, 2010 · Жалоба Я это к чему: Я дописал маленький отладочный кусочек в ядро, который сохраняет адрес сервиса, переведшего процесс в ожидание. И если процесс 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 14 31 марта, 2010 Опубликовано 31 марта, 2010 · Жалоба Я это к чему: Я дописал маленький отладочный кусочек в ядро, который сохраняет адрес сервиса, переведшего процесс в ожидание А если процесс заснул добровольно (и больше не проснулся), как у автора топика, то какой там будет адрес? :) 2 kurtis: Всё выглядит так, что процесс "Работа с UART" занимает всё процессорное время. Но при этом не работали бы и все остальные процессы, а не только TAnalogMeasure... Они точно работают? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 31 марта, 2010 Опубликовано 31 марта, 2010 · Жалоба А если процесс заснул добровольно (и больше не проснулся), как у автора топика, то какой там будет адрес? :)0 Можно добавить в OS::TBaseProcess:Sleep() занесение туда какого-то другого числа, скажем (void*) -1, чтобы отличить от работающего процесса, у которого более приоритетный отобрал управление насильно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kurtis 0 31 марта, 2010 Опубликовано 31 марта, 2010 · Жалоба 2 Сергей Борщ Попробовал вашу методику. Поместил ваш код в фунцию TBaseProcess::Sleep(), в переменной Waiter сохраняется адрес зависшего процесса AnalogMeasure. 2 AHTOXA Остальные работают. В других процессах идет опрос клавиатуры, вывод информации на жки и засветка светодиодов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 34 1 апреля, 2010 Опубликовано 1 апреля, 2010 · Жалоба 2 Сергей Борщ Попробовал вашу методику. Поместил ваш код в фунцию TBaseProcess::Sleep(), в переменной Waiter сохраняется адрес зависшего процесса AnalogMeasure. Значит, это он уснул добровольно. Посмотрите, чему равно значение таймаута этого процесса. При достижении таймаутом нуля процесс должен быть разбужен. Еще посмотрите ReadyProcessMap - точно ли процесс спит или готов к выполнению (соответствующий бит установлен), но по какой-то причине не работает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BAT 0 29 марта, 2011 Опубликовано 29 марта, 2011 · Жалоба Столкнулся с похожей проблемой. Есть проект, где в паре процессов используется в основном цикле Sleep. Что-то типа for(;;) { Sleep(10); . . . } Время от времени (достаточно редко) процессы застревают именно в Sleep. Timeout процесса при этом равен нулю. Процесс к выполнению в карте процессов не готов. Порт под STM Cortex-M3. IAR 6.10. Стек не переполняется с запасом. Какие, хотя бы приблизительно, могут быть косяки с моей стороны приводящие к такому результату? Не могу понять, где копать. Некорректное использование переменных с доступом из разных процессов может приводить к такому? Правда одновременная модификация нигде не используется. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
a9d 0 29 марта, 2011 Опубликовано 29 марта, 2011 · Жалоба У меня один раз косяк был, когда я для межпроцессорного обмена использовал глобальную переменную. Избавился от нее и все прошло. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 34 30 марта, 2011 Опубликовано 30 марта, 2011 · Жалоба Какие, хотя бы приблизительно, могут быть косяки с моей стороны приводящие к такому результату? Не могу понять, где копать. Некорректное использование переменных с доступом из разных процессов может приводить к такому? Правда одновременная модификация нигде не используется. Сложно сказать удалённо. Возможно, что с вашей стороны косяков и нет. Есть нюанс, связанный с приоритетным многоуровневым аппаратным контроллером и приоритетом прерывания переключения контекстов, который в текущей версии не учитывается (пофиксен в новой версии, которая готовится к выпуску). Не знаю в деталях, как это устроено у кортекса, и как это сконфигурировано в порте, поэтому, возможно, дело не в этом. Но на всякий случай. Добавьте в OS::TKernel::context_switch_hook() (OS_Kernel.h) первой строчкой TCritSect cs; и посмотрите, пропадёт ли зависание. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 14 30 марта, 2011 Опубликовано 30 марта, 2011 · Жалоба Стек не переполняется с запасом. Меня смутила эта фраза. Вы хотели сказать - "стеки"? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BAT 0 30 марта, 2011 Опубликовано 30 марта, 2011 · Жалоба Меня смутила эта фраза. Вы хотели сказать - "стеки"? ну да :) конечно для каждого процесса свой просто как-то по старой очень привычке называю их одним иногда Попробую добавить TCritSect cs. Попозже напишу результат. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться