Прошивка ESP32 через JTAG

Автор: | 30.11.2019

При разработке устройств настает момент, когда перестаешь использовать dev kit и переходишь на свою плату. Соответственно, меняются и механизмы взаимодействия устройства с компьютером. Я использую программаторы ARM-USB-OCD и ARM-USB-OCD-H. Они отличаются друг от друга только скоростью. Для STM32 вполне достаточно первого, а вот для ESP32 уже хочется второй…

Начнем с теории. На официальном сайте есть руководство по установке всего необходимого софта (компиляторы, библиотеки, отладчики и примеры кода). И рядом имеется руководство по отладке при помощи openocd. Этот софт через программатор подключается к чипу. Различными командами можно записать прошивку на чип, стереть его или считать. В общем, манипуляции с памятью, команды на перезагрузку и прочие низкоуровневые функции. Далее, openocd и предоставляет отладчику GDB доступ чипу. GDB уже понимает что переменная X лежит по адресу 0xff и так далее. Можно прыгать по прошивке, читать переменные… Можно сказать, высокоуровневая отладка. Как-то так оно и работает.

Теперь о железе. В первую очередь требуется подключить плату к программатору. На официальном же сайте есть схема подключения.

ESP32 PinJTAG Signal
CHIP_PUTRST_N
MTDO / GPIO15TDO
MTDI / GPIO12TDI
MTCK / GPIO13TCK
MTMS / GPIO14TMS
GNDGND

Но я дополню эту схему. Не знаю, для всех ли программаторов это актуально. В моем случае, в программаторе содержатся буферы, которые «запитывает» TARGET устройство. Таким образом, если мы подаем на пин V_TARGET/VREF (1 контакт 20-пинового разъема) напряжением 3.3 вольта, то и все сигнальные линии будут с уровнями 3.3 вольта. Так же и для 5 вольт. Таким образом программатор становится универсальным и подходит для работы с чипами, работающими на различных уровнях сигналов. Если V_TARGET не подключать, то openocd просто не обнаружит чип.

Теперь сам процесс прошивки. По умолчанию команда make flash скрывает вызовы компилятора и различных утилит для прошивки. В качестве примера возьмем проект работы с GPIO.

Но, если добавить ключ -e, то она их покажет.

Теперь мы видим, что на самом деле прошивается не только build/gpio.bin, а ещё и build/bootloader/bootloader.bin c build/partitions_singleapp.bin. Причем в определенном порядке и с определенными смещениями.

Если посмотреть файл с описанием esp32 в скриптах openocd (openocd-esp32/share/openocd/scripts/target/esp32.cfg), то можно найти в нем команду program_esp32, которая в качестве аргумента принимает имя файла и смещение. Можно воспользоваться и ей, но все равно нужно прошивать все три bin файла.

На самом деле эта команда просто проверяет входные данные и вызывает встроенные в openocd функции. Поэтому перейдем сразу к их описанию в документации. В ней описаны команды для работы с flash: erase_sector, erase_sector, write_bank, read_bank, verify_bank, write_image. Сейчас интересует только последняя. С остальными разобраться не проблема, если вдруг понадобятся.

Требуется указать имя файла с прошивкой, смещение и нужно ли предварительно стереть используемую область памяти и проводить проверку после записи. Загружать bin файлы скорее всего нужно в том же порядке, который получили из вывода make flash.

В моем случае, в домашней директории лежит скрипт ~/.openocd.sh, в котором находятся команды для запуска openocd со всеми параметрами. Это удобно.

[walhi@walhi] ~ $ cat ~/.openocd.sh
#!/bin/sh

#OCD=ocd-h
OCD=ocd

case `pwd` in
	*stm32*)
		exec openocd -f interface/ftdi/olimex-arm-usb-${OCD}.cfg\
        	-f interface/ftdi/olimex-arm-jtag-swd.cfg\
            -f target/stm32f1x.cfg\
            -c 'init'\
            "$@"
	*esp*)
		exec ~/esp/openocd-esp32/bin/openocd -s  ~/esp/openocd-esp32/share/openocd/scripts\
	    	-f interface/ftdi/olimex-arm-usb-${OCD}.cfg\
	    	-f board/esp-wroom-32.cfg\
        	"$@"
esac
[walhi@walhi] ~ $

Поясню один момент. Конструкция «$@» позволяет передать все параметры, которые передали этому скрипту, в openocd.

Теперь можно попробовать прошить ESP32. Сформируем команду:

~/.openocd.sh

Для начала нужно проинициализировать чип и остановить выполнение текущей программы. Добавим команды для этого:

-c "init" -c "reset halt"

Прошивка файла build/bootloader/bootloader.bin:

-c "flash write_image erase build/bootloader/bootloader.bin 0x1000"

Прошивка программы build/gpio.bin:

-c "flash write_image erase build/gpio.bin 0x10000"

Прошивка файла build/partitions_singleapp.bin:

-c "flash write_image erase build/partitions_singleapp.bin 0x8000"

На этом формирование команды на прошивку завершено. Но программа не начнет выполняться и openocd останется запущенным. Для решения этих проблем добавим ещё две команды

-c "reset run" -c "exit"

В результате полная команда на прошивку выглядит следующим образом:

~/.openocd.sh -c "init" -c "reset halt" -c "flash write_image erase build/bootloader/bootloader.bin 0x1000" -c "flash write_image erase build/gpio.bin 0x10000" -c "flash write_image erase build/partitions_singleapp.bin 0x8000" -c "reset run" -c "exit"

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

Набрать команду не так уж и сложно. А вообще, лучше бы оформить это в скриптик.

Результат успешного выполнения команды выглядит следующим образом:

А теперь давайте сравним скорости загрузки через UART Bootloader и через JTAG. Для справки приведу размеры прошивки:

[walhi@walhi] ~/esp/esp-idf/examples/peripherals/gpio $ make size
Toolchain path: /home/walhi/esp/xtensa-esp32-elf/bin/xtensa-esp32-elf-gcc
Toolchain version: crosstool-ng-1.22.0-80-g6c4433a
Compiler version: 5.2.0
App "gpio" version: v4.0-dev-73-gf1e9078cb
Python requirements from /home/walhi/esp/esp-idf/requirements.txt are satisfied.
Total sizes:
 DRAM .data size:    7852 bytes
 DRAM .bss  size:    4128 bytes
Used static DRAM:   11980 bytes ( 168756 available, 6.6% used)
Used static IRAM:   32839 bytes (  98233 available, 25.1% used)
      Flash code:   78932 bytes
    Flash rodata:   38508 bytes
Total image size:~ 158131 bytes (.bin may be padded larger)
ПрограмматорВремя (сек)
UART Bootloader14,245
Olimex ARM-USB-OCD16,093
Olimex ARM-USB-OCD-H4,084

Надеюсь, статья поможет освоиться.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *