STM32CubeMX по умолчанию отключает SWD для серии F1

STM32CubeMX — это генератор исходного кода для микроконтроллеров STM32. Позволяет настроить периферию с помощью графического интерфейса.

Если создать проект в STM32CubeMX, выбрать микроконтроллер серии F1 и сгенерировать исходный код, не производя никаких настроек, то этот код отключит интерфейсы программирования JTAG и SWD. Если такую программу скомпилировать и прошить, то в следующий раз прошить микроконтроллер будет затруднительно.

То есть новичок, делающий первую программу для STM32F1, гарантировано окажется в тупиковой ситуации.

Проблема проявляется только для микроконтроллеров серии F1. Для проверки использовался STM32CubeMX последней (4.17.0, на 13.11.2016) версии.

Проблема несколько раз упоминалась (раз, два, три) в 2015 году. И STM даже обещали (по третьей ссылке) ее исправить, но не исправили.

Код, отвечающий за отключение JTAG и SWD, находится в файле stm32f1xx_hal_msp.c в функции HAL_MspInit(), которая вызывается функцией HAL_Init(), и выглядит следующим образом:

 /**DISABLE: JTAG-DP Disabled and SW-DP Disabled
*/
__HAL_AFIO_REMAP_SWJ_DISABLE();

Чтобы избежать этой проблемы, нужно в STM32CubeMX на вкладке Pinout в дереве настроек найти пункт Configuration -> Peripherals -> SYS -> Debug и из выпадающего списка выбрать подходящее значение:

  • No Debug — значение по умолчанию, отключает отладочные интерфейсы JTAG и SWD.
  • Serial Wire — отключает JTAG, включает SWD, который использует только два вывода, подходит для программатора ST-Link.
  • JTAG (4 pin) — включает JTAG и SWD, используется 4 вывода (без NJTRST).
  • JTAG (5 pin) — включает JTAG и SWD, используется 5 выводов (с NJTRST), что соответствует состоянию микроконтроллера после сброса.

Как прошить микроконтроллер с отключенными JTAG и SWD

Если SWD и JTAG отключились, то не все потеряно. Уверен, что есть проекты в которых это даже необходимо.

Для начала нужно создать прошивку, которая бы не отключала SWD и JTAG.

Вариант 1

Вариант работает при прошивке через SWD с помощью ST-LINK/V2 (ST-LINK второй версии). Через JTAG тоже можно, но с ST-LINK, у которого версия прошивки V2J15Sx или новее.

В программе STM32 ST-LINK utility в настройках нужно выбрать режим (Mode) «Connect Under Reset» (подключение при сбросе). Этот режим позволяет подключиться к микроконтроллеру до начала выполнения программы.

Чтобы прошить микроконтроллер, нужно на вывод сброса микроконтроллера (NRST) подать низкий уровень (или соединить вывод с землей), запустить прошивку и сразу убрать низкий уровень с NRST.

Возможно, чтобы вручную не дергать NRST, можно соединить его с одноименным вывод ST-LINK и произвести еще какие-то настройки STM32 ST-LINK utility. Но автор эту идею не проверял. Если вы знаете, напишите в комментариях.

Вариант 2

Если у вас нет ST-LINK/V2, то микроконтроллер можно прошить через USART с помощью программы STM32 Flash loader demonstrator. Для этого понадобится переходник USB-UART, который создаст на компьютере виртуальный COM-порт.

Во флеш STM32 есть системная область, в которую на заводе зашит специальный загрузчик. Чтобы запустить выполнение программы загрузчика, нужно подать на ноги BOOT0 и BOOT1 необходимые уровни (согласно документации) и запустить микроконтроллер.

В Application note AN2606 можно уточнить какие USART с какими выводами использует загрузчик, а также необходимое состояние выводов BOOTx.

Реклама

Развертывание среды разработки для STM32

Большая часть статьи — это текстовое описание видео: 

В статье показано, как с помощью бесплатных кроссплатформенных инструментов развернуть среду разработки для микроконтроллеров STM32.

Программы и библиотеки, о которых будет идти речь, уже объединены в готовые бесплатные среды разработки, например CooCox CoIDE или SW4STM32. Первая только для Windows, а вторая для множества операционных систем, но ссылки для скачивания появляются только после регистрации.

Мы соберем свою среду, чтобы лучше ее понимать и контролировать.

Читать далее Развертывание среды разработки для STM32

Приоритеты прерываний в Cortex-M и их настройка в STM32Cube

STM32Cube — это набор библиотек фирмы STM для своих микроконтроллеров (STM32). Эти библиотеки пришли на смену библиотекам SPL.

Микроконтроллеры STM32 сделаны на базе ядра ARM Cortex-M. Это ядро служит основой микроконтроллеров и у других производителей.

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

Приоритет прерывания зависит от 3 факторов:

Читать далее Приоритеты прерываний в Cortex-M и их настройка в STM32Cube

Начало работы с STM32 в Keil MDK-ARM

Статья посвящается Пановой Ксении.

Все картинки в этой статье кликабельны.

STM32 — это семейство 32-разрядных микроконтроллеров фирмы STMicroelectronics.

Микроконтроллеры содержат микропроцессорное ядро ARM, точнее ARM Cortex-M. Это ядро присуще не только микроконтроллерам STM32, оно существует само по себе, и на его основе выпускается множество микроконтроллеров от разных производителей.

Keil MDK-ARM (произносится «Кеил эм-ди-кей арм») — это среда разработки для микроконтроллеров с ядром ARM Cortex-M.

Читать далее Начало работы с STM32 в Keil MDK-ARM

Переполнение при отсчете времени в STM32Cube

Ранее я писал об отсчете времени в STM32Cube.

STM32Cube считает время в миллисекундах. Время хранится в беззнаковой целочисленной 32-битной переменной:

static __IO uint32_t uwTick;

Это означает, что через 49 суток 17 часов 2 минуты 47 секунд и 295 миллисекунд произойдет переполнение этой переменной.

Хорошо, если устройство не может так долго работать, например, гарантировано сядет батарейка. Но, что если устройство должно работать непрерывно месяцами?

Время используется библиотекой в операциях ввода/вывода для организации таймаутов. Кроме того, библиотека предоставляет функцию задержки HAL_Delay().

Если переполнение обрабатывается неправильно, то мы получим неправильные таймауты и задержки.

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

файл stm32***_it.c:

void SysTick_Handler(void)
{
  HAL_IncTick();
}

файл stm32***_hal.c:

static __IO uint32_t uwTick;

__weak void HAL_IncTick(void)
{
  uwTick++;
}

__weak uint32_t HAL_GetTick(void)
{
  return uwTick;
}

__weak void HAL_Delay(__IO uint32_t Delay)
{
  uint32_t tickstart = 0;
  tickstart = HAL_GetTick();
  while((HAL_GetTick() - tickstart) < Delay)
  {
  }
}

Обработчик прерывания SysTick_Handler() вызывается каждую миллисекунду, и вызывает функцию HAL_IncTick(), которая просто увеличивает uwTick на единицу (инкрементирует). Функция HAL_GetTick() возвращает текущее время в миллисекундах; эта функция обильно используется библиотекой следующим образом:

uint32_t tickstart = HAL_GetTick();
...
if((HAL_GetTick()-tickstart) >= Timeout)
{ ... }

Операция сравнения времени довольно проста. Аналогичная операция используется в функции HAL_Delay().

Видите обработку переполнения? И я не вижу. А она есть.

Рассмотрим функцию HAL_Delay(). Для начала ситуацию без переполнения.

Допустим:

Delay = 100,
tickstart = 1000.

Разница

HAL_GetTick()-tickstart

будет расти от 0 до 100. Цикл будет прерван, когда HAL_GetTick() вернет 1100:

1100 - 1000 = 100

100 < 100 = ложь,

Теперь рассмотрим ситуацию с переполнением.

Допустим:

Delay = 100,
tickstart = 4294967290
.

Максимальное число в беззнаковой 32-битной переменной равно 4294967295. То есть до переполнения остается всего 5 инкрементов. При 6-м инкременте HAL_GetTick() вернет 0.

Что тогда вернет операция

HAL_GetTick()-tickstart

то есть, что будет если из 0 вычесть 4294967290?

Обе переменные беззнаковые и целочисленные. И операция вычитания вернет 6. А дальше, когда HAL_GetTick() возвратит 1, операция вычитания вернет 7.

То есть разница между текущим временем и tickstart все время будет расти, как и в нормальной ситуации. Функция задержки отработает правильно.

Важно, что такое поведение стандартизировано и должно реализовываться любым компилятор C и C++. Можете ознакомиться с обсуждением этого вопроса на Stack Overflow.

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

Вывод

Обработка времени в библиотеке STM32Cube происходит корректно, несмотря на то, что переменная uwTick, хранящая время, может переполнится.

Отсчет времени в STM32Cube

STMicroelectronics выпускает библиотеку STM32Cube для своих микроконтроллеров. Эта библиотека пришла на смену Standard Peripherals Library и содержит новые особенности.

Одна из особенностей — это отсчет времени. Благодаря ему библиотека может устанавливать время ожидания в операциях ввода/вывода.

Время считается в миллисекундах и хранится в беззнаковой целочисленной 32-битной переменной:

static __IO uint32_t uwTick;

Максимальное значение, которое может принимать эта переменная, равно 2^{32}-1. Что соответствует 49 суткам 17 часам 2 минутам 47 секундам и 295 миллисекундам.

Можно убедится:

49\cdot24\cdot60\cdot60\cdot1000+17\cdot60\cdot60\cdot1000+2\cdot60\cdot1000+47\cdot1000+295=\newline=4294967295

2^{32}-1=4294967295

Пользователю предоставляются две полезные функции:

  • uint32_t HAL_GetTick (void)
    Возвращает время в миллисекундах.
  • void HAL_Delay (uint32_t Delay)
    Создает задержку на заданное количество миллисекунд.

Отсчет времени запускается при инициализации библиотеки, вызовом функции HAL_Init().

Для отсчета времени используется таймер SysTick, который встроен в ядро Cortex-M. Функция HAL_Init() настраивает таймер так, чтобы он генерировал прерывание каждую миллисекунду. В обработчике прерывания SysTick (в функции SysTick_Handler()) должен быть вызов функции HAL_IncTick(). Эта функция увеличивает счетчик времени на единицу.

Приоритет прерывания SysTick задается определением TICK_INT_PRIORITY в файле stm32*_hal_conf.h. Чтобы функция HAL_Delay() работала в обработчиках других прерываний, требуется чтобы приоритет этих прерываний был меньше, чем у SysTick.

В другой своей статье я исследовал последствия переполнения переменной uwTick.