Так, после некоторых танцев с бубном, PRU программа начала компилироваться.

В двух словах:
На эмуляторе работает, значит можно переходить к
1) Созданию кнопки, которая создаст КДС.exp
2) Созданию кнопки "новый PRU проект"
3) Сделать PRU1. Надо сначала протестировать подход с PRU0 в железе, а потом уже делать PRU1.



PRU configuration.
Ничего особенного, просто выполняем программу с циклом в 1мкс, и фильтруем 4-ый вход с временем фильтрации 5
Снимок экрана 2016-10-22 в 20.36.37.png

Программа для PRU0.
Напомню суть задачи: при подаче "enable=true", должен запуститься мотор и выключиться тогда, когда энкодер отсчитает заданное количество импульсов.
Снимок экрана 2016-10-22 в 21.32.44.png

Собственно, так и написано. Проверяем энкодер, вызываем блок "управления мотором", выход блока подаём на fast_OUT1.
Эти три действия выполняются раз в микросекунду (согласно PRU configuration выше). В оставшееся время происходит обмен данными и обработка входов.

Если думаете, что в блоке FAST_OUTPUTS будет ассемблер, то там его не найдёте:
Снимок экрана 2016-10-22 в 21.33.43.png

Блок FAST_INPUTS выглядит так же (тоже пустой). Для работы с входами-выходами никакого ассемблера использовать не нужно. Есть несколько "волшебных" ФБ -- их и используем.
Код внутри блоков input/output и т.п. появляется в момент компиляции. Например, для входов там добавляется вызов фильтрации (если она указана в PRU configuration).


Как и планировалось, для передачи данных из-в КДС ассемблер тоже не нужен. Достаточно подставить @Export над теми переменными, которые понадобятся в КДС.

При компиляции получается программа для PRU и КДС библиотека.
В этом примере создался следующий блок обмена данными:
Снимок экрана 2016-10-22 в 21.43.35.png

Для порядка, протестируем программу. Сделаем вид, что цикл ПЛК составляет 1мс, и попробуем пару запусков нашей машины.

Что тут видно:
1) При запуске махины (enable 0 -> 1), она запускает мотор, энкодер начинает крутиться, и всё это добро останавливается при достижении нужного количества импульсов. Я указал runLength = 326, оно так и останавливается

2) Первые 12 мс значение на 4-ом входе дёргается (это прямо в тестовой программе сделана подача морганий на fast in), и фильтрация это верно отрабатывает. Вспомним, что в PRU configuration указана фильтрация 5мс. Как раз после этих 5мс значение in4_filtered переходит в единицу.

Код:
1 ms, in.enable=0, in.runLength=326, out.counter=0, out.position=0, out.zeroDetected=0, out.offset=0, out.state=STOP, in4_raw=0, out.in4_filtered=0, fastOut4=0, encoder=0
2 ms, in.enable=0, in.runLength=326, out.counter=0, out.position=0, out.zeroDetected=0, out.offset=0, out.state=STOP, in4_raw=1, out.in4_filtered=0, fastOut4=0, encoder=0
3 ms, in.enable=0, in.runLength=326, out.counter=0, out.position=0, out.zeroDetected=0, out.offset=0, out.state=STOP, in4_raw=0, out.in4_filtered=0, fastOut4=0, encoder=0
4 ms, in.enable=0, in.runLength=326, out.counter=0, out.position=0, out.zeroDetected=0, out.offset=0, out.state=STOP, in4_raw=1, out.in4_filtered=0, fastOut4=0, encoder=0
5 ms, in.enable=0, in.runLength=326, out.counter=0, out.position=0, out.zeroDetected=0, out.offset=0, out.state=STOP, in4_raw=0, out.in4_filtered=0, fastOut4=0, encoder=0
6 ms, in.enable=1, in.runLength=326, out.counter=100, out.position=100, out.zeroDetected=0, out.offset=0, out.state=STOP, in4_raw=1, out.in4_filtered=0, fastOut4=0, encoder=101
7 ms, in.enable=1, in.runLength=326, out.counter=200, out.position=200, out.zeroDetected=0, out.offset=99, out.state=MOVING, in4_raw=0, out.in4_filtered=0, fastOut4=1, encoder=201
8 ms, in.enable=1, in.runLength=326, out.counter=300, out.position=300, out.zeroDetected=0, out.offset=199, out.state=MOVING, in4_raw=1, out.in4_filtered=0, fastOut4=1, encoder=301
9 ms, in.enable=1, in.runLength=326, out.counter=400, out.position=400, out.zeroDetected=0, out.offset=299, out.state=MOVING, in4_raw=0, out.in4_filtered=0, fastOut4=1, encoder=401
10 ms, in.enable=1, in.runLength=326, out.counter=500, out.position=500, out.zeroDetected=0, out.offset=326, out.state=DONE, in4_raw=1, out.in4_filtered=0, fastOut4=0, encoder=501
11 ms, in.enable=1, in.runLength=326, out.counter=600, out.position=600, out.zeroDetected=0, out.offset=326, out.state=DONE, in4_raw=0, out.in4_filtered=0, fastOut4=0, encoder=601
12 ms, in.enable=1, in.runLength=326, out.counter=700, out.position=700, out.zeroDetected=0, out.offset=326, out.state=DONE, in4_raw=1, out.in4_filtered=0, fastOut4=0, encoder=701
13 ms, in.enable=1, in.runLength=326, out.counter=800, out.position=800, out.zeroDetected=0, out.offset=326, out.state=DONE, in4_raw=1, out.in4_filtered=0, fastOut4=0, encoder=801
14 ms, in.enable=1, in.runLength=326, out.counter=900, out.position=900, out.zeroDetected=0, out.offset=326, out.state=DONE, in4_raw=1, out.in4_filtered=0, fastOut4=0, encoder=901
15 ms, in.enable=1, in.runLength=326, out.counter=1000, out.position=1000, out.zeroDetected=0, out.offset=326, out.state=DONE, in4_raw=1, out.in4_filtered=0, fastOut4=0, encoder=1001
16 ms, in.enable=1, in.runLength=326, out.counter=1100, out.position=1100, out.zeroDetected=0, out.offset=326, out.state=DONE, in4_raw=1, out.in4_filtered=0, fastOut4=0, encoder=1101
17 ms, in.enable=1, in.runLength=326, out.counter=1200, out.position=1200, out.zeroDetected=0, out.offset=326, out.state=DONE, in4_raw=1, out.in4_filtered=1, fastOut4=0, encoder=1201
18 ms, in.enable=1, in.runLength=326, out.counter=1300, out.position=1300, out.zeroDetected=0, out.offset=326, out.state=DONE, in4_raw=1, out.in4_filtered=1, fastOut4=0, encoder=1301
19 ms, in.enable=0, in.runLength=326, out.counter=1301, out.position=1301, out.zeroDetected=0, out.offset=326, out.state=DONE, in4_raw=1, out.in4_filtered=1, fastOut4=0, encoder=1301
20 ms, in.enable=0, in.runLength=326, out.counter=1301, out.position=1301, out.zeroDetected=0, out.offset=0, out.state=STOP, in4_raw=1, out.in4_filtered=1, fastOut4=0, encoder=1301
21 ms, in.enable=0, in.runLength=326, out.counter=1301, out.position=1301, out.zeroDetected=0, out.offset=0, out.state=STOP, in4_raw=1, out.in4_filtered=1, fastOut4=0, encoder=1301
22 ms, in.enable=1, in.runLength=326, out.counter=1401, out.position=1401, out.zeroDetected=0, out.offset=0, out.state=STOP, in4_raw=1, out.in4_filtered=1, fastOut4=0, encoder=1402
23 ms, in.enable=1, in.runLength=326, out.counter=1501, out.position=1501, out.zeroDetected=0, out.offset=99, out.state=MOVING, in4_raw=1, out.in4_filtered=1, fastOut4=1, encoder=1502
24 ms, in.enable=1, in.runLength=326, out.counter=1601, out.position=1601, out.zeroDetected=0, out.offset=199, out.state=MOVING, in4_raw=1, out.in4_filtered=1, fastOut4=1, encoder=1602
25 ms, in.enable=1, in.runLength=326, out.counter=1701, out.position=1701, out.zeroDetected=0, out.offset=299, out.state=MOVING, in4_raw=1, out.in4_filtered=1, fastOut4=1, encoder=1702
26 ms, in.enable=1, in.runLength=326, out.counter=1801, out.position=1801, out.zeroDetected=0, out.offset=326, out.state=DONE, in4_raw=1, out.in4_filtered=1, fastOut4=0, encoder=1802
27 ms, in.enable=1, in.runLength=326, out.counter=1901, out.position=1901, out.zeroDetected=0, out.offset=326, out.state=DONE, in4_raw=1, out.in4_filtered=1, fastOut4=0, encoder=1902
28 ms, in.enable=1, in.runLength=326, out.counter=2001, out.position=2001, out.zeroDetected=0, out.offset=326, out.state=DONE, in4_raw=1, out.in4_filtered=1, fastOut4=0, encoder=2002

Из забавного, блок для фильтрации входов получился гораздо больше, чем я ожидал изначально:
Снимок экрана 2016-10-22 в 22.01.48.png
Работает, и ладно. Надо будет -- соптимизируем или сделаем другую реализацию.

Давным-давно, Yegor предложил сделать возможность использования ФБ без объявления в переменных. Например, для одноразовых RTRIG это в самый раз.
Эта штука пригодилась.

Например, ФБ для обработки входов (с фильтрацией) создаётся таким образом:
Снимок экрана 2016-10-22 в 22.13.17.png
PRU_DEBOUNCE не объявляется, и не захламляет "область объявления переменных".

Аналогично, в конце кода ABZ энкодера лаконично располагаем RTRIG и радуемся:
Снимок экрана 2016-10-22 в 22.22.20.png