Stm32 с чего начать изучение...

Кто любит RISC в жизни, заходим, не стесняемся.
Аватара пользователя
Just_Fluffy
Вымогатель припоя
Сообщения: 532
Зарегистрирован: Ср июн 29, 2022 16:25:45

Re: Stm32 с чего начать изучение...

Сообщение Just_Fluffy »

JackSmith писал(а):Чем "-Os" не угодил?
Ну говорю ж, блондинко со склерозом... -Os, не -О3... Вы правы. Давно не писала ничего уже, работа на работе полностью удовлетворяет...
Белая и Пушистая
Аватара пользователя
JackSmith
Потрогал лапой паяльник
Сообщения: 332
Зарегистрирован: Ср мар 09, 2016 08:07:41

Re: Stm32 с чего начать изучение...

Сообщение JackSmith »

[uquote="Nranddek",url="/forum/viewtopic.php?p=4737789#p4737789"]Отладка возможна на всех уровнях оптимизации, другое дело, что можно, например, удивиться невозможности поставить breakpoint - это место может исчезнуть в результате оптимизации. Да и вообще, мне кажется странным отлаживание в одном уровне, а затем его изменить и получить иную версию кода.[/uquote]
breakpoint ставится, но в локальных переменных при трассировке пишет "optimized out"
КотПротон
Открыл глаза
Сообщения: 76
Зарегистрирован: Чт июл 31, 2025 20:41:39

Re: Stm32 с чего начать изучение...

Сообщение КотПротон »

Правильно. Эти переменные могут не сохраняться в ОЗУ и находиться в регистрах ядра. Исключаются лишние операции записи в ОЗУ и обратного их считывания оттудава.
Аватара пользователя
JackSmith
Потрогал лапой паяльник
Сообщения: 332
Зарегистрирован: Ср мар 09, 2016 08:07:41

Re: Stm32 с чего начать изучение...

Сообщение JackSmith »

отладчик без проблем из регистров читает, тут что-то другое
Изображение
с флагом "-Og" все нормально.
КотПротон
Открыл глаза
Сообщения: 76
Зарегистрирован: Чт июл 31, 2025 20:41:39

Re: Stm32 с чего начать изучение...

Сообщение КотПротон »

uint32_t interval = WAIT;
Причем, WAIT - это, судя по виду, константа. А константы - они оптимизируются и помещаются внутрь параметров инструкций.
А вон она - строчка 29 справа, с movw r6, #3000 - компилятор посчитал константные выражения и поместил их сразу в параметр инструкции.

Напишите перед объявлением переменной (обоих переменных) volatile и еще раз посмотрите.

:) самая частая проблема - "Памагите, я включил оптимизацию и на выходе получил 0 кБ кода, хотя там было написано 300 строк!"
Так что нечего на зеркало то пенять :) А то крик то подняли, ай-ой, фуфло, константные выражения в функции оптимизатор выкинул, ой-ой, что такое Всё норм, посоны, не истерите. Всё нормальдос. Если продолжает работать, значит, всё норм. Хуже было бы, если бы из тыщщи строк он оставил 0 строк. Это говорило бы о том, что погромисътъ был пьян:)
Аватара пользователя
JackSmith
Потрогал лапой паяльник
Сообщения: 332
Зарегистрирован: Ср мар 09, 2016 08:07:41

Re: Stm32 с чего начать изучение...

Сообщение JackSmith »

константа ни при чем.
до строки
int remainder=smart_delay(interval);
отладчик показывает значение переменной interval, а после "optimized out".
КотПротон
Открыл глаза
Сообщения: 76
Зарегистрирован: Чт июл 31, 2025 20:41:39

Re: Stm32 с чего начать изучение...

Сообщение КотПротон »

Так я и говорю - перед объявлением обеих переменных напишите volatile.
С другой стороны, если после оптимизации всё работает как надо без сбоев, то значит, всё в порядке, не кричите. Переменная была оптимизирована и помещена в параметры инструкции movw.
Можете проийтись по отладке в режиме Instruction Step Mode (по ассемблерному листингу) и посмотреть, что происходит с переменной.
Аватара пользователя
JackSmith
Потрогал лапой паяльник
Сообщения: 332
Зарегистрирован: Ср мар 09, 2016 08:07:41

Re: Stm32 с чего начать изучение...

Сообщение JackSmith »

[uquote="КотПротон",url="/forum/viewtopic.php?p=4737839#p4737839"]Так я и говорю - перед объявлением обеих переменных напишите volatile.[/uquote]
Зачем менять код, если можно поставить флаг компиляции "-Og" и все будет норм?
КотПротон
Открыл глаза
Сообщения: 76
Зарегистрирован: Чт июл 31, 2025 20:41:39

Re: Stm32 с чего начать изучение...

Сообщение КотПротон »

А вам шашечки или ехать? В смысле - смотреть на ваши любимые переменные, или чтобы код работал эффективно?
Аватара пользователя
JackSmith
Потрогал лапой паяльник
Сообщения: 332
Зарегистрирован: Ср мар 09, 2016 08:07:41

Re: Stm32 с чего начать изучение...

Сообщение JackSmith »

КотПротон, это "volatile" что ли делает код эффективным?
КотПротон
Открыл глаза
Сообщения: 76
Зарегистрирован: Чт июл 31, 2025 20:41:39

Re: Stm32 с чего начать изучение...

Сообщение КотПротон »

Нет, volatile показывает вашу любимую переменную, чтобы вы могли наслаждаться созерцанием её.
А еще, volatile - способ вернуть неожиданно исчезнувшие из бинарника 500 строк важного кода, которые вы так старательно писали, а негодяй-оптимизатор посчитал ваши труды никчемной тратой пространства на флеше :)
Аватара пользователя
JackSmith
Потрогал лапой паяльник
Сообщения: 332
Зарегистрирован: Ср мар 09, 2016 08:07:41

Re: Stm32 с чего начать изучение...

Сообщение JackSmith »

[uquote="КотПротон",url="/forum/viewtopic.php?p=4737846#p4737846"]А еще, volatile - способ вернуть неожиданно исчезнувшие из бинарника 500 строк важного кода, которые вы так старательно писали[/uquote]
нафига такой оптимизатор?
КотПротон
Открыл глаза
Сообщения: 76
Зарегистрирован: Чт июл 31, 2025 20:41:39

Re: Stm32 с чего начать изучение...

Сообщение КотПротон »

А нафига такой погромист, который забыл (не знает) про volatile? :)
Аватара пользователя
JackSmith
Потрогал лапой паяльник
Сообщения: 332
Зарегистрирован: Ср мар 09, 2016 08:07:41

Re: Stm32 с чего начать изучение...

Сообщение JackSmith »

[uquote="КотПротон",url="/forum/viewtopic.php?p=4737573#p4737573"]А у вас инит I2C зависит от дисплея. Нелогично. Либо писать один и тот же инит I2C и в дисплее, и во всех остальных устройствах, либо обращаться к иниту дисплея, чтобы настроить I2C, либо просто вынести инит I2C за пределы модуля дисплея..[/uquote]
на самом деле ничего страшного не будет, если инициализация дисплея будет включать инициализацию I2C модуля и связанные GPIO. даже если на шине более чем одно устройство.
Аватара пользователя
Just_Fluffy
Вымогатель припоя
Сообщения: 532
Зарегистрирован: Ср июн 29, 2022 16:25:45

Re: Stm32 с чего начать изучение...

Сообщение Just_Fluffy »

JackSmith писал(а):отладчик показывает значение переменной interval, а после "optimized out".
Значит далее в данном программном блоке данная переменная не используется, программный код обходится и без нее без потери функционала
Белая и Пушистая
КотПротон
Открыл глаза
Сообщения: 76
Зарегистрирован: Чт июл 31, 2025 20:41:39

Re: Stm32 с чего начать изучение...

Сообщение КотПротон »

ичего страшного не будет, если инициализация дисплея будет включать инициализацию I2C модуля и связанные GPIO
Ничего страшного для тех, кто пишет как бох на душу положит :)
Но для тех, кто думает разумом, это сигнал к исправлению неверной структуры программы.

Показываю на гипотетическом примере: на одной шине I2C висит дисплей и датчик температуры. Инит I2C и инит его пинов написан только в функции инита дисплея:

Код: Выделить всё

void InitDisplay()
{
	InitI2CPins();
	InitI2C();
	
	WriteI2C(0xAA);
}

void InitSensor()
{
	WriteI2C(0xBB);
}
Хорошо. А теперь запускаем:

Код: Выделить всё

int main(void)
{
	InitSensor();
	InitDisplay();
Ога?
Ога. Обычный кодописатель впихнет InitI2CPins(); InitI2C(); и в функцию InitSensor(). На всякий случай.
Думающий программист прикинет возможные последствия - дублирование кода, лишние логические связи, и просто вынесет фукнции инита за пределы функций инита дисплея и сенсора. Всё просто, если мыслить думать!
Аватара пользователя
JackSmith
Потрогал лапой паяльник
Сообщения: 332
Зарегистрирован: Ср мар 09, 2016 08:07:41

Re: Stm32 с чего начать изучение...

Сообщение JackSmith »

[uquote="КотПротон",url="/forum/viewtopic.php?p=4737857#p4737857"]Обычный кодописатель впихнет InitI2CPins(); InitI2C(); и в функцию InitSensor(). На всякий случай.[/uquote]
грязные инсинуации.
[uquote="КотПротон",url="/forum/viewtopic.php?p=4737857#p4737857"]Думающий программист прикинет возможные последствия - дублирование кода, лишние логические связи, и просто вынесет фукнции инита за пределы функций инита дисплея и сенсора.[/uquote]
поздравляю, вы открыли распределительный закон из второго класса
Just_Fluffy писал(а):
JackSmith писал(а):Значит далее в данном программном блоке данная переменная не используется, программный код обходится и без нее без потери функционала
:)

КотПротон, девчонка шарит лучше тебя. надеюсь тебе стыдно?
КотПротон
Открыл глаза
Сообщения: 76
Зарегистрирован: Чт июл 31, 2025 20:41:39

Re: Stm32 с чего начать изучение...

Сообщение КотПротон »

я написал, что переменная была оптимизирована и перенесена в параметр инструкции movw r6, #3000, и даже показал, где она находится. Если вы не шарите в ассемблерном тексте и слабо понимаете написанное, то это исключительно ваша личная беда.
КотПротон
Открыл глаза
Сообщения: 76
Зарегистрирован: Чт июл 31, 2025 20:41:39

Re: Stm32 с чего начать изучение...

Сообщение КотПротон »

Пролистывая на досуге форум, наткнулся еще на один опус. В целом, товарищ погрузился в глубины, но навалял таких дров, как и в предыдущем разобранном примере. Код изобилует оверинженирингом и не очень хорошим пониманием того, что и для чего автор пишет. Такое впечатление, что он пишет наугад и возникшие проблемы решает наваливанием, а не разгребанием каши, пытаясь применить весь инструментарий языка, который он узнал.
Всё-таки, от написания лапшеобразного кода программиста должно удерживать знание принципов построения взаимосвязей и логики. То есть, когда ты понимаешь, что ты хочешь получить на выходе, ты выбираешь путь и инструменты именно те, которые минимально нужны для достижения цели. А не так, как там - наугад, не видя, что в конце.

Вот что представляет тот товарищ в виде схемы:
СпойлерИзображение
Похвала ему в том, что он составляет хоть какие-то схемы, это несомненно ценно.
Правда, есть там функциональная ошибка - unlock() в GPIO не будет работать, поскольку механизм блокировки настроек пинов не подразумевает разблокировки вообще. Блокируются они до следующего перезапуска после сброса.

А вот дальше портянка кода - довольно жуткое зрелище именно по причине неверного построения логики. Автор использует инструменты языка без понимания того, зачем он их использует в конкретной задаче.
Суть опуса - банальнейшая работа с портом и пинами на плюсах. И в целом, если по уму, это реализуется значительно проще. Значительно. Единственная не слишком красивая штука - это виртуальный параллельный порт с вариативным шаблоном списка пинов. Но виртуальный порт - это не аппаратная часть, он немножко на другом уровне. А в остальном, всё делается сильно проще.

Во-первых, прежде чем наворачивать списки параметров шаблона класса, надо включить голову и подумать.
Автор предлагает:

Код: Выделить всё

template<uint32_t GpioID, uint32_t PinsMask, typename TPM = STM32Fx_MODE::NotDefined,
         uint32_t pwr_moder=0, uint32_t pwr_ospeedr=0, uint32_t pwr_pupdr=0>
class TSTM32Fx_GPIO : public GpioTemplate<GpioID, 16, PinsMask, TPM> 
Но если подумать - а что вообще может быть общего у всего порта GPIO с его 16-ю пинами? Что общее вообще у всех этих пинов? А общее и неизменное у них только одно - буква в имени порта, или иначе говоря, базовы адрес регистров. Так вот этот параметр и следует выносить в шаблон для всего класса Gpio. Ну и во-вторых, имена классов надо задавать попроще, без несущественных уточнений: template<char Name> class Gpio; Всё, больше там ничего не надо, просто, понятно легко запоминается и кратко пишется. Маска пинов в классе аппаратного порта не нужна, она ставится в методах, а не в общем классе. Наследования так же не нужны, ибо описывается класс для работы с хардварным портом GPIOx как он есть, не придумывая того, чего в нем нет.
Для описания виртуального параллельного порта с произвольным набором пинов должен быть отдельный класс, работающий через класс аппаратного Gpio, и виртуальный порт может быть не ограничен максимум 16-ю пинами и не ограничен одним хардварным портом. И это - правильная логика взаимосвязей. Вообще, виртуальный параллельный порт довольно редко используется, можно по пальцам пересчитать случаи его применения. Но ладно.

Код: Выделить всё

_static_always_inline_ void write(uint32_t data)  // Тут вроде uint16_t надо
Да не "вроде", а точно там uint16_t надо. Сами ж написали в static_assert, что ширина порта максимум 16 пинов.

Дальше идут мелкие ошибки, такие как

Код: Выделить всё

_static_always_inline_ void toggle()
  {
      base()->ODR = ~base()->ODR;
и нелогичности

Код: Выделить всё

_always_inline_ TSTM32Fx_GPIO& operator=(const TSTM32Fx_GPIO& gpio)
  {
    write(gpio.read());
зачем копировать данные со входов одного Gpio в выход другого Gpio? На практике это вообще вряд ли когда будет использовано. Я не припомню ни единого случая, когда прочитанное со входов одного порта тут же без изменений передавалось на выход другого порта. А писать "мёртвый код" - лишь замусоривать класс. Этот мусор лишь ради дешевых понтов, или когда платят за кол-во строк, как у индусов. Индусский код - вот правильное слово для характеристики написанного автором. Индусский код. Участники форума подозревали это, но, к сожалению, не смогли аргументированно объяснить автору.

Так же есть каша в задании конфигурации пинов.
Конфигурация пинов описывается сильно проще. Опять же, надо посмотреть на конечную цель - какие есть режимы пина. А их 4 штуки - аналоговый, цифровой вход, цифровой выход и альтернативная функция. В аналоговом режиме нет настраиваемых параметров. В режиме цифрового входа - enum class InType {HiZ, PP, PD}, в режиме цифрового выхода - enum class OutType {PP, OD} и enum class Speed {LOW, MED, HIGH, VHIGH}. В режиме альт.функ. добавляется номер ф-ции, который при желании можно оформить аналогично в виде списка имен.
Если хочется конфигурировать за один раз разные пины в разные режимы, то тогда класс Gpio должен предоставлять открытый интерфейс для прямой записи регистров MODER, OTYPER и тд. как они есть. А вот сборку значений для этих регистров из отдельных пинов проводить следует вне класса Gpio. И тогда уж тем более в шаблоне класса Gpio не должно быть упоминания о режиме пинов, поскольку это будет нелогично, что режимы пинов - разные.
Хотя на практике чаще требуется конфигурировать в один режим несколько пинов. Например, SDRAM с её более чем 50-пинами в максималке требует одинаковой конфигурации используемых пинов. При этом, на одном аппаратном GPIO может находиться более половины пинов для нее.

Ну и в завершении, вместо

Код: Выделить всё

#ifdef GPIOA
  MAKE_PORT(A,PWR_CFG_A)
  MAKE_16PINS(GpioA,A)
#endif
напишите просто и коротко: using GpioA = Gpio<'A'>; Не нужно "создавать" порт и "создавать" его пины, всё уже создано производителем МК. Нужно только реализовать методы работы с ним.
Пример с "созданием" порта я видел когда-то много-много лет назад. Не знаю, чья это была идея, но автор разбираемого здесь опуса, как видно, пошел тем же путем. Чья-то ошибка распространилась в головы и других начинающих.

И если автор пишет, что
При том что самая жесть на самом деле слева от черты.
то я даже не представляю, что у него творилось в голове, когда он всё это писал :) Вот уж и правда - "Горе от ума" :) Автор пытается применить сразу все инструменты, которые он только что узнал.
Есть расхожая фраза: "Keep it simple, stupid". Что в переводе означает: "Пиши проще, чувак!" :)
Adrift
Вымогатель припоя
Сообщения: 539
Зарегистрирован: Вт окт 01, 2024 15:22:33

Re: Stm32 с чего начать изучение...

Сообщение Adrift »

BusMaster, ну сколько можно? )
Ответить

Вернуться в «ARM»