Отладочная плата LDM-K1986BE92QI содержим микроконтроллер Миландр К1986ВЕ92QI (или MDR32F9Q2I). Способы прошивки МК (загрузки прошивки в ПЗУ) описаны в разделе 8 спецификации. Рассмотрим 2 способа прошивки микроконтроллера на данной плате.
Для прошивки с помощью СОМ-порта не требуются внешние программаторы.
Прошивкой с помощью СОМ-порта можно оживить микроконтроллер если, например, заблокированы ПО выводы JTAG (SWD) и прошивка программатором становится невозможной.
При прошивке с помощью COM порта МК ожидает загрузки кода с интерфейса UART и запуск любого некорректного кода из других мест недоступен.
Для программирования МК через UART необходимо выполнить следующие действия:
1) Подключить mini-USB кабель к верхнему левому соединителю на отладочной плате LDM-K1986BE92QI, он подписан как "USB A USB UART". Включить питание платы и убедиться что в ОС Windows в диспетчере устройств. При необходимости установить драйвер USB-UART. В соответствии с рисунком 1, в системе подключенная отладочная плата должна определиться как СОМ-порт, например, на рисунке 1 это COM6, вы должны запомнить свой номер;
Рисунок 1. Подключенная к ПК отладочная плата (к соединителю USB-A) должна определиться как COM-порт.
2) На отладочной плате LDM-K1986BE92QI выставляем тремя большими черными переключателями с подписью "UDM mode M2...M0 101" значение 101, это крайние переключатели вверх, средний вниз. Когда переключатель включен вверх над ним загорается соответствующий светодиод. Данные переключатели определяют откуда будет загружаться программа МК.
3) Открываем программу USB-UART загрузчик и устанавливаем путь к прошивке *.hex, параметры COM-порта и режимы загрузки в соответствии с рисунком 2.
Рисунок 2. Настройки программы 1986WSD для прошивки МК через UART (COM-порт).
4) Нажимаем кнопку "Start+Run" должна зашиться в МК прошивка, он должен автоматически стартовать и загрузиться с ней. У меня получается успешно прошить далеко не с первого раза, если не помогает, нужно нажать кнопку с надписью "RESET" на отладочной плате (или выключить и включить питание кнопкой питания) и затем кнопку "Start+Run" в ПО 1986WSD. На рисунке 3 ниже показано неудачная и удачная прошивка МК.
Рисунок 3. Примеры неудачной и удачной прошивки МК.
После успешной прошивки МК должен моргать светодиод VD5 на отладочной плате LDM-K1986BE92QI
Более продвинутый способ прошивки МК чем через интерфейс UART является прошивка через интерфейс JTAG или SWD, дающие следующие преимущества в сравнении с использованием UART:
1) Прошивка МК занимает гораздо меньше времени, так как SWD, по умолчанию работают на частоте 4 МБит/сек, а UART 115200 Бит/сек.
2) Прошивка происходит прямо из среды разработки Keil, нажимаем клавишу F7 для сборки проекта и клавишу F8 для прошивки МК - бинго!
Для подключения интерфейса JTAG необходимо подключить к программатору 6 проводов, а для подключения интерфейса SWD всего 3 провода. Поэтому мы будем использовать интерфейс SWD и один из самых распространенных и дешевых отладчиков и программаторов ST-Link, приведенный на рисунке 4.
Рисунок 4. Программатор ST-Link для прошивки и отладки микроконтроллеров Миландр через интерфейс JTAG или SWD (цвет корпуса может быть любым).
После подключения ST_LINK к ПК и установке драйверов он должен быть отображен в диспетчере устройств в соответствии с рисунком 5.
Рисунок 5. ST_LINK в диспетчере устройств Windows.
У МК К1986ВЕ92QI два JTAG(SWD) интерфейса. Приведем таблицу с необходимыми соединениями отладчика и МК (отладочной платы LDM-K1986BE92QI).
ST-Link | JTAG A UDM MODE[2:0] = 001 | JTAG B UDM MODE[2:0] = 000 |
---|---|---|
SWCLK (вывод 2) | TCK (вывод 9 XS5) | TCK (вывод 9 XS6) |
SWDIO (вывод 4) | TMS (вывод 7 XS5) | TMS (вывод 7 XS6) |
GND (вывод 6) | GND (вывод 4, 6, 8, 10, 12, 14, 16, 18, 20 XS5) | GND (вывод 4, 6, 8, 10, 12, 14, 16, 18, 20 XS6) |
Нумерация выводов соединителей на отладочной плате LDM-K1986BE92QI приведено на рисунке 5.
Рисунок 6. Нумерация соединителей и выводов на отладочной плате LDM-K1986BE92QI.
Следует учитывать что выводы связанные с интерфейсами JTAG (SWD) также являются портами ввода-вывода и ряда периферийных устройств и нужно решать что использовать - JTAG (SWD) или периферию.
Заблокировать порты JTAG (SWD) можно если писать в их порты не единицы, что указано во втором абзаце пункта 16 спецификации микроконтроллеров серии 1986ВЕ9х и К1986ВЕ9х. Так, например, используя для прошивки МК интерфейс SWD от JTAG A мы блокируем только порты PB2 (TCK) и PB1 (TMS), но ниже приведенная запись в порт PB0, который не используется в SWD сделает невозможной дальнейшую прошивку или отладку.
MDR_PORTB->RXTX ^= (1 << 0); // Запись в PB0 заблокирует SWD использующий PB1 и PB2 т.к. если в них были при чтении регистра 1, то и записываться будут 1 - ЧТО ЗАПРЕЩЕНО!
Если такое произошло, исправляем программу, переключаем UDM MODE в UART (101) и перешиваем МК через UART. А что? Дурак и должен жить плохо!
Перепишем нашу программу с учетом защиты SWD от блокировок.
#include "MDR32F9Q2I.h"
#define PIN_LED 3 // Номер вывода светодиода
int main (void){
uint32_t val_b; // Переменная для хранения значения регистра B
for(int i = 0; i < 1000000; i++){} // Задержка которая даст нам время на прошивку через SWD, код блокирующий интерфейс может быть только дальше
MDR_RST_CLK->PER_CLOCK |= (1 << 22); // Разрешение тактирования порта B (п.14.7.8)
// Инициализация вывода со светодиодом, порта B как выхода.
MDR_PORTB->OE |= (1 << PIN_LED); // Вывод является выходом (п.16.1.2). Обязательно устанавливать в 1.
MDR_PORTB->ANALOG |= ((1 << PIN_LED)); // Режим работы - цифровой (п.16.1.4) Обязательно устанавливать в 1.
MDR_PORTB->PWR |= (1 << PIN_LED * 2); // Включить передатчик. Скорость фронта вывода - медленная (п.16.1.7). Обязательно устанавливать в 1, 2 или 3.
while(1){
for(int i = 0; i < 100000; i++){} // Задержка
val_b = MDR_PORTB->RXTX; // Считываем значение регистра B
val_b &= ~((1u << 1) | (1u << 2)); // Сбросить 1й и 2й бит в 0 (выводы SWD PB1 и PB2)
val_b ^= (1 << PIN_LED); // Инвертировать значение бита порта B со светодиодом
MDR_PORTB->RXTX = val_b; // Записываем значение в регистр. Теперь мы уверены что в PB1 и PB2 будут писаться нули, независимо от того что в них было при чтении.
}
}
Выше приведен пример программы с мигающим светодиодом и защиты порта SWD (JTAG A) от блокировки. Тут применено 2 вида защиты:
1) Сразу в начале функции main() идет задержка перед любым кодом и возможным блокированием порта SWD, дающая пару секунд на нажатие клавиши F8 (прошивки МК). Из минусов на те же пару секунд задерживается выполнение программы при старте.
2) В цикле while() применено принудительное зануление значений битов соответствующих SWD. Из минусов - код более громоздкий и медленный, но - всё чего-то стоит..
Поменяем бит со светодиодом на 2
#define PIN_LED 3 // Номер вывода светодиода
Компилируем прошиваем. Теперь мы точно блокируем вывод PB2(TCK) и интерфейс SWD.