STM32 fast start. Часть 2 Hello World на HAL, отладка в Atollic TrueSTUDIO

  • Tutorial
В прошлый раз мы осваивали создание нового проекта при помощи STM CubeMX первую часть можно найти здесь.

Для тех, кому лень перечитывать — закончилось все тем, что пустой проект успешно собрался.



В данной части напишем простейший пример Hello World на HAL, посмотрим как запускать и пользоваться отладчиком, ну и выясним, сколько же памяти кушает наша программа, которая в этой части будет написана на HAL.

За основу берем все тот же пустой проект, который инициализировали в прошлой части.

Для того, чтобы помигать светодиодом — нам необходимо придерживаться следующего алгоритма:

  1. Установить на ножке микроконтроллера состояние, инверсное текущему. То есть был 0 — ставим 1, был 1 — ставим 0 и тд.
  2. Подождать N количество микросекунд и вернутся к шагу 1.

Для того чтобы выполнить первый пункт — нам необходимо указать компилятору к какому пину и порту подключен светодиод и какой функцией делать инверсию его состояния.

Сначала найдем, куда мы подключили светодиод.

В файле main.c, сразу после вступительных комментариев, которые нам любезно написала компания ST — имеется строчка, для подключения заголовочного файл main.h



Нажимаем на эту строку правой кнопкой и находим пункт Open Declaration



Нажав на него — мы переместимся в файл main.h

Где найдем наши декларированные названия пинов и портов.



Помните, в первой части при инициализации вывода светодиода PC13 — мы заполняли поле User Label и вписывали туда CLOCK_LED?

STM32CubeMX при генерации проекта учел наши пожелания и теперь вместо абстрактных GPIO_PIN_13 и GPIOC мы можем обращаться к своему светодиоду через более понятные для восприятия CLOCK_LED_Pin и CLOCK_LED_GPIO_Port.

С тем — чем будем управлять — разобрались.

Теперь ищем функцию, которая умеет менять состояние нашего GPIO на противоположное.
Для этого в дереве проекта в левой части экрана — находим файл:

Drivers -> STM32F1xx_HAL_Driver -> Inc -> stm32f1xx_hal_gpio.h

В нем очень много всего, но нам нужны описания функций, которые идут в блоке /* Exported functions */

Находим там функцию

void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin);

Это как раз то, что нам необходимо.



Чтобы светодиод мигал постоянно — необходимо разместить вызов нашей функции в main в теле основного цикла программы.

А для того, чтобы различать мигания — добавить после этого задержку при помощи функции HAL_Delay(500);

В данном случае задержка будет 500мс.



Кстати, функция HAL_Delay описана так же в

Drivers -> STM32F1xx_HAL_Driver -> Inc

только в файле stm32f1xx_hal.h
То есть чтобы помигать светодиодом — нам потребовалось написать всего 2 строчки кода.
Если мы сделали все правильно — можно попробовать запустить отладчик и посмотреть как выполняется программа.





Перемещаться по коду программы можно при помощи кнопок F5 и F6
При этом кнопка F6 шагает только по вызовам функций, а кнопка F5 позволяет зайти в вызываемую функцию и посмотреть что же происходит внутри.



Единственное, если вы не хотите наловить глюков при отладке — советую отключить оптимизацию. Делается это через меню Project -> Properties

Значение Optimization Level необходимо установить в None(-O0)



После остановки отладки — контроллер перезапустит код еще раз и будет выполнять его циклически.

По итогу должна получится примерно такая картина



Подведем итоги


Использование HAL позволило реализовать данную задачу путем написания всего 2-х строчек кода.

Но за упрощение работы пришлось заплатить памятью



1.54 КБ оперативы и 4.69 КБ флеша.

Напомню, оптимизация отключена, то есть «-O0»

Много это или мало?

На этот вопрос можно будет с уверенностью ответить только в следующих частях статьи.

Оригинал статьи как всегда в моем блоге.

Комментарии 78

    0
    Атолик забросили, не? Уже вышла версия 1.1 Stm32Cube IDE.
      0
      Stm32Cube IDE тот же толик по сути
      +2
      … ммм да, столько абстракции, сущностей, условностей, флеша и оперативы для вкл/выкл
        0
        Для задачи нужен контроллер который имеет 1 порт и 1 таймер и RC цепь килогерц на 100 внутри и прога на 20-50 байт. (на самом деле для задачи вообще контроллер не нужен — ее 176ИЕ12 решает). А тут контроллер который небольшим космическим кораблем может управлять, 2 кварца, и компилятор какого то мусора притащил… Одних только *.c файлов в проекте 6 штук…
          0
          на самом деле для задачи вообще контроллер не нужен — ее 176ИЕ12 решает

          Для такой задачи и двух КТ-315 и пары резистров с конденсаторами хватит.

          Но я согласен с комментатором — 5 КБ мусора по-умолчанию это дичь.
            0
            Ну положим ладно 5к мусора там он притянул — черт с ним.
            но как он сожрал полтора килобайта оперативы?! что там физически может занять такой объем!? В видимой части кода ведь вообще ни одной переменной нет.
              0
              Стек?
                0
                Это какая же глубина у него должна быть и откуда ей взяться? — там уровень вложенности не больше двойки.

                Я мельком глянул в проект где usb 2.0 стек + CDC + некий функционал. занято 560 байт ОЗУ из 768 возможных.
            –1
            Ваш 176ИЕ12 быстро закончится, как только нужно будет мигать в немного другом режиме, например 1сек вкл — 2 сек выкл — 3сек вкл и т.п.
            А прога на 20-50 байт закончится, когда нужно будет делать тоже самое, только на немного другой модели контроллера. Вам снова придется изучать все его регистры (а они другие!) и весь код инициализации железа писать с нуля в ручную.
            А я просто сгенерирую новый проект в CubeMX под другой процессор и вставлю тем самые пару строчек кода мигания, и все гарантированно заработает.
              –1
              В точку! Люди не понимают, что в современном мире железо постоянно дешевеет и основной ценой устройства становится — оплата времени разработчика.
                +1

                Когда я смотрел на Cube – у меня было ощущение, что мне его придётся изучать заново не то что при смене проца, а вообще на любой чих. Ибо постоянно натыкался на какие-то косяки, искал пути их обхода, и уверен, что то и другое постоянно меняется: http://forum.easyelectronics.ru/viewtopic.php?f=7&t=24337&hilit=Cube


                Или он уже стабилизировался?


                Для сравнения, на PSoC с кипрессовской средой всё было прозрачно: при создании схемы генерился API, который просто работал, а его использование давало читаемый код, а не клубок макарон с "вставьте кусочек кода сюда" от CubeMX.
                Но, увы – экзотический контроллер...

            +1
            Слово fast в заголовке по-моему излишне. Первая часть была 1 марта. Предупредите нас, если и дальше ваш fast с нашим не совпадать будет. А по теме — спасибо!
              +2
              Предупреждаю, следующая часть будет не скоро
              0
              а если голую ассемблерную вставку написать, то компилятор всё равно нагенерит дополнительного фарша?
                0
                Об этом планирую написать в следующих частях.
                  0
                  Компилятор, вроде как, не оптимизирует ассемблерные вставки. А вот код на С/С++ он наверняка по разному «Оптимизирует» на разных уровнях флага "-o".
                  0
                  Стоило бы все-таки включить оптимизацию, переключить в Release (если позволяет), убрать отладочную информацию, и проверить. Вполне возможно, что там много неиспользуемого кода, который никогда не вызывается, либо подключен код для отладки.
                  Я смотрел исходники HAL, ничего криминального в них нету, то что бы сожрало столько памяти.
                    0

                    В bare-metal бинарниках обычно нет отладочной информации (или есть, но на девайс она не заливается); отладчик-то все равно на другом компе запускается.

                      0
                      Попробовал сгенерить аналогичный проект для IAR.
                      С максимальной оптимизацией по размеру, без отладочной информации и еще поотключав много галочек удалось получить такой минимум, на readwrite data memory не обращайте внимания, в настройках указал размер стека 256 байт, так что дополнительно он съел 52 байта RAM:
                      3024 bytes of readonly code memory
                      36 bytes of readonly data memory
                      272 bytes of readwrite data memory
                      Вот фрагмент map файла:
                      Module ro code ro data rw data
                      ------ ------- ------- -------
                      C:\PROJECTS\My\BluePill\BlueHello\EWARM\BlueHello\Obj: [1]
                      main.o 336
                      startup_stm32f103xb.o 256
                      stm32f1xx_hal.o 168 12 12
                      stm32f1xx_hal_cortex.o 176
                      stm32f1xx_hal_gpio.o 484
                      stm32f1xx_hal_msp.o 68
                      stm32f1xx_hal_rcc.o 1202
                      stm32f1xx_it.o 20
                      system_stm32f1xx.o 92 4 4
                      -------------------------------------------------
                      Total: 2802 16 16
                      dl7M_tln.a: [3]
                      exit.o 4
                      low_level_init.o 4
                      -------------------------------------------------
                      Total: 8

                      rt7M_tl.a: [4]
                      ABImemclr4.o 6
                      ABImemset48.o 50
                      XXexit.o 12
                      cexit.o 10
                      cmain.o 30
                      copy_init3.o 44
                      cstartup_M.o 12
                      data_init.o 40
                      -------------------------------------------------
                      Total: 204

                      Gaps 10
                      Linker created 20 256
                      -----------------------------------------------------
                      Grand Total: 3024 36 272


                      Больше всего занимает stm32f1xx_hal_rcc.o — 1200 байт.
                      Не стоит забывать, что у STM довольно навороченная система тактирования. Я не пытался что-то там схитрить и сэкономить, включил внешний кварц, PLL — все как в обычном устройстве. Можно конечно все эти прескалеры и PLL инициализировать вручную, может быть и сэкономите несколько сотен байт кода, но это будет совершенно не поддерживаемый код. Следующий программист, которому посчастливится залезть в код, просто ничего не поймет.
                        0
                        Также не стоит забывать, что у нас доступно 64 или даже 128 КБ флеш памяти и 20КБ RAM (если брать Blue Pill за 100 руб). Пусть 4КБ займет вся инициализация. Тогда останется 60КБ на пользовательский код, что очень даже немало. Хоть STM32 и позволяет помигать светодиодом, чтобы раскрыть весь его потенциал, еще нужно постараться.
                      0
                      А в stm32f1xx_hal_conf.h все модули открыты, да? Там же можно убрать лишнее, оставив только то что используется (и обязательно). Для мырга светиком посредством ногодрыга достаточно TIM_MODULE (при использовании SysTick он тоже не нужен), GPIO_MODULE и обязательные системные CORTEX_MODULE, FLASH_MODULE и RCC_MODULE.
                        0

                        Килобайт оперативы, скорее всего, почти целиком занят под стек, это норма.


                        А вот во флеше место, скорее всего, занимает код, который не используется. Прозревая компилятор gcc, предположу, что этот код можно выкинуть, сказав компилятору -fdata-sections -ffunction-sections, а линкеру -Wl,--gc-sections.


                        А если gcc там достаточно свежий, то можно и -flto добавить.


                        Это оптимизация уровня линковки, поэтому к "глюкам", которых вы боитесь от -О1 и выше, она приводить не должна.


                        Spoiler header

                        Правда, "глюки", скорее всего, вызваны неопределенным поведением у вас в коде :) Но это уже другой вопрос.

                          0
                          Не, прозрение не катит :) там по-умолчанию эти опции включены (ну, для gcc — точно), а вот с lto всё гораздо грустнее — что HAL, что LL не собираются в таком режиме, потому как линкер выкидывает все обработчики прерываний и ещё кучу всего из потрохов HAL-a

                          Ща, в процессе изучения stm32, пытаюсь перевести известный код 1wire на таймере с DMA из обращения к регистрам в (хотя бы) LL — третий день ищу, чем же оно пишет в TIM_CCMR2 :( То, что делается в 1 строку присвоения регистру, тут выливается в 10-30 байт структуру, плюс вызов нескольких функций :( А опции запуска таймера в режиме PWM в Cube32MX вообще не оказалось (в stm32fxx_ll_lim.h он есть)

                          Вот тут уже начинаешь подумывать, а не фиг ли с ней, переносимостью (тем более на другую линейку всё равно править — сравнивал stm32f103 и stm32f030)?.. Думаю, всё хорошо в меру…

                          arm-none-eabi-size build/hal_tim3_blink.elf
                          text data bss dec hex filename
                          4492 20 1636 6148 1804 build/hal_tim3_blink.elf

                          arm-none-eabi-size build/ll_tim3_blink.elf
                          text data bss dec hex filename
                          1900 12 1564 3476 d94 build/ll_tim3_blink.elf


                          бинарники, соответственно, 4512 и 1920 байт. Из кода — только дёрганье пином в обработчике прерывания…
                            0
                            Не, прозрение не катит :) там по-умолчанию эти опции включены (ну, для gcc — точно), а вот с lto всё гораздо грустнее — что HAL, что LL не собираются в таком режиме, потому как линкер выкидывает все обработчики прерываний и ещё кучу всего из потрохов HAL-a

                            Интересно. Могу предложить либо выключить lto для отдельных файлов (если, допустим, все обработчики прерываний в один сишник сложены, как STM любит) либо — как тут советуют, просто "вызвать" все обработчики из функций-заглушек, которые, в свою очередь, можно пометить атрибутом __attribute__((used));


                            Другие функции, по идее, выкидываться не должны, если их хоть откуда-нибудь вызывают.


                            третий день ищу, чем же оно пишет в TIM_CCMR2

                            Пробовали ставить access breakpoint на запись?


                            Из кода — только дёрганье пином в обработчике прерывания…

                            Можно еще попробовать ассерт выключить. Вообще, надо смотреть в ассемблер или в линкерный мап-файл, чтобы понять, че там столько места жрет :)

                              0
                              1. про атрибут советуют и где-то на ST-шном форуме, но это как-то грустно — там с пару десятков ошибок вываливается при линковке — все их править? И это не мой код, а потроха HAL-а…

                              2. У меня обратная «задача» — по простому коду
                              TIM2_CCMR2 = TIM_CCMR2_OC4M_PWM1 | TIM_CCMR2_OC4PE | TIM_CCMR2_CC3S_IN_TI4;
                              (привет, EddyEm :) ) понять, а) как это указать в Кубе (никак — ибо нет опции для _PWM1) б) сообразить, как сделать то же самое, средствами LL или HAL, причём так, чтобы было легко поправить под F0 и F1 (ну и перенести на другой таймер до кучи, чтоб на F030 завелось). Пока всё в образовательных целях ))

                              3. При сборке штатным Makefile с правками на DEBUG=0 и оптимизацией -Os оно, вроде, и так отключается (там везде (?) assert_param, что раскрывается в пустое место в Release)

                              ЗЫ: глянул пример «nolib» blink через SysTick — на «чистых регистрах» — там тоже 1144 байта бинарник — по сравнению моим тайменром на LL — примерно вдвое разница на только инициализацию фактически
                                +1
                                > глянул пример «nolib» blink через SysTick
                                А ничего, что у меня там не просто «блинк», а псевдоморзянка «SOS» на светодиоде + опрос кнопочек?
                                  0
                                  +1
                                  Ничего. Плохого :)
                                  Я как раз о том, что даже «типа-низкий-железный-уровень» и то даёт вдвое оверхеда…
                                  Попробовал собрать gcc 4.5 (лень было пути прописывать к 7):
                                  text data bss dec hex filename
                                  804 336 916 2056 808 mk/blink.elf

                                  Вот. А с учётом порядка 280 байт «полезного» кода для кнопок и кода SOS, так и втрое!
                                  0
                                  1. про атрибут советуют и где-то на ST-шном форуме, но это как-то грустно — там с пару десятков ошибок вываливается при линковке — все их править? И это не мой код, а потроха HAL-а…

                                  Ну, а чего ж вы хотели. С точки зрения линкера обработчики прерывания — это функции, которые никогда не вызываются.
                                  Конечно, разумнее было бы, если бы разработчики HAL'a сразу об этом подумали и все обработчики прерываний пометили бы этим атрибутом.


                                  А так — ну хоть какое-то решение.


                                  Наверное, можно еще переписать стартапный ассемблерный файл, в котором таблица векторов прерываний собирается.


                                  1. У меня обратная «задача» — по простому коду

                                  Тут не подскажу, с HALом плотно дело не имел.

                            +3
                            Крайне плохо, что везде рекламируется хал. Многие новички даже не знают, что STM32 можно программировать правильно — без оверхеда.
                            Уныло…
                              0
                              Реалии диктуют свои условия.
                              Никто не будет пилить проект неделю на регистрах, если его можно сделать за час на хале, но взять при этом контроллер пожирнее.
                              Так что правильно это только с вашей стороны.
                                –3
                                Дело в том что даже не нужно брать контроллер пожирнее.
                                Даже обычного BluePill за 100 руб с 60КБ свободной памяти, оставшейся после инициализации, хватит чтобы воплотить все самые смелые желания разработчика. А есть контроллеры и с 1МБ памяти. Просто некоторые застряли в начале 2000х, когда все делали ручками на довольно примитивных контроллерах. Сейчас за программирование регистров STM32 напрямую, я считаю, нужно сразу увольнять человека, потому что это вредительство обойдется значительно дороже в последствии.
                                  0
                                  Вот именно! К сожалению, сейчас не модно делать надежно. А если ресурсов не хватает — не беда, возьмем «контроллер пожирнее». Сейчас модно «тяп-ляп и в продакшн». Копроэкономика во всей ее красе!
                                  Вот так и плодится невежество.
                                    –1
                                    писать на регистрах != надежно
                                    С чего вы вообще взяли, что ваш самописный не поддерживаемый код будет работать стабильнее, чем библиотека, которую каждый день используют миллионы разработчиков?
                                    Правильно выше написал коллега, что есть разработчики застрявшие в 2000.
                                    Нравится писать долго и самобытно — пожалуйста, но тогда будет правильным отказаться и от других благ человечества. Например от 4G, ведь GPRS надежнее…
                                      +3
                                      С того, что я видел исходники этого кала!
                                      А вы, похоже, в этот индусокод даже не заглядывали…
                                      Нет, калокуб — это из разряда ардуины. Рассчитано на безмозглых бракоделов.
                                        0
                                        Отлично.
                                        Покажите класс, напишите статью как надо делать, почему так надо делать и в чем ваш вариант выигрывает (относительно калокуба).
                                        А еще желательно, чтобы это был пример боевого проекта, а не ваши домашние игрушки, на которые можно тратить годы жизни бесплатно.
                                        Такое будет интересно почитать всем «Безмозглым бракоделам»
                                          +2

                                          Боевой проект то вряд ли кто покажет, надёжный код обычно под NDA попадает. Например библиотека тестирования ALU от ST только с NDA поставляется, кто вам её покажет то? Поэтому только примеры на домашних игрушка могут быть, но те которые следуют принципам надёжности.
                                          Подтверждаю в Cube баг на баге, даже у студентов отобрал греха подальше.

                                            +2
                                            Если кому интересно, может ко мне на гитхаб заглянуть. А в этой помойке я ничего писать не буду. Уже был опыт. Только что-нибудь напишешь, налетит школота и вендотролли и все заминусуют.
                                              0
                                              Тогда адрес в студию
                                                +1
                                                А в профиль не судьба заглянуть?
                                                github.com/eddyem/stm32samples
                                                Смотреть то, что «nolib», т.к. остальное на opencm3 — я перестал им пользоваться после того, как авторы сильно побили апи.
                                                Кстати, на заметку лентяям. Opencm3 не в пример круче хала!!! По крайней мере, по оптимизации. И код писан программистами, а не «индусокодерами».
                                                Еще у меня есть кое-какие проектики, оформленные отдельно. Они уже связаны с конкретными железяками, скажем, фотометр (уже больше года работает), система термомониторинга главного зеркала БТА (прошлая версия отработала год, в этом году обновил с учетом проблем с разъемами RJ-45 для CAN-шины — заменил их на DB9), а это — мое первое приличное детище (контроллер ИК-спектрометра/фотометра).
                                                  0
                                                  Не судьба

                                                    0
                                                    Странно, а в профиле я данные заполнял:
                                                    image
                                        +2
                                        Ваша «копроэкономика» произвела на свет youtube, который может 4К видео вам показывать в браузере телефона. Просто задумайтесь, насколько тут глубока кроличья нора стека технологий во всем этом процессе.
                                        Если бы люди продолжали работать на языках низкого уровня (С, ассемблер), без абстракций, то у них ничего бы этого не получилось. Застряли бы в 80х-90х, оптимизируя байтики в АОНах.
                                          +2
                                          И что хорошего в том, что теперь каждый может оболваниваться? И так образование ниже плинтуса, а с этими гаджетами скоро народ совсем в идиотов превратится!
                                          Вы посмотрите, какая сейчас ситуация сложилась на рынке трудоустройства: нормальных программистов не найти почти. Сплошные «тяп-ляп» — всякие питонщики,.нетщики и прочая жабоскриптодрянь, совершенно не умеющая делать что-нибудь стоящее. Только копипастить.

                                          И не надо С называть языком низкого уровня! Что за невежество?
                                            0
                                            В 2000x в РФ для АОНа был разработан специализированный микропроцессор R100-XP на базе архитектуры MCS-51 с дополнительными командами и встроенным синтезатором звука. От моргания светодиодиками в чужой IDE на чужом камне, до разработки своего проца с захардкоженными часто используемыми функциями на уровне системы команд (чтоб более лучше байтики экономить) — как от земли до луны.

                                            Так что кто где застрял — это смотря с какой стороны поглядеть, с моей: да у вас другие камни, другой язык, другая производительность, более аляпистая IDE, ОЗУ вон полтора кб с свистом куда-то делось — но вы как мигали светодиодиком так им и мигаете! Решаете ту же самую скучную, никому не нужную и никого ничему не учащую задачу… В АОНе же по одному только коррелятору — 3 диплома написано и защищено было. А калькулятор с плавающей точкой там занимал 1.2к ROM 128 байт RAM (повторно используемого буфера обработчика — т.е по факту НОЛЬ RAM) — на процессоре где умножения и деления даже в помине не было.
                                              –1
                                              И где он сейчас, этот R100-XP?
                                              Где эти дипломы, их обладатели или новые устройства которые они спроектировали?
                                              Кому сейчас нужен калькулятор, который занимал 1.2к ROM 128 байт RAM?
                                              ОЗУ вон полтора кб с свистом куда-то делось — но вы как мигали светодиодиком так им и мигаете! Решаете ту же самую скучную, никому не нужную и никого ничему не учащую задачу…

                                              Напишите свою статью, пусть даже про тот злосчастный АОН
                                              Распишите как делать правильно, где экономить на спичках
                                              Или вы только языком в комментариях чесать умеете — а на деле ноль без палочки?
                                              И не надо отмаз, ткнете носом в свою статью с тем как надо правильно — продолжим обсуждение, сольетесь — останетесь просто диванным троллем.
                                                +1
                                                Я ноль без палочки.

                                                Только вот софт от АОН — произведение искусства!
                                                Кладезь методов и алгоритмов.
                                                Идеальное средство обучению программирования.

                                                Ваш — обычный мусор сгенерированый компилятором из чужого однотипного кода, где вашего — 2 строки. В ваших программах через много много лет специалист так и будет видеть «мигание светодиодиком»… Пройдет 2-3 года — выйдет новое IDE, новый HAL, и новые процессоры по еще более мусорной цене — ваша статья к ним будет не применима, потому что единственная вечная тема тут — светодиодик который мигает.
                                                0
                                                При всем моем уважении к разработчикам АОНов, таксофонов (там действительно внутри все не просто), если говорить о специализированных процессорах, то компания Sony выпустила свой Playstation еще в далеком 94г. en.wikipedia.org/wiki/PlayStation_technical_specifications
                                                Там был не просто процессор общего назначения, внутри еще был сопроцессор для ускорения 3D графики. Плюс дополнительные GPU, SPU. Просто космос по сравнению с АОНами.
                                                Могли бы наверное спрайты на ассемблере продолжать рисовать, но рынок и копроэкономика требовала 3D графику.
                                                В примере в статье ОЗУ никуда со свистом не делось. Точнее делись только 50 байт, остальное — это пожелания пользователя, который захотел себе сделать стек в 1.5 КБ.
                                          +3
                                          Таки поколение Ардуино, жи!
                                          Сплошная копи-паста! Для многих юзверей, переопределить пин для работы с 1-w, это уже «проблема».
                                          ЗЫ
                                          Многие и не знают, что есть форк ЯП Forth, для STM32 (MeacrispForth). Где всё возможности контроллера, можно подёргать в интерактивном режиме, а при желании «скомпилировать» и заставить исполнять код «нативно»!
                                            +1
                                            Мой декан, когда я учился в универе, рассказывал как в своей молодости они делали систему оптического наведения для управляемого снаряда на радиолампах.
                                            А сейчас программисты без OpenCV не знают как жить.
                                            Поколение ардуино…
                                              0
                                              +1 Вот кстати, очень бы было интересно/познавательно послушать рассказ вашего декана! На каких принципах это всё работало!
                                              ЗЫ если это конечно не секретно! ;)
                                              ЗЗЫ Ардуино — это удачный проект, для привлечения неофитов (сам с него начинал), но если остановиться и продолжать «натягивать сову на глобус» (Атмегу), то это просто «не очень разумно»!
                                          0
                                          HAL от CubeMX содержит множество увлекательных ошибок с которыми сталкиваешься постоянно. Из свежего stm32f4xx_hal_uart.c для UART9 не в курсе, что он подключен к APB2 и если вы решились использовать его в своем проекте и у вас разные частоты APB1 и APB2, то вас ждет увлекательнейший квест по поиску причин неработоспособности простейшего UARTа инициализированного восхваляемым вами HALом. И таких примеров — множество, не говоря уже про элементарно раздутый код.

                                          Вот diff что бы не быть голословным:
                                          Index: stm32f4xx_hal_uart.c
                                          ===================================================================
                                          --- stm32f4xx_hal_uart.c	(revision 2632)
                                          +++ stm32f4xx_hal_uart.c	(revision 2633)
                                          @@ -2487,7 +2487,7 @@
                                             {
                                               /*-------------------------- USART BRR Configuration ---------------------*/
                                           #if defined(USART6) 
                                          -    if((huart->Instance == USART1) || (huart->Instance == USART6))
                                          +    if((huart->Instance == USART1) || (huart->Instance == USART6) || (huart->Instance == UART9))
                                               {
                                                 huart->Instance->BRR = UART_BRR_SAMPLING8(HAL_RCC_GetPCLK2Freq(), huart->Init.BaudRate);
                                               }
                                          @@ -2506,7 +2506,7 @@
                                             {
                                               /*-------------------------- USART BRR Configuration ---------------------*/
                                           #if defined(USART6) 
                                          -    if((huart->Instance == USART1) || (huart->Instance == USART6))
                                          +    if((huart->Instance == USART1) || (huart->Instance == USART6) || (huart->Instance == UART9))
                                               {
                                                 huart->Instance->BRR = UART_BRR_SAMPLING16(HAL_RCC_GetPCLK2Freq(), huart->Init.BaudRate);
                                               }
                                          
                                          


                                            0
                                            Да, у кубовских либ есть ошибки, но как правило они легко локализуются. В вашем варианте можно было просто посмотреть какие значения в регистрах в отладчике и додумать что тактирование идет не от туда.
                                            Да и благодаря сообществу — решение находится за 5 секунд github.com/ARMmbed/mbed-os/issues/12090
                                            ST обещали исправить
                                              +1
                                              В данном случае изучение регистров не дало бы полезной информации т.к. в них находятся правильные значения, но для APB1. А что бы разобраться в чем проблема пришлось лезть в Reference Manual и смотреть куда подключен UART9 т.к. не HAL задает источник тактовой для периферии, а архитектура процессора. А до этого еще некоторое время медитировать над внешне работающим UARTом, который почему-то присылал мусор вместо данных. Ах, да, насчет общества на которое все рассчитывают когда ничего не работает. У меня коммит от 27го ноября :) Другими словами, использование HALа не освобождает он необходимости разбираться в регистрах процессора и вдумчиво (а иногда очень вдумчиво) читать Reference Manual. А это на корню убивает все аргументы выше про «написал и заработало», «написал под один процессор, перенес под другой» и т.д.
                                                0
                                                Я делал проекты на HAL и на регистрах. Начинал с регистров, когда хала еще не было и в помине.
                                                Хал (как и регистры) — не панацея от всех бед.
                                                Нельзя сказать: один раз написал и таскаю туда сюда бездумно
                                                Нет. Это работает не так.
                                                Пишу еще раз
                                                Хал экономит ваше время, когда необходимо сделать довольно сложный проект за короткое время.
                                                Хал помогает вам, когда надо проверить новую идею руководства сегодня-завтра.
                                                Хал экономит вам время, когда у вас есть работающий код — который необходимо запустить на плате с отличающимся железом.
                                                Он не защищает вас от ошибок (ваших или своих)
                                                Нельзя бездумно делать копипаст, нужно понимать как это работает внутри.
                                                Я сам много раз сталкивался с ошибками в хале, но эти ошибки нужно устранить один раз — а польза будет всем.
                                                PS Кстати в вашем варианте устранение ошибки USART9 породило новую скрытую ошибку, надеюсь найдете сами.
                                                  –1
                                                  А можно пример чего-нибудь более-менее сложного на хале? А то я только игрульки какие-то встречал.
                                                  Скажем, одновременно работающие: USB-устройство (да хоть CDC для начала), CAN, SPI через DMA на пару устройств, I2C через DMA, штук 5 таймеров (SysTick как обычно — для счета системного времени под многочисленные КА, пару таймеров на разные ШИМы, таймер на захват, таймер для DMA), эмуляция параллельного 8-битного интерфейса через DMA, штуки 4 канала АЦП через DMA, три UART'а… Еще можно добавить полуаппаратный 1-wire на таймере с DMA или UART+DMA.
                                                  И не надо рассказывать байки о том, что для построения подобного не придется корпеть над RM и даташитом!!!
                                                  Ну и вопрос: а коли все равно нужно очень хорошо изучить RM и даташит, то какой будет профит от хала (ведь дополнительно придется еще и его документацию изучать + внимательно читать исходники в поисках многочисленных багов).

                                                  Эх, ардуинщики… Славно у них светодиодом получается моргать, но лишь только они собираются что-то более-менее сложное сделать, как внезапно оказывается, что надо бы на уровень пониже спуститься…
                                                    +1
                                                    1) Делал полный аналог MOXA NPort 5450
                                                    STM32F4 + HAL + FreeRTOS + LWIP
                                                    Работало с родным ПО и драйверами
                                                    2) Так же делали контроллер для электропитающего узла.
                                                    STM32F4 + HAL + FreeRTOS + LWIP
                                                    На нем была веб морда для показа параметров с ява скриптами и динамическим отображением параметров
                                                    modbus tcp на 4 одновременных сессии
                                                    самописный modbus rtu slave на 2 uart (тоже полностью на HAL)
                                                    самописный modbus rtu master на 1 uart (тоже полностью на HAL)
                                                    крутилась внутренняя логика которая считала параметры установки в зависимости от полученных modbus master значений из сторонних приборов и состояний дискретных входов.
                                                    так же крутилась логика работы для резервного отключения нагрузки
                                                    был поднят самописный ftp для заливки файлов веб морды на spi флешку at...161 на плате
                                                    и вишенка на торте — эта штука могла обновить свое ПО по сети, параллельно с основной работой.
                                                    естественно еще была внешняя рамка на плате, чтобы было где разгуляться
                                                      0

                                                      Лично создал прошивку для платы управления имитатора стрелкового оружия тренажёра профи http://inter-sim.ru/profi.html.
                                                      Будучи абсолютным нулем в микроконтроллерах примерно за 2-3 месяца с использованием hal был создан промышленный образец прошивки, которая работает и по сей день(уже как 3 года).
                                                      В проекте использовалось 2 uart, несколько каналов АЦП для датчиков, несколько пинов для управления клапанами и лазером.
                                                      Если это игрушка, что что по вашему не игрушка?

                                                        0
                                                        «что по вашему не игрушка?» то что прошло сертификацию и соответствие отраслевым стандартам.
                                                        0

                                                        Ваш комментарий из серии. Когда технологии поворачиваются лицом к разработчикам, разработчики поворачиваются к технологиям
                                                        консервативным задом.

                                                0

                                                Мне казалось уже прошло время, когда кто-то тратит уйму времени изобретая велосипед (явно со стальной рамой и шатунами на клиньях) для того, чтобы сэкономить лишние пару байт-мегабайт памяти(дорогого люминия, итана или арбона). Помню лет 15 назад в колледже мы с однокурсниками тоже удивлялись тому, что форма с кнопкой написанная на асм-е занимает 10кб, а на delphi / vcl все 300, но почему-то более чем формы с кнопкой никто ничего не писал на асм-е (ну так думаю надеюсь). Выводы, которые вы сделали в вашей статье примерно из этой же серии.
                                                К счастью для разработчиков реальность сегодня такова, что никого не интересуют лишние 5кб памяти, когда на кону выпуск продукта на месяц раньше конкурентов. Будем благоразумны, мы же не для спутников и межпланетных кораблей софт пишем. Как минимум потому, что ни там ни там вряд-ли кто-то будет использовать абсолютно не защищённый от космической радиации stm32.

                                                  +1
                                                  Это зависит от того, что вы пишите, кто-то и для спутников софт разрабатывает условно. 5 кБ памяти это много, особенно если проект имеет долги цикл жизни и поддержку. И как раз умение писать хороший софт позволило Китаю клепать за копейки миллионы единиц оборудования на всяких С51 и stm8 за 10 центов. Банальный пример: есть у меня печка для пайки и внутри стоит STM8S, аналогичную печку в РФ производят и внутри F407. Думаю не надо объяснять почему российское оборудование не конкурентноспособное?

                                                  Подход, который предлагает st со своим халом — это в лучшем случае быстрое прототипирование какой-то мелочи типа умной розетки, но не более. Но все таки основная часть эмбеда это все таки про надежность и индастриал.
                                                    0

                                                    "плюсик" за STM8S
                                                    Мигалка по таймеру с ожиданием прерывания:


                                                    source code
                                                    #include <stdint.h>
                                                    #include <stdio.h>
                                                    
                                                    #define CLK_DIVR    (*(volatile uint8_t *)0x50c6)
                                                    #define CLK_PCKENR1    (*(volatile uint8_t *)0x50c7)
                                                    
                                                    #define     __IO    volatile
                                                    
                                                    typedef struct GPIO_struct
                                                    {
                                                      __IO uint8_t ODR;
                                                      __IO uint8_t IDR;
                                                      __IO uint8_t DDR;
                                                      __IO uint8_t CR1;
                                                      __IO uint8_t CR2;
                                                    }
                                                    GPIO_TypeDef;
                                                    
                                                    #define GPIOB_BaseAddress       0x5005
                                                    #define GPIOB ((GPIO_TypeDef *) GPIOB_BaseAddress)
                                                    
                                                    #define TIM1_CR1    (*(volatile uint8_t *)0x5250)
                                                    #define TIM1_IER    (*(volatile uint8_t *)0x5254)
                                                    #define TIM1_SR1    (*(volatile uint8_t *)0x5255)
                                                    #define TIM1_CNTRH    (*(volatile uint8_t *)0x525E)
                                                    #define TIM1_CNTRL    (*(volatile uint8_t *)0x525F)
                                                    #define TIM1_PSCRH    (*(volatile uint8_t *)0x5260)
                                                    #define TIM1_PSCRL    (*(volatile uint8_t *)0x5261)
                                                    
                                                    volatile uint8_t led = 0;
                                                    
                                                    void TIM1_overflow_Handler() __interrupt(11)
                                                    {
                                                         TIM1_SR1 &= ~1;
                                                         if (led == 1) {
                                                            GPIOB->ODR |= (1 << 5);
                                                         }
                                                         else
                                                         {
                                                            GPIOB->ODR &= ~(1 << 5);  
                                                         }
                                                         led  ^= 1;
                                                    }
                                                    
                                                    void main(void)
                                                    {
                                                        CLK_DIVR = 0x00;
                                                        CLK_PCKENR1 = 0xFF;
                                                    
                                                        GPIOB->DDR |= (1 << 5);
                                                        GPIOB->ODR |= (1 << 5);
                                                    
                                                        TIM1_PSCRH = 0x00;
                                                        TIM1_PSCRL = 0xF4;
                                                        TIM1_CR1 = 0x01;
                                                        TIM1_IER = 0x01;
                                                        __asm__ ("rim");
                                                        while(1)
                                                        {
                                                            __asm__ ("WFI");
                                                        }
                                                    }
                                                    

                                                    SW — SDCC + stm8flash
                                                    HW — STM8S103F3P6 + ST-LINK V2
                                                    240 байт флэша:
                                                    image

                                                      0
                                                      А у STM8 не нужно инитить как-то ноги? Ведь даже у AVR надо как минимум DIR дёрнуть.
                                                        0

                                                        Естественно!
                                                        Вот эти две строки этим и занимаются:


                                                        GPIOB->DDR |= (1 << 5); //настройка пина на выход
                                                        GPIOB->ODR |= (1 << 5); //инициализация выхода

                                                        P.S. по умолчанию выход с ОС, а светодиод подключен анодом к питанию

                                                          0
                                                          del
                                                          0
                                                          Мне очень не нравятся вот эти магические константы
                                                          #define CLK_DIVR (*(volatile uint8_t *)0x50c6)
                                                          #define CLK_PCKENR1 (*(volatile uint8_t *)0x50c7)
                                                          TIM1_PSCRL = 0xF4;
                                                          TIM1_CR1 = 0x01;
                                                          TIM1_IER = 0x01;

                                                          Какой это процессор? Почему этим числам стоит доверять? Сколько вы времени потратили на создание таких define'ов?
                                                          Как минимум стоит использовать файлы с описанием регистров от производителя. Да, внутри они могут быть тем же самым, что у вас. Но у них нет описанных недостатков.
                                                            0

                                                            Процессор — STM8S103F3P6
                                                            Дефайны — из файла stm8s.h, вынимаем оттуда только то, что нужно для конкретного проекта (такой метод вполне сработал и для преобразователя PS/2-UART, хотя дефайнов там оказалось малость побольше)
                                                            Настройки таймера — из даташита
                                                            "Магия" — это, конечно, так, но для конкретного контроллера вполне оправдана.

                                                              0
                                                              А зачем вынимать то? Лишний дефайн в флеш память не залезет.
                                                              Вместо магических чисел в регистры пишем комбинированные битовые маски, которые имеют те же названия, что и в даташите. Их опять же берем от производителя, а не сами руками создаем.

                                                                –1
                                                                А зачем вынимать то? Лишний дефайн в флеш память не залезет.

                                                                Мне так больше нравится :-)

                                                                  0
                                                                  Вы так повышаете шанс на ошибку, опечатку, а также сильно затрудняете понимание кода другими программистами.
                                                                    0

                                                                    Верно, так и есть!

                                                          0
                                                          Думаю, что дело тут далеко не в цене контроллера. Пусть контроллер и будет дороже на 300 руб. Но российская печка разве дороже на 300 руб.? В печке, мне кажется, гораздо больше стоит сам корпус, нагревательные элементы, работа по изготовлению и сертификации.
                                                          Опять же, какой функционал? Может быть в китайской печке on-off термостат, а в российской PID. Может в российской графический дисплей с кучей термопрофилей, а в китайской какой-нибудь примитив?
                                                          5КБ флеши много где? На AtTiny2313 — да, много. На копеечном BluePill F103 — около 10%.
                                                            0
                                                            тут далеко не в цене контроллера
                                                            Дело в самом подходе при проектирование. Думаете механики не такие же «ардуинщики»? Расточительный подход к проектированию в СНГ повсеместно в железе, т.к. основное производство и деньги завязаны на государственный сектор, а там денег много. Но вот как только надо конкурировать за пределами страны, то все становится плохо из-за низкой оптимизации примененных решений.
                                                            0
                                                            Вы хотите сказать, разница 200 рублей между этими МК делает Российские продукты неконкурентоспособными? Я думаю больше на это влияет упаковка, реклама и маркетинг… И тем не менее мы вторые по продаже оружия, боюсь там уже тоже ХАЛы и прочие калы применяют ибо рынок ждать не будет
                                                          0
                                                          del
                                                          0
                                                          Просто для справки ретроградам: да, можно на LL API написать все без хала.
                                                          Лично у меня мигалка светодиодом заняла под STM32L0:
                                                          Used FLASH: 720 bytes out of 128KB (0%)
                                                          Used SRAM: 28 bytes out of 20KB (0%)


                                                          #include <stm32l0xx_ll_bus.h>
                                                          #include <stm32l0xx_ll_gpio.h>
                                                          #include <stm32l0xx_ll_utils.h>
                                                          
                                                          int main(void)
                                                          {
                                                          	LL_InitTick(16000000, 1000);
                                                          
                                                          	LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_ALL);
                                                          	LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_5, LL_GPIO_MODE_OUTPUT);
                                                          	LL_GPIO_SetPinOutputType(GPIOB, LL_GPIO_PIN_5, LL_GPIO_OUTPUT_PUSHPULL);
                                                          	LL_GPIO_SetPinSpeed(GPIOB, LL_GPIO_PIN_5, LL_GPIO_SPEED_FREQ_LOW);
                                                          
                                                          	for (;;)
                                                          	{
                                                          		LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_5);
                                                          		LL_mDelay(500); 
                                                          		LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_5);
                                                          		LL_mDelay(500);
                                                          	}
                                                          }
                                                          


                                                          Для си и ассемблеро-ретроградов, вот столько добавляет std::map и переменная с его использованием:
                                                          Used FLASH: 1932 bytes out of 128KB (1%)
                                                          Used SRAM: 160 bytes out of 20KB (0%)
                                                            0
                                                            Для ассемблерных ретроградов есть процессоры с 256 слов флеш и 16 байт Sram — и мигалка не будет использовать ни одного байта Sram и слов 20 в flash.

                                                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                          Самое читаемое