STLink в виде терминала

Как обычно, ушат помоев выливаем на ST за то, что не всегда пользуются головой при создании дев. борд*. Я честно, не знаю ни одного эмбеддерщика, который бы при работе не юзал терминал последовательном порту для отладки. (Или может мало их знаю?). А общем, gdb хорошь, да старый добрый ‘dmesg’-образный лог бывает иногда даже полезнее.
Так или иначе, пока суровые мужики реверсинженерят фирмварю StLinkV2 пытаясь найти следы вменяемости у разработчиков из ST, но находят только дыры в безопасности эпических размеров, я решил использовать STLinkV1 и STLinkV2 как есть.
Первой мыслью было взять и запихнуть VCP из примеров в стлинковский МК (А это у нас STM32F103C8T6) кинуть пару проводочков, но в конце концов — не хотелось выпиливать STLink окончательно (он меня выручал пару раз). Мысли? Их есть у меня!

IMG_20130506_100917

Шаг первый. Что у нас делает STLink? Правильно, помимо шаманства с брейкпойнтами, степами он пишет и читает память. Звучит хорошо? Хорошо! Этого нам и хватит чтобы реализовать что угодно.

Хитрый план:

  • Положить структурку с меджиком (Например, 0xdeadf00d) где-нибудь в SRAM’е MCU
  • Пошарить по SRAM’у STLINK’ом и найти меджик
  • Использовать парочку буферов внутри структурки для IO
  • ПРОФИТ!!1
  • Зачем изголяться? Потому что получаем простое решение, не требующее на соплях подцеплять USB2UART донглы и прочее дело, и платкой можно рулить с компьютера. А потом можно и подцепить к newlib’у.

    Ладно, теперь выдавим из себя немного кода. Чтобы оно заработало, надо вспомнить немного теории. Самая большая неприятность тут — и ARM, и отладчик будут лазать по памяти одновременно, и средств синхронизации чуть меньше чем никаких.

    Тут надо понимать, что все записи и чтения памяти превратятсяв транзакции по AXI, и шина эта нам их выстроит последовательно. НО! Мы можем быть уверены, что атомарными тут будут только записи/чтения 32/16/8 бит.
    Но прочитать флажок занятости, и после чтения выставить его мы не может. Это нам сразу откроет потенциальный рейс. Так что логика ‘проверить если не занят, выставить флажок занятости’ тут непрокатит. Зная это в голову пришло два алгоритма как это можно реализовать. Первая — два кольцевых буфера, по которым отправлять сообщения туда и обратно (оверкил), или более простой вариант, с двумя буферами и счетчиком байтов. Другими словами:

    struct stlinky {
    	uint32_t magic; /* [3:0] */
    	unsigned char bufsize; /* 4 */
    	char txsize; /* 5 */ 
    	char rxsize; /* 6 */
    	char reserved; /* 7 */
    	char txbuf[CONFIG_LIB_STLINKY_BSIZE];  
    	char rxbuf[CONFIG_LIB_STLINKY_BSIZE];
    } __attribute__ ((packed));;

    ‘packed’ значит, что нам компилятор не воткнет никаких дырок, и высчитать положения нужных полей будет просто.
    Итак, STLINK будет искать меджик, находить размеры буферов. Далее, Когда txsize не равно нулю, хост может считать txbuf, а после выставить txsize в 0, сказав MCU что тот может положить еще данных.

    Звучит весело? В общем, у меня есть рабочий proof-of-concept который отлично работает будучи обернут в newlib’овские _write/_read.
    Код есть в этом хедере и этом исходнике.
    Либо можно сразу взять всю мою Antares Билдсистему (И так оно почти стабильно, дело идет к релизу). Так же есть готовый пример под stm32vl-discovery который шлет привет поверх stlink’а

    Ну и потребуется мой форк stlink, в котором есть утилита st-term, которая раотает на хосте.
    Не прошло и 30 минут, как texane смержил мой pull request, так что теперь st-term должен появиться в апстриме.

    * Если (в очень маловероятной ситуации) этот текст читают ребята из ST — не обижайтесь, МК у вас и впрямь неплохие. Вот только когда будете делать новую версию STLINK’а — пожалуйста, сделайте его композитным устройством с последовательным портом до таргета. А заодно наведите порядок с STM32F1X Periph Lib’ами. А то в архиве с ST Periph Libs версия 3.5.Х, а в архиве с USB FS Kit — цельный ST Periph Libs 3.6.x.

    UPDATE: Простой бенчмарк показал производительность в 16129 байт в секунду, с буферами по 64 байта. В разы больше, чем я ожидал!
    UPDATE2: В комментах к английскому варианту мне напомнили, что я изобретаю колесо — есть ‘arm semihosting’ который по сути тоже и делает. Я буду делать дополнительный пост по семихостингу, а так же выложу более подробные бенчмарки.

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