skilful 0 16 февраля, 2021 Опубликовано 16 февраля, 2021 · Жалоба Здравствуйте. Имеется критичный по времени работы кусочек кода, который работает в цикле и ему лучше не мешать :) Однако этот кусок кода должен поработать минут 15-20 и прекратить работать. МК -- AVR. Сейчас я сделал так: cli(); //запустили таймер1 с делителем 1024 без прерываний. Будем следить за битом переполнения //сработка равна ~ 4 секунды на 16 МГц TCCR1A = 0; TCCR1B = 0; TIMSK1 = 0; TCCR1B |= (1 << CS12); TCCR1B |= (1 << CS10); uint8_t TOV1_cnt = 255; ~ 4 секунды do { ////////тут критичный по времени код. Написан на ассемблере //.... //////// // выход из цикла примерно через 15-20 минут if ((TIFR1) & (1 << TOV1)) { //таймер1 с предделителем работает в фоне. Сработка каждые 4 секунды TIFR1 = 0x01; //сброс бита переполнения. Пишем туда 1 для сброса TOV1_cnt--; } } while (TOV1_cnt > 0); sei(); Т.е. запустили Таймер1 в фоне и без прерываний, и опрашиваем бит его переполнения в критичном по времени работы цикле. Если Таймер1 переполнился -- сбрасываем этот бит, и декрементируем счетчик времени работы цикла. Этот код я дизассемблировал и он как бы во временном допуске получается. Но может как-то еще быстрее можно контролировать время работы цикла? Можно применять абсолютно любую периферию МК AVR, программные трюки в том числе и сторожевой таймер :) Задача: максимально не мешать критично важному по времени куску кода и завершить его через 15-20 минут. Спасибо! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrBearManul 0 16 февраля, 2021 Опубликовано 16 февраля, 2021 · Жалоба 20 минут назад, skilful сказал: программные трюки в том числе и сторожевой таймер :) Не знаю, реально ли. Лень заглядывать в доку. Но перед запуском критического цикла, настраиваете таймаут сторожевика на 15 минут. Запускаете код. Через 15 минут сторожевик аккуратно прерывает ваш цикл. Никаких проверок в самом цикле не нужно. А в секции .noinit располагаете переменную, которая будет хранить результат предыдущей работы программы. После сброса там будет, скорее всего, мусор. Т.к. в AVR вроде нет встроенных загрузчиков, которые могут занулить ОЗУ. З.Ы. Понимаю, что фантастика, но вдруг, если даже и не сработает, то наведёт на мысль. Стоп! А почему фантастика? Настраиваете таймер (не сторожевик) на прерывание через 15 минут (если делители позволят), в цикле никаких проверок. А в прерывании аккуратно выходите из цикла, подменив адрес в счётчике команд PC: адрес возврата же в стэке храниццца? Вот там его и покорябаете аккуратно) Если таймер нельзя на такой таймаут настроить, то считаете RC-цепь или берёте 555-таймер, заводите выход цепи или таймера на ногу прерывания и в прерывании делаете то же самое, что я чуть выше описал. А сбрасываете 555-таймер или RC-цепь другой ножкой. Просчитать время выполнения цикла, ведь он у вас на асме. В нём декрементировать переменную, в которую изначально занесено отношение времени работы цикла к длительности вашего критического кода. Тут, конечно, одна проверка понадобится. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 16 февраля, 2021 Опубликовано 16 февраля, 2021 · Жалоба 1 час назад, MrBearManul сказал: Стоп! А почему фантастика? Настраиваете таймер (не сторожевик) на прерывание через 15 минут (если делители позволят), в цикле никаких проверок. А в прерывании аккуратно выходите из цикла, подменив адрес в счётчике команд PC: адрес возврата же в стэке храниццца? Вот там его и покорябаете аккуратно) Это всё называется - "задача вытесняющей ОС реального времени". Только врукопашную (закат солнца вручную) ;) ТС видимо никогда не имел дела с РТОС, раз задаёт такие вопросы. Совет: изучить работу под РТОС, а затем написать алгоритм в виде низкоприоритетной задачи, вытесняемой через 15-20 мин более приоритетной. И всё. А результат работы первой задачи, вторая может взять из сохранённого контекста задачи (который имеет фиксированный формат в РТОС-ах). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rkit 1 16 февраля, 2021 Опубликовано 16 февраля, 2021 (изменено) · Жалоба longjmp из прерывания по таймеру. Таймер нужно заводить на весь интервал времени. Если нет такой возможности, то лучше уже не сделать. Изменено 16 февраля, 2021 пользователем rkit Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrBearManul 0 16 февраля, 2021 Опубликовано 16 февраля, 2021 · Жалоба 44 минуты назад, jcxz сказал: Это всё называется - "задача вытесняющей ОС реального времени". Только врукопашную (закат солнца вручную) ;) Из переключалки контекста мне эта идея и пришла. 48 минут назад, jcxz сказал: Совет: изучить работу под РТОС, а затем написать алгоритм в виде низкоприоритетной задачи, вытесняемой через 15-20 мин более приоритетной. Возьму уже себе на заметку. Именно в контексте решения задачи автора. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rkit 1 16 февраля, 2021 Опубликовано 16 февраля, 2021 · Жалоба 1 hour ago, jcxz said: Это всё называется - "задача вытесняющей ОС реального времени". Только врукопашную (закат солнца вручную) ;) Нет. Для ртос нужен таймер с постоянными прерываниями (100-1000Гц), что прямо противоречит условию "лучше не мешать". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 16 февраля, 2021 Опубликовано 16 февраля, 2021 · Жалоба 9 минут назад, rkit сказал: Нет. Для ртос нужен таймер с постоянными прерываниями (100-1000Гц), что прямо противоречит условию "лучше не мешать". Нет. Для РТОС нужен таймер, частота прерываний которого определяется пользователем. Какую удобно - такую и следует ставить. Кроме того - можно вообще без периодических прерываний. Читайте что такое tickless OS. PS: А вот насчёт "longjmp из прерывания по таймеру" - это нужно ещё проверять, не уверен что это возможно на AVR-ах. Я не спец. в AVR-ах, но в ARM/Cortex-M например такое невозможно. Да и на многих других платформах. Возможно только с уровня приложений, но не из ISR. В общем случае: если на платформе возможны вложенные прерывания - то будет не возможно. И по другим причинам. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
skilful 0 16 февраля, 2021 Опубликовано 16 февраля, 2021 · Жалоба 1 hour ago, jcxz said: Это всё называется - "задача вытесняющей ОС реального времени". Только врукопашную (закат солнца вручную) ;) ТС видимо никогда не имел дела с РТОС, раз задаёт такие вопросы. Совет: изучить работу под РТОС, а затем написать алгоритм в виде низкоприоритетной задачи, вытесняемой через 15-20 мин более приоритетной. И всё. А результат работы первой задачи, вторая может взять из сохранённого контекста задачи (который имеет фиксированный формат в РТОС-ах). проведите немного ликбез: что поменяется при применении RTOS ? Таймеры в AVR выше этих 4 секунд не настроить на 16 МГц. Значит будут прерывания, которые будут прерывать мой код для проверки переключения задачи? По тактам, если использовать прерывания, то больше выходит, чем код, который я написал. Хотя могу ошибаться из-за недопонимания. К сожалению, сторожевик в AVR только максимально 8 секунд может отсчитать. Так бы его применил как параллельный процесс и не парился бы :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrBearManul 0 16 февраля, 2021 Опубликовано 16 февраля, 2021 · Жалоба 2 минуты назад, skilful сказал: Так бы его применил как параллельный процесс и не парился бы :) 1. NE555) 2. RC-цепь. Это вообще дешёвый вариант. Тут, правда, с порогом срабатывания придётся всё внимательно посчитать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
skilful 0 16 февраля, 2021 Опубликовано 16 февраля, 2021 · Жалоба 3 minutes ago, MrBearManul said: 1. NE555) 2. RC-цепь. Это вообще дешёвый вариант. Тут, правда, с порогом срабатывания придётся всё внимательно посчитать. да жаль, что столько еще неиспользуемой периферии на борту и внешние цепи/устройства ставить Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrBearManul 0 16 февраля, 2021 Опубликовано 16 февраля, 2021 · Жалоба 5 минут назад, skilful сказал: да жаль, что столько еще неиспользуемой периферии на борту и внешние цепи/устройства ставить Вряд ли вы смените микроконтроллер на другой, с подходящей периферией) Но согласитесь, что резистор и конденсатор много места не займут. Если AVR не умеет открытый сток, то ещё внешний полевичок придётся добавить для сброса. В обще чем-то платить придётся) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 16 февраля, 2021 Опубликовано 16 февраля, 2021 · Жалоба Внешней дорожкой замкнуть выход одного таймера на вход другого (имитация Master-Slave), считать Slave-ом необходимые 20 минут. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rx3apf 0 16 февраля, 2021 Опубликовано 16 февраля, 2021 (изменено) · Жалоба Если абсолютно критично отсутствие прерываний - то да, аппаратно (внешними соединениями) каскадировать два-три таймера, по прерыванию подменить адрес PC в стеке. Если допустимы относительно редкие прерывания - отсчитать требуемое количество переполнений и сделать то же самое. Изменено 16 февраля, 2021 пользователем rx3apf Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Sergey_Aleksandrovi4 0 16 февраля, 2021 Опубликовано 16 февраля, 2021 · Жалоба Очень долго не работал с AVR, память может подводить. В SREG есть пользовательский флаг T. Его устанавливать в прерывании и тестировать в конце цикла для выхода/повтора (команды BRTC, BRTS). Единственно, надо на 100% быть уверенным, что компилятор не использует этот флаг для иных целей. Таймеры, как уже подсказали, можно каскадировать внешними межсоединениями чтобы не отвлекаться на промежуточные обработчики прерываний. Еще, вроде как, один из таймеров можно было тактировать от внешнего (часового) кварцевого резонатора. upd вместо флага T лучше использовать флаг I (разрешение прерываний). Перед началом цикла I установлен, в единственном прерывании от таймер он сбрасывается, цикл анализируя флаг I завершает работу. Дальше I снова устанавливаем чтобы не страдали остальные прерывания системы и останавливаем интервальный таймер. На словах как всегда просто получается) upd2 не пойдёт. SREG в прологе обработчика прерывания сохраняется, затем восстанавливается. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 16 февраля, 2021 Опубликовано 16 февраля, 2021 · Жалоба 1 час назад, skilful сказал: проведите немного ликбез: что поменяется при применении RTOS ? Таймеры в AVR выше этих 4 секунд не настроить на 16 МГц. Значит будут прерывания, которые будут прерывать мой код для проверки переключения задачи? По тактам, если использовать прерывания, то больше выходит, чем код, который я написал. Хотя могу ошибаться из-за недопонимания. У Вас в цикле при каждом проходе цикла выполняется участок: Цитата if ((TIFR1) & (1 << TOV1)) { //таймер1 с предделителем работает в фоне. Сработка каждые 4 секунды TIFR1 = 0x01; //сброс бита переполнения. Пишем туда 1 для сброса TOV1_cnt--; } и если остальное тело цикла достаточно мало, то этот участок контроля таймера может занимать значительную долю времени одного прохода цикла. Если например полезная часть цикла == 90 тактов, а эта контрольная = 10 тактов, то значит она будет занимать целых 10% времени. Если же контролировать таймер в прерывании, то контрольная часть будет занимать очень малую часть общего времени работы. 1 час назад, skilful сказал: К сожалению, сторожевик в AVR только максимально 8 секунд может отсчитать. Так бы его применил как параллельный процесс и не парился бы :) Придумываете проблему на ровном месте. Всё просто: ISR вызываемый с частотой 1/4 Гц в котором - декрементируемый счётчик. При обнулении счётчика - стоп фоновой задачи. Суммарное время выполнения всех вызовов ISR думаю будет намного меньше, чем время затрачиваемое участком контроля сейчас. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться