Forger 26 7 ноября, 2017 Опубликовано 7 ноября, 2017 · Жалоба Как правильно сделать? Как бы вы не старались, по методике SST правильно не будет никак, поскольку ядро ARM (в частности контроллер прерываний) разрабатывался изначально под классические принципы работы RTOS. Очевидно, что для этого были веские основания. Если вам принципиально нужно "по методике SST", то придется городить адские костыли с полной потерей всех прелестей вложенного приоритетного контроллера прерываний. Отлаживать такой говнокод - еще тот мартышкин труд. Мало того, что полностью теряется полезнейшая функция sleep/delay, так еще и "задачи" теряют свой привычный очень многим смысл. Невозможно будет применить чужой код без его тотальной переделки. Зачастую будет написать его заново. Мифическая экономия ОЗУ и флэши (я бы сказал копеешная экономия) превратиться в неоправданные траты памяти там, где в этом не было нужды под обычной RTOS. Особенно сочувствую тем, кому придется работать с вашим кодом ... Вангую, что такой код будет напрочь переписан под привычную и понятную всем схему, где задачи выполняются в фоне задач, а прерывания - в фоне прерываний.... Впрочем, если вы по-прежнему упорно настроены на SST (задачи работают в фоне прерываний), то придется поломать голову и сделать свое решение самостоятельно, тогда только в этом случае вы поймете тупиковость этой затеи, как минимум на ARM процах. Для убедительности моих слов разместите тут код простейшей задачи моргания светодиода с различной скважностью в бесконечном цикле "по методике SST". Время включенного и выключенного состояния - параметры изменяемые и кратны 1мс. Разумеется, процессорное время должно тратиться лишь на включение и выключение светодиода, но не на задержки. Вот так эта задачка выглядит на привычной OS (все времена в мс): while(true) { led.on(); sleep(onTime); led.off(); sleep(offTime); } Как это будет выглядеть под мифической SST? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DASM 0 7 ноября, 2017 Опубликовано 7 ноября, 2017 · Жалоба Меня устраивает карусель кооперативная на таймерах, не столь удобно писать код, но мне его поведение выглядит более понятным. Это скорее "железный" стиль, а не программисткий. Да и задач у меня нет промежуточных почти, либо простые, где достаточно прерываний и таймеров с флагами, либо на Линукс всякие видеокамеры. Мутить что то достаточно сложное на малых ресурсах не доводилось. Круто конечно сервер на коппечном проце замутить, только интерес это академический, никому это не надо. Железо стоит копейки, тот же расперри за 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 20 7 ноября, 2017 Опубликовано 7 ноября, 2017 · Жалоба Как бы вы не старались, по методике SST правильно не будет никак, поскольку ядро ARM (в частности контроллер прерываний) разрабатывался изначально под классические принципы работы RTOS.Да,похоже всё так. Для убедительности моих слов разместите тут код простейшей задачи моргания светодиода с различной скважностью в бесконечном цикле "по методике 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 26 7 ноября, 2017 Опубликовано 7 ноября, 2017 · Жалоба void LedTaskOn (void *pparam) { SetTimer (LedTaskOff, onTime); led.on(); } void LedTaskOff (void *pparam) { SetTimer (LedTaskOn, offTime); led.off(); } Очень печальное зрелище - простейший пример усложнил читаемость и очевидность кода на порядки. Также вырос размер кода во флэш. Уж боюсь предположить, во что превратить более объемный код после переписывания его под SST. Короче, прихожу к очевидному выводу: SST - это для потомственных мазахистов.... Я пас :cranky: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DASM 0 7 ноября, 2017 Опубликовано 7 ноября, 2017 · Жалоба Первое, что приходит в голову так::) о как, у меня также, только я не знал что это SST называется. Просто каруселька и все "простейший пример усложнил читаемость и очевидность кода на порядки. Также вырос размер кода во флэш.", а насколько вырос ваш пример в ОЗУ? И можно плиз зажечь диод через 13.65845 мс ровно? И не надо про отладка на порядок сложнее, многопоточные приложения всегда отлаживать сложнее. К тому же ваш пример содержит ошибку, вы шину GPIO не захватили, а по ней сейчас другой поток занят важным делом - писк на зумер выводит. А потом жалуются, почему динамик хрипит на 1 кГц :) Добавьте плиз SemaphoreGet. SemaphorePost с кодом иниициализации семафора. А то как-то нечестно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 7 ноября, 2017 Опубликовано 7 ноября, 2017 · Жалоба Просто каруселька и все Ну-ну, песочница оживилась :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DASM 0 7 ноября, 2017 Опубликовано 7 ноября, 2017 · Жалоба Ну-ну, песочница оживилась :) ну ну , понторезка оживилась, давненько тут гастролеров с хабра не было Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
arhiv6 20 7 ноября, 2017 Опубликовано 7 ноября, 2017 · Жалоба Первое, что приходит в голову так::) о как, у меня также, только я не знал что это SST называется. Просто каруселька и все Как я понимаю, для SST нужно добавить задачам приоритеты и возможность асинхронного переключения на более приоритетную задачу из менее приоритетной. Без этого на чистом си можно использовать простейшие планировщики, например этот. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DASM 0 7 ноября, 2017 Опубликовано 7 ноября, 2017 · Жалоба Ну да , тут собственно у меня так и есть Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 7 ноября, 2017 Опубликовано 7 ноября, 2017 · Жалоба Первое, что приходит в голову так::) о как, у меня также, только я не знал что это SST называется. Просто каруселька и все "простейший пример усложнил читаемость и очевидность кода на порядки. Также вырос размер кода во флэш.", а насколько вырос ваш пример в ОЗУ? И можно плиз зажечь диод через 13.65845 мс ровно? Можно, но в данном случае - в этом нет нужды. Это - главное отличие RTOS от самодельных "каруселек" - не делать то, что не нужно делать. И не надо про отладка на порядок сложнее, многопоточные приложения всегда отлаживать сложнее. Нет, все в точности наоборот. Именно поэтому везде, где возможно, ставлю RTOS. Это сильно упрощает код и делает его легко переносимым из одного проекта в другой. К тому же ваш пример содержит ошибку, вы шину GPIO не захватили, Во-первых, чтобы зажечь светодиод, не нужно как выговорите "захватывать шину GPIO". Читайте матчасть по ARM Cortex. Не позорьтесь )) Во-вторых, тут не указана реализация методов класса led - on и off. Да и не имеет это отношения к делу. а по ней сейчас другой поток занят важным делом - писк на зумер выводит.Читайте матчасть. А потом жалуются, почему динамик хрипит на 1 кГц :) Хрипит он скорее всего по другой причине - меандр сделан средствами RTOS, без использования аппаратных таймеров. Бывшие ардуинщики именно так и делают. Правильно будет - реализовывать разные задачи разными инструменты, а не городить все одним. Добавьте плиз SemaphoreGet. SemaphorePost с кодом иниициализации семафора. А то как-то нечестно. Вот: // создаем семафор OS::Semaphore semaphore; // гипотетическая задача: while(true) { semaphore.waitForever(); // что-нить делаем } // обработчик прерываний или другая задача { semaphore.signal(); } Для примера, ожидание семафора бесконечное, но есть другие методы у этого класса OS::Semaphore, в частности позволяющие ждать его не более указанного времени. Ваша очередь ... давненько тут гастролеров с хабра не было Такая реакция говорит о том, что "про песочницу" я попал в самую точку Кстати, кто такие "гастролеры" с некого "хабра"? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DASM 0 7 ноября, 2017 Опубликовано 7 ноября, 2017 · Жалоба @ Читайте матчасть по ARM Cortex.@ Ладно, спорить тут не о чем. В молодости я тоже был такой горячий и восторженный. Удачи Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 7 ноября, 2017 Опубликовано 7 ноября, 2017 · Жалоба @ Читайте матчасть по ARM Cortex.@ Ладно, спорить тут не о чем. ОК, слив опять защитан. Счет 2:0 :) Для тех, кто не в теме: в ARM Cortex есть такой механизм - BitBanging (вроде правильно написал). Он позволяет упростить работу с обращениями типа чтение-модификация-запись. В частности, изменение состояния пинов не требует создания критических секций и т. п, как это было необходимо в более архаичных ARM. В молодости я тоже был такой горячий и восторженный. В молодости я тоже страдал всякой херней наподобие SST ("каруселек") и т. п. подобной дребедени лишь чисто ради "академического" интереса (в ту пору на Microchip процах). Кстати, на Microchip только так и можно было использовать RTOS - кооперативная с вагоном соотв. костылей. Но это было давно и осталось в далеком прошлом (к счастью)... Но времена меняются, и, чтобы не отстать от поезда, нужно осваивать новые решения. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 3 7 ноября, 2017 Опубликовано 7 ноября, 2017 · Жалоба Для тех, кто не в теме: в 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 0 7 ноября, 2017 Опубликовано 7 ноября, 2017 · Жалоба А где тут DMA и что и куда оно грузит? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 244 7 ноября, 2017 Опубликовано 7 ноября, 2017 · Жалоба Смотрел я исходники ОС, но они все по похожему принципу сделаны - переключение между разными стеками. ... Да, примерно так и есть. А можете примерно так-же объяснить, что мне сделать для пререключения задач по методике SST? Выполняем мы задачу А. Так же через вызов прерывания PendSV хотим запустить более приоритетную задачу (запустить функцию). Попали в PendSV_Handler, сохранили (R4-R11) на текущем стеке. "На текущем" - это на каком? На стеке обработчиков прерываний что-ль? Вы имеете представление, что в ядре Cortex-M есть два стека (аппаратных) - MSP/PSP? И зачем так сделано? Всё, контекст задачи 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 :) Именно поэтому вам и пишут, что смысла изобретать свой лисапед нет никакого. Разве что в целях собственного ликбеза. Остаться внутри ISR аппаратного прерывания каким-то образом не выходя из него, а что-то там замутив со стеком - невозможно без нарушения работы всей системы прерываний - пока не выйдете из этого ISR это прерывание больше не вызовется (и менее приоритетные тоже). Так что такой способ, который Вы описали в первом сообщении, на Cortex-M - нереализуем. PS: И прежде, чем что-то подобное делать - настоятельно рекомендую изучить мануал на ядро. Особенно в части касаемой режимов процессора, входов и выходов в ISR. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться