Не могу назвать себя очень аккуратным и внимательным человеком, но тем не менее, за более чем 10 лет разработки ПО для встраиваемых устройств мне толком не удалось ничего сжечь или испортить. С одной стороны, стоит за это сказать "спасибо" моим коллегам — схемотехникам. С другой стороны, современная "умная" микроэлектроника имеет достаточно серьезную "защиту от дурака". Но пару дней назад произошел один интересный случай. Мне удалось превратить в "кирпич" микроконтроллер Atmel SAMD21G18AU, выполняя обычные манипуляции, описанные в user manual.
Как-то так получилось, что еще со студенческих времен меня учили, что "с Atmel работают одни дилетанты", поэтому использовать его не стоит. Аргумент весьма сомнительный, но по принципу "не читал, но осуждаю", нелюбовь к Atmel передалась и ко мне.
Однако в один прекрасный момент к нам пришел очередной заказчик и принес проект устройства, которое нужно доработать и для которого нужно написать "прошивку". Ядром этого устройства является микроконтроллер Atmel SAMD21G18AU. Так мне пришлось откинуть свои предрассудки и начать изучать данный кристалл.
Микроконтроллер оказался достаточно известным и распространенным благодаря ArduinoZero.
После изучения общих параметров я был очень впечатлен. Контроллер имеет мало общего со старыми атмеловскими семействами, работает на ядре Cortex M0 и использует мудреную систему конфигурации периферии, которой у него очень много.
Эта система позволяет гибко настраивать кристалл под широкий круг задач, но она же и повышает его "сложность" и отрицательно влияет на кривую обучения работы с ним (Arduino IDE я в расчет не беру :).
При этом Atmel имеет собственную программную библиотеку для работы со своими микроконтроллерами Atmel Software Framework. Дело хорошее, до тех пор, пока не начинаешь ей пользоваться :) Библиотека рассчитана для работы в IAR и Atmel Studio и содержит огромное количество драйверов, модулей и примеров почти для всех контроллеров Atmel… Но спроектирована и задокументирована она, на мой взгляд, достаточно плохо (попробуйте разобраться с ней сами)
Архитектура библиотеки спроектирована так, что все "завязано" на отладочные платы:
То есть чтобы использовать библиотеку для своей собственной платы, вам нужно сделать ее "описание" в определенном формате (весьма невнятно документированном) и поправить пару файлов (в частности, board.h). При этом, если вы хотите просто взять конкретный драйвер и использовать его в своем проекте, то вы столкнетесь с серьезными трудностями. Особенно если ваш проект сделан не в IAR или Atmel Studio. Придется долго разгребать зависимости модулей и вычленять необходимые файлы.
Этот-то процесс и погубил мой экземпляр контроллера. Мне нужен был драйвер Watchdog. Он в свою очередь тянет несколько других драйверов, среди которых драйвер Clock, занимающийся настройкой тактовых генераторов как для ядра, так и для периферии. Ну а Clock использует специальный .h файл, содержащий конфигурацию генераторов для конкретного устройства. И мне так "повезло", что мне попался не тот файл, который в итоге отключил мне тактовый генератор ядра, а заодно и модуля для работы с SWD.
SAMD21G18AU имеет два встроенных тактовых генератора и позволяет использовать два внешних. Модуль GENERIC CLOCK CONTROLLER имеет в своем составе несколько внутренних генераторов. Первый из них тактирует ядро, остальные используются для тактирования периферии. Для каждого внутреннего генератора можно задать источник (внутренний или внешний), множитель и другие параметры, среди которых есть "OnDemand". Он позволяет запускать генератор "по требованию", тем самым уменьшая потребление системы.
После перезагрузки SAMD21G18AU по умолчанию настраивает работу ядра от внутреннего генератора на 8 МГц, а остальные генераторы отключает.
Файл, который попался мне, заставляет драйвер Clock настроить тактирование ядра на внутренний 8 МГц'овый генератор, но при этом переводит его в режим "OnDemand". Но этот режим почему-то не срабатывает и генератор не заводится. Получается, что как только контроллер начинает выполнять код, он отключает себе тактирование.
При этом модуль работы с SWD тоже перестает тактироваться, а значит и перестает отвечать при попытке соединения. И никакие ухищрения не помогают поймать момент, когда процессор уже включился, но еще не успел отработать кривую настройку модуля GENERIC CLOCK CONTROLLER.
Можно было бы воспользоваться перепрошивкой через bootloader. Обычно в микроконтроллерах есть "зашитый" загрузчик, позволяющий программировать его как минимум через COM-порт. Но не тут-то было! Atmel перехитрил сам себя. Хотя использование bootloadr'а и предусмотрено, но из-за "гибкости" в настройках место, зарезервированное под него, может быть использовано для хранения исполняемого кода. И, похоже, это является настройкой по умолчанию.
То есть, чтобы работать с bootloader'ом, его нужно сначала "зашить" в контроллер. И конечно, в моем случае это сделано не было.
Самое забавное, что хотя на плате распаяны оба внешних кварца, в итоге ни один не работает. Подступиться к контроллеру не получается ни через SWD, ни через Bootloader.
В заключении истории хочу сказать, что я все-таки не обладаю глубокими навыками работы с данным микроконтроллером, поэтому, возможно, есть способ его "оживить". Может быть, кто-то мне подскажет решение проблемы, пока мы не отпаяли "кирпич" и не припаяли новый SAMD21G18AU?
p.s. Ну а моя нелюбовь к Atmel получила первый аргумент в свою пользу. Контроллер, позволяющий загнать себя в тупик комбинацией настроек, при этом не имеющий штатных средств восстановления — это как-то не солидно...
Комментарии (39)
Sergei2405
29.08.2016 10:12+2Как вариант попробовать разогнать SWD до максимальных частот и попробовать перехватить управление (остановить программу) до момента когда она стопит тактовые частоты. Или «поиграть» с настройками сброса «connect under reset». Перебрать отладочные шнурки типа Ulink/ULINK-pro/J-link…
AlexandrSurkov
29.08.2016 11:45+1Я пробовал только uLink. С ним ничего не получилось. Когда добуду JLink — попробую с ним.
golf2109
29.08.2016 11:07+2а что пишет Datasheet о режиме OnDemand — каковы условия для входа в него и выхода из него?
каким программатором-отладчиком пользуетесь?
в J-link есть режим Connect under Reset — может это поможет?AlexandrSurkov
29.08.2016 11:47У меня сейчас есть только uLink и соответственно uVision. Там перепробовал все режимы — не помогает. Тут же еще SWD. Он не все режимы полноценного JTAG поддерживает.
golf2109
29.08.2016 12:02+3Для STM32 мне помогло Debug->Connect & Reset Option -> Connect:under Reset Reset:HW RESET
vilgeforce
29.08.2016 11:16Внешние кварцы не помогают? JTAG или подобное есть?
AlexandrSurkov
29.08.2016 11:48Кварцы стоят, но они программно отключаются сразу после выполнения пользовательского кода.
Polarisru
29.08.2016 11:33+1еще со студенческих времен меня учили, что «с Atmel работают одни дилетанты»
Дальше можно не читать. Специалисты — такие специалисты!
Tsvetik
29.08.2016 11:54+1Неужели у этого МК нет ноги или комбинации для полоног стирания кристалла?
AlexandrSurkov
29.08.2016 11:54Похоже что нет.
Tsvetik
29.08.2016 12:01+1А это что?
http://www.atmel.com/Images/Atmel-42181-SAM-D21_Datasheet.pdf
пункт 13.7AlexandrSurkov
29.08.2016 12:20The Chip-Erase operation is triggered by writing a '1' to the Chip-Erase bit in the Control register (CTRL.CE)
Это программный сброс.Tsvetik
29.08.2016 12:34+9Там далее, по ссылке «cold start» можно узнать, что есть, так называемый «CPU reset extension».
После внешнего ресета CPU, если видит отладчик, то сидит и ждет записи бита в спец регистр CSRTEXT.
Пока отладчик этого не сделал, CPU не выйдет из ресета и программа в МК не запустится.
Поэтому копайте в сторону скриптов для вашего отладчика. После подачи ресета и до подачи CSRTEXT можно полностью стереть кристалл. Наверняка к вашей IDE такой скрипт уже прилагается, либо его не сложно написать самому.rsx11
29.08.2016 13:36+5Более того, этот CPU reset extension прекрасно описан там же в 13.6.2. Судя по всему, всё, что требуется, — это притянуть SWCLK к земле, пока отпускается ресет. Может, даже никаких скриптов или специальных отладчиков не нужно.
FloppyFormator
29.08.2016 12:00+2Можно аккуратно вскрыть кристалл и ультрафиолетом засветить ПЗУ, где хранятся настройки.
vehar
29.08.2016 13:36+1Ещё из вариантов:
— ултрафиолет+вскрытие = рентген без вскрытия. Или другое ионизирующее излучение достаточной мощности чтобы пройти через корпус
— пощупать его мощным высокочастотным эми
— аккуратно(!) пройтись высоким напряжениям по пинам контроллера (типа електрозажигалки, но на расстоянии, дабы не было пробоя). Это если совсем безнадёга :D — имеется риск сжечь что-то работающее(!)
А по хорошему — успеть программатором, как советовали. У STM32F4 (горький опыт) тоже есть такая фишка, если случается переход в какой-то глубоко спящий режим(точно не вспомню) а доступ только через SWD. Про Hwreset не скажу, т.к. обошлось без него.
Возможно для ATMEL есть ещё какие-то свои отладочные ср-ва
a_volkov1987
29.08.2016 13:36Не знаю в точности, как обстоит с кортексом, но серия mega у Atmel в случае ошибочно прошитого конфига источника тактирования (например вместо кварца выбрали RC-цепочку) тоже не поддается сбросу, если у вас нет программатора с выходом тактирования. При входе в режим программирования mega выбирает в качестве источника тактирования или источник, указанный в настройках кристалла или же тактируется внешним генератором, который входит в состав программатора (особо подчеркну, что не любой программатор имеет выход тактирования. Phyton'оновские имеют точно). Прочитайте внимательно даташит на контроллер, скорее всего его тоже можно сбросить подобным способом.
masai
29.08.2016 16:27+1AVR — это принципиально другая архитектура. Там тестирование задается жёстко фьюзами. У ARM нет фьюзов.
masai
29.08.2016 16:36Прошу прощения, мой телефон внёс правки. :)
Не тестирование, а тактирование, конечно. И я не дописал: у ARM нет фьюзов для жёсткого задания тактирования, это делает программный код. Собственно, об этом и речь в статье.
pftbest
29.08.2016 13:59+2Радиационно стойкие микроконтроллеры от Atmel сейчас очень популярны для малых космических аппаратов, и я бы не сказал что их дилетанты проектируют.
MyXoMoPz
29.08.2016 14:14+1Была аналогичная проблема на Stm32f100 при попытке переносе проекта из Cube'a в кокос, мк тоже не подавал признаков жизни. Из-за того что программатор был от VLdiscovery, не было возможности сделать Connect under Reset, просто потому что у программатора не было этого провода. Решилось так: прижимаем ресет, в утилитке нажимаем full chip erase, отпускаем ресет и мк очищается.
andi123
29.08.2016 14:15+1На старых добрых «мегах», всегда можно было воспользоваться HV-программированием и подключить выключенный SPIEN.
> Я пробовал только uLink. С ним ничего не получилось. Когда добуду JLink — попробую с ним.
Мдя. Видимо про OpenOCD, вы ничего не слышали?
Arcanum7
29.08.2016 14:46-2Стандартный высоковольтный программатор не? ВСЕ (поправьте если не прав) чипы от атмеля могут прошиваться через 12в программаторы.
Read datashee, Luke!masai
29.08.2016 16:50+2Стандартный высоковольтный программатор — это для AVR, у ARM по-другому всё, они программируются через SWD. Atmel ? AVR.
olekl
29.08.2016 15:24У ATMEGA похожая фича есть. В фьюзах есть биты, определяющие, откуда тактировать. И среди всех комбинаций есть неиспользуемые. И если таковую туда записать, то получается необратимый кирпич… А еще чтоб положительных эмоций себе добавить, попробуйте обратиться в их техподдержку :)
ulole
29.08.2016 18:41+1Не подскажете пример такой комбинации? Сколько я ни издевался над Мегой, пытаясь превратить ее в кирпич, всегда удавалось воскресить МК параллельным программатором (у меня Фитон)
olekl
30.08.2016 11:18ATMEGA165p, в байте Fuse Low четыре младших бита — CKSEL. По умолчанию там 0010 (внутренний клок), а зарезервированные значения — 0011, 0001, 0101, 0100. Значение 0000 — внешний клок (если записать туда 0000 при отсутствии внешнего клока — тоже весело, но все же решаемо).
unsvp
30.08.2016 11:22Классический вариант — в прошивке переключаемся на внешний кварц, который нераспаян. В поздних ревизиях чипов это исправили — RC генератор продолжает работать на низкой частоте и чип живет, хоть и очень медленно.
У некоторых чипов (например ATmega8) пин RESET совмещен с GPIO и фьюзом можно заблокировать RESET, что делает последовательное программирование и отладку невозможными.
Параллельное программирование спасает только если у вас все нужные пины или свободные, или толерантны к внешним сигналам. Такое в реальных схемах редко встречается — держать 16 пинов в качестве запасных довольно расточительно.ulole
30.08.2016 11:39Да, это понятно. Но подразумевалось, очевидно, что кирпичом становится сам МК, то есть никакими манипуляциями его уже не воскресить. А на самом деле имелось в виду, что запаянный МК в smd-корпусе с разъемом для последовательного програмирования становится кирпичом. А так, если корпус DIP(что нередко в любительских конструкциях) — достаем проц из панельки и восстанавливаем заводские настройки фьюзов параллельным программатором. Можно заморочиться и отпаять МК от платы и также воскресить параллельным программатором через специальный переходник(ZIF socket for SMD). Только не уверен, что МК выдержит еще один цикл запайки.
unsvp
30.08.2016 12:32Любительские конструкции и DIP-корпус — это отдельная тема…
В коммерческих же устройствах нет разницы — окирпичился МК или всё устройство, в любом случае — это возврат по гарантии со всеми вытекающими издержками. А если устройство нельзя перепрошить на месте или хотя бы в сервисе — значит, это кирпич. Фьюзы у ATmega пишутся как-то ненадёжно, бывает, что сдвигаются на 1 байт — сталкиваемся с этим даже в производстве. Что уж говорить об удаленном обновлении прошивки — каждый раз стресс. Порядка 80% возвратов по гарантии — сбой фьюзов при обновлении firmware. Дизайн старый, параллельное программирование невозможно, так что чипы выбрасываются и впаиваются новые. Если прибавить сюда так и не исправленный за 15 лет flash (непредсказуемая выносливость по числу перезаписей), то становится понятно, почему у Атмел репутация — «контроллеры для любителей».
Dark_Purple
29.08.2016 23:05Ну так это дело не в контроллере, «проблема с руками». Эдак любой контроллер убить можно. Как в анекдоте: «Один сломал, второй потерял.»
Имеет смысл на этапе отладки поставить после старта задержку на пару сек. чтобы отладчик успел зацепится.masai
29.08.2016 23:45Да контроллер не убит вовсе, а очень даже наоборот. Просто его теперь не запрограммировать, пока он работает. Но для этого и придумали Cold-Plugging (он же "Connection under reset" много раз тут упоминавшийся). Надеюсь, автору это поможет и он добавит в статью историю о решении возникшей проблемы. :)
armature_current
30.08.2016 09:08+1Имея опыт разработки аппаратных проишивальщиков/загрузчиков могу с большой долей уверенности сказать, что в любом контроллере в режиме Under-reset должен осуществляться опрос портов встроенного дебагера. Дебагер ждет появления определенной входной последовательности на выделенной для этого ноге, при этом тактируется по заводским настройкам. В зависимости от задачи, иногда ведь приходится задействовать и пины отладочного модуля в пользовательском режиме. Причем с конфигурацией через так называемые option-bits, которые загружаются еще до попадания на вектор Reset. Чтоб была возможность перепрошить контроллер каждый производитель просто обязан предусмотреть вход в отладочный режим в состоянии reset'a. Конечно же, если речь не идет об однократно-программируемых. Другое дело, что указанный внутрисхемный отладчик не полностью реализует необходимую последовательность подключения.
za121
Двойные стандарты.
za121
Прошу прощения, за мой коммент выше, ошибся вкладкой.
uSide
Это вторая статья, где я это увидел и в обоих случаях ваш комментарий заминусовали. Задумайтесь