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. Если кто-то хочет сделать красивее, асинхроннее и на прерываниях — ради бога, это просто быстрый прототип и ни на что не претендует.
За сим откланиваюсь. Замечания, предложения, улучшения — с радостью выслушаю.
- +6
- 19 августа 2012, 21:29
- marvin_yorke
Быстро, 128к за пару секунд с верификацией. Хотя может оно умное и полностью не перезаписывает, есть там какой-то флаг «оптимизация»
- marvin_yorke
- 20 августа 2012, 07:10
- ↑
- ↓
Там явно не вся флеш память пишется. На скорости 115200 8E1 что бы передать 128кБ чистых данных потребуется больше 12.5 секунд.
там есть флаг --о, который позволяет не записывать страницы толи из 0x00 толи 0xFF. А сама прошивка, которую я загружал ок. 2кБ была
- marvin_yorke
- 20 августа 2012, 15:14
- ↑
- ↓
Интересно, пригодится.
Вопрос по поводу платы: она покупалась или как-то досталась? Просто discovery с полноценным отладчиком в той же цене (ну на пару баксов подороже). Вывод отладочной информации это совсем не то, по сравнению с отладкой в железе.
Вопрос по поводу платы: она покупалась или как-то досталась? Просто discovery с полноценным отладчиком в той же цене (ну на пару баксов подороже). Вывод отладочной информации это совсем не то, по сравнению с отладкой в железе.
Купил на ebay как-то, уже достаточно давно. Не помню, почему не взял дискавери — толи потому что в чип-нн их тогда еще не завезли, толи потому, что stm8-discovery уже был и была надежда заточить его отладчик для работы с stm32. Если полноценные приложения писать, то конечно, гораздо лучше иметь аппаратную отладку. Но поболоваться, поизучать камень и этого мне пока что хватит
- marvin_yorke
- 20 августа 2012, 09:45
- ↑
- ↓
сейчас думаю отладку с F4 взять, интересно ейные DSP функции пощщупать…
- marvin_yorke
- 20 августа 2012, 09:45
- ↑
- ↓
Кстати, мне вот сейчас такая плата как у вас очень пригодилась бы :)
Делаю девайс на F103м. Нужен макет. Переносить код потом с F4го геморно, слишком много нюансов. Поэтому решил макет залутить на отдельной платке.
Делаю девайс на F103м. Нужен макет. Переносить код потом с F4го геморно, слишком много нюансов. Поэтому решил макет залутить на отдельной платке.
полагаю CP2102 имелась в виду, только я тоже не понял, к чему она в данном случае. Есть же st-link от F4
- marvin_yorke
- 20 августа 2012, 13:25
- ↑
- ↓
схему могу вечером скинуть, если нужно, хотя там примитивно все вроде бы
- marvin_yorke
- 20 августа 2012, 15:12
- ↑
- ↓
Да, такая штука весьма в хозяйстве полезная есть. Я еще в прошлом октябре сделал аналогичную доску на L151 — пользуюсь до сих пор, выручает весьма (хотя там всего два с половиной порта полностью разведено, и USB отдельно выведен + 2 светодиода). А то дрючить по мелочам F407 на discovery тоже жаба давит.))
Там не то, что бы дрючить, просто даже элементарщина типа мигания светодиодом требует сконфигурить порты, а оно для F1 и F4 конфигурится по-разному. И тупо перенести код потом не выйдет. Надо писать всякие прослойки с кучей ифдефоф и т.д. Можно, но желание быстро проверить какую-нибудь идею убивается на корню.
А, ну это тоже. Я просто мелочи не гонял особо на отладке — только то, под что потом разводил печатную плату; а тут уже есть смысл заморочиться.
Вообще, конечно, иметь маленькие, пусть даже самодельные, отладочные платки под разные линейки (пусть хоть для f1xx, L1xx, f2xx) было бы неплохо — но иногда приходится таки портировать код.
Мне сейчас будет обидно, если придется переносить код из-под L151 под F103 в проекте с тачпадом…
Вообще, конечно, иметь маленькие, пусть даже самодельные, отладочные платки под разные линейки (пусть хоть для f1xx, L1xx, f2xx) было бы неплохо — но иногда приходится таки портировать код.
Мне сейчас будет обидно, если придется переносить код из-под L151 под F103 в проекте с тачпадом…
Вот, кстати, для таких задач очень неплохо подходит libmaple. С одной стороны она достаточно неплохо абстрагирует железо, что бы перенос между семействами был с минимальными затратами усилий, а с другой она достаточно низкоуровневая, что бы не вносить значительных накладных расходов. Что-то типа стм-овской standard peripheral library, только написаной с использованием головы по назначению.
У меня такая плата:ПЛАТА на плате 2 мини юсб, один из них через микросхему pl2303 подключён к МК. Подсоединил кабель, поставил драйвер, и на компе прописался ком порт. Пользуюсь Flash loader demonstrator. Компию код в CoIDE, раздражает то что два разных действия, хотелось бы прошивать прямо со среды разработки. За статью спасибо, поищу выводы и сделаю как автор. Может у кого нибудь есть схема платы? Хотя можно найти с помощью мультиметра и даташита.
ни как не вкурю почему не работает
программы в контроллере нет. через GUI интерфейс все получается
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
пишет:
Комментарии (31)
RSS свернуть / развернуть