Добрый день, после lpc, захотелось познакомится с stm32, и тут возник вопрос, в lpc для работы всего и вся, я использовал настройку регистров через явное обращение к ним, в stm32 же есть удобная обертка SPL, так вот какой путь будет правельнее, писать как раньше или использовать удобную либу, на которую некоторые грешат?
SPL
плюсы:
1. Приемлемый уровень абстракции между разными камнями и семействами, есть мануалы как переводить софт с одного на другое семейство стм32 и в них описан ТОЛЬКО SPL
2. Он понятнее чем запись в регистры, особенно если нужно наработки использовать потом через пару лет или другим человеком.
3. Сама фирма производитель тестировала чипы именно на SPL и значит порядок работы с периферией что заложен в SPL даст существенно меньше глюков чем любой другой.
4. В SPL интуитивно понятный и можно писать "на деревню дедушке", т.е. DAC_deinit() например зная что ADC_DeInit() существует значит и другое есть
5. В SPL всё таки много наработок - в множестве функций есть очень тонкие моменты и ньюансы которые уже сделаны и при работе с регистрами на них точно напорешся и потратишь не одну неделю.
МИНУСЫ:
1. SPL медленный, особенно ножкодрыганье - но он для этого не предназначен вообще то и ждать от него скоростей в пару тактов глупо. Да и для 99% задач SPL достаточно быстр. Как решение проблемы использовать побитовый доступ для ножкодрыгания, или один раз через SPL настроил что надо, сохранил все значения регистров в временные переменные и одним memmove просто скопировал в блок регистров сразу всё - максимально быстро особенно для ДМА которой надо дофига всего сделать.
2. SPL толстый - жрёт много флеша, решается сия проблемма превращением части функций в инлайн вариант, тогда отпадают все проверки для всех блоков переферии и код уменьшается в 3-5 раз но только если он использован разово. Можно напороться на особенности инлайн функций и прочие недостатки. Но для 99% задач размера флеша хватает и садить SPL на диету не нужно или просто глупо.
3. код SPL громоздкий ... ну вы батенька WinAPI не видели и другие высокоуровневые языки.
4. SPL написан с учотом что кодить на нём будет профессионал Си и такие ляпы как забыть очистить структуру от мусора стека подразумевается что профессионал не сделает, но если новичок допускает их то сам дурак и можно долго на форумах вонять что SPL гавно - руки от этого не выпрямятся.
> SPL толстый - жрёт много флеша
Эта проблема хорошо решается опцией компилятору (аля --gc-sections у gcc или --feedback у Keil). Выключив USE_ASSERT тоже пару килобайт можно сэкономить.
А вот инлайнить SPL (если для этого надо руками в код библиотеки лезть) - это, я считаю, нехорошо.
Amomum: "инлайнить SPL" ТОЛЬКО когда другого не остаётся, например когда пишешь загрузчик в 4к, а превращать код в шифровку (на асме или прямой доступ к регистрам) ещё глупее, код нужен для людей и чем меньше стилей тем лучше. пусть уж будут те же самые структуры и функции что и в остальном проекте и пофик что с суфиксом XXX_inline или ещё как, зато переносимо и изменения удобно применять к всем. А изменения будут.
Amomum: -O3 вреднее чем -О2. Потому что компилятор на О3 разворачивает циклы и в угоду скорости многие вещи делает более громоздко (заполнения структур, математика и тд - не делает скрытых мини функций а всё пишет тупо в линию много раз).
Во вторых "любую функцию заинлайнить может", только ту что статичная в пределах одного Си файла, а не статичные он может как раз раздублировать - одна версия для всех видная извне, а вторая версия инлайном идёт где попало внутри одного объектника/си файла. Компилятор GCC для разных си файлов вызывается отдельно, и о коде в других Си файлах не знает вообще.
Просьба давать те советы которые были проверены на практике, ок?
Mirn: обычно у компилятора можно выбрать оптимизацию по размеру или по скорости. Что у конкретного компилятора сделает -О3 по-умолчанию, зависит от конкретного компилятора.
Замечу, что я предложил "попробовать".
Amomum: эээ, я вообще то про Си говорил, а не си++, они процессингом при компиляции отличаются как небо и земля, про с++ спору нет.
Да в GCC для си, есть ещё очень скрытый пакостная особенность на -О3: функции то он инлайнит особенно в цикле, т.е. цикл из 4 вызовов функции приведёт к дублированию её тела четырежды ... но все параметры и локальные переменные так же будут ПЕРЕД этими 4 телами распределены в стеке, т.е. если функция жрала 64 слова в стеке на -О0 ... -О2, то на -О3 она скушает 256 слов после такого разворачивания, а часто для СТМ32 стек делают в 256 слов (старые кейлы, кокосы, эклипсы и тд), т.е. порча данных рядом с стеком гарантированна и трудно выловима
Amomum: хех а вот про это не знал "-flto" всего один раз сталкивался с тем что старый gcc не работал с этой опцией, у нас 2/3 изделий это всякое старьё которое надо скорее сопровождать и их объём настолько мал что апгрейдить компилятор до 201х версий и не выгодно и не интересно (часть из них - мои первые учебные по АРМам которые внезапно продаваться стали сами). И как то само собой получилось что настройки передались из старых проектов в новые и в принципе всем был доволен.
Спасибо за апдейт знаний
Amomum: как понимаю -flto появилась после 2012ого, а нормально заработало в https://launchpad.net/gcc-arm-embedded где то в 14-15 году судя по отзывам и то надо с осторожностю?
Mirn: к сожалению, практическим опытом я с вами поделиться не могу; я gcc использую только для самопроверки. Но вообще - гарантий-то на него никаких не дается, поэтому вообще все надо с осторожностью. Особенно в embedded.
На SPL сам ST уже грешит, поэтому придумали HAL. Но порой, ни там ни там не находится необходимых функций. Поэтому приходится делать огород из библиотеки и своих функций работы регистрами.
Сам пишу на какой-то дикой смеси из вырезок из HAL и самописных регистровых обращений. Вторые преобладают.
В некоторых местах архитектура самого HAL достаточно странная и ставит буквально в тупик. Например, ETH_HAL_ReceivePacket так и не удалось заставить работать по причине того, что он просто плохо описан.
Пришлось ваять свои шустрые велосипеды.
С отправкой было легче, но тоже перехожу на более легковесные свои функции.