Category: работа

Category was added automatically. Read all entries about "работа".

QuatCore

Так ли страшно 0,99969 вместо 1?

В размышлениях о DMA, о возможных последствиях "смешивания" старых и новых значений при выдаче целевой информации, опять выполз вопрос:

насколько это плохо/некрасиво, если мы вместо кватерниона малого поворота 1+(φx/2)i+(φy/2)j+(φz/2)k возьмём 0,999969+(φx/2)i+(φy/2)j+(φz/2)k? То есть, вместо 1 будет 1-2-15, максимальное число, которое можно представить в формате Q1.15 (в целых числах это 32767).

И внезапно прихожу к выводу: Ещё лучше взять 0,9999084 (в целых числах 32765)

Collapse )


Убедил? :)

Poll #2112344 Кватернион малого поворота

Какое приближение вы бы взяли?

1+(a/2)i+(b/2)j+(c/2)k
1(33.3%)
-1-(a/2)i-(b/2)j-(c/2)k
0(0.0%)
32767/32768+(a/2)i+(b/2)j+(c/2)k
2(66.7%)
32765/32768+(a/2)i+(b/2)j+(c/2)k
0(0.0%)


PS. Впрочем, почти завершив это "исследование", я вспомнил, почему в своё время так настаивал на -1 вместо 0,99969, но это заслуживает ещё одной небольшой главки в "ликбезе по кватернионам"...
QuatCore

"МКО через UART" в железе - 2

Продолжим проверять этот модулёк.


Collapse )

Выглядит неплохо! Есть, что улучшить:
- пусть и на индивидуальную команду "Синхронизация (с СД)" отвечает правильно, подтверждая, что команда пришла,
- если "пообещать" длинное сообщение (например, 32 слова), но не передать его целиком - контроллер будет до посинения ждать, пока нужное число слов данных будет передано, здесь никакого таймаута пока не предусмотрено. Когда "ручками" с ним общаешься - неприятно, что-то немного не то вбил - и вдруг ни ответа ни привета, и поди разберись, что с ним. На деле, не так уж это и страшно, пошлёшь запрос повторно, он "доберёт" сколько надо слов, уйдёт в sIdle по несовпадению CRC, и дело с концом. Но вообще с таймаутом правильнее, ГОСТ предписывает проверять временнЫе параметры и при отступлении от норм тихо ругаться.
- у меня были предусмотрены команды "дамп памяти" и "передать изображение", там маленькими кусочками передаётся содержимое памяти, "внутренней" и "внешней" соответственно. Можно было бы это дело на контроллер "взвалить", чтоб делал без участия процессора. Но пока было лень...

А сейчас, пожалуй, надо взяться за DMA.
QuatCore

"Ошибка на единицу" при передаче CRC

В прошлый раз обнаружили нехорошую вещь: при передаче данных от нашего устройства, CRC начинает работать одним словом раньше, чем надо, и результат своей работы отсылает одним словом раньше.

Пора уже это исправить, чего-то задолбался я немного.

Collapse )
Действительно обошлись "малой кровью", не добавив ни одного ЛЭ.

Вот, кажется, и всё, протокол информационного обмена исполнен в полном объёме, на "жёсткой логике", без обращения к процессору.

Осталось всё это "в железе" посмотреть, заодно написав "программу рабочего места". Потом, если всё нормально, написать примитивный DMA. Дальше ожидаю раунд борьбы с фиттером, который может завалить трассировку всего проекта целиком, и второй раунд, когда в кои-то веки придётся все части программы свести в единое целое, так что и ROM и RAM подрастут, и ширина адресных шин вместе с ними.

Тяжело идёт, и уже как-то "через силу". Кажется, что всё творческое уже позади, а сейчас надо просто стиснуть зубы и довести хреновину до кондиции...
QuatCore

16-битный полудуплексный UART, тестируем

В прошлый раз мы его вроде как написали, теперь пора проверить. Попробуем взять "с нахрапу" и сразу присоединим его к модулю CRC, вообще не задумываясь (вытащили 8-битный модуль, поставили 16-битный, только ширину шины поменяли):


Синтезируется в 68 ЛЭ, при 48 регистрах - очень "плотно" :) Предельная частота 68,97 МГц, меня устраивает (у меня 25 МГц пока).

Далее, для этого модуля "UART+CRC" создаём схемотехнический символ и кидаем две штуки на "тестовую схему":


(проверяем, что один как надо передаст, а второй корректно примет)

Запускаем синтез - и получаем очень нехорошее предупреждение:


Collapse )

Как будто бы работает. Теперь ещё протокольный контроллер МКО (к которому вместо МКО пока что прикрутили UART) доработать, чтобы CRC проверял (давал управляющие сигналы на модуль HalfDuplexUART16bitwCRC) - и пора бы уже на реальное железо перебираться, смотреть, что там получается. А потом ещё написать простенький DMA, чтобы протокольный контроллер и процессор одну память делили на двоих (с приоритетом процессора) - и золотой ключик у меня в кармане.

Уже ведь можно в РКК Энергию попасть, у меня QR-код есть и справка с круглой печатью от врача, и треугольной и прямоугольной печатями из регистратуры :)
QuatCore

О выборе самого подходящего CRC-кода

Каюсь, что в вопросе выбора полинома для CRC я исходил из "моды": взял попросту самый популярный из CRC-16, под названием CCITT, 0x1021. Другие названия (в зависимости от выбора начального значения, инверсии битов на входе и на выходе): AUG-CCITT, GENIBUS, MCRF4XX, RIELLO, TMS37157, CRC-A, KERMIT, X-25 и X-MODEM, и это только то, что знает crccalc.com.

Сейчас решил всё-таки поискать, а в чём же, собственно, разница, и какой было бы лучше всего выбрать мне для поставленной задачи: МКО (Mil-Std 1553) со своими проверками чётности, от 1 до 32 слов данных (каждое слово 16 бит), ошибки предполагаются случайными и довольно редкими (вероятность 10-7).

Бешеную активность в этом направлении (исследование CRC) развил Филипп Купман (https://users.ece.cmu.edu/~koopman/crc/). Информации очень много, она "утрамбована", вроде бы наконец разобрался, что с ней делать.

Основная идея: выбрать такой код, который для твоего размера сообщения даст наибольшую возможную дистанцию Хэмминга, т.е позволит ГАРАНТИРОВАННО обнаружить как можно больше неправильных битов.

Collapse )

В общем, мне повезло: ровно в моём случае этот полином CCITT действительно хорошо подходит. Для более коротких сообщений или для более длинных лучше подошли бы другие. А здесь мы имеем гарантированное обнаружение до 3 ошибок, а также любого их нечётного количества, и вероятность 99,997% обнаружить 4 ошибки.
QuatCore

CRC и полудуплексный UART

Апологеты "модели OSI" скажут, что генерация и проверка CRC (Cyclic Redundancy Codes) - это уже канальный уровень, а не физический, и мешать их между собой не стоит. Дескать, физический уровень - это когда говоришь "передай вот этот байт" - и самому передатчику должно быть пофиг, что это за байт такой, частью чего он является. А всей остальной системе должно быть пофиг, как именно этот байт передаётся - хоть оптикой, хоть медяшкой, хоть по радио.

Но если уж я заранее знаю, что у меня будет на физическом уровне (поначалу, для "обкатки", RS485, позже - МКО, он же ГОСТ Р 52070-2003, он же Mil-Std 1553), и у меня была возможность, исходя из этого, придумать конкретный вид применяемого CRC, то более "тесное" проникновение одного в другое позволяет заметно упростить проект.

Смысл в том, что наиболее простая реализация CRC - когда мы подаём по одному биту за раз, поэтому если уж во время передачи данных они всё равно должны "сериализоваться" - то почему бы этот поток бит и не пустить на CRC. Да и мультиплексировать один бит (поставить ли его из "обычного" сдвигового регистра, или из CRC) получается не так затратно, чем 8-битную шину, а тем более 16-битную.

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

Для начала раскомментируем выражение isDataBit:
assign isDataBit = (State[3] | State[0])&(~isStopState)&ce;	


И ещё разок смотрим работу передатчика:


Collapse )

Ладно, начало неплохое, при передаче CRC ведёт себя прилично. Воспользовались "недокументированным оператором верилога" &~& и ужаснулись возможностям по обфускации кода, которые он открывает :)

Теперь осталось посмотреть работу CRC на приёме, а потом сделать "схему", работающую и на приём, и на передачу.
QuatCore

"МКО через UART", часть 8 - CRC

Наличие контрольной суммы CRC (Cyclic Redundancy Code) также не является частью ГОСТ 52070-2003, это дополнительное требование конкретно в нашем протоколе информационного обмена.

На самом деле, можно было и какую-нибудь другую контрольную сумму впихнуть, но мне захотелось CRC, именно исходя из лёгкости его реализации на ПЛИС. Как ни странно, при аппаратной реализации он куда приятнее, чем какая-нибудь "сумма слов по модулю, близкому к 65536" (Fletcher, Adler), или "сумма слов с битом переноса, прибавляемым к младшему разряду" (контрольная сумма заголовка IPv4), и даже самой простой 16-битной контрольной сумме (когда все слова складываются, и берутся только 16 бит результата) CRC даст фору, оказываясь вдвое компактнее!

Впрочем, эти преимущества ещё надо суметь реализовать, для чего генерацию и проверку CRC засунуть в непосредственной близости от приёмопередатчика, где биты будут идти один за другим, притом в правильном порядке...

Для протокола я нарисовал такую хреновину:


Collapse )

Продолжение следует... Вообще, мне очень хочется сделать совмещённый модуль на приём и передачу, специально для RS485. Когда-то давно я такое делал, но маленьким был, надо попробовать ещё разок, и теперь на 16 бит и с "заделом" под CRC.
QuatCore

"МКО через UART", часть 7 1/2 - проверка заголовков ПОПРОЩЕ

Что-то я не доволен тем, что получилось в прошлый раз. С одной стороны, работает, и есть определённая "гордость" в том, что мы на ходу, весьма малой кровью перевели 5-битный подадрес в 16-битный код Рида-Мюллера. С другой - радость омрачил квартус, выдав странный баг. Потом он ушёл, но "осадочек остался".
И ещё одна возможная проблема: в той логике сопоставления заголовков массивов подадресам содержался изъян в лице сообщения "СЫРЫЕ ДАННЫЕ ДЛЯ СТЕРЕОРЕЖИМА", которые один прибор передаёт другому. Поскольку разные подадреса на приём и на передачу, то и заголовки получались разными, а надо было выбрать какой-то один. И я, не сильно задумываясь, вписал тот, что соответствует подадресу при передаче. И тогда такая "жёсткая" логика его бы забраковала, проверяя подадрес приёма. Вообще, не поздно это дело поменять, там вообще в протоколе было обозначено, что сообщение содержит "наши служебные данные", которые мы вправе поменять, но обязательно поставим всех в известность.
Ну и в целом у меня осталось впечатление, что можно было сделать гораздо проще, если свою гордость пока что отодвинуть и просто свериться с содержимым оперативной памяти.

Ведь у нас всё содержимое памяти автоматически инициализируется нужными нам значениями при включении ПЛИС, почему бы этим не воспользоваться! В тех "сегментах", что мы отвели на ПРИЁМ, самым первым значением положим ПРАВИЛЬНЫЙ заголовок соответствующего массива.

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

Collapse )

Любопытно! На этапе синтеза мы действительно сэкономили аж 4 ЛЭ, но потом приходит фиттер и впихивает лишних 16 ЛЭ, делая эту реализацию ещё толще, чем была! Конечно, фиттер вещь непредсказуемая, сегодня впихал, а завтра, в общей схеме (с процессором, DMA, видеопроцессором и пр.) - обойдётся, но здесь я могу его понять, схема стала более связной, чем была. Раньше приёмник и передатчик почти что жили своей жизнью, можно было их разнести по разные стороны, теперь же между ними вставился 16-битный компаратор, а эти ПЛИС, 5576ХС4Т (функциональный аналог Flex10k) имеют недостаточно мощные интерконнекторы, толстые шины ему тяжело даются.

Так что придётся оставить два варианта, а там уж выбрать по обстоятельствам. Зато буриданов осёл во мне доволен: рассмотрели оба варианта и всё съели!

На очереди по-прежнему генерация и проверка CRC. Ох, подлянка меня ждёт!
QuatCore

"МКО через UART", часть 7, проверка заголовков массивов

В части 5 мы выполнили проверку командного слова, на соответствие полей "подадрес" и "приём/передача" - далеко не все их комбинации разрешены, и если пришло что-то не то, выставляем признак "ошибка в сообщении", слова данных не посылаем, а принимаемые слова данных никуда не записываем. На самом деле ещё зачастую проверяют, чтобы количество слов данных на приём/передачу соответствовало заранее оговоренному для каждого подадреса. Но мы пока что прописали в протоколе, что запрашивать можно любое количество. Знаешь, что на дальней дистанции с хорошей точностью только "активные" углы и дальность - запрашиваешь поменьше слов, только с ними. Подошли поближе и "появился" кватернион взаимной ориентации - запрашиваешь ещё на 4 слова больше. А если решили-таки выполнить фильтр Калмана по всей науке и нужна ещё ковариационная матрица шума измерений (см. прокрустово ложе 16 бит) - запрашиваешь ВСЕ СКОЛЬКО ЕСТЬ! В микросхеме 1895ВА2Т можно для каждого подадреса, отдельно на приём и на передачу, задать все возможные количества слов, которые допустимо передавать, ещё и отдельно на групповые сообщения и отдельно на "индивидуальные", хотя ГОСТ просит интерпретировать их одинаково.

Далее, если мы принимаем информацию (полётное задание, конфигурация мишени и пр.), надо проверить первое слово данных. Это уже не ГОСТ 52070-2003, а конкретно наш "протокол информационного обмена", где представители РКК Энергия решили ещё подстраховаться и предварять каждый массив данных "заголовком", уникальным для каждого подадреса.

Потом уже я, чтобы выпендриться, ввёл здесь коды Рида-Мюллера, позволяющие выбрать 32 различных 16-битных слова (каждое - на свой подадрес) таким образом, что они будут отличаться друг от друга МИНИМУМ на 8 бит!

Collapse )

Что ж, проверка работает. Квартус подложил очередную свинью, точнее, Шрёдинбага (или это Гейзенбаг?), не знаю, как именно, но сейчас этой проблемы нет.

На самом деле, я думал и о более простом методе проверки заголовков, где мы не пытаемся самостоятельно генерировать коды Рида-Мюллера, а просто сверяться с ячейкой памяти. Может, если будет охота, опробую и его.

А тем временем протокол информационного обмена практически реализован. Остаётся проверка и генерация CRC, и, может быть, автоматическая (без участия процессора) выдача дампа памяти и изображения...
QuatCore

"МКО через UART", часть 5, проверка командного слова

Контроллер оконечного устройства МКО у нас в неплохой степени готовности, но пока он слишком доверчив, позволяя записать данные на любой подадрес и прочитать данные с любого подадреса. Пока я ковырялся с процессором, считал "доверчивость" нормальной чертой - на прописанные команды мы откликаемся как надо, а на "недокументированные" может отреагировать неким интересным сочетанием разных функций, потому как это наша внутренняя память, а если мы ей не доверяем, то должны будем ввести коды коррекции ошибок, на одних только "недокументированных командах" всё равно далеко не уйдёшь! (их не так-то много)

Но в информационном обмене вероятность схватить ошибочные слова гораздо выше, тут нужно быть параноиком до мозга костей!

Collapse )

Я доволен, провели практически полное покрытие кода - всё работает. Осталось ещё с командами управления разобраться, это уже завтра.