Открыть коробочку с такими платами и быстро взять одну для решения каких-то задач — в порядке вещей. Именно так, недавно я взял очередную плату, прошил уже хорошо отлаженной и проверенной «прошивкой» и… получил неопознанное USB-устройство. Взял другую плату, «прошил» её, там устройство заработало. Тут бы делу и конец, но интересно же, в чём дело. Поэтому, как пришли выходные, я занялся детальным исследованием, почему же она не работает.
Вообще, перед тем как «прошивать» платы, я убеждаюсь, что тест, влитый производителем, работает: светодиод мигает. Так что я был уверен, что процессор, в целом, жив. Что же тогда виновато? Возможно, линии USB либо кварц.
Линии все были в порядке, кварц не запускался. Но он может не запускаться по множеству причин. Его запуск производится программно, уже в недрах функции main(), Ну и прекрасно, начинаем отладку программы.
Всё бы ничего, но на функцию main() отладчик не выходит. Программа «висит» где-то между запуском и этой функцией.
Останавливаем программу: вполне ожидаемо, мы находимся в обработчике HardFault.
Что же привело нас сюда? Сбрасываем счётчик адреса:
И начинаем аккуратно шагать по программе. Вот на этой строке всё умирает, используй мы хоть операцию Step, хоть Step Over.
Весёлый Keil… Ну, да ничего. Сбрасываем всё в очередной раз (RST), щёлкаем «мышью» по окну дизассемблера и шагаем там. В этом случае, мы можем понять, что всё умирает внутри функции __scatterload.
Вообще, если всё умирает в этой функции, уже повод глянуть, не перепутан ли тип контроллера. Но нет, всё верно (настройки я тоже перепроверял, но эта прошивка в других платах же работает).
Хорошо. Снова всё сбрасываем и трассируем уже эту функцию. Через несколько проб, зависаний и сбросов находим виновную строку…
Да-да. Умирает всё при сохранении регистров в стеке. При этом слева видно, что SP равен 0x200030A0. Смотрим документацию на контроллер:
Смотрим, какое окно выделено для SRAM:
Всё верно. Указатель стека (SP) находится в разрешённом диапазоне. Так что же виновато? Попробуем нахально подменить значение SP с 0x200030A0, скажем, на 0x200020A0, благо отладчик это позволяет… Чпок! Зависание в указанной строке прекратилось! Значит, у нашего кристалла памяти не 20 килобайт. А сколько? Проверив несколько раз, выясняем, что последнее работающее значение SP равно 0x20002800. То есть, 10 килобайт. Это соответствует кристаллу STM32F103C6. Перед нами перепиленная микросхема. Увы.
Всё бы ничего, но платы из этой партии в моей немаленькой коробке легко отличить. У них особый цвет джамперов и очень красивый изумрудный светодиод (у остальных — менее приятный оттенок зелёного). Поэтому они легко выделяются из кучи остальных плат. Разумеется, я их проверил. Разумеется, перепилена вся партия (я брал десяток).
Что с этим делать, не ясно. Когда мне пришли в десятке плат три штуки, у которых не работал штатный тест: не мигал светодиод (поэтому я теперь проверяю их не выборочно, а тотально), я неделю бодался с продавцом. Он «включил дурочку». Постоянно интересовался, что я хочу сделать, обещал помочь советами. А я ему вновь и вновь повторял, что я тупо подключил к питанию, семь плат мигают глазом, три — нет. Значит, они дохлые. А он снова свою шарманку. И так неделю. Но там же всё было очевидно. Не проходил штатный тест. Здесь же штатный тест проходит, ему много памяти не нужно. Как доказывать, что пришла подделка, не ясно. А если и удастся доказать, то всё равно же по правилам Ali Express, надо отправлять товар назад. В общем, выглядит всё, как безнадёга. А главное, конечный продавец не имел злого умысла. Я у него брал ещё одну партию, уже позже. Там всё хорошо. Его самого подвели.
Так или иначе, информирую общественность, что вот так бывает. Проверяйте платы не только на общую работоспособность, но и на реальные характеристики. Правда, что делать при несовпадении, не ясно.
Статья имеет ещё одну практическую пользу. Она показывает, как можно быстро найти причину, почему вдруг плата не работает, если дело не в полной неработоспособности контроллера (он откликается по отладочному порту SWD).
Источник