У PRU ядра всего один поток команд.
Т.е. В каждый момент времени PRU берет следующую команду и выполняет. Никаких прерываний нет.
До этого я составлял программы, в которых было все-все-все. И чтение входов, и обмен данными и
ожидания, и запись выходов.
Мне, конечно так проще, да и всё равно никто другой черепахой не программировал.
Но есть "незадача". Например, для управления ШД нужно мигать выходом с разной частотой. Например, на разгоне вообще частота с каждым импульсом меняется.
В результате, пока "ждём момент для очередного ШД импульса, опрашивать энкодер все равно нужно".
Напомню: прерываний нет, и единственный вариант "переключить выход ровно через 1мкс" это "выполнить 200 каких-нибудь команд" (на частоте 200МГц как раз так получается, что 200 простых команд занимают 1 мкс".
Опрос входа -- 1 команда. Проверка "менялось ли значение за последнюю микросекунду" -- это ещё штук 5-6 команд.
В итоге, 4 входа с примитивной фильтрацией займут ~ 4*7 == 30 тактов == 30/200 мкс == 3/20 = 0.15мкс.
Ещё может случиться "обмен с HOST'ом" (он, ведь, каждую миллисекунду случаться будет?) Это ещё команды непредвиденные.
В итоге, чтобы всё успеть, нужно делать фарш из опросов входов-выходов, фильтрации, и т.п.
Я вижу как минимум следующие варианты:
1) Оставить как есть и "в первой версии PRU среды" сделать режим, когда программист пишет полную программу (включая while true). Так сказать, отложить решение проблемы. При желании всё равно можно будет и ШД и энкодер в одной программе обслуживать, но придётся в правильные моменты добавлять опрос энкодера.
2) Вынести ожидание из ШД программы, и сделать так, чтобы основной цикл всегда вызывал все действия. Тогда в ШД блоке нужно будет добавить проверку "пора ли уже". Казалось бы, вот решение, но при этом точность упадёт. выход будет не "когда нужно" переключаться, а тогда, когда дойдёт управление до ШД блока. Это может оказаться 50-100 команд, т.е. 0.25...0.5 мкс.
3) При создании PRU программы указывать: "вот этот код нужно вызывать раз в 1мкс, вот этот раз в 20мкс, а у этого расписание плавает и он сам будет говорить когда надо". Вроде, подобное в КДС называется task configuration.
4) Ещё можно подумать над тем, что PRU программы будут не сразу входы изменять, а будут говорить "через какое время вход должен измениться".
В случаях 3 и 4 код "основного цикла" будет формироваться из фрагментов, предоставленных программистом и разбавляться проверками времени.
Возможно, есть ещё варианты.
Последний раз редактировалось Владимир Ситников; 12.10.2016 в 21:08.
Проблемы варианта 1 в том, что "ппограммировать сложнее". Грубо говоря, у многих проблемы с пониманием цикла плк, а тут основной цикл придётся вручную целиком писать. Не домохозяйки, конечно собрались, но все же.
В варианте 2 будет рваный ритм. То туда, то сюда в зависимости от того, сколько каждый блок занял. ШД на разгоне и ШД во время основного хода занимает разное время.
Как разновидность 2го, можно всегда дополнять цикл, скажем, до 1 мкс. Выполнили все блоки, обменялись данными с хостом, и, если 1мкс ещё не прошла, то крутим пустой цикл (но с фильтрацией входов). Тут минус в том, что реакция будет привязана к этой самой "длительности цикла"
Последний раз редактировалось Владимир Ситников; 12.10.2016 в 21:52.
Казалось бы, вот решение. Просто указываем "длину мин цикла и радуемся". Но, нет.
На частоте 200кГц (нормальная такая частота для работы ШД) цикл нужен порядка 2.5мкс (2.5мкс единица, потом ещё столько же ноль).
Даже если умудриться сделать "минц=0.5мкс" (там сложность в том, что ШД на разгоне потребляет как раз примерно 0.5мкс), то всё равно получаемые частоты будут кратны 0.5мкс. Т.е. либо 2.5мкс (5 циклов), либо 3.0мкс (6 циклов), либо 3.5мкс, .... В частотах это:
1/(2*2.5e-6) == 200кГц, 1/(2*3.0e-6) == 167кГц, 1/(2*3.5e-6) = 143кГц, 1/(2*4.0e-6) == 125кГц.
Нехилый такой шаг. Особенно перескок 167кГц -> 200кГц. Вот если бы была возможность менять минц по ходу, то можно было гораздо точнее сделать переход.
Текущая моя ШД программа обеспечивает длительность импульса с точностью ~5-10нс (наносекунд!). И переходить от такой точности к точности "0.5мкс" как-то не по себе.
Хотя, для небольших частот, возможно, вариант с "мин ц порядка нескольких микросекунд" будет достаточным и весьма понятным для типичных инженеров (ну, тех, кто понимает что такое минц=1мс в ПЛК).
В ФБ для ШД надо ограничиться максимальной частотой в 200 кГц. Минимальный полупериод следования импульсов будет 2,5 мкс. Этого времени должно хватить для опроса быстрых входов, к которым подключены энкодеры.
Начну с варианта, когда длина цикла фиксирована.
В конце концов, это не помешает сделать переменную длину цикла, если в пользовательском коде добавить while true...
Ещё вопрос: безопасные состояния, watchdog, вот это всё, нужно?
Если, вдруг, PRU заклинило, то в основной программе должен флаг аварии взводиться? Или перезапуск PRUграммы?
Я склоняюсь к флагу "авария", а перезапуск PRU уже не автоматический, а по запросу основной программы.