Инструменты пользователя

Инструменты сайта


doc:doclist:jtagisc

Немного о Jtag, ISC и 5576РС1У

Подвернулась небольшая подработка по программированию микросхемы конфигурирования ПЛИС 5576РС1У. Здесь собраны тезисы того, что удалось узнать при решении данной задачи.

Про 5576РС1У

Микросхема 5576РС1У - это микросхема флеш памяти, которая выдает сохраненные в ней данные через последовательный интерфейс в микросхему ПЛИС, тем самым ее конфигурируя. Диаграммы режима PassivSerial уже были представлены тут - Конфигурация в режиме Passive Serial

5576РС1У является аналогом микросхемы EPC4QC100N от Altera, поэтому алгоритм работы с 5576РС1У можно найти в BSDL файле для EPC4QC100N (epc4q100_1532.bsd) и в векторном файле test_epc.svf.

  • BSDL файл - это файл описания внутренних регистров микросхемы для реализации периферийного сканирования (Boundary Scan Description Language).
  • SVF файл - это файл описания воздействий на микросхему, которым проверяется ее функционал (Serial Vector Format ).

Доступ к внутренним регистрам микросхемы и подача тестовых воздействий происходят по интерфейсу JTAG. Под него эти файлы и написаны.

BSDL файл

В BSDL файле нам интересен в первую очередь раздел с описанием регистров и инструкций. Вот содержимое раздела:

-- *********************************************************************
-- *                   INSTRUCTIONS AND REGISTER ACCESS                *
-- *********************************************************************

attribute INSTRUCTION_LENGTH of EPC4Q100 : entity is 10;
attribute INSTRUCTION_OPCODE of EPC4Q100 : entity is
  "BYPASS            (1111111111), "&
  "EXTEST            (0000000000), "&
  "SAMPLE            (0001010101), "&
  "IDCODE            (0001011001), "&
  "USERCODE          (0001111001), "&
-- Following 10 instructions are IEEE 1532 instructions
  "ISC_ENABLE	     (0001000100), "&
  "ISC_DISABLE	     (0001001010), "&
  "ISC_PROGRAM	     (0110010110), "&
  "ISC_ERASE	     (0110010010), "&
  "ISC_ADDRESS_SHIFT (0100001110), "&
  "ISC_READ_INFO     (0001000010), "&
  "ISC_READ	     (0110100110), "&
  "ISC_NOOP	     (0011111111), "&
  "ISC_STAT	     (0000111110)";

По данному отрывку мы узнаем перечень доступных инструкций и то, что все они являются 10-битными. Инструкции с префиксом ISC относятся к интерфейсу In-System Configuring, который регламентируется стандартом IEEE 1532. Который является в свою очередь расширением стандарта JTAG (IEEE 1149.1 Standard Test Access Port and Boundary-Scan Architecture - Wikipedia).

Ранее каждый производитель предлагал свои способы прошить то или иное устройство, что затрудняло работу с микросхемами разных производителей (например в составе одного устройства). Требовалось изучение каждого отдельного способа программирования и необходим был свой программатор. Чтобы это дело упростить придумали отдельный стандарт на внутрисхемное конфигурирование (ISC) и теперь каждый производитель внутри микросхемы реализует поддержку команд данного стандарта.

Найти в сети описание стандарта ISC (IEEE 1532) не удалось, поэтому остается только предположить назначение инструкций исходя из их названия. Некоторые уточнения:

  • IDCODE - Позволяет считать идентификатор микросхемы, в данном случае это 0x0100A0DD.
  • USERCODE - Позволяет записать / считать ID который можно использовать в своих целях. Например версия прошивки.
  • ISC_ENABLE / ISC_DISABLE - вход в режим ISC и выход.
  • ISC_NOOP - вероятно No Operation.
  • ISC_STAT - статус исполнения инструкции.
  • ISC_ADDRESS_SHIFT - установка текущего адреса перед ISC_READ / ISC_PROGRAM / ISC_ERASE.
  • ISC_PROGRAM / ISC_READ - вход в режимы программирования / чтения. Адрес инкрементируется автоматически с каждым новым словом данных
  • ISC_ERASE - стирание сектора данных. Стертые данные соответствуют логическим 1-цам, соответственно при программировании записываются только нули. Стирается сектор целиком.

Далее в файле представлены доступные регистры:

attribute REGISTER_ACCESS of EPC4Q100 : entity is
  "DEVICE_ID        (IDCODE), "&
-- Following 7 registers are IEEE 1532 registers
  "ISC_Default[2]	(ISC_DISABLE, ISC_NOOP)," &
  "ISC_PData[16]	(ISC_PROGRAM)," &
  "ISC_RData[18]	(ISC_READ, ISC_STAT)," &
  "ISC_Sector[23]	(ISC_ERASE)," &
  "ISC_Address[23]	(ISC_ADDRESS_SHIFT)," &
  "ISC_Config[2]	(ISC_ENABLE)," &
  "ISC_Info[5]		(ISC_READ_INFO)";

По этому описанию мы узнаем разрядность внутренних регистров. Чтобы записать или считать тот или иной регистр необходимо сначала подать инструкцию, а затем считать или записать значение в данный регистр. Грубо говоря, записывая по jtag инструкцию мы выбираем внутренний регистр с которым дальше будем обмениваться данными.

Основные интересующие нас регистры:

  • ISC_PData - 16-битный регистр в который записываются слова для записи в память. Слова пишутся по одному, необходимо выждать лишь требуемую задержку.
  • ISC_RData - 18-битный регистр чтения значений из памяти. Используется для верификации данных, которые были запрограммированы. Два младших бита являются значениями CRC для 16-битного слова.
  • ISC_Sector - 23-битный адрес сектора, который будет стерт.
  • ISC_Address - 23-битный адрес с которого будут читаться слова или куда слова будут программироваться.

В этом же файле BDSL описано как применять эти инструкции и регистры. Возьмем к примеру функцию программирования памяти:

"FLOW_PROGRAM (array) " &
    "INITIALIZE " &
      "(ISC_ADDRESS_SHIFT 23:000000 WAIT TCK 1)" &
      "(ISC_PROGRAM       16:?      WAIT 3.0e-4 )" &
    "REPEAT 249999 " &
      "(ISC_PROGRAM       16:?      WAIT 3.0e-4 )";

Я трактую это следующим образом:

  • "ISC_ADDRESS_SHIFT 23:000000" - Подать инструкцию ISC_ADDRESS_SHIFT и 23-битный адрес равный 0x000000.
    • "WAIT TCK 1" - После этого следует подать один тактовый сигнал на вывод TCK интерфейса JTAG.
  • "ISC_PROGRAM 16:?" - Записать инструкцию ISC_PROGRAM и 16-ное значение данных. (? - означает не конкретное значение как в случае с адресом, а значение из массива array).
    • "WAIT 3.0e-4" - выждать задержку 300мкс пока слова программируется.
  • "REPEAT 249999" - повторить все это еще 249999 раз.

В обрывках литературы который выдал поиск в Google встречается различие между задержками "WAIT TCK 1" и "WAIT 3.0e-4". Суть его в том, что когда указано "WAIT TCK 1", то это требование именно подать тактовый сигнал. Т.е. если бы было написано "WAIT TCK 100", то необходимо было бы подать 100 тактовых периодов на вывод TCK интерфейса JTAG. В отличие от этого, задержка "WAIT 3.0e-4" - это всего лишь временной интервал.

В машине состояний JTAG, которую мы рассмотрим дальше, наличие лишнего такта TCK не имеет никакого смысла. Возможно требование к TCK это нечто из расширения ISC, поскольку большинство инструкций ISC в BSDL файле заканчивается так. Поэтому при реализации обмена мы этот такт оставим.

Аналогично расшифровывается чтение памяти, например верификация того, что память стерта:

 "FLOW_BLANK_CHECK " &
    "INITIALIZE" &
      "(ISC_READ                    WAIT TCK 1  16:DFFF*0000, 2:2*0)  "&  
      "(ISC_ADDRESS_SHIFT 23:000000 WAIT TCK 1)" &
      "(ISC_READ	                WAIT TCK 1 18:3FFFE*FFFFF)" &
     "REPEAT 249999 " &
      "(ISC_READ                    WAIT TCK 1 18:3FFFE*FFFFF)," &
  • "ISC_READ WAIT TCK 1" - Подается команда с лишним тактом
    • 16:DFFF*0000, 2:2*0 - Читается 16-битный ответ и еще 2 бита CRC. Используется маска AND 0000, что говорит о том, что чтение служебное (пустое) - данные никак не проверяются.
  • "ISC_ADDRESS_SHIFT 23:000000 WAIT TCK 1" - Выставляется начальный адрес.
  • "ISC_READ WAIT TCK 1" - Запись инструкции чтения.
    • 18:3FFFE*FFFFF - Читается 18-битное слово памяти, которое должно быть равно 3FFFE (стертое значение 0xFFFF с CRC). Маска на считанное значение FFFFF.
  • "REPEAT 249999" - Повторить 249999 раз.

Остальные функции можно посмотреть в самом BSDL файле. Под описанием функций представлены операции, которые выполняются с микросхемой программатором. Каждая операция состоит из нескольких функций. Мы рассмотрели сейчас только функции PROC_PROGRAM(array) и PROC_BLANK_CHECK:

attribute ISC_ACTION of EPC4Q100 : entity is
  "VERIFY_IDCODE = (TEST_VERIFY_IDCODE)," &   
  "PROGRAM =       (TEST_VERIFY_IDCODE RECOMMENDED," &
                    "PROC_ENABLE," &
                    "PROC_ERASE," &
                    "PROC_BLANK_CHECK," &  
                    "PROC_PROGRAM(array)," &
                    "PROC_VERIFY(array)," &  
                    "PROC_PROGRAM_DONE," &
	            "PROC_VERIFY(donebit)," &  
                    "PROC_DISABLE)," &
  "VERIFY =        (TEST_VERIFY_IDCODE RECOMMENDED," &
                    "PROC_ENABLE," &
                    "PROC_VERIFY(array)," &
                    "PROC_VERIFY(donebit)," & 
                    "PROC_DISABLE)," &
  "ERASE =         (TEST_VERIFY_IDCODE RECOMMENDED," &
                    "PROC_ENABLE," &
                    "PROC_ERASE," &
                    "PROC_BLANK_CHECK," &  
                    "PROC_DISABLE)," &
 "BLANK_CHECK =    (TEST_VERIFY_IDCODE RECOMMENDED," &  
                    "PROC_ENABLE," &                    
                    "PROC_BLANK_CHECK," &               
                    "PROC_DISABLE)," &                  
 "VERIFY_DONEBIT = (TEST_VERIFY_IDCODE RECOMMENDED," &
                    "PROC_ENABLE," &
                    "PROC_VERIFY(donebit)," & 
                    "PROC_DISABLE)," &
 "PROGRAM_DONE =   (PROC_ENABLE," &
                    "PROC_PROGRAM_DONE," & 
                    "PROC_DISABLE)";

Интерфейс JTAG

Из BSDL файла мы узнали что в 5576РС1У есть внутренние регистры и для доступа к ним есть набор инструкций. Встает вопрос - что с этим делать, куда и как это все подавать? Для этого необходимо рассмотреть машину состояний JTAG и понять как она работает.

В общем-то моя многолетняя фобия перед JTAG оказалась напрасной. Это достаточно простой последовательный интерфейс для записи инструкций и значений во внутренние регистры. Что там дальше делать с этими инструкциями и регистрами решает внутреннее устройство микросхемы. Назначение JTAG осуществить транзакцию, к дальнейшему он уже отношения не имеет.

Основным регистром является регистр BoudaryScan который бывает длиной в сотни бит и позволяет тестировать выводы микросхемы в готовом устройстве. Есть так-же регистр ByPass длиной в один бит, который позволяет пропускать транзакции сквозь микросхему в следующие микросхемы объединенные в одну Jtag цепь (DaisyChain). Бывают всякие специализированные регистры. Например, как мы уже знаем, в 5576РС1У есть регистры ISC через которые происходит программирование микросхемы.

Линии JTAG:

  • TCK - тактовый сигнал, весь "экшн" происходит по возрастающему фронту этого сигнала.
  • TDI - по фронту TCK уровень на данном выводе записывается в текущий сдвиговый регистр внутри микросхемы.
  • TDO - одновременно с защелкиванием бита TDI в сдвиговый регистр, из этого регистра выдвигается бит на вывод TDO.
  • TMS - сигнал перемещения по машине состояний JTAG.
  • TRST - опциональный сигнал сброса подключенного устройства, в микроконтроллерах обычно подключается к выводу Reset.

Про TDI и TDO полагаю понятно, что они подключаются с двух сторон внутреннего сдвигового регистра. Данные от TDI вдвигаются в регистр, а из регистра синхронно данные выдвигаются в линию TDO. Но поскольку регистров внутри устройства может быть несколько, то необходим способ выбора того регистра с которым будут работать линии TDI и TDO. Для этого предназначен автомат состояний и перемещение по этому автомату происходит с помощью сигнала TMS. Сразу стоит сказать, что TDI и TDO подключаются к внутреннему регистру только в состояниях Shift-DR и Shift-IR. Поэтому чтобы записать / считать регистры необходимо в автомате состояний дошагать до Shift-DR или ShiftIR соответственно.

IR - это регистр инструкций. Он один и он выбирает который внутренний регистр будет подключен к линиям TDI и TDO в состоянии Shift-DR. Например записав в IR инструкцию ISC_ADDRESS_SHIFT, а в DR записав значение адреса мы переключим в 5576РС1У текущий активный адрес. Посмотрим как это осуществить по машине состояний JTAG.

(Картинка из шикарного видео, где наглядно расказывается про Jtag - YouTube - TechSharpen, "JTAG TAP Controller Tutorial")

При работе по JTAG обычно выбирают "парковочное" состояние - это то состояние в которое возвращается автомат между транзакциями. Обычно это либо состояние Idle, либо Select-DR. Select-DR подходит, потому что из него можно попасть и в ветвь DR и в ветвь IR. Но состояние Idle лучше тем, что в нем можно подать импульс TCK при TMS=0, который ничего не изменит, т.к. автомат останется в том-же Idle. А нам как раз необходим один лишний такт TCK для реализации выражения "WAIT TCK 1" из файла BSDL. Состояние Reset не подходит под парковочное, потому что при выходе в reset к линиям TDI и TDO подключается регистр по умолчанию, а это обычно ByPass или BoundaryScan.

Выставление внутреннего адреса происходит в два этапа - запись инструкции ISC_ADDRESS_SHIFT в IR и запись самого адреса через регистр DR. Запись инструкции по автомату состояний происходит так:

//допустим мы находимся в состоянии idle, тогда подаем
TMS   Idle
1:    -> Select-DR
1:    -> Select-IR              // Дошли до ветки инструкций
0:    -> Caprute-IR
0:    -> Shift-IR               // Перешли в состояние сдвига бит IR
0:    TDI[0] -> reg ->TD0[0]    // Начинаем побитно сдвигать инструкцию в регистр IR
0:    ...                       // ISC_ADDRESS_SHIFT (0100001110), 10 bit
0:    TDI[9] -> reg ->TDO[9]    // На TDO выдвигаются биты предыдущего значения IR
1:    -> Exit-IR
1:    -> Update-IR              // Значение сдвигового регистра записалось в регистр инструкций. 
                                // Теперь к линиям TDI и TDO подключен регистр ISC_Address[23]
0:    -> Idle                   // Возвращаемся в Idle
0:    -> Idle                   // В Idle делаем дополнительный такт TCK - "WAIT TCK 1"

two beer…

Диаграмма программирования слова (кликабельно):

  • Красными линиями на фронтах TCK выделены служебные такты на перемещение по машине состояний JTAG.
  • Синими линиями выделены биты данных задвигаемые через линию TDI во внутренние регистры.
  • Сдвиг последнего бита совмещен с переходом на состояние Exit1, поэтому линия покрашена разноцветно.
  • Фиолетовым цветом выделен служебный такт "WAIT TCK 1".

SVF файл

doc/doclist/jtagisc.txt · Последние изменения: 2020/02/25 19:25 — vasco