Jump to content

    
Nagisa

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

Recommended Posts

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

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

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

Интересно:

- протокол

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

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

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

 

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites

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

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

428717168_.thumb.png.f87cddaa084bd99970c467ee12ac8541.png

 

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

682991546_.thumb.png.640d6b0aa540b4340bf204aba1f3f25f.png

Share this post


Link to post
Share on other sites
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

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites
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 запишет конфигурацию ПЛИС в заданном регионе

Share this post


Link to post
Share on other sites
On 7/16/2021 at 5:13 PM, adnega said:

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

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

Share this post


Link to post
Share on other sites
1 час назад, HardWareMan сказал:

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

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

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

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

 

Share this post


Link to post
Share on other sites
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МГц нельзя тактировать при прогрузке битстрима.

Edited by HardWareMan

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites
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

Edited by HardWareMan

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.