Автор оригинала: Doug Brown
Пару лет назад я слишком увлёкся разбором проблем с клонами Altera USB Blaster. Пока писал тот пост, я наткнулся на несколько очень раздражающих плавающих проблем с jtagd под Linux, и разобраться в них так и не смог. Вот что я тогда писал:
Ещё на одном из компьютеров я столкнулся с очень странной проблемой в Quartus Programmer 18.1 под Linux, никак не связанной с остальными. В захвате Wireshark было видно, что исходящий USB-трафик приходит уже испорченным, ещё до того, как в дело вступают FT245 или CPLD. Это касалось всех моих программаторов, а не только тех, что собраны на CPLD и FT245.
Иногда я всё ещё вижу долгую задержку (около 30 секунд) при первой JTAG-операции под Linux после подключения любого из моих USB Blaster на CPLD. Случается это не каждый раз, но когда случается, похоже, что jtagd зависает в ожидании байта, который так и не приходит. Он отваливается по таймауту и пробует снова, после чего всё работает нормально.
Я тогда и так вымотался со всеми остальными бедами USB Blaster, так что копать дальше эти мелкие, но назойливые проблемы мне совсем расхотелось, и я их бросил. До сих пор. С ИИ такие маленькие загадки можно закрывать, не тратя на расследование кучу времени. Поверьте, отладка бывает захватывающей задачей, но диагностировать плавающие проблемы совсем не весело.
Я скормил обе проблемы Claude Opus 5.5. Он охотно взялся за реверс-инжиниринг jtagd и без особого труда нашёл обе причины. В какой-то момент, пока он исследовал и проверял первый баг, он начал упираться в защитные ограничения по кибербезопасности. Но я заметил, что Opus 5.5 чуть лучше прежних версий справляется с такими ситуациями: пробует слегка другой подход, когда срабатывает ограничение, и даже даёт мне шанс переформулировать запрос. Раньше меня в таких случаях сразу понижало до Opus 4.8, а тот потом мог и вовсе завершить сессию, наткнувшись на похожее ограничение. Это очень приятное улучшение.
В общем, я решил коротко поделиться тем, что в итоге нашлось, и заодно дать ссылку на инструмент, которым можно пропатчить свой jtagd, если эти баги вас тоже сводили с ума. Сначала ссылка на патчер: https://github.com/dougg3/altera-jtagd-linux-fixes
Баг первый: забытая переменная в конструкторе
Первый баг, который портит USB-трафик, оказался неинициализированной переменной в конструкторе JTAG_SERVER_USB_BLASTER. Конструктор обнуляет целую пачку соседних переменных, а эту, видимо, случайно забыли. Если в ней случайно оказывается значение больше 0, в исходящие USB-данные вставляются дополнительные данные, предназначенные только для более нового USB-Blaster II от Altera, и это сбивает с толку старые USB Blaster. Это прекрасно объясняет порчу данных, о которой я писал в прошлом посте. В отличие от языковой модели, у меня в голове не было достаточно контекста, чтобы связать «испорченные данные» с протоколом нового USB Blaster. Все клоны, которые я видел, говорят на протоколе оригинального USB Blaster, так что затронуты они все. В итоге они зависают на 30 секунд, после чего выдают ошибку Unable to read device chain - JTAG chain broken.
Похоже, это происходит, только если отключить и снова подключить программатор, не останавливая jtagd: первая выделенная область памяти, как правило, оказывается обнулённой. При каждом горячем подключении создаётся новый объект JTAG_SERVER_USB_BLASTER, а куски кучи используются повторно. В 2024 году я много работал через виртуальную машину с Windows, так что, скорее всего, действительно часто переподключал устройство. Может, мало кто с этим сталкивается, но меня это бесило страшно.
Баг второй: порядок команд для FT245
Второй баг, с задержкой в 30 секунд, хитрее. Похоже, он зависит от того, какой чип серии FTDI FT245 стоит в вашем программаторе, а может, даже от того, как он подключён к компьютеру. Суть в том, что при первом открытии чипа jtagd отправляет FT245 такие команды, именно в этом порядке:
Reset
Purge TX
Purge RX
Set Latency Timer
Похоже, эта последовательность заставляет некоторые клоны примерно на 250 мс перестать принимать входящие данные. Обычно в этом не было бы большой беды, но jtagd сразу же начинает опрашивать устройство, чтобы выяснить, что подключено к JTAG-цепочке, и застревает на 30 секунд в ожидании ответа. Разные мои клоны реагируют на эту последовательность каждый по-своему (одних она задевает, других нет), хотя это всего лишь команды FT245. Может, у разных клонов разные ревизии чипа? Знаю одно: если переставить команды так, чтобы Set Latency Timer шла первой, проблема полностью исчезает.
Что в итоге
Обе проблемы живут в jtagd как минимум с Quartus 18.1 и никуда не делись в Quartus 25.1. Altera, если вы читаете этот пост, пожалуйста, подумайте о том, чтобы исправить хотя бы первый баг! Насчёт второго я, честно говоря, не уверен, баг ли это вообще или просто в некоторых клонах стоят чипы, которые ведут себя не совсем так, как в официальном устройстве. Но задержка в 300 мс после Set Latency Timer, вероятно, тоже решила бы проблему.
С исправлениями обеих проблем все клоны USB Blaster, до которых я могу дотянуться, теперь работают отлично (конечно, после моих прежних исправлений прошивки и CPLD). Я даже взял USB-хаб, совместимый с uhubctl, чтобы автоматически передёргивать питание всех моих клонов. Так у меня получился цикл обратной связи для серии стресс-тестов, которыми я как следует проверил, что исправление действительно работает.
Оглядываясь назад, первый баг я вполне мог (и должен был) найти сам. Похоже, valgrind просто преподнёс бы мне его на блюдечке. Немного досадно, что я не догадался его попробовать. Тогда я по уши ушёл в расследование с rr, пытаясь воспроизвести баг, но rr не работал на моей основной машине для разработки. А когда я поставил Quartus на старый компьютер, с которым rr был совместим, воспроизвести проблему уже не получалось. К тому моменту мне всё это осточертело, и я сдался. В своё оправдание скажу: этот баг сидит в jtagd как минимум 8 лет и почти никем не был замечен, если не считать одного короткого сообщения на форуме Altera, где человек понял, что происходит что-то странное, и его в общем-то проигнорировали.
Мой блог не превращается целиком в витрину «смотрите, что ИИ для меня сделал». Я хочу поделиться с сообществом полезным обходным решением и, надеюсь, привлечь внимание Altera, чтобы она наконец исправила давний баг. А ещё, может, я просто чокнутый, но чинить надоедливые баги в закрытом софте с помощью ИИ довольно весело. Особенно когда это старый хвост из прошлого, который я считал непрактичным закрывать. Кстати, у этого поста будет продолжение: в нём я отвечу на последний оставшийся без ответа вопрос из моих прошлых раскопок с USB Blaster.
![[Перевод] Почему клоны USB Blaster под Linux зависают на 30 секунд: две находки в jtagd из Quartus](https://habrastorage.org/extt/3c/0b/59/3c0b5990a420f0268a61ded347b79380.jpg)
Комментарии 0