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

scmRTOS: если в одном из процессов "быстрый цикл", то все остальные процессы загибаются

Здравствуйте!

Такая вот проблема. Использую ОС scmRTOS на ATmega16. Создано два процесса. Первый: работа с USART, второй - с ЖКИ. Проблема: если во втором процессе применить цикл вида

while(PINB & (1 << KEY0));

, то первый процесс не работает. Если цикл исправить на такой

            while(PINB & (1 << KEY0))
                Sleep(50/OS_SWITCH_TASK);

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

Сложилось впечатление, что если в задаче (процессе) применен бесконечный цикл, то все остальные процессы "падают" до тех пор, пока это цикл не прекратится. Доку перечитал. Не нашел никаких комментариев на эту тему. Сам сообразить, в чем дело, не могу. Прошу помощи у бывалых. Заранее спасибо!

Детали:

МК ATmega16, кварц 16MHz

Время тика ОС 4.096 мс (TCCR0 = 0x04;)

Версия ОС 1.10

Компилятор WinAVR 20060421

 

На всякий случай прикладываю некоторые файлы своего проекта.

WAKE_RTOS.rar

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


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

Ну тут все очень просто. Чтобы могли крутиться другие процессы, надо чтобы "скоростной" процесс дал им такую возможность - грубо говоря "приспнул" (пардон за жаргон) на некоторое время. Именно это и делает функция Sleep. Без нее процесс никому управление и не отдаст.

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


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

Ну тут все очень просто. Чтобы могли крутиться другие процессы, надо чтобы "скоростной" процесс дал им такую возможность - грубо говоря "приспнул" (пардон за жаргон) на некоторое время. Именно это и делает функция Sleep. Без нее процесс никому управление и не отдаст.

Я почему-то считал, что в scmRTOS вытесняющая многозадачность ... Невнимательно читал мануал?

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


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

Я почему-то считал, что в scmRTOS вытесняющая многозадачность ... Невнимательно читал мануал?

Вытесняющая, но вытесняет тот процесс, у кого приоритет выше.

Если процесс с наивысшим приоритетом будет крутиться бесконечно, то все остальные будут курить бамбук...

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


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

Я почему-то считал, что в scmRTOS вытесняющая многозадачность ... Невнимательно читал мануал?

Вытесняющая, но вытесняет тот процесс, у кого приоритет выше.

Если процесс с наивысшим приоритетом будет крутиться бесконечно, то все остальные будут курить бамбук...

Так чтоже получается, любой процесс может угробить всю ОС простым зацикливанием. И как быть? Оооочень внимательно программировать? И как опеределить, сколько может такой цикл крутиться? Чутье мне подсказывает, что не более, чем один тик ОС. В моем случае 4 мс. Так ли это?

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


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

Вытесняющая, но вытесняет тот процесс, у кого приоритет выше.

Если процесс с наивысшим приоритетом будет крутиться бесконечно, то все остальные будут курить бамбук...

Так чтоже получается, любой процесс может угробить всю ОС простым зацикливанием. И как быть? Оооочень внимательно программировать? И как опеределить, сколько может такой цикл крутиться? Чутье мне подсказывает, что не более, чем один тик ОС. В моем случае 4 мс. Так ли это?

Не совсем так.

Программирование под OS несколько отличается от "обычного" программирования.

1. Работа должна выполняться на основе "событий". Никаких зацикливаний быть не должно.

2. Когда процессу делать нечего он должен отдать управление, управление будет передано тому, которому есть что делать.

 

Чутье не то чует, тик OS нужен только для таймера OS.

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


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

Вытесняющая, но вытесняет тот процесс, у кого приоритет выше.

Если процесс с наивысшим приоритетом будет крутиться бесконечно, то все остальные будут курить бамбук...

Так чтоже получается, любой процесс может угробить всю ОС простым зацикливанием. И как быть? Оооочень внимательно программировать? И как опеределить, сколько может такой цикл крутиться? Чутье мне подсказывает, что не более, чем один тик ОС. В моем случае 4 мс. Так ли это?

Не совсем так.

Программирование под OS несколько отличается от "обычного" программирования.

1. Работа должна выполняться на основе "событий". Никаких зацикливаний быть не должно.

2. Когда процессу делать нечего он должен отдать управление, управление будет передано тому, которому есть что делать.

 

Чутье не то чует, тик OS нужен только для таймера OS.

А если в моем процессе будет такого рода цикл?

for(i = 0; i < 1024; i++)
  Array[i] = log(c);

Пример привел чисто для примера...

Тоже получается зацикливание...

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


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

Кстати, сменил приоритет процесса с зацикливанием на более низкий, все работает... Теперь буду знать это...

 

В этом случае, если вы захотите использовать хук задачи Idle, то он не будет выполняться.

Кроме того, длительная работа более приоритетной задачи отложит обработку нажатия кнопки (или что там на пине). Насколько это критично, решать вам.

 

Конкретно по вашему случаю.

Если ваша задача должна выполнить что-то по внешнему событию, то можно поступить 2 путями:

1. Если отработать нужно срочно (похоже, что у вас так), то сажаете его на прерывание. В ISR шлете семафор задаче.

2. Еще один подход - "поллить" сигнал с таймаутом (что вы и сделали, когда вставили sleep()).

 

Приоритеты задач - это не та штука, которой вертят, "потому что работает".

Не обижайтесь, но у вас есть непонимание работы ОСРВ.

Документация на scmRTOS хорошая, но, возможно, для новичка (в ОС) стоит прочитать книгу Лябруса, хотя бы первые главы, в которых написано об общих принципах работы ОС: как должен быть организован код задачи, о приоритетах. Где-то в сети был перевод на русский нескольких глав.

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


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

Кстати, сменил приоритет процесса с зацикливанием на более низкий, все работает... Теперь буду знать это...

 

В этом случае, если вы захотите использовать хук задачи Idle, то он не будет выполняться.

Кроме того, длительная работа более приоритетной задачи отложит обработку нажатия кнопки (или что там на пине). Насколько это критично, решать вам.

 

Конкретно по вашему случаю.

Если ваша задача должна выполнить что-то по внешнему событию, то можно поступить 2 путями:

1. Если отработать нужно срочно (похоже, что у вас так), то сажаете его на прерывание. В ISR шлете семафор задаче.

2. Еще один подход - "поллить" сигнал с таймаутом (что вы и сделали, когда вставили sleep()).

 

Приоритеты задач - это не та штука, которой вертят, "потому что работает".

Не обижайтесь, но у вас есть непонимание работы ОСРВ.

Документация на scmRTOS хорошая, но, возможно, для новичка (в ОС) стоит прочитать книгу Лябруса, хотя бы первые главы, в которых написано об общих принципах работы ОС: как должен быть организован код задачи, о приоритетах. Где-то в сети был перевод на русский нескольких глав.

 

Что Вы... я нисколько не обижаюсь, ибо пока действительно не очень пониаю ОСРВ... но хочу научиться... Ну хорошо, с кнопкой ясно. Но как быть с приведенным ниже примером, ведь там тоже зацикливание?

Кстати, последнюю строку своего сообщения (вы ее в цитату взяли) я убрал, потому что спустя минут 10 после запуска все накрылось.

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


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

А в вашем привере цикл можно разбать на несколько подциклов с небольшой длительностью выполнения и периодически передавать управление (Sleep). Все зависит от срочности выполнения цикла.

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


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

Ну хорошо, с кнопкой ясно. Но как быть с приведенным ниже примером, ведь там тоже зацикливание?

В примере не зацикливание (бесконечный цикл, цикл ожидания медленноного процесса и т.п.), а рабочий, нужный цикл. Он выполняется вполне определенное время, в это время процессор не "толчет воду в ступе", а занимается необходимым делом.

 

Всякие кнопки и т.п. должны обрабатываться по прерываниям или таймерам. Зашел в прерывание (проснулся от таймера), быстро все сделал, если есть нажатие - сформировал событие (флаг, семафор ) и отдал управление (уснул) до следующего момента проверки кнопки.

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


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

ИМХО в основном цикле "влет" проверять состояние "кнопки" и переходить куда надо :)

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


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

haker_fox, Вы писали, что у Вас два процесса: UART и индикатор.

Не вижу никаких проблем в том, чтобы применять цикл в процессе индикатора если он менее приоритетный, чем UART.

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

В Вашем случае процесс индикатора является как бы фоновым и будет тут же вытеснен процессом UART как только наступят соответствующие события. Этим как раз и отличается вытесняющая ОС от кооперативной. Вам не нужно делать принудительного слипа в цикле (если конечно не хотите сэкономить электроэнергию, в этом случае большую часть времени система будет находиться в процессе Idle). И уж тем более не нужно изощряться с машинами состояний.

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


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

"cпустя минут 10 после запуска все накрылось."

 

Посмотрел ваш код, вложенный в первое сообщение.

В задаче TUserLoop после выхода из цикла while счетчик команд попадет в новый цикл - for (;;) и из него уже не выйдет. Причем, т.к. вы установили приоритет этой задачи выше, чем у задачи обработки пакета по uart, то последняя не получит управление, если внутри методов класса Lcd нет вызовов системных методов.

 

В scmRTOS вызовом sleep (wait etc) вы позволяете ("разрешаете") менее приоритетным _задачам_ сделать их работу. Планировщик, если надо, отберет у задачи управление и без ее "разрешения".

В кооперативных ОС вызовом sleep (wait etc) вы отдаете управление _планировщику_, без этого перепланирование невозможно.

 

PS. Заметил, что вы шлете каждый принятый символ в задачу. Этот подход вполне "законен", но не лучший. На каждый принятый символ производится вызов шедулера, время работы которого измеряется десятками микросекунд. При высоких скоростях обмена по uart процессор только и будет заниматься тем, что "щелкать" контекстом. Поэтому, для уменьшения расходов времени на перепланирование, следует принимать пакет в буфер в ОЗУ, а по окончании приема - семафорить в задачу или посылать ей указатель на принятое сообщение (если есть очередь сообщений). Разгребать пакет в задаче.

Насколько я понял, у вас протокол wake. Так вот, протокол уровня serial line (байт-стаффинг, фрейминг) разумно перенести в ISR приема по uart, а разбор команды (если она принята корректно) вести в задаче.

Изменено пользователем amusin

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


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

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

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

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

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

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

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

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

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

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