Содержание

Как вернуть кирпич в рабочее состояние

Отладчик по Jtag перестает работать как правило в двух случаях:

  1. Сломано тактирования ядра. Т.е. некорректное ПО переключило тактирование на не рабочую частоту. Например, на HSE, предварительно не включив сам HSE. При этом ядро, обычно, видно в настройках отладчика Keil, но не работает прошивка памяти и не удается войти в режим отладки.
  2. Некорректное ПО переключает пины Jtag, ломая протокол, который на этих пинах использует отладчик. Этот случай возникает в микроконтроллерах, в которых пины Jtag совмещены с пинами GPIO - т.е. это 1986ВЕ9х, 1986ВЕ4, 1986ВК2х4, 1901ВЦ1Т. При этом микроконтроллер обычно не виден в настройках программатора совсем, как будто бы отладчик не подключен к плате. В портах GPIO, где активен Jtag нельзя выводить в пины jtag не нулевые значения. Запись "1" в пины Jtag приводит к сбою протокола. Поэтому при записи в регистр порта RXTX необходимо обнулять биты используемые Jtag! Такая защита используется в функциях SPL при работе с портами MDR32F9Qx_port.c, например
void PORT_SetBits ( MDR_PORT_TypeDef* PORTx, uint32_t PORT_Pin )
{
#if defined  (USE_MDR1986VE9x) || defined (USE_MDR1901VC1T)
	PORTx->RXTX = PORT_Pin | (PORTx->RXTX & (~JTAG_PINS(PORTx)));
#endif

#if defined ( USE_MDR1986VE3 ) || defined (USE_MDR1986VE1T)
	PORTx->SETTX = PORT_Pin;
#endif
}

Активируется защита в файле MDR32F9Qx_config.h

#if (defined(USE_MDR1986VE9x) || defined (USE_MDR1901VC1T))
 //#define USE_JTAG_A 
 #define USE_JTAG_B 
#endif

Помимо программного вывода в пины Jtag через регистр RXTX, нельзя назначать функции периферии на эти пины. Поскольку тогда периферия может выводить на Jtag линии свои сигналы и ломать протокол отладчика.

Режим BitBand реализует ядро, блокируя на время транзакции "чтение-модификация-запись" системную шину. Т.е. BitBand реализован аппаратно, но делает все тоже самое, что делается при "чтение-модификация-запись" отдельными инструкциями при прямом исполнении в коде. Отличие лишь в том, что шина заблокирована и между отдельными операциями "чтение"-"модификация"-"запись" не влезут какие-либо другие инструкции, включая прерывание. Это дает атомарность переключения бита, но не решает проблему с пинами совмещенными с Jtag. При аппаратном чтении пины так-же могут вернуть не 0-е значения в битах Jtag, а запись модифицированного слова нарушит протокол отладчика так-же, как если бы работа с битом шла отдельными инструкциями.

Режим BitBand с портом использующим отладчик не применим!

Cortex-M3 Technical Reference Manual, Bit-banding: Ядро уйдет в Stall, если во время операции Bit-Band код запросит новое обращение к системной шине, пока она выполняет текущую Read-Modify-Write операцию. Это говорит о том, что bit-banding реализует само ядро, а не периферия. Bus-Matrix в данном режиме только дешифрует обращение в bit-band регион на реальный адрес в памяти.

При работе по SWD достаточно обнулять при записи в RXTX только биты TDO и TMS, которые используются в SWD. Остальные пины JTAG (TDO, TDI, TRST) можно использовать на свое усмотрение.

Но защита JTAG в функциях библиотеки SPL рассчитана только на использование всех 5 битов. Т.е. функции SPL обнуляют либо все 5 бит на весь Jtag, либо ни одного. Поэтому в случае SWD необходимо работать с регистрами напрямую, либо поправить библиотечный макрос JTAG_PINS.


В обоих описанных случаях проблема заключается в некорректном ПО, которое чаще всего зашито во внутренней памяти Flash. Микроконтроллер, запускаясь, исполняет это ПО и, когда доходит до кода, ломающего отладку, перестает быть доступен для перепрограммирования - превращается в кирпич!

Внесение задержки

Из понимания этого сразу напрашивается простейшая мера предосторожности - необходимо, чтобы отладчик подключался до того, как исполнение кода дойдет до команд, ломающих отладку. Сделать это просто: достаточно в самом начале функции main вставить пустой цикл на пару секунд, а в свойствах отладчика выбрать - "подключаться с ResetTarget". Тогда при подключении отладчик будет сбрасывать ядро и, пока происходит рестарт и исполнение введенной задержки, отладчик успеет остановить исполнение и выполнить необходимые задачи - загрузить FLM для программирования или зайти в режим отладки. К слову, далее в режиме отладки по шагам можно найти инструкции, при которых происходит сбой, и диагностировать причину.

Это превентивная мера, задержку полезно использовать на начальной стадии реализации ПО. Т.е. при реализации тактирования и настройки пинов GPIO. После этого задержку необходимо удалить, чтобы не задерживать старт программы.

Рекомендованные настройки программатора представлены тут - Настройки программатора.

Не исполнение кода из Flash памяти

Если сбой уже случился и отладчик заблокирован, то необходимо запустить микроконтроллер так, чтобы не исполнялась программа, записанная в flash память. Для этого необходимо использовать варианты загрузки, где отладчик активен, а код читается не из flash. Как правило это "запуск с внешней шины" и "запуск в режиме UART загрузчика". (В серии 1986ВЕ9х эти варианты доступны только с отладчиком Jtag_B, поэтому желательно именно его оставлять доступным на плате для реанимации МК.)

При смене режима запуска важно снять все напряжения питания с МК, чтобы разрядился бит FPOR в батарейном домене. Т.е. необходимо отключить:

После этих манипуляций необходимо выставить режим "внешней шины" / "UART загрузчика", подключить отладчик и подать питание. При этом запустится начальный загрузчик, который будет "исполнять код с внешней шины" / "ждать команд по UART", код из EEPROM не будет выполнен, и отладчик останется доступен. Теперь можно стереть прошивку, вызвав EraseFlash из выпадающего пункта главного меню Flash (для среды Keil), либо прошить новую версию программы. Для запуска новой программы необходимо будет вернуть режим запуска из EEPROM.

Режим загрузки выбирается напряжениями на выводах MODE в момент старта микроконтроллера, т.е. только при подаче питания! При последующих Reset, в большинстве микроконтроллеров, режим загрузки заново не считывается. Поэтому при смене режима загрузки обязательно необходимо снимать все питание! Иначе микроконтроллер запустится в ранее выбранном режиме и стереть прошивку не удастся.

В случае UART загрузчика, код исполняется из масочного ПЗУ, где собственно и записан Bootloader (в информационной памяти для 1986ВЕ4У, 1986ВК2х4). Подробнее процесс загрузки описан тут - Загрузка микропроцессора и реанимация

Более наглядно данный вариант стирания прошивки описан в этой статье, на примере 1986ВЕ93У - Не работает JTAG A. Для прочих микроконтроллеров принцип аналогичный.

Перепрошивка по UART

В случае выбора режима загрузки по UART можно использовать не Jtag, а сам UART. Этот вариант связан с применением утилит, которые загружаются в ОЗУ в режиме UART загрузчика и могут прошить во FLASH новую пользовательскую прошивку. Такие утилиты представлены на форуме пользователем Vasili.

Либо можно на основе данной статьи реализовать свой "прошиватель" или "стиратель" flash памяти по UART - Прошивка программы в Flash и запуск через UART

UPD: Добавлена программа на Python для стирания памяти через UART - GitHub