На одном проекте нам нужно было поменять STM микроконтроллер на Linux модуль типа BeagleBone. Суть задачи заключалась в том, чтобы переподключить SPI шину, по которой были подключены модули устройства. Вроде бы, и драйвер есть, и шина работает, и модуль живой, но просидев не один день, ребята зашли в тупик.
Итак, по порядку:
Вторник
- Выяснено, что spi шина настроена на слишком большую частоту – 10 MHz. Максимальная частота, на которой работает микросхема измерения фидера, – 1.2 Mhz (рекомендуется 900 KHz). Скорость шины уменьшена.
- Выяснено, что на Linux модуле управление чипселект линией осуществляется внутри драйвера spi (аналогично, если бы на stm32 использовался аппаратный чипселект). Так как драйвер фидера рассчитан на самостоятельное управление чипселект линией, пришлось поменять функцию обмена с шиной и использовать другие функции драйвера Linux.
- Выяснено, что не совпадают настройки spi линии. СPOL = 0, CPH = 0, а необходимо СPOL = 1, CPH =1. Исправлено на нужные.
Все эти исправления были произведены во вторник. Микросхема, тем не менее, на попытку прочитать любой регистр возвращает 0xFFFF. Высоко-импедансное состояние, которое выставляется на линии miso после включения чипселекта и падает в ноль после его отключения.
Все измерительные приборы, включая осциллограф, были задействованы.
Тут уже и начались сложности. Были проверены все сигналы на всех линиях. Все линии spi выглядели нормально на осциллографе. Уровни сигналов, порядки байт соответствовали даташитам.
Возникла мысль: может быть, не хватает длительности начальной паузы после опускания чипселект линии и началом обмена. Она составляла порядка 125 микросекунд, так как управлялась внутри драйвера Linux.
По опыту, этой паузы вполне должно было хватать (в даташите микросхемы ATM90E36A длительность минимально необходимой паузы не указана). Но так как на stm32 пауза кратно выше, было принято решение поработать в этом направлении и исключить эту ситуацию.
Среда
- При изучении драйвера spi в Linux выяснено, что управление паузой после включения чипселекта в данной версии ядра ещё не реализовано, но в более новых версиях уже есть.
Смена ядра – операция сложная, потому было решено перейти на «ручное» управление чипселектом.
В драйвере Linux была произведена смена управляющего пина, и драйвер стал дёргать ножкой, ни к чему не подсоединённой. После было реализовано управление нужным пином через драйвер GPIO. Это заняло некоторое время, поскольку старый интерфейс управления GPIO пинами в Linux был задепрекейчен (помечен как устаревший и лишённый функциональности), и пришлось настраивать пин по-другому. Однако после всего этого микросхема так и не ожила. - Были проверены несколько модулей, они все одинаково не работали.
- Был заменен Linux модуль на stm модуль, дабы проверить работоспособность модулей. И они работали нормально.
- Прошивка на stm модуле была модифицирована, чтобы имитировать ту же самую последовательность работы с микросхемой, на которой проверялась работоспособность модуля Linux, дабы минимизировать разницу.
На stm модуле фидер отвечает, на Linux модуле – нет.
В ходе многочисленных проверок spi линии, были сфотографированы все этапы обмена.
И ёлки-палки, spi линия была идентична. Уровни, сигналы, последовательность бит и байт на cs, clock и mosi линиях. Скорость и паузы отличаются незначительно, то есть stm32 модуль и Linux модуль опрашивают микруху идентично. НО на Linux по-прежнему ответ 0xffff.
Проверено предположение, что именно на miso линии в случае с Linux модулем что-то висит и мешает передаче достоверной инфы. Miso линия была отключена от процессора, и на ней остался только осциллограф. И по-прежнему на висящей в воздухе линии при stm32 ответ от микрухи есть, на Linux – нет.
Дело к ночи...
- Проверено питание модуля мультиметром – норма.
- Начинаем проверять все остальные пины, что идут на модуль. Выясняется, что на модуль кроме линии spi и питания заходят ещё два сигнала от процессора – RESET и DMA (этот сигнал меняет в микросхеме режим работы с SPI slave на SPI мастер). Stm32 модуль на линию RESET выставляет жёстко 0, а c пином DMA вообще не делает ничего (там тоже ноль).
При проверке этих сигналов мультиметром при включенном модуле Linux выяснено, что на обеих ножках висит потенциал в 1.8 вольт.
При дальнейшем разборе стало понятно, что модуль Linux при включении не задаёт на эти пины нули, и потому микруха находится чёрт знает в каком состоянии. При попытке настроить нужные пины на 0 оказалось, что на этих ножках висит линия i2с, на которой, в частности, «сидит» модуль RTC, необходимый для работы. То есть пины заведены неправильно, и при включении микруха ловит обмен по i2c линии и подвисает.
Вот он триумф и радость! Всё стало на свои места. Два дня работы до полуночи завершились успехом!
Так как i2c отключать нельзя, решено просто отрезать на модуле эти две линии и соединить их наглухо с землёй, чтоб на них был ноль, и проверить.
Веселье наше было недолгим. Оно сменилось недоумением и горечью, так как после проделанного микруха продолжает отвечать 0xffff, но если подключить stm32 модуль, она отвечает нормально!
Проверены все ножки, входящие на модуль. Это питание, 2 пина i2c, что теперь отрезаны и сидят на земле, и spi шина, на которой сигналы от двух модулей идентичны (за исключением ответа). И больше ничего. Где влияние?! Куда ещё смотреть?! Столько всего найдено и исправлено, и всё равно результата нет.
Модуль переставлен в другой слот, уже просто чтоб проверить и это. Картина всё та же.
И вот на этом наши изыскания остановились.
Далее праздники до понедельника.
На выходных с ребятами поменяли частоту шины на 3 Mhz и, получив в ответ от микросхемы данные, отличные от 0xFFFF, исследования прекратили.
Понедельник
При проверке ответного значения выяснено, что оно не валидное. Значение скачает туда-сюда. Прочитали пару других регистров – та же история.
Далее стали проверять тайминги и уменьшили частоту с 3 Mhz сначала до 1.5 Mhz, чтоб проверить изменения таймингов и задержек, а потом и до 1 Mhz.
При уменьшении частоты до 1 Mhz (или ниже) значения начинают приходить валидными.
На этом шина заработала, модули устройства считываются. Дальше дело техники – дописать драйвер.
При выставлении частоты на 1.5 Mhz произошла ситуация, которая может пролить свет на ночь среды, когда после отключения ножек RESET и DMA от i2c микросхема фидера так и не заработала, и мы все пошли спать с тяжёлым сердцем.
При проверке таймингов с помощью осциллографа заметили, что длительность передачи 16 бит на линии clock равна примерно 1.1 us, хотя по расчётам должна быть в 10 раз дольше. Оказалось, что при выставлении настройки скорости в 1.5 Mhz (1500000) был случайно добавлен лишний 0, в результате фактическая частота шины была равна 15 Мhz. На такой большой частоте, естественно, микросхема не работает. И при этом наблюдался так хорошо знакомый нам эффект – в ответ приходила 0xFFFF.