Как стать автором
Обновить
15
0

Пользователь

Отправить сообщение

Интересная статья как раз для начинающих. Было бы полезно более детально, возможно даже на ассемблере показать как же все-таки происходит вызов функций - public, private, что как упаковывается и почему именно так. Например, почему если я даже подменю ABI, то все равно не смогу вызвать private функцию.

Я случайно нажал не туда, как отменить минус ? Хотел поставить + )

Ну а зачем тогда вообще использовать вытесняемую RTOS если не различать семафоры, мьютексы и не использовать наследие приоритетов? Это ведь основной плюс реалтайма. Тогда лучше использовать contiki https://github.com/contiki-ng/contiki-ng. Кстати тоже очень оригинальное решение, все задачи - это по сути машины состояний (автоматы), только в линейном виде протопотоки (вот тут про них хорошо написанно https://bsvi.ru/protopotoki-protothreads/), как плюс ООЧЕНЬ маленкий расход RAM, как минус нет вытеснения и нельзя организовать жесткий реал тайм.

Это все очень хорошо, но на сколько я помню в стандартной TNKernel не была решена проблема инверсии приоритетов для мьютексов путем наследия приоритета. Вернее там было решение, но оно было одноранговое, то есть когда выстраивалась сложная цепочка из заблокированных мьютексов и задач, наследие приоритета уже не работало. Во FreeRTOS эта проблема тоже не решена. Вот кстати, что они пишут по этому поводу https://forums.freertos.org/t/priority-inheritance-proposal/11175, https://www.freertos.org/FreeRTOS_Support_Forum_Archive/June_2017/freertos_Nested_mutexes_and_priority_inheritance_again_30f4e9ebj.html.
TNeo я так глубоко не изучал, но интересно было бы посмотреть, как это реализовано у них.
Но в моей RTOS, если Вы уже посмотрели исходники, все сделано полностью для цепочек любой сложности ))

Согласен, что можно сделать и через одно прерывание, об этом я тоже писал в статье, но смысла в этом особого нет, я думаю, что с двумя код выглядит гораздо лаконичнее (хотя это наверное на любителя).
Я очень хорошо знаком с TNKernel даже использовал ее в своих проектах когда-то, но насколько я знаю проект уже давно не поддерживается, про TNeo тоже слышал - это форк TNKernel в нем немного оптимизировали код и добавили поддержку pic32 (по моему), а в остальном тоже самое, что и TNKernel. Если рассматривать стороние RTOS, то мне больше нравится RT-Thread, в ней действительно очень много интересных вещей https://github.com/RT-Thread/rt-thread

Есть конечно, можно и так измерить. Вот пример для stm32, но это всех ядер cortex касается https://hubstub.ru/stm32/82-vremya-vipolneniya-koda-stm32.html

Смотря какая частота и надо считать по асм инструкциям. Но именно про void PendSV_Handler(void) я имел в виду. Работа планировщик тоже происходит очень быстро, когда происходит какое-нибудь событие, не важно где в прерывания или в задаче, устанавливается флаг программного прерывания. Если это прерывание, то поскольку PendSV имеет более низкий приоритет, прерывание заканчивается на PendSV (без дополнительного входа-выхода из irq, это тоже одна из фикеш cortex)

Для таких целей можно использовать виртуальную машину, например, pawn https://www.compuphase.com/pawn/pawn.htm. Однажды собранная программа будет работать везде: линукс, микроконтроллер, Windows и т. д. Она поддерживается на ARMv7. Имеет достаточно хорошую производительность, позволяет писать свои нативные функции и имеет СИ похожий синтаксис. И главное - она влазит даже в самый мелкий cortex.

Но все-таки в чем оптимизация? И там и там 2 инструкции на ассемблере. Проблем тоже вроде нет.

Если две задачи равного приеритета?

Могу объяснить свою фразу. Дело в том, что я достаточно долго работал с AVR, stm8, pic16, mcs51 и т.д. В них также реализовывал различного рода переключатели контекстов. И как бы так сказать, там все как-то не очень удобно. И поэтому многие вещи, которые заложены в Cortex-m (также как и в либом ARM) , я думаю они закладывались специально при проектировании ядра с учётом того, чтобы для него было удобно писать rtos.

return __CLZ(__RBIT(taskStatus));

Спасибо за комментарий, но как этот код позволит определить номер установленного старшего бита? Он определяет номер установленного младшего бита, но нам не это нужно.

Если я Вас правильно понял, то что Вы описываете - это кооперативная многозадачность. Вытесняемая многозадачность устроена по другому. Данной RTOS - вытесняемая многозадачность.

  1. Мне кажется это разные задачи. Я не работал с Rpi pico, но у меня был опыт с atsam4c и он имеет два ядра, но они не предназначены для rtos и имеют разную архитектуру. Их нужно рассматривать как два ядра в одном корпусе и они не равноправны, имеют доступ к разной периферии, одно dma может работать с одним ядром с другим нет, одно ядро имеет доступ ко всей RAM другое только к её части, одно ядро может выполнять код из flash - другое только из RAM и. д.т. Возможно существуют полноценные N ядерные микроконтроллеры, но в своей практике мне не приходилось с ними работать. Обычно если более одного ядра, то второе - это специализированное ядро для особых задач.

  2. Для cortex-m0 время переключения можно посчитать по асемблерным командам, но я думаю даже на частоте 20-40 МГц, оно будет либо соизмеримо либо меньше 1 микро секунды.

Я рассматривал именно одноядерные микроконтроллеры, например как stm32F103. Если ядер больше одного, то все маленько усложняется. Я даже не встречал, чтобы использовали N ядерные системы на cortex-m3 или cortex-m4.
Cortex-A53 - это вполне мощное ядро на котором уже запускают Linux. Но Linux - это не Real Time (в отличие от QNX) на нем сложно добится даже 100 микросекундного отклика на события, нпаример, реакция на внешнее прерывание.
Если же Embdedded RTOS (на том же stm32F103) спроектирована правильно, то она обладает очень хорошей реакцией на события (в разы лучше чем Linux). При написание RTOS я делал упор именно на низкую латентность.

Честно сказать не совсем понятен коментарий.

  1. Два стека позволяют существенно экономить на памяти. Их я использую, потому что cortex позволяет это делать. Конечно это не является обязательным условием, но если микроконтроллер это поддерживает на аппаратном уровне почему бы это не использовать.

  1. По поводу двусвязного списка - это стандартное определение. Есть односвязный, двусвязный и XOR списки вещи вполне стандартные https://ru.wikipedia.org/wiki/Связный_список. В статье я показываю, как использовать двусвязный список и почему именно его. Это тоже вполне стандартная практика, посмотрите хотя бы ядро линукс, там он везде используется.

  2. Критические секции по коду используются везде, где нужно, за это отвечаю функции
    EM_DISABLE_TASK() и EM_ENABLE_TASK(). Почему я не описал критические именно в этой статье, потому что в ней я хотел рассказать об общих принципах. Использование критических секций планировалось описать в следующей статье

  3. Вот это если честно я вообще не понял, что не так-то?

Сложилось в печатление, что Вы даже не открывали код самой RTOS хотя ссылка на нее есть в самом начале статьи. Давайте еще раз ее продублирую https://github.com/IvanShipaev/EmTask.git

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность