Ожидал примера создания очередей и обмена данными чрез них но тут только теория. пошл разобрался на практике) не с первого раза конечно и не с третьего но разобрался, не идеально конечно писал код. теперь задача кнопки посылает команду светодиоду. Видео сподвигло пойти найти статью))
Спасибо за продолжение темы RTOS. (момент видео - 11.47) vTaskDelete лучше переключить в положение Disabled ? (чтобы задачи не могли удалятся и фрагментировать память).
Владимир добрый день. Хорошее видео, но заинтересовал один момент про удаление задач и их нецелесообразности удаления. В своём приложении я многократно удаляю и создаю задачу, но ещё не разу не упёрся в переполнение стека или кучи (специально проверял, около 40 раз точно происходил цикл создания- удаления). Более того, при просмотре отладчиком ясно видно, что выделяется одна и та же область памяти. Возможно все таки присутствует механизм защиты от таких утечек памяти. И сам собственно вопрос, в документации по freertos есть описание данного феномена очистки памяти при удалении задач?
Если вы удаляете задачу а потом ее создаете заново ничего плохого не произойдет. Более того я ни слова не сказал про утечку памяти. Я говорил о фрагментации памяти а она возникает если одну задачу удалили, а третью создали. Т.е. если вы создаете и удаляете разные задачи. В этом случае т.к. задачи разные соответственно и памяти выделяется под них разное количество. Это и приводит к ее фрагментация. Фрагментация памяти описана в документации на FreeRTOS. Более того, есть несколько (4) модели использования памяти. Как-нибудь сделаю видео по безопасному использованию FreeRTOS. И если посмотреть на safe FreeRTOS то можно увидеть что именно ее делает safe, и прежде всего это отсутствие возможности удалять задачи.
Хочется продолжения уроков по FreeRTOS . Если можно остановитесь более подробно как правильно посчитать сколько нужно выделить байт для КУЧИ, сколько выделять под задачи. Еще не могу понять как правильно организовать работу с приемником UART . у меня все это работает на прерываниях с определением конца пакета данных и дальнейшим разбором данных в пакете , пока не пойму как это правильно перенести на FreeRTOS.
Да через какое-то время продолжение будет. А по поводу прерываний они как работали так и работают ничего специфического там менять под FreeRTOS не надо.
Я сейчас попробовал. Пока лучшее, что нашел для передачи двух USART из разных тасков - DMA, там же и NVIC включить каждому прийдётся. Немного посплю, и попробую сделать приём, у narodstream вроде как есть разжёванный материал по приёму через DMA - попробую повторить))
Спасибо за ролики. Прозвучало что память не фрагментируется. Но когда изучал документацию, в каждом порте есть несколько вариантов кучи heap1, 2,3 1й как сказано 2й серединка и 3й с сильной дефрагментацией. Может это только для АТМЕЛА или в КУБЕ этого не видно?
Да в видео действительно есть определенная неточность. И связано именно с heap. В последних версиях FreeRTOS действительно осуществляется дефрагментация памяти. Однако в версиях safe по прежнему не рекомендуется удаление задач.
Т.е. под каждую новую задачу память выделяется статично и последовательно. При освобождении не в конце, возникает дыра, которая больше не может быть использована. Верно? Или даже с концом всё плохо? И если снять последнюю задачу, то под новую память выделится как будто последнюю задачу не удаляли?
@@OlegBovykin На самом деле у каждого подход к программированию индивидуальный. Как правило разделение по задачам - функциональное. Вычисление отдельно, обработка отдельно, сбор данных и так далее. Все задачи это определенные функциональные узлы из которых состоит ваша программа. Скорее всего вы создадите отдельную задачу которая будет обслуживать прием-передачу данных по шине CAN. В этом я не вижу каких-либо проблем. Вы просто задействуете стандартные функции CAN для отправки, приема и фильтрации сообщений. Если про передачу и писать отдельно не стоит, то на приеме вы будете или осуществлять "входной контроль" принятых данных и соответственно корректировать ошибки или просто воспользуетесь очередями для передачи полученных данных в обрабатывающую их задачу. Это не требует использования каких-либо специальных приемов.
Если я, например, начну передачу/прием по SPI неких данных, то данная ОС не оборвет передачу/прием во время процесса для перехода обслуживания других заданий? Если предположим не обрывает, то если этот процесс будет долгим, то другие задачи будут простаивать N-е время?
Есть специальные функции, прямо запрещающие ОС прерывать критически важные секции кода. С другой стороны используйте SPI совместно с DMA и головная боль не будет возникать в принципе.
А как быть с прерываниями? Ну вот есть пара задач, которые выполняются операционкой и тут прилетает прерывание которое меняет данные. Как им уживаться вместе?
Есть варианты! Но в общем это есть проблема общая для всех ОС. Что поделаешь! Алгоритмы должны быть слгка иными. Например буфферизация! Или очередь событий
Использовать очередь в прерывании, а потом уже обработать значение в нужной задаче. Или использовать глобальную переменную, потом её значение сохранять в другую переменную, не меняя исходную. Это позволит не терять данные
Скажу откровенно, у меня уже несколько лет не было задач с Modbus. Я даже вспоминать не хочу как это делалось. За предложение спасибо всем, кто предлагает идеи для роликов, но Modbus в ближайшее время точно не будет.
Владимир, если я хочу объявить свои функции, их нужно объявлять вне тасков и использовать так же как и при написании кода без RTOS? Или есть нюансы? Спасибо за видосы!
Это же не IBM PC, создал задачу, выделилось под нее место и пусть себе живёт родимая. Под нее ресурсы не перевыделяются. Там есть разные модели использования памяти на самом деле, в документации хорошо про это сказано.
И чем же это плохо? Мне искренне интересно это узнать. Меня аж разрывает от любопытства почему же всегда обязательно и именно очередями... А вообще... У всего есть свое предназначение и ко всему надо относится с умом. Например результаты измерений, вычислений, обмен данными разумеется правильнее делать очередями. В то же время глобальные настройки и параметры однозначно глобальными переменными.
@@VladimirMedintsev Я и писал о передаче данных между задачами, в видео Вы говорили о передаче через глобальные переменные, что не есть хорошо, поскольку возможно одновременное (относительно одновременное) обращение задач к чтению и записи глобальной переменной. С Уважением!
@@alexandrsemenkoff6935 Да это невозможно, ни относительно, ни абсолютно. В один момент времени работает только одна задача или планировщик. Вы мыслите категориями многоядерных процессоров. А данные, если, к примеру, они не прут сплошным потоком от задачи к задаче, лучше передавать через глобальную переменную. Удобно, безопасно и быстро.
Существует общеизвестная рекомендация (не правило, а именно рекомендация) не использовать глобальные переменные там, где без них можно обойтись, потому что их использование таки может быть небезопасно. Первая потенциальная опасность - глобальная область видимости: когда проект большой, а еще вероятнее если над ним работают нескольких людей, есть вероятность получить трудноуловимый баг из-за обращения не туда. Например, у вас в модуле есть глобальная переменная dataCounter, а у вашего коллеги в модуле - глобальная переменная DataCounter. Вы можете по ошибке обратиться к его переменной, полагая что это ваша. При этом компилятор предательски промолчит и не укажет вам ни на какую ошибку и придется очень долго искать что не так. Вторая опасность проявляется при отсутствии атомарности доступа к переменной. Например, на 32-битной машине вы объявили 8-битную переменную. При ее инкременте, при отсутствии у процессора этой архитектуры специальных команд для работы с 8-битными данными, компилятор добавит дополнительные команды, для проверки на максимальное значение, обнуление и т.д. В этот момент может произойти переключение задач и данные в памяти будут искажены и другая задача, которая будет полагаться на эту глобальную переменную, получит неверные данные. Ситуация конечно крайне маловероятная, но нельзя полагаться на то, что она никогда не произойдет. В таком случае нужно обеспечить атомарность доступа к переменной. Но проще все же не использовать глобальные переменные без особой надобности.
Мне так привычнее и удобнее. Меня уже пытались тут убедить что это не правильно, я с ними согласился но все-равно так делаю. Ну хотя бы по той причине что эта разница не существенна и на понимание описанного в видео не влияет. А еще я микросхемы называю мелкосхемами и микрофон - мелкофоном. Но если вас это сильно парит, то видимо нам не по пути.
@I S Да проскакивало как-то видео паренек работающий в яндексе разбирает умную колонку и рассказывает. Правда как выяснилось он разрабатывал только какую-то малую часть и в конструкции самой колонки понимает так себе. Да и схему нам так и не покажут и все такое. Ну чутка для хайпа.
Передача через глобальные вредно для новичков ... В вашем случае сработает , если процессор 32-битный и переменная одна ... иначе можно передать неполные данные , а особенно если кто-то захочет передать массив
Вот уже не первый раз я слышу такие утверждения и еще ни один человек не сумел нормально обьяснить чем же это плохо. Напишите код который приведет к ошибке и тогда мы с вами это с радостью обсудим.
@@VladimirMedintsev В первую очередь, спасибо за видео - очень помагает разобраться с stm32. Возможно имелась ввиду проблема с синхронизацией данных между потоками/задачами. Не уверен, примнимо ли это для микроконтроллера, но в прикладном программировании (с++, java) встречается когда, например один поток начинает писать в массив/список/очеред/объект и посреди этой операции другой поток начинает читать/записывать в тот же массив/список/очеред/объект. самый позитивный исход: один(или два) потока будут иметь неправильные данные, худший исключение (exception) и аварийное завершение приложения. Если rtos записывает состояние невыполненной (например) задачи(task) в стек, то есть и вероятность что другая задача повлияет на глобальную переменную. Не могу утверждать насчёт микроконтроллеров - только начинаю эту тему осваивать
@@fizarum Можно было так не расписывать долго. В данном случае процессор - одноядерный. Поток один. Параллельного доступа нету. Речь идет о том, что люди слышали что так делать нельзя, а почему нельзя они не разобрались. Вот и боятся сами не понимая чего. Так нельзя делать только на процессоре STM32MP1.
Честно сказать более информативных и понятных уроков не видел! Спасибо большое за ваше желание помочь!
Добро пожаловать.
Одни комментарии полезнее других! Автору прежде всего спасибо и всем остальным также благодарность за горячие дисскусии!
Спасибо Вам за труды!
Было бы очень здорово увидеть продолжение темы.
Варианты правильной реализации очереди и мьютексов
Rudolph Sikorskiy хороший вопрос ! Тоже жду наглядную реализацию использования
До ваших роликов не знал, что freertos такая удобная
Ждемс примеров по очередям, симофорам и мутексам.
Спасибо, в основном по вашим видео изучаю стм32
Отлично видео.Довольно ясно и просто, но не примитивно, рассказывается про FreeRTOS.
Отличное очень понятное видео. С нетерпением жду продолжение по RTOS
Ожидал примера создания очередей и обмена данными чрез них но тут только теория. пошл разобрался на практике) не с первого раза конечно и не с третьего но разобрался, не идеально конечно писал код. теперь задача кнопки посылает команду светодиоду. Видео сподвигло пойти найти статью))
спасибо за интересное видео
Отличное видео. Ждём продолжения.
Отличные видео.
Спасибо за продолжение темы RTOS.
(момент видео - 11.47) vTaskDelete лучше переключить в положение Disabled ? (чтобы задачи не могли удалятся и фрагментировать память).
Достаточно просто ее не использовать.
Владимир, добрый день. А можно комбинировать вместе с ОС обычную фоновую задачу, например опрос энкодера?
Ничего этому не мешает.
Спасибо! А что если задача требует больше времени чем слот для неё?
все-таки, лучше звучит "планировщик", чем "шедулер")))
Владимир добрый день. Хорошее видео, но заинтересовал один момент про удаление задач и их нецелесообразности удаления.
В своём приложении я многократно удаляю и создаю задачу, но ещё не разу не упёрся в переполнение стека или кучи (специально проверял, около 40 раз точно происходил цикл создания- удаления).
Более того, при просмотре отладчиком ясно видно, что выделяется одна и та же область памяти.
Возможно все таки присутствует механизм защиты от таких утечек памяти.
И сам собственно вопрос, в документации по freertos есть описание данного феномена очистки памяти при удалении задач?
Если вы удаляете задачу а потом ее создаете заново ничего плохого не произойдет.
Более того я ни слова не сказал про утечку памяти. Я говорил о фрагментации памяти а она возникает если одну задачу удалили, а третью создали. Т.е. если вы создаете и удаляете разные задачи. В этом случае т.к. задачи разные соответственно и памяти выделяется под них разное количество. Это и приводит к ее фрагментация.
Фрагментация памяти описана в документации на FreeRTOS. Более того, есть несколько (4) модели использования памяти. Как-нибудь сделаю видео по безопасному использованию FreeRTOS. И если посмотреть на safe FreeRTOS то можно увидеть что именно ее делает safe, и прежде всего это отсутствие возможности удалять задачи.
@@VladimirMedintsev , спасибо за разъяснения. Буду ждать видео подобного рода, так как очень востребованы они
Хочется продолжения уроков по FreeRTOS . Если можно остановитесь более подробно как правильно посчитать сколько нужно выделить байт для КУЧИ, сколько выделять под задачи. Еще не могу понять как правильно организовать работу с приемником UART . у меня все это работает на прерываниях с определением конца пакета данных и дальнейшим разбором данных в пакете , пока не пойму как это правильно перенести на FreeRTOS.
Да через какое-то время продолжение будет.
А по поводу прерываний они как работали так и работают ничего специфического там менять под FreeRTOS не надо.
Я сейчас попробовал. Пока лучшее, что нашел для передачи двух USART из разных тасков - DMA, там же и NVIC включить каждому прийдётся. Немного посплю, и попробую сделать приём, у narodstream вроде как есть разжёванный материал по приёму через DMA - попробую повторить))
А сколько памяти занимает операционнка?
Не у Вас ли был видиоурок про отображение переключений задач во freertos?
Спасибо за ролики.
Прозвучало что память не фрагментируется. Но когда изучал документацию, в каждом порте есть несколько вариантов кучи heap1, 2,3 1й как сказано 2й серединка и 3й с сильной дефрагментацией.
Может это только для АТМЕЛА или в КУБЕ этого не видно?
Да в видео действительно есть определенная неточность. И связано именно с heap. В последних версиях FreeRTOS действительно осуществляется дефрагментация памяти. Однако в версиях safe по прежнему не рекомендуется удаление задач.
Ok. Спасибо.
Чтобы дефрагментация работала, у процессора должно быть достаточно "свободного времени".
Т.е. под каждую новую задачу память выделяется статично и последовательно. При освобождении не в конце, возникает дыра, которая больше не может быть использована. Верно? Или даже с концом всё плохо? И если снять последнюю задачу, то под новую память выделится как будто последнюю задачу не удаляли?
Спасибо за ролик! А как подружить FreeRTOS и CAN?
Вызвать функции CAN из FreeRTOS. Разумеется это на половину шутка. Потому, что я не понимаю в чем сложность.
@@VladimirMedintsev Как правильно организовать задачи, очереди и процессинг входящих и исходящих сообщений в парадигме FreeRTOS?
@@OlegBovykin На самом деле у каждого подход к программированию индивидуальный. Как правило разделение по задачам - функциональное. Вычисление отдельно, обработка отдельно, сбор данных и так далее. Все задачи это определенные функциональные узлы из которых состоит ваша программа.
Скорее всего вы создадите отдельную задачу которая будет обслуживать прием-передачу данных по шине CAN. В этом я не вижу каких-либо проблем. Вы просто задействуете стандартные функции CAN для отправки, приема и фильтрации сообщений. Если про передачу и писать отдельно не стоит, то на приеме вы будете или осуществлять "входной контроль" принятых данных и соответственно корректировать ошибки или просто воспользуетесь очередями для передачи полученных данных в обрабатывающую их задачу. Это не требует использования каких-либо специальных приемов.
Если я, например, начну передачу/прием по SPI неких данных, то данная ОС не оборвет передачу/прием во время процесса для перехода обслуживания других заданий? Если предположим не обрывает, то если этот процесс будет долгим, то другие задачи будут простаивать N-е время?
Есть специальные функции, прямо запрещающие ОС прерывать критически важные секции кода. С другой стороны используйте SPI совместно с DMA и головная боль не будет возникать в принципе.
Не понимаю, у процессора 8к памяти, но вылазит ошибка недостатка памяти, если ставишь тотал хип сайз в 3к. Как так?
Все доходчиво, понятно, как обычно.. riotOs' а не будет случаем в обзорах?
Я не использую riot, так что сказать ничего не могу.
А как быть с прерываниями? Ну вот есть пара задач, которые выполняются операционкой и тут прилетает прерывание которое меняет данные. Как им уживаться вместе?
Используйте DMA.
Есть варианты! Но в общем это есть проблема общая для всех ОС. Что поделаешь! Алгоритмы должны быть слгка иными. Например буфферизация! Или очередь событий
Использовать очередь в прерывании, а потом уже обработать значение в нужной задаче. Или использовать глобальную переменную, потом её значение сохранять в другую переменную, не меняя исходную. Это позволит не терять данные
Как на счет рассмотреть очереди и синхронизацию задач на примере реализации клиента MODBUS RTU?
Скажу откровенно, у меня уже несколько лет не было задач с Modbus. Я даже вспоминать не хочу как это делалось.
За предложение спасибо всем, кто предлагает идеи для роликов, но Modbus в ближайшее время точно не будет.
Владимир, если я хочу объявить свои функции, их нужно объявлять вне тасков и использовать так же как и при написании кода без RTOS?
Или есть нюансы?
Спасибо за видосы!
Точто так же как и без FreeRTOS. Т.е. согласно требований языка программирования.
@@VladimirMedintsev спасибо
Спасибо. Скажите, а как определить необходимый размер стека для каждой из задач? Или как понять, что стека не хватает?
Третье видео из серии смотрите, там рассказано как это делать.
@@VladimirMedintsev , спасибо. Поспешил с вопросом, виноват.
А можно сслыку на сайт документации freertos?
Freertos.org
Фрагментированная куча может привести к нехватке памяти. А не удаление задач не может?
Это же не IBM PC, создал задачу, выделилось под нее место и пусть себе живёт родимая. Под нее ресурсы не перевыделяются. Там есть разные модели использования памяти на самом деле, в документации хорошо про это сказано.
Уважаемый, лучше всего всегда пользоваться очередями, глобальные переменные это плохо в ос
И чем же это плохо? Мне искренне интересно это узнать. Меня аж разрывает от любопытства почему же всегда обязательно и именно очередями... А вообще...
У всего есть свое предназначение и ко всему надо относится с умом. Например результаты измерений, вычислений, обмен данными разумеется правильнее делать очередями. В то же время глобальные настройки и параметры однозначно глобальными переменными.
@@VladimirMedintsev Я и писал о передаче данных между задачами, в видео Вы говорили о передаче через глобальные переменные, что не есть хорошо, поскольку возможно одновременное (относительно одновременное) обращение задач к чтению и записи глобальной переменной. С Уважением!
@@alexandrsemenkoff6935 Да это невозможно, ни относительно, ни абсолютно. В один момент времени работает только одна задача или планировщик. Вы мыслите категориями многоядерных процессоров. А данные, если, к примеру, они не прут сплошным потоком от задачи к задаче, лучше передавать через глобальную переменную. Удобно, безопасно и быстро.
Вопрос: Какой префикс лучше использовать для имен глобальных переменных? Ответ: //
Существует общеизвестная рекомендация (не правило, а именно рекомендация) не использовать глобальные переменные там, где без них можно обойтись, потому что их использование таки может быть небезопасно. Первая потенциальная опасность - глобальная область видимости: когда проект большой, а еще вероятнее если над ним работают нескольких людей, есть вероятность получить трудноуловимый баг из-за обращения не туда. Например, у вас в модуле есть глобальная переменная dataCounter, а у вашего коллеги в модуле - глобальная переменная DataCounter. Вы можете по ошибке обратиться к его переменной, полагая что это ваша. При этом компилятор предательски промолчит и не укажет вам ни на какую ошибку и придется очень долго искать что не так. Вторая опасность проявляется при отсутствии атомарности доступа к переменной. Например, на 32-битной машине вы объявили 8-битную переменную. При ее инкременте, при отсутствии у процессора этой архитектуры специальных команд для работы с 8-битными данными, компилятор добавит дополнительные команды, для проверки на максимальное значение, обнуление и т.д. В этот момент может произойти переключение задач и данные в памяти будут искажены и другая задача, которая будет полагаться на эту глобальную переменную, получит неверные данные. Ситуация конечно крайне маловероятная, но нельзя полагаться на то, что она никогда не произойдет. В таком случае нужно обеспечить атомарность доступа к переменной. Но проще все же не использовать глобальные переменные без особой надобности.
Вопрос немного не в тему: почему вы микроконтроллер называете процессором? Разные же устройства по назначению и по содержанию.
Мне так привычнее и удобнее. Меня уже пытались тут убедить что это не правильно, я с ними согласился но все-равно так делаю. Ну хотя бы по той причине что эта разница не существенна и на понимание описанного в видео не влияет. А еще я микросхемы называю мелкосхемами и микрофон - мелкофоном. Но если вас это сильно парит, то видимо нам не по пути.
Большинство микроконтрольщиков называют процом. Парень из Яндекса, который умную колонку разрабатывал, тоже все время называет проц.
@I S Да проскакивало как-то видео паренек работающий в яндексе разбирает умную колонку и рассказывает. Правда как выяснилось он разрабатывал только какую-то малую часть и в конструкции самой колонки понимает так себе. Да и схему нам так и не покажут и все такое. Ну чутка для хайпа.
@@81n90 вообще не показатель.
@@nikotinesmola ну да не показатель, можете называть как хотите, хоть утюгом, дело ваше, ну и ваше окружение. Если им так будет понятнее, почему нет.
Передача через глобальные вредно для новичков ... В вашем случае сработает , если процессор 32-битный и переменная одна ... иначе можно передать неполные данные , а особенно если кто-то захочет передать массив
Вот уже не первый раз я слышу такие утверждения и еще ни один человек не сумел нормально обьяснить чем же это плохо. Напишите код который приведет к ошибке и тогда мы с вами это с радостью обсудим.
@@VladimirMedintsev Беру свои слова обратно , я ошибался ... ибо только что узнал о критических секциях , из вашего видео ))
@@Константин-у9у8и это где у него было, чего то пропустил я. На каком моменте, подскажи пожалуйста.
@@VladimirMedintsev
В первую очередь, спасибо за видео - очень помагает разобраться с stm32.
Возможно имелась ввиду проблема с синхронизацией данных между потоками/задачами. Не уверен, примнимо ли это для микроконтроллера, но в прикладном программировании (с++, java) встречается когда, например один поток начинает писать в массив/список/очеред/объект и посреди этой операции другой поток начинает читать/записывать в тот же массив/список/очеред/объект. самый позитивный исход: один(или два) потока будут иметь неправильные данные, худший исключение (exception) и аварийное завершение приложения. Если rtos записывает состояние невыполненной (например) задачи(task) в стек, то есть и вероятность что другая задача повлияет на глобальную переменную.
Не могу утверждать насчёт микроконтроллеров - только начинаю эту тему осваивать
@@fizarum Можно было так не расписывать долго. В данном случае процессор - одноядерный. Поток один. Параллельного доступа нету.
Речь идет о том, что люди слышали что так делать нельзя, а почему нельзя они не разобрались. Вот и боятся сами не понимая чего.
Так нельзя делать только на процессоре STM32MP1.
полагаю, автору должно государство назначить оклад. вклад бесценен.
Спасибо