Не могу назвать себя очень аккуратным и внимательным человеком, но тем не менее, за более чем 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 получила первый аргумент в свою пользу. Контроллер, позволяющий загнать себя в тупик комбинацией настроек, при этом не имеющий штатных средств восстановления — это как-то не солидно...
Update:
Продолжение истории читайте тут.