Перейти к содержанию
    

Загрузка прошивки из STM32 через JTAG в ПЛИС

Странного хочется:

хочу облегчить процедуру обновления прошивок на железке, и вижу такой путь: у меня есть на плате STM32 с MicroSD карточкой, что соответственно позволяет хранить прошивку для ПЛИС (циклон2) и есть время при старте на прошивку (2секунды).

Подозреваю, что я не первый озадачился таким путем, но вот что-то не нашел описаний подобного.

Интересно:

- протокол

- особенности реализации на STM32, подводные камни

- надо ли как-то переформатировать прошивку *.sof для заливки ?

и если есть какие-то ccылки / примеры будет супер

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, Nagisa сказал:

Странного хочется:

Нормальное желание. Только грузить лучше не по JTAG, а через PS (Passive Serial).

Примерно так:

- дергаете nCONFIG на GND;

- CONF_DONE падает вниз;

- затем через DCLK и DATA0 подаете битовый поток (из .rbf, но там биты в байте обращены);

- получаете на CONF_DONE единицу.

Многое зависит от объема прошивки (кста, поддерживается сжатие), у меня при DCLK порядка 20 МГц получилось чуть более 20 мс.

Это как раз EP2:

29278765_.thumb.png.5b185c5c8b257d8c963aadba107c5518.png

ep2_data.rbf ep2_ps.dsl

275535862_.thumb.png.9757d8004c48b1ba9daa6db2a0de9c47.png

3 часа назад, x893 сказал:

Для второго циклона: https://www.intel.in/content/dam/www/programmable/us/en/pdfs/literature/hb/cyc2/cyc2_cii51013.pdf

Пример

main.c

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сконвертировать можно sof->rbf можно при помощи Convert Programming File (есть в меню File проекта).

Внизу нужно будет нажать Add File и добавить ваш sof.

428717168_.thumb.png.f87cddaa084bd99970c467ee12ac8541.png

 

Либо установить соответствующую галочку в настройках проекта.

682991546_.thumb.png.640d6b0aa540b4340bf204aba1f3f25f.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 7/16/2021 at 6:13 PM, adnega said:

Нормальное желание. Только грузить лучше не по JTAG, а через PS (Passive Serial).

Примерно так:

- дергаете nCONFIG на GND;

- CONF_DONE падает вниз;

- затем через DCLK и DATA0 подаете битовый поток (из .rbf, но там биты в байте обращены);

- получаете на CONF_DONE единицу.

Многое зависит от объема прошивки (кста, поддерживается сжатие), у меня при DCLK порядка 20 МГц получилось чуть более 20 мс.

Это как раз EP2:

29278765_.thumb.png.5b185c5c8b257d8c963aadba107c5518.png

ep2_data.rbf 47.86 kB · 1 download ep2_ps.dsl 87.14 kB · 1 download

275535862_.thumb.png.9757d8004c48b1ba9daa6db2a0de9c47.png

Для второго циклона: https://www.intel.in/content/dam/www/programmable/us/en/pdfs/literature/hb/cyc2/cyc2_cii51013.pdf

Пример

main.c 4.57 kB · 2 downloads

Огромное спасибо за развернутый ответ! буду делать макетку для обкатки

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Проще сделать файл ttf. Затем циферки через запятую в тексте программы для STM32 оформить в виде масссива данных.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, copov сказал:

Проще сделать файл ttf. Затем циферки через запятую в тексте программы для STM32 оформить в виде масссива данных.

Несжатая прошивка в ПЛИС занимает довольно много памяти:

1283651602_.png.6efa55fd04a197c562b94f85813eb78d.png

Мне проще .rbf (по сути bin) записать при прошивке МК в выделенный регион памяти, чем каждый раз компилировать исходник, содержащий текстовый файл под 300 килобайт.

Причем в будущем этот хардкод-массив не поменяешь - только прошивкой. А если только прошивкой, то она автоматом возрастает на 300 килобайт. Кста, после сжатия blink для EP2C5 занимает порядка 50 кбайт.

$(PG) -c SWD UR -ME -P ./ep2_data.bin 0x08008000 -P $(MAIN_OUT_BIN) 0x08000000 -Halt -Rst -Run

Такой командой ST-Link запишет конфигурацию ПЛИС в заданном регионе

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 7/16/2021 at 5:13 PM, adnega said:

Нормальное желание. Только грузить лучше не по JTAG, а через PS (Passive Serial).

А почему PS? Ради экономии ног? А я вот через JTAG гружу и за одно по окончанию проверяю CONFIG_DONE флаг при Boundary Scan. Грузить могу как из внутренней FLASH так и из файла с карты через FatFS. Ну и как бонус - могу проверять CHIP_ID, на всякий случай.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, HardWareMan сказал:

А почему PS? Ради экономии ног?

И ног меньше, и алгоритм проще, и решение универсальное.

У меня Циклоны EP1, EP2, EP4 и Spartan-3AN одинаково управляются, хотя платы расширения могут быть реализованы на разных FPGA.

Есть ли где-то подробное разжевывание про загрузку через JTAG?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Quote

И ног меньше, и алгоритм проще, и решение универсальное.

Ну, допустим, ног у вас, я вижу, тоже 4. К простоте алгоритма и скорости претензий нет, да и универсальность тоже плюс. Но если подключен JTAG то там появляются дополнительные фишки, вроде Boundary Scan.

 

On 8/6/2021 at 1:40 PM, adnega said:

Есть ли где-то подробное разжевывание про загрузку через JTAG?

 

Да вроде там обычный стандартный JTAG TAP. А команды и расположение сигналов/флагов прописаны в BSDL файле. Например, для Cyclone IV описаны следующие (но я использую не все):

// Команды JTAG
const uint16_t JI_EXTEST		= 0x000F;
const uint16_t JI_PROGRAM		= 0x0002;
const uint16_t JI_STARTUP		= 0x0003;
const uint16_t JI_CHECK_STATUS		= 0x0004;
const uint16_t JI_SAMPLE		= 0x0005;
const uint16_t JI_IDCODE		= 0x0006;
const uint16_t JI_USERCODE		= 0x0007;
const uint16_t JI_ACTIVE_DISENGAGE	= 0x02D0;
const uint16_t JI_BYPASS		= 0x03FF;
const uint16_t JI_PULSE_NCONFIG		= 0x0001;
const uint16_t JI_CONFIG_IO		= 0x000D;
const uint16_t JI_HIGHZ			= 0x000B;
const uint16_t JI_CLAMP			= 0x000A;

Cам код у меня ногодрыжкый, от чего не привязан к конкретным пинам, а узкий цикл написан на асме:

// Прогружаем буфер в JTAG через TDI в узком цикле
__attribute__ ((naked)) void WriteJTAGBuf(uint32_t Buf, uint32_t Size)
{	// Все в наших руках
	__asm volatile
	(	// Вводная часть
		"PUSH	{R0-R8}\n"
		// План распределения регистров
		// R0 - указатель на массив данных
		// R1 - счетчик байт (преобразуем в счетчик двойных слов)
		"ORRS	R1, R1, #0\n"
		"BEQ	WriteJTAGExit\n"
		// R2 - указатель на GPIOD->BSRR
		"MOVW	R2, #0x0C18\n"
		"MOVT	R2, #0x4002\n"
		// R3 - Установить TDI в 1
		"MOVW	R3, #0x8000\n"
		"MOVT	R3, #0x0000\n"
		// R4 - Сбросить TDI в 0
		"MOVW	R4, #0x0000\n"
		"MOVT	R4, #0x8000\n"
		// R5 - Установить TCK в 1
		"MOVW	R5, #0x1000\n"
		"MOVT	R5, #0x0000\n"
		// R6 - Сбросить TCK в 0
		"MOVW	R6, #0x0000\n"
		"MOVT	R6, #0x1000\n"
		// R7 - Счетчик бит (8 за раз)
		// R8 - Временный регистр с данными
		"WriteJTAGLoop:\n"
		// Цикл BYTEов
		"LDRB	R8, [R0, #0]\n"
		"ADD	R0, R0, #1\n"
		"MOVW	R7, #0x0008\n"
		"MOVT	R7, #0x0000\n"
		"WriteJTAGBits:\n"
		// Цикл бит BYTEа
		"LSRS	R8, #1\n"
		"BCS	WriteJTAGOne\n"
		"STR	R4, [R2, #0]\n"
		"B	WriteJTAGCont\n"
		"WriteJTAGOne:\n"
		"STR	R3, [R2, #0]\n"
		"B	WriteJTAGCont\n"
		"WriteJTAGCont:\n"
		"STR	R5, [R2, #0]\n"
		"SUBS	R7, #1\n"
		"NOP\n"
		"NOP\n"
		"NOP\n"
		"STR	R6, [R2, #0]\n"
		"BNE	WriteJTAGBits\n"
		"SUBS	R1, #1\n"
		"BNE	WriteJTAGLoop\n"
		// Конец
		"WriteJTAGExit:\n"
		"POP	{R0-R8}\n"
		"BX		LR\n"
	);
}

Он прогружает распакованный стрим RBF от EP4CE22E22C8N размером 718569 байт на STM32F437 @168MHz примерно 0.5 секунды, точно не измерял. Сначала делаю тест линка через команду JI_BYPASS, затем проверяю ID чипа через JI_IDCODE. Если всё правильно, то посылаю JI_ACTIVE_DISENGAGE и потом JI_PROGRAM, немного жду (в букваре на циклопа есть это время) и загоняю битстрим единым куском. Потом делаю JI_CHECK_STATUS и смещаюсь на бит CONFIG_DONE согласно BSDL файла и проверяю его. По результату проверки принимаю решение дальнейших действий. Уверен, что можно ещё оптимизировать, но оно и так работает и меня устраивает, а если сделать аппаратный TAP или попробовать заюзать набортный JTAG то конечно всё будет на порядки быстрее.

 

PS Записал. Скорость получилась порядка 10МHz.

1.thumb.PNG.49e5fa529cf34b47fe674420dde60ec5.PNG

2.thumb.PNG.f10ddbcc85e3067b4ef60c6687d1d26b.PNG

3.thumb.PNG.efc73b651c6f758d87498adc75aceb52.PNG

Про ускорение в разы немного погорячился, там вроде бы больше 20МГц нельзя тактировать при прогрузке битстрима.

Изменено пользователем HardWareMan

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо за информацию! Нужно будет попробовать. У меня сейчас только PS и AS варианты заложены, но JTAG очень интересен в перспективе.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

11 hours ago, adnega said:

Спасибо за информацию! Нужно будет попробовать. У меня сейчас только PS и AS варианты заложены, но JTAG очень интересен в перспективе.

А ещё JTAG позволяет обслуживать целую цепочку устройств, если в проекте несколько FPGA или CPLD. В том числе, можно через него обновлять конфигурационное устройство (то самое ПЗУ, с которого грузится FPGA на старте) через файл JIC. И всё только по 4м проводам. Ну, так-то можно вообще полноценный плеер STAPL (Jam™ Standard Test and Programming Language) написать. Но лично мне это пока не надо.

Снимок.PNG

 

PS Внезапно, есть исходники JAM плеера на 8051. Удивлён. Ну и доступны исходники Jam STAPL Byte-Code Player Version 2.2 и Jam STAPL Player Version 2.5. Работает плеер с файлами *.jbc

Изменено пользователем HardWareMan

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...