Хочу рассказать о необычном использовании ESP8266 в качестве посредника между STM32 и openOCD. У этого способа довольно много недостатков и его применение может быть вызвано только невозможностью использования обычного (проводного) средства отладки.

Плюс у этого способа один и он очевиден, поэтому перейду сразу к недостаткам:

  1. Требуется патчить openOCD
  2. Необходимо изменить прошивку в ESP8266
  3. Низкая скорость работы

Как это работает. В openOCD реализована поддержка протокола SWD, кроме того там есть драйвер под названием remote_bitbang. Из названия видно, что логические уровни просто передаются числами 1 и 0 и далее отправляются по сети.

Приемник (в нашем случае ESP8266) должен в соответствие этим числам выставить на выводах соответствующий уровень. К сожалению в remote_bitbang отсутствует поддержка SWD, однако добавить ее туда совсем не трудно:

Вот небольшой патч
--- remote_bitbang.c	2016-10-31 11:06:57.812267924 +0600
+++ remote_bitbang.c	2016-10-31 12:33:57.921692808 +0600
@@ -120,11 +120,25 @@
 	remote_bitbang_putc(c);
 }
 
+static int remote_bitbang_swdio_read (void)
+{
+	remote_swd_putc ('R');
+	return remote_bitbang_rread ();
+}
+
+static void remote_bitbang_swdio_drive (bool is_output)
+{
+	char c = is_output ? 'o' : 'i';
+	remote_bitbang_putc (c);
+}
+
 static struct bitbang_interface remote_bitbang_bitbang = {
 	.read = &remote_bitbang_read,
 	.write = &remote_bitbang_write,
 	.reset = &remote_bitbang_reset,
 	.blink = &remote_bitbang_blink,
+	.swdio_read = &remote_bitbang_swdio_read,
+	.swdio_drive = &remote_bitbang_swdio_drive,	
 };
 
 static int remote_bitbang_init_tcp(void)
@@ -271,10 +285,14 @@
 	COMMAND_REGISTRATION_DONE,
 };
 
+static const char * const remote_bitbang_transport[] = { "jtag", "swd", NULL };
+
 struct jtag_interface remote_bitbang_interface = {
 	.name = "remote_bitbang",
+	.transports = remote_bitbang_transport,
 	.execute_queue = &bitbang_execute_queue,
 	.commands = remote_bitbang_command_handlers,
+	.swd = &bitbang_swd,
 	.init = &remote_bitbang_init,
 	.quit = &remote_bitbang_quit,
 };


Далее нам нужно изменить прошивку ESP8266, чтобы он понимал команды, поступающие от openOCD. Для этой цели я воспользовался открытым SDK esp-open-rtos. Весь код прошивки я приводить не буду — он довольно объемистый, приведу только его часть, касающуюся обработки данных поступающих от openOCD.

Спойлер
#define SWCLK				0
#define SWDIO				2

IRAM void openocd_handler (void *pvParameters)
{
	struct netconn *nc = (struct netconn *) pvParameters;
	struct netbuf *rbuf = NULL;
	char *rx_buf;
	char d, r;
	err_t err;
	uint16_t len;
	uint16_t i;
	
	gpio_set_pullup (SWCLK, false, false);
	gpio_set_pullup (SWDIO, false, false);
	gpio_enable (SWCLK, GPIO_OUTPUT);
	gpio_enable (SWDIO, GPIO_OUTPUT);
	
	while (1)
	{
		if ((err = netconn_recv (nc, &rbuf)) != ERR_OK) {
			printf ("R ERROR %d\n", err);
			return;
		}
		
		netbuf_data (rbuf, (void **) &rx_buf, &len);	
		
		for (i = 0; i < len; i++)
		{
			switch (rx_buf [i])
			{
			case 'Q':		// Quit
				netconn_disconnect (nc);
				return;
			
			case '0'...'7':
				d = rx_buf [i] - '0';
				gpio_write (SWDIO, (d & 0x1));
				gpio_write (SWCLK, !!(d & 0x4));								
				break;
			
			case 'i':
				gpio_enable (SWDIO, GPIO_INPUT);
				break;
			
			case 'o':
				gpio_enable (SWDIO, GPIO_OUTPUT);
				break;
			
			case 'R':		// Writeback
				r = ((char) gpio_read (SWDIO)) + '0';
				netconn_write (nc, &r, 1, NETCONN_COPY);
				break; 
			}
		}
		
		netbuf_delete (rbuf);
	}
}


Полный исходный код можно взять здесь.

Я использую ESP-01. У нее две свободные ноги GPIO-0 и GPIO-2, причем при включении на 2-й ноге должен быть высокий уровень иначе контроллер войдет в режим загрузчика. Поэтому желательно подтянуть ножку к питанию через 10к резистор.

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

Теоретически, если портировать openOCD на ESP8266 можно добиться скорости работы сравнимой с st-link, но это я оставляю сделать читателям.

Надеюсь, кому-то мог быть полезен.
Поделиться с друзьями
-->

Комментарии (5)


  1. LeftRadio
    02.11.2016 20:49

    Спасибо Вам за материал, сам хотел сделать отладку «по воздуху» на ESP, с наилучшей гальванической изоляцией :), как раз этим и весьма полезен такой отладчик.
    Медленно работает понятно почему, используется режим remote_bitbang, накладных расходов на несколько/много порядков(!) больше полезных данных. Для записи/чтения без отладки лучше наверно использовать TFTP, можно и без openOCD, используя загрузчик в самом МК, протокол загрузчиков STM32 достаточно простой. Так именно прошить/прочитать будет намного быстрее.


  1. rooi-oog
    03.11.2016 07:25

    Для записи/чтения без отладки лучше наверно использовать TFTP, можно и без openOCD, используя загрузчик в самом МК, протокол загрузчиков STM32 достаточно простой


    Мне кажется лучше выдернуть нужные части из openOCD, чем реализовывать все с нуля.


  1. YDR
    03.11.2016 08:14

    А это — хорошая идея. И если нужна только заливка, можно bootloader по usart использовать. для ESP достаточно скрипт на LUA написать.


    1. LeftRadio
      03.11.2016 13:28
      +1

      Это и имел ввиду, только для большей скорости лучше наверно не на LUA.
      Заразили идеей :), нужно засесть и сделать, ну и еще к ST3 прикрутить через плагин.


      1. NikitosZs
        03.11.2016 14:26

        Да нет, с юартом нормально выйдет, протокол не особо быстрый сам по себе. Это если дрыгать ногами из-под nodemcu, то esp8266 может в перезагрузку чертыхнуться, видимо, если запросы кидать быстрее, чем они успевают выполняться.