USB-to-UART в качестве программатора/отладчика для STM32

Или «Вот что лень с программистом делает»

Наконец дошли руки поиграться с платкой с STM32 (у меня такая). Камень STM32F103RBT6, пины разведены на гребенки, подключен USB, UART выведен на DB9 через MAX3232, есть разъем JTAG, пара кнопок, пара светодиодов — ничего особенного.

Первый вопрос, который возник сразу — как прошивать. JTAG-адаптером пока обзавестись не успел, но не раз читал, что STMки умеют вшитый на заводе UART-бутлоадер. Ок, пробуем. Качаем архив с прошивальщиком, расчехляем USB-to-UART переходничок на CP2102, переставляем джампер на BOOT0, запускаем, прошиваемся. Все с первого раза, это успех. Переставляем джампер еще раз, жмем ресет — видим мигающий диодик.

Это круто, подумал я. Но вручную переставлять джампера и жать ресет каждый раз — это не путь джедая. Поэтому «We need to go deeper»



Сначала я решил удовольствоваться малым (черт с ними, с джамперами) и хотя бы запускать саму прошивку прямо из CooCox'a, для чего директория установки STM Flash Loader'a была происследована на предмет консольного интерфейса к прошивальщику. Он нашелся в виде файла STMFlashLoader.exe, прочитав справку которого мы сразу видим, что, де, вот она, рыба нашей мечты:
-Rts                 (set Rts line to Hi, Lo)
   --State           : State in {Hi, Lo}
-Dtr                 (Set Rts line to Hi, Lo)
   --State           : State in {Hi, Lo}

У нас есть аж две линии, которые (судя по лежащему рядом примеру в файле MB786revB.bat) мы можем использовать как GPIO, т.е. управлять уровнями на них по собственному желанию. Запаиваем дополнительную гребенку в адаптер, благо нужные нам линии разведены, и подключаем 2 дополнительных провода от адаптера к плате: я подключил RTS на BOOT0 (прямо туда, где подключается джампер) и DTR на Reset (нашелся на колодке JTAG, пин 15). Осталось задать правильную команду для запуска прошивальщика. Вот, что получилось у меня:
STMFlashLoader.exe \
    -c \
        --pn 3 --br 115200 --db 8 --pr EVEN --sb 1 --ec ON --to 1000 \
    -Rts \
        --Lo \
    -Dtr \
        --Hi --Lo \
    -i STM32_Med-density_128K \
    -d --a 8000000 --fn <file path> --v --o \
    -Rts \
        --Hi \
    -r --a 8000000


Пара комментариев.
Разбивка на строки не случайна. По сути сама программа- прошивальщик представляет собой некий интерпретатор, а коммандная строка его запуска — программу для него. Опции, начинающиеся с одного минуса — операторы программы, с двух минусов — их операнды/опции. Самые интересные тут для нас опции — это -Rts и -Dtr. Слеующие за ними флаги --Hi/--Lo задают последовательность, которая будет выдана на эти пины. Причем, как видите, за одну строку можно изменить состояние пина несколько раз.

Итак, вначале мы открываем порт с заданными настройками (-c), затем по линии RTS переключаем состояние BOOT0 (-Rts), затем по линии DTR выполняем Reset (-Dtr). Указываем семейство контроллера и даем команду на загрузку прошивки из указанного файла (-i, -d). Затем переводим BOOT0 в нормальное состояние и запускаем выполнение программы.

Заставить Кокос вызывать эту команду мне пока не удалось (буду рад, если кто-то поделится соображениями — теоретически можно прописать ее в build.xml, но с ходу у меня это не получилось), поэтому сохранил в BAT-файл и запускаю прошивку одним кликом.

Надеюсь, что кому-то мое мини-исследование оказалось полезным и сэкономило время.

А к слову об отладке — раз у нас все равно постоянно подключен к компьютеру UART, ничего не мешает нам задействовать его для отправки отладочной информации. Для этого я добавил в проект следующие фрагменты кода:

// main.c

#include <stdio.h>

#define PRINTF_USART USART1

void PrintChar(char c)
{
    /* Loop until the end of transmission */
    USART_SendData(PRINTF_USART, (uint8_t) c);
    while (USART_GetFlagStatus(PRINTF_USART, USART_FLAG_TC) == RESET);
}

void SetupUSART()
{
    GPIO_InitTypeDef gpio;
    USART_InitTypeDef usart_init;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

    gpio.GPIO_Speed = GPIO_Speed_50MHz;

    // Tx on PA9 as alternate function push-pull
    gpio.GPIO_Mode = GPIO_Mode_AF_PP;
    gpio.GPIO_Pin = GPIO_Pin_9;
    GPIO_Init(GPIOA, &gpio);
    
    // Rx on PA10 as input floating
    gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    gpio.GPIO_Pin = GPIO_Pin_10;
    GPIO_Init(GPIOA, &gpio);

    usart_init.USART_BaudRate = 57600;
    usart_init.USART_WordLength = USART_WordLength_8b;
    usart_init.USART_StopBits = USART_StopBits_1;
    usart_init.USART_Parity = USART_Parity_No;
    usart_init.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    usart_init.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    
    USART_Init(USART1, &usart_init);
    USART_ClearFlag(USART1, USART_FLAG_CTS | USART_FLAG_LBD  |
                            USART_FLAG_TC  | USART_FLAG_RXNE
                    );

    USART_Cmd(USART1, ENABLE);
}


Из репозитория Кокоса подключаем C Library и Retarget Printf и все, можем использовать функцию printf() для вывода информации в UART. Если кто-то хочет сделать красивее, асинхроннее и на прерываниях — ради бога, это просто быстрый прототип и ни на что не претендует.

За сим откланиваюсь. Замечания, предложения, улучшения — с радостью выслушаю.

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

RSS свернуть / развернуть
Прикольно. А быстро шьется? Я имею ввиду весь процесс, от начала прошивки до резета и старта.
0
  • avatar
  • ACE
  • 20 августа 2012, 01:48
Быстро, 128к за пару секунд с верификацией. Хотя может оно умное и полностью не перезаписывает, есть там какой-то флаг «оптимизация»
0
Там явно не вся флеш память пишется. На скорости 115200 8E1 что бы передать 128кБ чистых данных потребуется больше 12.5 секунд.
0
там есть флаг --о, который позволяет не записывать страницы толи из 0x00 толи 0xFF. А сама прошивка, которую я загружал ок. 2кБ была
0
Добей ее до 128кб рандомными данными и проверь еще раз.
0
На самом деле оно совсем не быстро шьется. Правда, скорость порта можно поднять (я поднимал почти до мегабита), но тогда соединяется через раз.
0
Интересно, пригодится.

Вопрос по поводу платы: она покупалась или как-то досталась? Просто discovery с полноценным отладчиком в той же цене (ну на пару баксов подороже). Вывод отладочной информации это совсем не то, по сравнению с отладкой в железе.
0
  • avatar
  • ploop
  • 20 августа 2012, 09:32
Купил на ebay как-то, уже достаточно давно. Не помню, почему не взял дискавери — толи потому что в чип-нн их тогда еще не завезли, толи потому, что stm8-discovery уже был и была надежда заточить его отладчик для работы с stm32. Если полноценные приложения писать, то конечно, гораздо лучше иметь аппаратную отладку. Но поболоваться, поизучать камень и этого мне пока что хватит
0
сейчас думаю отладку с F4 взять, интересно ейные DSP функции пощщупать…
0
У меня есть F4-discovery (взял по дешевке в промэлектронике, когда они по 400 рублей были), если честно, не знаю, какое применение найти всем этим наворотам. Пока буду использовать еёшний st-link в качестве программатор для F1.
0
Кстати, мне вот сейчас такая плата как у вас очень пригодилась бы :)
Делаю девайс на F103м. Нужен макет. Переносить код потом с F4го геморно, слишком много нюансов. Поэтому решил макет залутить на отдельной платке.
0
Так залутьте туда и СР-шку. там обвязу минимум и вполне доставабельны в магазинах
0
эммм, не понял немного, что за СР-шка?
0
полагаю CP2102 имелась в виду, только я тоже не понял, к чему она в данном случае. Есть же st-link от F4
0
Тем более 103й с аппаратным USB :)
0
Это был ответ на
мне вот сейчас такая плата как у вас очень пригодилась бы
А что с ней делать дальше — решайте сами ;)
0
А, полностью её повторить? А что, в принципе вариант. Делов-то — камень, обвязку, и гребёнки. Может как-нибудь займусь :)
0
схему могу вечером скинуть, если нужно, хотя там примитивно все вроде бы
0
Да всё равно своё налеплю, что-то добавить, что-то убрать… в итоге другое выйдет :)
0
За основу имеет смысл брать что-то типа Maple. Например что-то из этого. В последних версиях libmaple уже есть поддержка разных серий стм-ок и перенос с серии на серию сильно упрощен. Ну и готовый загрузчик через USB тоже упрощает задачу (если отладка не нужна).
0
Да, такая штука весьма в хозяйстве полезная есть. Я еще в прошлом октябре сделал аналогичную доску на L151 — пользуюсь до сих пор, выручает весьма (хотя там всего два с половиной порта полностью разведено, и USB отдельно выведен + 2 светодиода). А то дрючить по мелочам F407 на discovery тоже жаба давит.))
0
Там не то, что бы дрючить, просто даже элементарщина типа мигания светодиодом требует сконфигурить порты, а оно для F1 и F4 конфигурится по-разному. И тупо перенести код потом не выйдет. Надо писать всякие прослойки с кучей ифдефоф и т.д. Можно, но желание быстро проверить какую-нибудь идею убивается на корню.
0
А, ну это тоже. Я просто мелочи не гонял особо на отладке — только то, под что потом разводил печатную плату; а тут уже есть смысл заморочиться.
Вообще, конечно, иметь маленькие, пусть даже самодельные, отладочные платки под разные линейки (пусть хоть для f1xx, L1xx, f2xx) было бы неплохо — но иногда приходится таки портировать код.
Мне сейчас будет обидно, если придется переносить код из-под L151 под F103 в проекте с тачпадом…
0
Вот, кстати, для таких задач очень неплохо подходит libmaple. С одной стороны она достаточно неплохо абстрагирует железо, что бы перенос между семействами был с минимальными затратами усилий, а с другой она достаточно низкоуровневая, что бы не вносить значительных накладных расходов. Что-то типа стм-овской standard peripheral library, только написаной с использованием головы по назначению.
0
В кокосе кстати тоже есть своя PL. И тоже написанная с использованием головы по назначению (т.е. абстрагирует периферию в общий для всех поддерживаемых МК интерфейс).
0
Надо поковырять эту штуку. Слышать слышал, но не видел.
0
Вот тут лежит свежая версия.
0
У меня такая плата:ПЛАТА на плате 2 мини юсб, один из них через микросхему pl2303 подключён к МК. Подсоединил кабель, поставил драйвер, и на компе прописался ком порт. Пользуюсь Flash loader demonstrator. Компию код в CoIDE, раздражает то что два разных действия, хотелось бы прошивать прямо со среды разработки. За статью спасибо, поищу выводы и сделаю как автор. Может у кого нибудь есть схема платы? Хотя можно найти с помощью мультиметра и даташита.
0
  • avatar
  • Nemo
  • 20 августа 2012, 22:23
Спасибо!!!
0
ни как не вкурю почему не работает
STMFlashLoader.exe -c --pn 9 --br 115200 --db 8 --pr EVEN --sb 1 --ec ON --to 1000 -i STM32F1_Med-density_64K -d --a 8000000 --fn "D:\work\sources\IAR_STM32_C\6_usb_uart\EWARM\led2 Configuration\Exe\led2.bin" --v --o -r --a 8000000
пишет:
программы в контроллере нет. через GUI интерфейс все получается
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.