Comments 95
Вы там мысли читаете, что ли? :D
Прямо сейчас отлаживаю девайс с L051 в основе.
P.S. Насчёт режима неиспользуемых выводов — читал, что best choice — неиспользуемые выводы на плате соединять с землёй, программно выставить режим выхода и притянуть вниз. У себя, собственно, так и сделал.
Я бы не стал соединять выводы прямо с землёй. Нужен хотябы токоограничивающий резистор на аварийные случаи. Что если программа дёрнет этот выход в лог.1? А если группу выводов соединишь, а они будут переключаться вразнобой? Получатся неприятные сквозняки.
Ну этот вариант да, с точки зрения ошибок программирования — самый опасный. Но я перепроверяю всё по 3-4 раза.
По умолчанию(в моём случае) выводы — аналоговые входы.
Последовательность инициализации у меня такая:
1. Включение тактирования порта.
2. Запись 1 в соответствующий бит BRR(переключение выхода на 0).
3. Включение режима OD.
4. Включение пина на выход.
И тем не менее есть вероятность самопроизвольного переключения содержимого регистра — от брака до космического излучения. Был даже один контроллер, который по мере работы переключал выходы к которым подключен индикатор в режим входа. И так постепенно гасли сегменты индикатора без видимой периодичности и логики. Перезапускаешь — и моментально всё становится в порядке. Поэтому, если можно защитить аппаратно, надо это делать. p.s. есть SMD-сборки резисторов по 4 в одном корпусе, места практически не занимают.
Эх, даже возразить нечего)
Да, надо, но это надо расширять BOM, что не всегда удаётся :(
Тогда самое лёгкое, что остаётся — перевод на аналоговый вход или в режим выхода и притянуть к земле.
Хотя, если подумать — ведь можно перевести пин в выход типа OD и заблокировать (в STM32 можно заблокировать изменение конфигурации пина). Тогда, если вдруг сменится состояние — пин просто повиснет в воздухе. Хотя, наверняка, сама блокировка пина может подглючить.
Вплоть до того что каждый переход в сон обновлять состояние регистров, если проблема и произойдёт то распространяться она будет только на один цикл сон-работа, ну это порядка секунды, минуты но не вечность. Вот такое небольшое дополнение в процедуру входа в сон многократно повышает живучесть схемы. Правда, это имеет свою цену — дольше переход в сон и конкретное потребление электричества в целом. Тут надо играться уже с вероятностями возникновения события «нештатное состояние» и сравнивать с дополнительным потреблением энергии на его преодоление.
Где-то видел статистику исследования возникновения ошибок в RAM серверов, там где память порядка 128Гб ошибки из-за космического излучения возникают с частотой порядка одной в минуту. И были ещё исследования в 80-е годы динамической памяти объёмом 1Мб без коррекции — там тоже оценивалась возможная частота ошибок от космического излучения в 1 ошибку в минуту на мегабайт(старая технология, по нормам 1.2мкм). Но сейчас все модули RAM с внутренней коррекцией ошибок и поболее тонким нормам. И тем не менее, ошибки при больших объёмах всё же просачиваются и не спасают даже современные методы коррекции ошибок, но по крайней мере ошибки хотябы регистрируются.
Так более тонкие нормы гораздо хуже с точки зрения сбоев от одиночных частиц) Они разве что от хлопка дверью не переключаются.
Наоборот. У ячеек по более тонким нормам сечение захвата меньше, вероятность попасть частицей в ячейку при прочих равных условиях гораздо меньше.
Зато количество ячеек намного больше и порог сбоя на порядок ниже. Поэтому вероятность попадания в каждую конкретную ячейку ниже, а вероятность сбоя в любой из имеющихся ячеек выше.
Ну казалось бы что должно быть выше… но она такая, ядерная физика. Сечение захвата у ячеек меньше, и это сечение не связано с физическим размером ячейки когда она исчисляется десятками атомных слоёв. На атомном уровне всё гораздо сложнее.
Вам казалось бы, а у меня цифры есть) И цифры почему-то говорят, что все там прекрасно пропорционально площади.
А ещё например при попадании частицы в чип, у которого «десятки атомных слоев», могут сбиться сразу несколько ячеек памяти одновременно. Я лично видел десять в эксперименте.
Эм, а какой выход в итоге? Просто обновлять состояния всех регистров каждый раз — фигня же какая-то. Или про регистры GPIO речь?
Выход… либо взаимный контроль, либо и вправду периодически «обновлять» регистры GPIO. Обычные регистры то и так в процессе обновляются, главное алгоритм разработать так чтобы ловил грубые ошибки и не допускал накопление ошибки из-за одиночных сбоев. Как это делают с обшивкой самолёта — вся обшивка разделена на небольшие сектора с уменьшенной прочностью, если где-то образуется трещина то она идёт только до границы сектора и дальше не распространяется. Такими же должны быть надёжные программы, с ловушками и ограничениями по распространению ошибки, обладающими свойством самовосстановления после сбоя.
Это в принципе не так сложно, но повышает надёжность и устойчивость программы к одиночным сбоям.
Например, алгоритм вычисления среднего методом подвижного окна. Среднее можно каждый раз считать по окну, суммировать все значения в буффере и делить на размер окна — это надёжный но ресурсоемкий алгоритм. Можно не считать каждый раз значение, а посчитать его только в первый раз а при каждом сдвиге окна на шаг — вычитать убывающее значение и прибавлять прибывающее, но из-за сбоя значение средней суммы может не отражать действительность и чтобы этого не происходило выполнять периодически полный рассчет суммы в окне, тогда если ошибка и появится она действовать будет максимум до следующего полного пересчета. Так и ресурсы экономятся и защита от сбоев осуществляется.
А какие регистры перезаписывать? GPIO? А почему только их? А как содержимое памяти контролировать? Испорченный указатель с достаточно высокой вероятностью приведёт к хардфолту, испорченный флажок можно искать вечность…
Очень напоминает анекдот "- почему здесь ищешь? — здесь светлее!".
Потому что испорченный указатель это лишь программная ошибка, а тут можно выжечь сначала порт а потом и часть кристалла. К тому же, это не защита от ошибок а устойчивость к внешнему воздействию. Указатель, приводящий к хардфолту как раз детектируется а опрокинувшийся регистр может находится в неподобающем состоянии до следующей перезагрузки, которая может состояться через год например.
Ну и да, эффективней сначала пошарить по светлым местам и только потом доставать фонарик и идти в темноту.
Главное — пользователю объяснить, что «это лишь программная ошибка, вы расслабитесь, кофейку попейте».
Поменявшийся флажок где-то в середине логики — это такой же фатальный сбой. В лучшем случае (если система хорошо спроектирована и отлично протестирована) устройство всё аварийно отключит. В худшем — включит что-то не то…
Вывод — контроллер, у которого с исчислимой вероятностью течёт память, использовать нельзя совсем никак вообще абсолютно.
Троировать, экранировать. Разобраться наконец, почему тут место такое проклятое…
> есть SMD-сборки резисторов по 4 в одном корпусе

А чем именно обычное «притянуть вниз» не устраивает и надо дублировать снаружи?
Ценой ошибки. Хотя в наше время… вероятность ошибки помноженная на стоимость контроллера(или ошибки?) может оказаться дешевле нескольких резисторов. А может и не оказаться. И ещё во времена 155-х микросхем существовали рекомендации не вешать выводы микросхем напрямую на шины питания — обязательно нужен резистор если требуется надёжность от схемы. Импульсные помехи они коварны, достаточно короткого импульса по шине(чтобы на индуктивности дорожки между выводом питания и входом микросхемы образовалось напряжение больше 0.3В в минус) чтобы привести к тиристорному защёлкиванию входа и выгоранию части кристалла. Конечно есть технологии изготовления микросхем лишённых этого недостатка но они дороговаты и обычно называют радиационно стойкими микросхемами.
Конечно есть технологии изготовления микросхем лишённых этого недостатка но они дороговаты и обычно называют радиационно стойкими микросхемами.
Радиационностойкие микросхемы в подавляющем большинстве случаев делаются на тех же технологиях, что и обычные, специальные технологии почти забросили из-за дороговизны их поддержания при обсутствии больших серий продукции. Различия между обычными микросхемами и защищеннными от тиристорного эффекта (чаще автомобильными и другими силовыми, чем радстойкими) в первую очередь в топологии и схемотехнике, а не в технологии.

PS Кремний на изоляторе здесь не считаем специальной технологией, потому что у него очеь много других применений, помимо встроенной защиты от тиристорного эффекта.
Я не предлагаю вешать на шины питания, я предлагаю оставить в воздухе, но притянуть к земле встроенным в чип резистором
Надо смотреть что там за подтяжка, её может оказаться недостаточно. Собственно, аналоговый режим пина это и делает.
1кОм хватит всем. А на самом деле, зависит от требований стойкости к ЭМИ, ведь даже 50Ом подтяжка с небольшой дорожкой может сработать как эффективная антенна для ЭМИ определённой частоты. Благо в быту такие поля не встречаются.
155-я серия давно на пенсии, а баечки живее всех живых…
Долбали как-то наши изделия наносекундными помехами (даже генератор специальный купили в сытые годы). 8 киловольт в разъем (RS232, USB) приводят к резету, пока TVS'ами всё не обвешаешь. Сгоревших приборов я что-то не припоминаю…
Это были не баечки, а рекомендации производителя, чем точно обусловлены — утверждать не стану, может быть «у нас так принято», но точно были в документации.
Что если программа дёрнет этот выход в лог.1?

Сгорит (точнее даже — может сгореть. Контроллеры нынче довольно живучие) опытный образец. Скатертью дорожка.
Главное, чтоб у заказчика не в нужный момент ненужный выход не включился. Дыма будет не на 5, а на 500 баксов…
Я слышал STM-ы как раз очень чувствительны к перегрузкам и перенапряжениям. Кроме того, закороченный вывод может привести к локальному разогреву кристалла. А посаженный на землю без резистора — словить спайк и тиристорное защелкивание.
В случае, который я описал далее — вывод просто повиснет в воздухе(OD же).
best choice — неиспользуемые выводы на плате соединять с землёй


С точки зрения энергопотребления разницы с AIN нет.
Олег, если есть возможность — хочется посмотреть разницу потребления между analog input / pullup (pulldown) input / output.
Вообще как-то неочевидно, что плавающий, по сути, аналоговый вход, лучше чем однозначно подтянутый.
Никакой измеримой. Ток утечки цифрового входа — максимум 50 нА, типовой будет как минимум десятикратно меньше, так что если вы не собираетесь у 100-ногого чипа на все ноги подтяжку вешать, это даже измерить в бытовых условиях будет трудно.

Плавающий аналоговый вход не лучше и не хуже цифрового.
Вопрос не в тему статьи, может знает кто как программно попасть в бутлоадер на STM32L073?
Переход по адресу *(uint32_t *)(0x1FF00000 + 4) запускает механизм выбора банка флэша и в результате — опять попадаем на User Flash memory Bank1.

Если кто-то готов предложить что-то типа этого — повторюсь, не работает:
volatile uint32_t addr = 0x1FF00000;
void (*SysMemBootJump)(void);
__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();
__set_MSP(*(uint32_t *)addr);
SysMemBootJump = (void (*)(void)) (*((uint32_t *)(addr + 4)));
SysMemBootJump();

хочу предостеречь:
лучше вызывать так

__attribute__( ( naked ) )
void jump_main(uint32_t stack, uint32_t func)
{
	__set_MSP(stack);
	(*(void (*)())(func))();
}

иначе если новый стек указывает на конец РАМ (что обычно и бывает),
но компилятор то не знает что стек сменился, и он при вызове функции может что нибудь в стек сохранить или из него считать, в том случае если функция делающая вызов бутлоадера будет обычной, не naked.
И в этом случае получим либо мусор в стеке либо вылет за пределы РАМ и прерывание исключения и то не всегда и на не на всех кортексах м — есть опции отключить такие прерывания.
Но когда функция «naked» то компилятор ничего не делает ни при заходе в неё ни при вызове других вложенных функций из неё. Мне это кажется более безопасным и в своё время помогло избежать очень пакостных багов и зависаний.
Спасибо! Но конкретно с этим камнем проблема не в отсутствии naked, а в реализации dual bank флэша. Точнее того, как загрузчик с ним работает.
А как это поможет попасть в загрузчик, а не просто перезагрузить прошивку?
Ну вообщем довольно легко, я конечно не знаю применимо ли это к STM32L073, но на stm32f103 я устанавливаю байт в RTC Backup Registers (например RTC_BKP_DR1) и проверяю его в загрузчике. RTC Backup Registers сохраняют своё значение при сбросе.

Вот специально писал описание, кто то просил, ну и себе оставил, на память.
github.com/denruss/stm32_MyDfu

П.С. Прочитал про STM32L073, у вас там 20-byte backup register
Системный загрузчик. В system flash. Не свой загрузчик. Со своим загрузчиком все очевидно.
Вы не сможете использовать загрузчик (именно ту часть, которая конфигурирует USB в DFU режим). Если у вас BOOT0 в «0», то запустится лишь алгоритм выбора банка памяти для загрузки (выбор производится по наличию корректного указателя на стек), при этом сначала проверяется второй банк, затем первый. Если оба банка не содержат прошивку, запустится встроенный загрузчик.
Загрузчик также запустится, если BOOT0 будет в «1» и не будет проверять банки памяти.
Т.е. в вашей ситуации BOOT0 в «0», раз вы работаете из внутренней памяти, и в том банке, в котором вы работаете точно есть правильный указатель на стек — следовательно в загрузчик таким образом не попасть.
Вся эта информация есть в AN2606.
Обратите внимание на FLASH OPTION BYTES. Иногда, зависит от проца и зашитого в нем бутлодера, проц прыгнет но загрузчик не сработает если есть защита от чтения-записи
1. Из приведенного рисунка никак не следует, что аналоговый режим отключает ТШ — это точно?
2. А все таки, почему измерение не в нижнем плече — и у TI в их отладке датчик стоит в питании и у Вас — просто потому, что потребуется минусовое питание для операционника, или есть еще основания? Хотя у TI операционник все равно имеет питание +12В и -12В.
Судя по рисунку, в режиме аналогового входа подключается подтяжка к + питания, триггер шмидта не отключается но оказывается обезврежен. Впрочем, это решение лишь частичное — всеравно будет существовать уровень помехи который приведёт к опрокидыванию триггера, например тыкнуть антенной радиостанции работающей на передачу в девайс(у меня бесперебойник сходит с ума на 20см от работающего 2Вт передатчика).

Почему тогда просто не сделать это ноги входами с подтяжкой к питанию? Видел как-то такой совет на хабре.

Встроенная обычно очень слаба и только повышает порог помехи которая может просочится на вход, например близкий статический разряд от человеческих рук(модель обычной человеческой статики — 100В@1кОм, это та что без видимых искр и под которую рассчитывают ESD-защиту).
Может, вы слышали проблему с ардуиной если понядеется на встроенную подтяжку вывода сброса(а там где-то около 50кОм) то она перезагружается от статики и даже от переключения реле рядом.
У меня на ардуино аллергия, извините. О рекомендациях Atmel слышал, что нужно подтягивать ресет. Но я и не знал, что внутри там еще своя подтяжка есть.
Судя по рисунку, в режиме аналогового входа подключается подтяжка к + питания

Судя по рисунку (Очень интересный рисунок, кстати. Первоисточник я не нашёл. Во всех reference manual'ах схема чуток другая) в режиме аналогового входа НЕ подключается подтяжка. Подключается некая паразитная фигня со встречно включённым диодом в комплекте.
Первоисточник я не нашёл


AN-не-помню-номера, посвященный как раз снижению энергопотребления. Чуть ли не единственный, в котором необходимость переключения в AIN вообще рассматривается более подробно, чем упоминанием в одну строчку.
Вероятно, речь о AN3430 How to achieve the lowest current consumption with STM32F2xx. Ревизия документа одна единственная.
Но там вообще нет картинки со структурой порта.
Ну да чёрт с ним, смысл везде одинаковый, а есть ли этот parasitic resistor, или нет — не суть важно. Главное, что он при номинальных режимах (напряжение на ножке не ниже земли и не ниже питания) не влияет.

UPD. Нашёл. Эта картинка из AN4899 STM32 GPIO configuration for hardware settings and low-power consumption. На сайте ST его нет (!!). Надо будет покурить этот документ…
В меня сейчас точно кинут тухлым помидором, но даже б-гмерзкий CubeMX предлагает загнать неиспользуемые ноги в аналоговый режим для экономии питания, причём не только для L семейства.
UT120C имеет разрешение 0,1 мкА при паспортной точности ±1% ±3 разряда

Погрешность, увы, указана для полной шкалы а это порядка 1мка в вашем диапазоне, что говорит о том что потребление контроллером измерено… на уровне погрешности измерения прибора и реальное запросто может отличаться на +-50% от того что в данном случае показал ваш прибор. Но это обычно не проблема, вы же измеряете токи для сравнения друг с другом на одном и том же приборе.

положения «mA» и «uA» практически во всех приборах на шкале рядом, гнёзда для измерения на обоих диапазонах одни, так что можно спокойно запустить контроллер на пределе «mA», а когда он уйдёт в сон, перещёлкнуться на «uA» — это происходит достаточно быстро, чтобы контроллер не успел потерять питание и перезагрузиться.

Токовый шунт на эти диапазоны прибора как правило один единственный и НЕ КОММУТИРУЕТСЯ вообще. Даже выключите прибор цепь не будет разорвана. Сделано это с одной единственной очевидной целью — чтобы на результаты измерения не влияло переходное сопротивление контактов переключателя(что механического, что электронного), и по этой же причине выводы измерения тока находятся отдельно.
Как вы себе представляете на одном шунте измерение тока от долей микроампера до 400 мА? Чисто технически? Вы либо на одном конце диапазона влетите в доли микровольта, либо на другом — в доли ватта.

Шунт, разумеется, переключается.
Не знаю, ни в одном из моих более менее серьёзных приборов шунт не переключается. Один резистор и один вход под диапазон до 200(400)мА, другой для диапазона 10А. Причем они включены последовательно и жестко связаны. Может быть в дешёвых приборах шунты и переключаются…
В хотя бы одном из ваших серьёзных приборов микроамперный диапазон вообще есть?

Не 200(400) мА, а микроамперный.
Хм, и правда переключается. На одном 5Ом/500Ом, на другом 2Ом/100Ом.
Но на третьем приборе, где разрешение в 10мкА там фикс шунт.
Для измерения есть ещё такая штука как логарифмический операционник. Скомпрессировать 5 декад а 10 бит как нефиг делать. Там и на 8 декад бывают.
Более того, тут даже подойдёт «ненастоящий», от AD, где как раз внутри батарея операционников с разным коэффициентом и схема коррекции. Честный, на паре транзисторов, такой как TI LOG112/LOG114 не нужен.
AD8305/AD8307, например.

Кстати, я совсем забыл (сам я для своей задачи выбрал TI LOG112), у них есть ещё и классические «двухтранзисторные», AD8304/AD8305, с токовым входом.

И трёхдекадный (если хватит) ADL5306.

В общем, выбор богатый.

Хорошая статья. Жаль только, что отладочные платы для LoRa у вас нельзя купить, чтобы на практике эти знания обкатать.

Там есть приемопередатчик диапазона 868 с достаточной шириной канала и выходной мощностью 16 дбм — все остальное в Ваших руках.
Этот передатчик умеет FSK и 802.15.4, сделать на нём LoRa-модуляцию… проблематично.
Конечно, задача непростая, даже если бы был доступ к радио ядру и его периферии, но если его совсем нет, то, пожалуй, что и нерешаемая.

Интересно, а если не использовать OS, то можно получить ещё меньшее потребление?

Большая часть статьи про режим STOP, как наличие ОС сказывается на потреблении в нем?

Ну не в режиме стоп, а в режиме ран конечно.
Статья же называется оптимизация потребления;)

В RUN потребление зависит от тактовой частоты и количества активной периферии, от выполняемой задачи — нет, соответственно и от наличия ОС. Для экономии используют комбинацию режимов RUN, SLEEP (для коротких простоев) и STOP (для длительных ожиданий и если нужные Вам ожидаемые события способны вывести из этого состояния). Наличие ОС влияет только на организацию переходов между RUN и SLEEP. При наличие ОС переход в SLEEP обычно выполняют при входе в idle задачу. Без ОС, теоретически, Вы сможете сэкономить, если все Ваши задачи, кроме начальной инициализации, выполните полностью в обработчиках прерываний, при выходе из которых сразу возвращаться в SLEEP (или в более глубокий сон, если это возможно и ждать долго). Возможность и целесообразность такого решения зависит от конкретной задачи.
Ну в общем я так и делаю, в беспроводных сенсорах.
Только ни когда не использовал OS, поэтому хотелось бы сравнить цифры.
В ОС тоже ничто не мешаёт выполнять хоть вообще всё на свете только в обработчиках прерываний (кроме того, что в куче задач будет или адская каша, или выполняющиеся десятки и сотни миллисекунд обработчики).
Tickless ОС (в которой нет периодического таймера, тикающего независимо от наличия и периода выполнения задач в шедулере) на потребление не влияет.
В кубе можно поставить галочку: переключать неиспользуемые пины в аналоговые. Однако, если делать через HAL то переключает, если делать через LL включает высокий уровень на выход.
Очень полезную железку сделали. Надо б заморочиться, сделать подобную — регулярно требуется, а нету — приходится мультиметром тыкать…
К слову, у TI есть ещё один вариант измерителя: на программном DC/DC, который считает время включения/выключения ключа. Попробовать руки не дошли, к сожалению (вроде б тексасовцы отладку эту дарили...).
Подробности: схема, описание.
Сейчас собираюсь сделать приспособу для измерения такую:
Шунт + усилитель с большим КУ. Один канал осциллографа вешаем на шунт напрямую, второй к выходу усилителя. По первому каналу осциллографа смотрим потребление в рабочем режиме, по второму во время сна. Может не так точно, но проще некуда.
Во-первых, точность будет низкая, осциллографы обычно всего лишь 8-битные, во-вторых, автоматический логгер даёт отличную возможность оставить железку в рабочем режиме на неделю, а потом придти и посмотреть её среднее реальное потребление.
Очень интересная статья, спасибо, почти через все описанное пришлось столкнуться.
Еще Вы не указали, что для серии L1 в блоке RTC есть еще один таймер — «Periodic auto-wakeup». Он также пробуждает контроллер из режима Stop, и его можно запрограммировать с периодом от 122 мкс до 32 секунд.
Он не подходит для организации нормальных часов, т.к. невозможно узнать, сколько натикало в данный момент.

Его можно для каких-то одиночных задач использовать, типа сброса сторожевого таймера.
Так он и не предназначен для этого, проснулись по сигналу считали RTC и радуемся. Или ведём собственный подсчет.
Какой смысл нам просыпаться по его сигналу, если потом всё равно приходится считывать RTC, чтобы понять, сколько сейчас времени? Какую задачу это решает?
Можно использовать и в других задачах, кроме сброса сторожевого таймера. По-моему, используется где-то в проектах именно такой механизм, когда необходимо проверять состояния входов с заданной периодичностью (например, при опросе различных счетчиков с импульсными входами).

Поясните, пожалуйста, момент, зачем нужно irq_disable перед WFI. И что делает irq_disable — cpsid i или что?

cpsid i

Чтобы ничего не вылезло между моментом, когда мы собрались засыпать, и моментом, когда мы не только проснулись, но и восстановили частоты (обработчик прерывания, пытающийся что-то сделать на проце, работающем на 65 кГц после LP Sleep — это душераздирающее зрелище).

Спасибо, очень наглядно. Увидел, что Вы это и в статье объясняли, просто я сразу не разобрался.

Only those users with full accounts are able to leave comments. Log in, please.