Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Прерывание в прерывании
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Страницы: 1, 2
arhiv6
Super Simple Tasker - один из вариантов реализации вытесняющей многозадачности для микроконтроллеров. Как в нём работает асинхронное переключение на более приоритетные задачи написано в статье под рисунком 3. Для реализации SST нужна такая вещь: в функции-обработчике прерывания, после выполнения необходимого кода, нужно как-то сообщить микроконтроллеру, что с прерыванием закончили работать но из функции-обработчика не выходить. Т.е. нужно разрешить вложенные прерывания (одни и те же).

В статье в примере для ПК это делается так: используется команда End Of Interrupt (EOI) - outportb(0x20, 0x20). Обычно она выполняется непосредственно перед выходом из функции-обработчика прерывания, но в SST после EOI вызывается диспетчер, прямо в контексте прерывания. Т.е. вызвав EOI, но оставаясь в контексте прерывания, мы разрешаем вложенные прерывания. Как это можно сделать для ARM (Cortex)?
Forger
Цитата(arhiv6 @ Nov 7 2017, 15:00) *
один из вариантов реализации вытесняющей многозадачности для микроконтроллеров...

Может быть я стал слишком старый и "отстал от поезда", поэтому на всякий случай спрошу: НАФИГА ???
Чем не годится готовая RTOS? В частности freeRTOS позволяет использовать вложенные прерывания без подобного "дрочева".... laughing.gif
arhiv6
Как минимум, это интересно - попробовать разные подходы к построению ПО. А ещё есть мелкие контроллеры, у которых мало свободных ресурсов. Вот на них особенно интересно попробовать SST - тут при наличии вытесняющей многозадачности очень эффективное использование памяти.
Forger
Цитата(arhiv6 @ Nov 7 2017, 16:17) *
А ещё есть мелкие контроллеры, у которых мало свободных ресурсов.

В мелких МК прекрасно влезает классическая готовая RTOS, особенно если использовать минимум ресурсов - семафоры и на край мьютексы. Использую RTOS даже в мелких ARM CM0.
Я относительно недавно перешел на KEIL RTX, она занимает меньше места, чем freeRTOS да и сделана более что-ли классически - системные вызовы используют SVC, т.е. как это изначально и было задумано ARM.

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

Obam
Цитата(arhiv6 @ Nov 7 2017, 16:00) *
нужно как-то сообщить микроконтроллеру, что с прерыванием закончили работать но из функции-обработчика не выходить. Т.е. нужно разрешить вложенные прерывания (одни и те же).

"Всё смешалось в доме Облонских" - прерывания для того и выдуманы, чтоб, быстро отреагировав, быстро выполнить требуемое и вернуться к "рутине".

Цитата
В статье в примере для ПК это делается так: используется команда End Of Interrupt (EOI) - outportb(0x20, 0x20). Обычно она выполняется непосредственно перед выходом из функции-обработчика прерывания, но в SST после EOI вызывается диспетчер, прямо в контексте прерывания. Т.е. вызвав EOI, но оставаясь в контексте прерывания, мы разрешаем вложенные прерывания. Как это можно сделать для ARM (Cortex)?

Вот прям "дословно" как по ссылке - никак. Но у кортекса весьма изощрённый контроллер прерываний: вложенные (если приоритет не ниже текущего (базового)) там получаются нативно.
AHTOXA
Цитата(arhiv6 @ Nov 7 2017, 17:00) *
Как это можно сделать для ARM (Cortex)?

Здесь была тема про SST. Посмотрите там, может, там есть ответ.
DASM
Цитата(Forger @ Nov 7 2017, 16:30) *
В мелких МК прекрасно влезает классическая готовая RTOS, особенно если использовать минимум ресурсов - семафоры и на край мьютексы. Использую RTOS даже в мелких ARM CM0.
Я относительно недавно перешел на KEIL RTX, она занимает меньше места, чем freeRTOS да и сделана более что-ли классически - системные вызовы используют SVC, т.е. как это изначально и было задумано ARM.

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

Я отказался от FreeRTOS, 256 К памяти не хочу транжирить, SST "х расходы стековой памяти по сравнению с традиционными операционными системами сокращается на 80%."
. Так что насчет "нечем заняться" не стоит огульно, SST прекрасно ложится на мелкие 1M/256K контроллеры, на средние (16G/1G) полноценный Линукс проще. Места классическим RTOS я лично не вижу
Forger
Цитата(DASM @ Nov 7 2017, 17:28) *
Я отказался от FreeRTOS, 256 К памяти не хочу транжирить, SST "х расходы стековой памяти по сравнению с традиционными операционными системами сокращается на 80%."

Какие-то дикости вы тут рассказываете wacko.gif
Звучит как попытка экономии на соли при мариновке огурцов sm.gif

Ядро RTOS занимает всего несколько кБ флэши, а объем занимаемого ОЗУ сильно зависит от кода: стек прерываний общий, большой не нужен, обычно хватает 0.2кБ, стеки задач - зависит от самих задач, у меня их стеки крайне редко превышают 0.5 кБ, обычно хватает 128....256 байтов.
Съэкономить ОЗУ можно перейдя на кооперативную многозадачность.
У меня МК по 16...32к флэши (озу 4..6 кб) и при этом там прекрасно живут несколько объемных задач и делают некислый функционал.
А уж что говорить про "толстые" МК с 256 кб, там вообще нет никакого смысла экономить на спичках - суём RTOS с самым серьезным функционалом (например, моя любимая трассировка под Segger SystemView).
По-моему вы сильно заморачиваетесь на пустом месте )))

Цитата
SST прекрасно ложится на мелкие 1M/256K контроллеры

Голый ассемблер тоже прекрасно ложится на любой МК, но что-то желающих сидеть на голом асм все меньше и меньше...
Нужда в RTOS пропадает в реально примитивных проектах, но таких уже и не осталось, не те времена нынче ))

Цитата
Места классическим RTOS я лично не вижу
Вот это-то и вызывает у меня некоторое недоумение!
И потому прихожу лишь к одному выводу - вы вообще не использовали RTOS.
Искренне советую исправить это недочет sm.gif
ViKo
Подтверждаю, RTX RTOS от Keil - весьма достойная простая "классическая" ОС.
DASM
"прихожу лишь к одному выводу " - приходите
", обычно хватает 128....256 байтов"- просто у вас " в реально примитивных проектах"
Вы лучше скажите, каким образом вы доказываете, что данная задача никогда не превысит отведенный стек, при условии, что если такое возникнет - аппарат под контролем процессора с вашим замечательным ртос со стеком задачи 128 байт отрежет например рабочему руку.
" "толстые" МК с 256 кб" вы серьезно считаете, что это толсто? Это копейки с нынешними стеками и протоколами, стек BLE один сожрет 300 кб флеша, порядка 100 к ОЗУ, а к нему еще Thread прикуртить надо, оный тоже 250 кбайт и ОЗУ немерянно.
Очень интересно глянуть вашу "сурьезную задачу" с 128 байт ОЗУ
jcxz
Цитата(arhiv6 @ Nov 7 2017, 15:17) *
Как минимум, это интересно - попробовать разные подходы к построению ПО. А ещё есть мелкие контроллеры, у которых мало свободных ресурсов. Вот на них особенно интересно попробовать SST - тут при наличии вытесняющей многозадачности очень эффективное использование памяти.

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

PS: При задавании подобных вопросов, очень уместно указывать ядро о котором спрашивается. Ибо реализация очень сильно зависит от этого самого ядра.
scifi
Гугл вводит на гитхаб. Возможно, всё украдено до нас?
jcxz
Цитата(DASM @ Nov 7 2017, 16:28) *
Я отказался от FreeRTOS, 256 К памяти не хочу транжирить

Интересно - на что у вас FreeRTOS транжирил память?
ЗЫ: Всегда думал, что память в программах транжирит исключительно программист... наверное старый стал - чего-то уже не понимаю.... wacko.gif
DASM
Так может Вы дадите совет, сколько памяти давать каждой задачи, чтобы ей гарантированно хватило, и при этом не было бы потерь памяти из-за этого "на всякий случай"?
Потоки и жрут.
jcxz
Цитата(DASM @ Nov 7 2017, 16:53) *
Вы лучше скажите, каким образом вы доказываете, что данная задача никогда не превысит отведенный стек

А вы каким доказываете, что руки пролетарию не отхватите? Поделитесь опытом....
DASM
Я немного преувеличил для ясности. Эти РТОС замечательны для обучения студентов имхо, только вот в реальной аппаратуре, с более ответсвенными целями чем очередной вебсервер - очень неуверен. MMU нет, MPU ни о чем, процы просто не предназначены под многозадочность, а то, что есть - костыли
jcxz
Цитата(DASM @ Nov 7 2017, 17:08) *
Так может Вы дадите совет, сколько памяти давать каждой задачи, чтобы ей гарантированно хватило, и при этом не было бы потерь памяти из-за этого "на всякий случай"?

А в чём разница между стеком задачи под ОС и стеком той же самой задачи без ОС? У Вас, что ОС сама ваш код компилирует? Или может даже пишет? biggrin.gif

Цитата(DASM @ Nov 7 2017, 17:08) *
Потоки и жрут.

Что за злобные такие "потоки", лазящие по Вашим исходникам и жрущие память??? Жутко даже становится... help.gif
Forger
Цитата(DASM @ Nov 7 2017, 17:53) *
"прихожу лишь к одному выводу " - приходите
", обычно хватает 128....256 байтов"- просто у вас " в реально примитивных проектах"

Я не кладу в стек гигантские структуры, а стараюсь их использовать статически. Динамическую память не использую.
Там, где это нужно, память выделяю пулами (фиксированными кусками).

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

Это делается средствами RTOS, разумеется, соотв. аварийные ситуации обрабатываются. Перед запуском проекта, он долгое время отрабатывается под systemview, где видно, кто и сколько чего кушает.
Это позволяет подстроить стеки более тонко (если нужно).
Используются ГОТОВЫЕ решения. Это работает и переполнения стека отлично отлавливаются (при тестировании это проверяю - занижаю размеры стеков и контролирую работу кода в таких условиях).

Цитата
" "толстые" МК с 256 кб" вы серьезно считаете, что это толсто?
Для любой примитивной RTOS (та же freeRTOS -одна из них) эти ТТХ контроллера вполне толстые. Речь об этом.

Цитата
Это копейки с нынешними стеками и протоколами, стек BLE один сожрет 300 кб флеша, порядка 100 к ОЗУ, а к нему еще Thread прикуртить надо, оный тоже 250 кбайт и ОЗУ немерянно.

Речь не про это, речь про совсем про другое - гипотетическую экономию на абсолютно ровном месте.
В конце-концов, существует cmsisOS, даже cmsisOS-II, стандарт. Но нет же, ведь всегда найдутся энтузиасты, которым нужно "изобрести велосипед с квадратными колесами" и пытаться на нем ехать, делая вид, что это нормально smile3046.gif

Цитата
Очень интересно глянуть вашу "сурьезную задачу" с 128 байт ОЗУ
Мы сейчас говорим про проекты для бытовых МК, а не толстых CPU с мб флэши и озу.
Второй случай требует RTOS другого класса, скорее всего платной RTOS.
Здесь же речь про простые вещи, где экономия на спичках выглядит очень и очень странно - вместо простой готовой RTOS колхозить некий самодельный костыльный SST ...
Вот мне лично совсем не ясна реальная мотивация подобной задумки.... Пытаюсь разобраться, может быть что-то упускаю )))
DASM
Цитата(jcxz @ Nov 7 2017, 18:11) *
А в чём разница между стеком задачи под ОС и стеком той же самой задачи без ОС? У Вас, что ОС сама ваш код компилирует? Или может даже пишет? biggrin.gif

Тем, что без ОС такой - стек общий, и памяти не хватит тогда, когда ее не хватит вообще. А с потоками вытесняющими - это как коробка конфет , места много займет, а конфет мало, в отличии от единого стека. Второй пример фрагментации памяти с malloc - памяти до хрена, а получаем NULL - ибо впихнуть нужный кусок некуда. Я надеюсь вы уже решили эту проблему сборщиками мусора на микроконтроллерах? wink.gif Короче не стоит далее спорить, все останутся при своих это очевидно. Меня недетерминированность поведения таких РТОС во многих задачах не устраивает, расход памяти тоже


"другого класса, скорее всего платной RTOS. " - то есть все бесплатное - это дерьмо по умолчанию? Странная мысль.
Forger
Цитата(DASM @ Nov 7 2017, 18:11) *
Эти РТОС замечательны для обучения студентов имхо, только вот в реальной аппаратуре, с более ответсвенными целями чем очередной вебсервер - очень неуверен.

По-вашему выходит, что ручная ножовка по дереву годится только для обучения и пару тонких дощечек для полочки под цветы всякий нужно раз пилить мощной бензопилой .... Хм, необычный подход, кардинальный :D
Каждая задача требует своего инструмента. А всякая попытка недооценивать и хаять готовые инструменты выставляет их автора в не самом лучшем свете ... по крайней мере перед теми, кто успешно использует эти инструменты wink.gif
Точно так же очень странно выглядит попытка пилить вековую сосну лобзиком под фанеру ....



Цитата(DASM @ Nov 7 2017, 18:29) *
Тем, что без ОС такой - стек общий, и памяти не хватит тогда, когда ее не хватит вообще. А с потоками вытесняющими - это как коробка конфет , места много займет, а конфет мало, в отличии от единого стека.

Видать, первые попытки применения RTOS в лоб оказались для вас негативными...
Однако, остальным почему-то повезло больше wink.gif Может быть дело не в "инструменте" вовсе, а в "слесаре", который пытался его использовать не очень удачно wink.gif

Цитата
Второй пример фрагментации памяти с malloc - памяти до хрена, а получаем NULL - ибо впихнуть нужный кусок некуда.

Сходу на тракторе да в соседский забор ... с дин. памятью в МК нужно быть аккуратнее. Это во всех книжках написано ))

Цитата
Я надеюсь вы уже решили эту проблему сборщиками мусора на микроконтроллерах? wink.gif
Удивитесь, но да - проблема решена: не использовать дин. память в каждой дырке, или вообще не использовать. Это не так сложно, как кажется ))

Цитата
Меня недетерминированность поведения таких РТОС во многих задачах не устраивает
Все верно! Криво спроектированный код именно так себя и ведет 1111493779.gif
А RTOS тут совсем ни при чем ))
DASM
Да никто не хает, каждый до..ит как хочет. Просто Вы так огульно говорите вопрошавшему "занять вам нечем" что именно это и вам выставляет в таком свете. Ваши РТОС далеко не панацея. Мало того, если мы посмотрим профессиональные проекты, нет статистики, но навскидку 70-80 процентов используют либо суперлюп, либо свой простенький кооператив. Нужели мозгов им не хватило? Не думаю. Можем дальше спорить , но зачем? Вот например С - зачем на нем писать, у нас же аж 256 кбайт памяти! Язык устарел, примитивен, от асма ушел недалеко . Ну и так далее. Просто не стоит, изучив и используя что-то одно говорить, что сие есть истина, а остальным нечем заняться
" Криво спроектированный именно так себя и ведет. RTOS тут ни при чем ))))" ртос тут вообщем непричем, давайте MMU, нет памяти - page fault - выделяем, едем дальше. А без MMU - "если заняться нечем" (с)
Forger
Цитата(DASM @ Nov 7 2017, 18:39) *
Ваши РТОС далеко не панацея... если мы посмотрим профессиональные проекты, нет статистики ...

Ну, хорошо, хорошо, слив защитан sm.gif Проехали ))

Цитата
Просто не стоит, изучив и используя что-то одно говорить, что сие есть истина, а остальным нечем заняться

Мне стало интересно, что такого вносит этот SST по сравнению с готовыми решениями, в частности с RTOS.
Оказалось, что он приносит лишь головную боль, причем, на ровном месте: без нужды усложняет структуру кода, от суперлупа со всеми его костылями в целом ничем не отличается.
(С) "Те же яйца, только в профиль."
Вот и пытаюсь увидеть мотивацию ... пока не увидел... Любопытно все же, что заставляет народ изобретать велосипеды с квадратными колесами laughing.gif
jcxz
Цитата(DASM @ Nov 7 2017, 17:29) *
Тем, что без ОС такой - стек общий, и памяти не хватит тогда, когда ее не хватит вообще. А с потоками вытесняющими - это как коробка конфет ,

"Без ОС" - это значит всё в одной задаче. Если вы, не меняя алгоритма, перенесёте эту задачу в одну из задач (потоков) РТОС, что что изменится с потреблением стека? Ничего!
Так в чём разница???
Далее - конечно под РТОС вы потом можете эту же задачу реализовать в виде многих потоков РТОС. Это разве будет тем же самым алгоритмом? Нет конечно, это новая реализация, совершенно по другому написанная. И да, если писать не включая голову, можно сколько угодно памяти израсходовать.
Так в чём преимущество "без РТОС" по-вашему, в том что в таком случае заведомо меньше возможностей и криворукий программист сделает меньше багов? Не уверен что это преимущество....

Цитата(DASM @ Nov 7 2017, 17:29) *
места много займет, а конфет мало, в отличии от единого стека.

Так если задачу можно реализовать в виде одного потока ОС, то зачем его делить на несколько?
Или всё-таки нельзя (или будет заведомо худшее решение), то очевидно тогда что с РТОС - лучше? Разве не?

Цитата(DASM @ Nov 7 2017, 17:29) *
Второй пример фрагментации памяти с malloc

"Смешались в кучу люди кони"... динамическая память-то тут причём??? Разговор про стеки вроде шёл. Нафига стеки в дин. память пихать??? Да ещё выделять/освобождать периодически.
Какие-то нереальные примеры выдумываете....
PS: За последние ~15 лет в отрасли и десятках реализованных проектов, я ни разу ещё не использовал malloc() в embedded-проектах. Что делаю не так? blink.gif
arhiv6
Цитата(AHTOXA @ Nov 7 2017, 21:17) *
Здесь была тема про SST. Посмотрите там, может, там есть ответ.

Да, тоже вспомнил про эту тему, перечитываю. Но, насколько я помню, копкретной реализации переключения контекстов для SST там нет.

Цитата(DASM @ Nov 7 2017, 21:28) *
Я отказался от FreeRTOS, 256 К памяти не хочу транжирить, SST "х расходы стековой памяти по сравнению с традиционными операционными системами сокращается на 80%."
. Так что насчет "нечем заняться" не стоит огульно, SST прекрасно ложится на мелкие 1M/256K контроллеры, на средние (16G/1G) полноценный Линукс проще. Места классическим RTOS я лично не вижу

О, Вы на практике используете SST? А под какие процессоры?

Цитата(jcxz @ Nov 7 2017, 22:00) *
PS: При задавании подобных вопросов, очень уместно указывать ядро о котором спрашивается. Ибо реализация очень сильно зависит от этого самого ядра.

Как указано в первом посте - ARM, Cortex. Пусть будет STM32F030 (Cortex-M0).

Цитата(scifi @ Nov 7 2017, 22:04) *
Гугл вводит на гитхаб. Возможно, всё украдено до нас?

Видел. Но насколько я понял, там использую один обработчик прерывания PendSV (без его вложенного вызова), и можно реализовать всего 2 уровня приоритетов - idle в основном цикле в main + все остальные задачи в контексте PendSV_Handler. Они будут выполняться синхронно, в порядке приоритетов. А в SST из статьи более приоритетные задачи могут асинхронно прерывать менее приоритетные.

Пожалуйста, не нужно писать про FreeRTOS и KEIL RTX. Это отличные системы, с первой работал (и работаю), но в этом топике речь идёт о реализации SST.
jcxz
Цитата(DASM @ Nov 7 2017, 17:39) *
но навскидку 70-80 процентов используют либо суперлюп

90% железных "программистов" используют ардуйню. Предлагаете на них равняться и бросать наши кортексы/DSP?

Цитата(Forger @ Nov 7 2017, 17:46) *
Мне стало интересно, что такого вносит этот SST по сравнению с готовыми решениями, в частности с RTOS.

Когда автор наконец-то реализует свой SST (если конечно реализует wink.gif, он с удивлением обнаружит, что у него получился шедулер обычной РТОС. biggrin.gif
Поэтому и совет ему: сразу идти и посмотреть как это сделано в какой-нить РТОС. Чтобы попусту время не терять.

Цитата(arhiv6 @ Nov 7 2017, 17:59) *
Да, тоже вспомнил про эту тему, перечитываю. Но, насколько я помню, копкретной реализации переключения контекстов для SST там нет.

Возьмите порт под нужное ядро любой РТОС и посмотрите на "конкретную реализацию".

Цитата(arhiv6 @ Nov 7 2017, 17:59) *
Как указано в первом посте - ARM, Cortex. Пусть будет STM32F030 (Cortex-M0).

Ну наконец-то! Cortex-M всё-таки.
На первой странице указано "ARM, Cortex". И всё. А среди них есть как Cortex-M, так и Cortex-A. И др. И да будет Вам известно, что система прерываний у них устроена совершенно по разному.
Forger
Цитата(jcxz @ Nov 7 2017, 19:11) *
Чтобы попусту время не терять.

Не тот случай ... wink.gif
jcxz
Цитата(arhiv6 @ Nov 7 2017, 17:59) *
Пожалуйста, не нужно писать про FreeRTOS и KEIL RTX. Это отличные системы, с первой работал (и работаю)...

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

Цитата(Forger @ Nov 7 2017, 18:13) *
Похоже, это - совсем не тот случай wink.gif

Человек пишет, что работает с системой, но не знает как она работает.
Это то же самое, если-б водитель самосвала написал, что он работает на самосвале, но не знает от чего у него колёса крутятся. "Вот залазю туда и колёса начинают крутиться, кто его знает от чего они крутятся. Наверное потому что круглые" biggrin.gif
arhiv6
Смотрел я исходники ОС, но они все по похожему принципу сделаны - переключение между разными стеками. Вот например: для каждого потока выделен свой стек. Для переключения между двумя контекстами вызывается прерывание PendSV (при этом на стек складываются R0-R3) и в PendSV_Handler сохраняются оставшиеся регистры (R4-R11), потом вызывается функция os_context_switch_hook, которая возвращает указатель на стек другой задачи. С этого стека восстанавливаем (R11-R4) , переписываем LR и выходим из PendSV_Handler, при этом восстанавливаются (R3-R0). Всё, мы переключились на другую задачу/другой стек.

А можете примерно так-же объяснить, что мне сделать для пререключения задач по методике SST?
Выполняем мы задачу А. Так же через вызов прерывания PendSV хотим запустить более приоритетную задачу (запустить функцию). Попали в PendSV_Handler, сохранили (R4-R11) на текущем стеке. Всё, контекст задачи A сохранён. Как теперь правильно запустить задачу В? Сделать просто вызов LDR R1, =taskB, BLX R1 нельзя - функция будет выполняться в контексте прерывания. Как правильно сделать? Из прерывания если выйдем ( BX LR) мы попадём обратно в задачу А. Как мне выйти из прерывания и при этом запустить функцию taskB?
Forger
Цитата(jcxz @ Nov 7 2017, 19:16) *
Наверное потому что круглые" biggrin.gif

Не тот случай - тут колеса НЕкруглые, сделаны
Цитата
по методике SST
arhiv6
jcxz, Forger, я не знаю, как правильно сделать, поэтому и спрашиваю совета на форуме. Вы подсказать можете? Или Вы сами тоже не знаете, но хоть что-нибудь написать так и чешется (например, шутку про колёса)?

DASM, а можете рассказать, как у Вас реализовано? И под какой микроконтроллер?
Forger
Цитата(arhiv6 @ Nov 7 2017, 20:28) *
Как правильно сделать?

Как бы вы не старались, по методике SST правильно не будет никак, поскольку ядро ARM (в частности контроллер прерываний) разрабатывался изначально под классические принципы работы RTOS.
Очевидно, что для этого были веские основания.
Если вам принципиально нужно "по методике SST", то придется городить адские костыли с полной потерей всех прелестей вложенного приоритетного контроллера прерываний.
Отлаживать такой говнокод - еще тот мартышкин труд.
Мало того, что полностью теряется полезнейшая функция sleep/delay, так еще и "задачи" теряют свой привычный очень многим смысл.
Невозможно будет применить чужой код без его тотальной переделки. Зачастую будет написать его заново.
Мифическая экономия ОЗУ и флэши (я бы сказал копеешная экономия) превратиться в неоправданные траты памяти там, где в этом не было нужды под обычной RTOS.
Особенно сочувствую тем, кому придется работать с вашим кодом ...
Вангую, что такой код будет напрочь переписан под привычную и понятную всем схему, где задачи выполняются в фоне задач, а прерывания - в фоне прерываний....


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

Для убедительности моих слов разместите тут код простейшей задачи моргания светодиода с различной скважностью в бесконечном цикле "по методике SST".
Время включенного и выключенного состояния - параметры изменяемые и кратны 1мс. Разумеется, процессорное время должно тратиться лишь на включение и выключение светодиода, но не на задержки.
Вот так эта задачка выглядит на привычной OS (все времена в мс):
Код
while(true)
{
  led.on();
  sleep(onTime);
  led.off();
  sleep(offTime);
}

Как это будет выглядеть под мифической SST?
DASM
Меня устраивает карусель кооперативная на таймерах, не столь удобно писать код, но мне его поведение выглядит более понятным. Это скорее "железный" стиль, а не программисткий. Да и задач у меня нет промежуточных почти, либо простые, где достаточно прерываний и таймеров с флагами, либо на Линукс всякие видеокамеры. Мутить что то достаточно сложное на малых ресурсах не доводилось. Круто конечно сервер на коппечном проце замутить, только интерес это академический, никому это не надо. Железо стоит копейки, тот же расперри за 10 баксов имеет полноценный линукс, зачем жать доллар в российской реальности, где тиражи малы, конкурентоспособность определяется родственными связями начальникам и величиной откатов заказчику, в время разработки важнее этого несчастного доллара

Цитата
void LedTaskOn (void *pparam)
{
SetTimer (LedTaskOff, onTime);
led.on();
}
void LedTaskOff (void *pparam)
{
SetTimer (LedTaskOn, offTime);
led.off();
}

Можно и одной функцией
Стек не жрет, дискретность микросекнды, никаких проблем с разделением ресурсов - все работают из прерываний. Недостаток - функция такого потока реализуется как машина состояний, что вобщем то не напрягает
Все эти
Цитата
led.on();
sleep(onTime);
led.off();
sleep(offTime);

хороши как заманилово студентам как все красиво и прекрасно. В реальной задаче все увы не совсем так, обрастает критическими секциями, мьютексам итп. Где-то удобно, а где-то - не нужно. Мне - не нужно пока что точно
arhiv6
Цитата(Forger @ Nov 8 2017, 01:27) *
Как бы вы не старались, по методике SST правильно не будет никак, поскольку ядро ARM (в частности контроллер прерываний) разрабатывался изначально под классические принципы работы RTOS.
Да,похоже всё так.

Цитата(Forger @ Nov 8 2017, 01:27) *
Для убедительности моих слов разместите тут код простейшей задачи моргания светодиода с различной скважностью в бесконечном цикле "по методике SST".
Время включенного и выключенного состояния - параметры изменяемые и кратны 1мс. Разумеется, процессорное время должно тратиться лишь на включение и выключение светодиода, но не на задержки.
Вот так эта задачка выглядит на привычной OS (все времена в мс):
...
Как это будет выглядеть под мифической SST?

Не знаю, я же ещё толком и не работал с SST. Первое, что приходит в голову так:
Код
void task_ledBlinker_on()
{
  led.on();
  setTask(task_ledBlinker_off, onTime, 0);
}

void  task_ledBlinker_on()
{
  led.off();
  setTask(task_ledBlinker_on, offTime, 0);
}

или так:
Код
task_ledBlinker()
{
  led.toggle();

  if (led.state())
    setTask(task_ledBlinker, onTime, 0);
  else
    setTask(task_ledBlinker, offTime, 0);
}
Forger
Цитата(DASM @ Nov 7 2017, 21:50) *
void LedTaskOn (void *pparam)
{
SetTimer (LedTaskOff, onTime);
led.on();
}
void LedTaskOff (void *pparam)
{
SetTimer (LedTaskOn, offTime);
led.off();
}

Очень печальное зрелище - простейший пример усложнил читаемость и очевидность кода на порядки. Также вырос размер кода во флэш.
Уж боюсь предположить, во что превратить более объемный код после переписывания его под SST.
Короче, прихожу к очевидному выводу: SST - это для потомственных мазахистов.... Я пас cranky.gif
DASM
Первое, что приходит в голову так:sm.gif о как, у меня также, только я не знал что это SST называется. Просто каруселька и все

"простейший пример усложнил читаемость и очевидность кода на порядки. Также вырос размер кода во флэш.", а насколько вырос ваш пример в ОЗУ? И можно плиз зажечь диод через 13.65845 мс ровно? И не надо про отладка на порядок сложнее, многопоточные приложения всегда отлаживать сложнее. К тому же ваш пример содержит ошибку, вы шину GPIO не захватили, а по ней сейчас другой поток занят важным делом - писк на зумер выводит. А потом жалуются, почему динамик хрипит на 1 кГц sm.gif
Добавьте плиз SemaphoreGet. SemaphorePost с кодом иниициализации семафора. А то как-то нечестно.
Forger
Цитата(DASM @ Nov 7 2017, 22:02) *
Просто каруселька и все

Ну-ну, песочница оживилась sm.gif
DASM
Цитата(Forger @ Nov 7 2017, 22:05) *
Ну-ну, песочница оживилась sm.gif

ну ну , понторезка оживилась, давненько тут гастролеров с хабра не было
arhiv6
Цитата(DASM @ Nov 8 2017, 02:05) *
Первое, что приходит в голову так:sm.gif о как, у меня также, только я не знал что это SST называется. Просто каруселька и все

Как я понимаю, для SST нужно добавить задачам приоритеты и возможность асинхронного переключения на более приоритетную задачу из менее приоритетной. Без этого на чистом си можно использовать простейшие планировщики, например этот.
DASM
Ну да , тут собственно у меня так и есть
Forger
Цитата(DASM @ Nov 7 2017, 22:05) *
Первое, что приходит в голову так:sm.gif о как, у меня также, только я не знал что это SST называется. Просто каруселька и все

"простейший пример усложнил читаемость и очевидность кода на порядки. Также вырос размер кода во флэш.", а насколько вырос ваш пример в ОЗУ?

И можно плиз зажечь диод через 13.65845 мс ровно?

Можно, но в данном случае - в этом нет нужды. Это - главное отличие RTOS от самодельных "каруселек" - не делать то, что не нужно делать.


Цитата
И не надо про отладка на порядок сложнее, многопоточные приложения всегда отлаживать сложнее.

Нет, все в точности наоборот. Именно поэтому везде, где возможно, ставлю RTOS. Это сильно упрощает код и делает его легко переносимым из одного проекта в другой.

Цитата
К тому же ваш пример содержит ошибку, вы шину GPIO не захватили,

Во-первых, чтобы зажечь светодиод, не нужно как выговорите "захватывать шину GPIO". Читайте матчасть по ARM Cortex. Не позорьтесь ))
Во-вторых, тут не указана реализация методов класса led - on и off. Да и не имеет это отношения к делу.

Цитата
а по ней сейчас другой поток занят важным делом - писк на зумер выводит.
Читайте матчасть.

Цитата
А потом жалуются, почему динамик хрипит на 1 кГц sm.gif

Хрипит он скорее всего по другой причине - меандр сделан средствами RTOS, без использования аппаратных таймеров. Бывшие ардуинщики именно так и делают.
Правильно будет - реализовывать разные задачи разными инструменты, а не городить все одним.

Цитата
Добавьте плиз SemaphoreGet. SemaphorePost с кодом иниициализации семафора. А то как-то нечестно.

Вот:
Код
// создаем семафор
OS::Semaphore semaphore;

// гипотетическая задача:
while(true)
{
  semaphore.waitForever();
  // что-нить делаем
}

// обработчик прерываний или другая задача
{
  semaphore.signal();
}

Для примера, ожидание семафора бесконечное, но есть другие методы у этого класса OS::Semaphore, в частности позволяющие ждать его не более указанного времени.



Ваша очередь ...

Цитата(DASM @ Nov 7 2017, 22:08) *
давненько тут гастролеров с хабра не было

Такая реакция говорит о том, что "про песочницу" я попал в самую точку biggrin.gif
Кстати, кто такие "гастролеры" с некого "хабра"?
DASM
@ Читайте матчасть по ARM Cortex.@ Ладно, спорить тут не о чем. В молодости я тоже был такой горячий и восторженный. Удачи
Forger
Цитата(DASM @ Nov 7 2017, 22:29) *
@ Читайте матчасть по ARM Cortex.@ Ладно, спорить тут не о чем.


ОК, слив опять защитан. Счет 2:0 sm.gif

Для тех, кто не в теме: в ARM Cortex есть такой механизм - BitBanging (вроде правильно написал).
Он позволяет упростить работу с обращениями типа чтение-модификация-запись.
В частности, изменение состояния пинов не требует создания критических секций и т. п, как это было необходимо в более архаичных ARM.

Цитата
В молодости я тоже был такой горячий и восторженный.

В молодости я тоже страдал всякой херней наподобие SST ("каруселек") и т. п. подобной дребедени лишь чисто ради "академического" интереса (в ту пору на Microchip процах).
Кстати, на Microchip только так и можно было использовать RTOS - кооперативная с вагоном соотв. костылей. Но это было давно и осталось в далеком прошлом (к счастью)...
Но времена меняются, и, чтобы не отстать от поезда, нужно осваивать новые решения.
AlexandrY
Цитата(Forger @ Nov 7 2017, 21:36) *
Для тех, кто не в теме: в ARM Cortex есть такой механизм - BitBanging (вроде правильно написал).

Да чего сейчас только нету в этих ARM-ах.
В последнее время у меня светодиоды RGB и управляются строго по DMA. Никаких обращений в порты.
Пишу шаблон работы типа микроскрипта, гружу в автомат, а тот расчитанные RGB коды пишет просто в память, никаких портов.
Код
const uint32_t RGB_ptrn_Green_blink[6] = {VAL_LEV(0), 250, HSV_GREEN+SAT_LEV(100)+VAL_LEV(50), 50, B_JMP, (uint32_t)&RGB_ptrn_Green_blink[0] };

Set_RGB_led_ptrn((uint32_t *)RGB_ptrn_Green_blink);

Мигает, плавно меняет цвет, интенсивность, цветность. Все что хочешь.
Само собой автомат сделан в отдельной задаче RTOS.
DASM
А где тут DMA и что и куда оно грузит?
jcxz
Цитата(arhiv6 @ Nov 7 2017, 19:28) *
Смотрел я исходники ОС, но они все по похожему принципу сделаны - переключение между разными стеками.
...

Да, примерно так и есть.

Цитата(arhiv6 @ Nov 7 2017, 19:28) *
А можете примерно так-же объяснить, что мне сделать для пререключения задач по методике SST?
Выполняем мы задачу А. Так же через вызов прерывания PendSV хотим запустить более приоритетную задачу (запустить функцию). Попали в PendSV_Handler, сохранили (R4-R11) на текущем стеке.

"На текущем" - это на каком? На стеке обработчиков прерываний что-ль? Вы имеете представление, что в ядре Cortex-M есть два стека (аппаратных) - MSP/PSP? И зачем так сделано?

Цитата(arhiv6 @ Nov 7 2017, 19:28) *
Всё, контекст задачи A сохранён. Как теперь правильно запустить задачу В? Сделать просто вызов LDR R1, =taskB, BLX R1 нельзя - функция будет выполняться в контексте прерывания. Как правильно сделать? Из прерывания если выйдем ( BX LR) мы попадём обратно в задачу А. Как мне выйти из прерывания и при этом запустить функцию taskB?
Так Вы же читали как это делают переключатели задач РТОС - сделайте точно так же. Сохраните все регистры на стеке прерванной задачи, также в сегмент данных прерванной задачи сохраните её SP, загрузите SP новой задачи в PSP, восстановите со стека новой задачи ту часть регистров, которая программно сохраняется (R4-R11) и всё - можете выходить из прерывания в контекст уже новой задачи (так как на её стеке сейчас остались регистры, аппаратно сохраняемые при входе в ISR). Естественно - перед первым запуском каждой задачи, её стек нужно проинициализировать корректными значениями регистров расположенных именно в том порядке, в котором они сохраняются/восстанавливаются при входе и внутри PendSV.
Если нужно возбуждать переключение задач из ISR аппаратного прерывания, то естественно в ядре Cortex-M для этого нужно программно возбудить PendSV, выйти из аппаратного ISR и уже в ISR PendSV переключить контекст. Именно такой метод и был задуман проектировщиками ядра. Чтобы такой механизм работал, необходимо чтобы приоритет PendSV был ниже приоритета любого аппаратного прерывания.
И вот когда вы всё это проделаете, то получите стандартную РТОС для Cortex-M sm.gif Именно поэтому вам и пишут, что смысла изобретать свой лисапед нет никакого. Разве что в целях собственного ликбеза.
Остаться внутри ISR аппаратного прерывания каким-то образом не выходя из него, а что-то там замутив со стеком - невозможно без нарушения работы всей системы прерываний - пока не выйдете из этого ISR это прерывание больше не вызовется (и менее приоритетные тоже). Так что такой способ, который Вы описали в первом сообщении, на Cortex-M - нереализуем.

PS: И прежде, чем что-то подобное делать - настоятельно рекомендую изучить мануал на ядро. Особенно в части касаемой режимов процессора, входов и выходов в ISR.
Forger
Цитата(AlexandrY @ Nov 7 2017, 23:41) *
Да чего сейчас только нету в этих ARM-ах.


Но, выходит, что не все об этом знают ... wink.gif
jcxz
Цитата(DASM @ Nov 7 2017, 21:05) *
вы шину GPIO не захватили, а по ней сейчас другой поток занят важным делом - писк на зумер выводит.

А зачем её захватывать? Как почту/телефон/телеграф/интернет? (сегодняшняя дата навеяла wink.gif
Во всех МК на Cortex-M с которыми мне приходилось иметь дело, периферия GPIO имеет средства для атомарной модификации отдельных битов порта (ну или хотя-бы находится в области bit-band). Можете пиликать вашим динамиком сколько угодно. После того как ознакомитесь с мануалом на периферию своего МК.

Цитата(DASM @ Nov 7 2017, 21:05) *
Первое, что приходит в голову так:sm.gif о как, у меня также, только я не знал что это SST называется. Просто каруселька и все

У Вас на вашей карусельке в любимом суперцикле, пока процессор сидит в очередной паузе (для ногодрочества динамиком), никакая полезная работа не выполняется. А в случае с РТОС на время такой паузы, время CPU будет передано другой менее приоритетной задаче, которая в нём сейчас нуждается, либо процессор будет выполнять WFI/WFE экономя миллиамперы. А у вас просто будет всё тупо висеть и впустую жрать миллиамперы.
Вот в этом как раз и есть главное преимущество РТОС с её задачами/потоками от суперцикла. И с современными объёмами ОЗУ в МК, как правило не составляет труда выделить каждой задаче необходимое кол-во стека. Ну если руки конечно не совсем из неподходящего места растут, то памяти это много не займёт.
DASM
Ну не знаю, у меня на Ардуино все проще, а на малинке тем более, на питоне. fman.gif А у вас сложно как то, dma какие то, А как это "зачем захватывать". Под gpio драйвер надо, может gpio в Калифорнии висят и управляются какими нибудь post запросами. А вот тут вроде проще https://developer.microsoft.com/en-us/windo...les/helloblinky но я не уверен, что win10 iot влезет в процессор без mmu. О, кстати идея, сейчас залью винду эту на малину, интересно какая частота в цикле мигания получится
AlexandrY
Цитата(DASM @ Nov 7 2017, 23:01) *
А где тут DMA и что и куда оно грузит?

О, это длинная запутанная история - https://geektimes.ru/post/284248/

Цитата(DASM @ Nov 8 2017, 00:35) *
Ну не знаю, у меня на Ардуино все проще, а на малинке тем более, на питоне. fman.gif

Эт как гнаться за семью зайцами.
Нет, хардварная платформа должна быть своя.
Тогда из нее можно выжать максимум: и прерывания в прерываниях, и SST, и RTOS, и всё вместе.
AVR
Цитата(Forger @ Nov 7 2017, 22:36) *
ОК, слив опять защитан. Счет 2:0 sm.gif

У меня сей уважаемый господин (под псевдонимом dasm), уже давно находится в списке игнора форума.
Ради него старался и нашел такую опцию. Ничего не потерял cool.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.