В прошлый раз мы осваивали создание нового проекта при помощи 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»

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

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

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

Комментарии (75)


  1. synka
    21.12.2019 13:56

    Атолик забросили, не? Уже вышла версия 1.1 Stm32Cube IDE.


    1. IronHead Автор
      21.12.2019 13:57

      Stm32Cube IDE тот же толик по сути


  1. Ostrovv
    21.12.2019 14:13

    … ммм да, столько абстракции, сущностей, условностей, флеша и оперативы для вкл/выкл


    1. emmibox
      21.12.2019 15:26

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


      1. staticmain
        21.12.2019 15:32

        на самом деле для задачи вообще контроллер не нужен — ее 176ИЕ12 решает

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

        Но я согласен с комментатором — 5 КБ мусора по-умолчанию это дичь.


        1. emmibox
          21.12.2019 16:27

          Ну положим ладно 5к мусора там он притянул — черт с ним.
          но как он сожрал полтора килобайта оперативы?! что там физически может занять такой объем!? В видимой части кода ведь вообще ни одной переменной нет.


          1. staticmain
            21.12.2019 23:14

            Стек?


            1. emmibox
              22.12.2019 00:26

              Это какая же глубина у него должна быть и откуда ей взяться? — там уровень вложенности не больше двойки.

              Я мельком глянул в проект где usb 2.0 стек + CDC + некий функционал. занято 560 байт ОЗУ из 768 возможных.


      1. towin
        21.12.2019 17:24
        +1

        Ваш 176ИЕ12 быстро закончится, как только нужно будет мигать в немного другом режиме, например 1сек вкл — 2 сек выкл — 3сек вкл и т.п.
        А прога на 20-50 байт закончится, когда нужно будет делать тоже самое, только на немного другой модели контроллера. Вам снова придется изучать все его регистры (а они другие!) и весь код инициализации железа писать с нуля в ручную.
        А я просто сгенерирую новый проект в CubeMX под другой процессор и вставлю тем самые пару строчек кода мигания, и все гарантированно заработает.


        1. IronHead Автор
          21.12.2019 18:19

          В точку! Люди не понимают, что в современном мире железо постоянно дешевеет и основной ценой устройства становится — оплата времени разработчика.


        1. aamonster
          21.12.2019 20:34
          +1

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


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


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


  1. tea1975
    21.12.2019 14:22

    Слово fast в заголовке по-моему излишне. Первая часть была 1 марта. Предупредите нас, если и дальше ваш fast с нашим не совпадать будет. А по теме — спасибо!


    1. IronHead Автор
      21.12.2019 14:23
      +2

      Предупреждаю, следующая часть будет не скоро


  1. ibrin
    21.12.2019 14:25

    а если голую ассемблерную вставку написать, то компилятор всё равно нагенерит дополнительного фарша?


    1. IronHead Автор
      21.12.2019 14:35

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


    1. Fox_exe
      21.12.2019 19:12

      Компилятор, вроде как, не оптимизирует ассемблерные вставки. А вот код на С/С++ он наверняка по разному «Оптимизирует» на разных уровнях флага "-o".


  1. towin
    21.12.2019 15:07

    Стоило бы все-таки включить оптимизацию, переключить в Release (если позволяет), убрать отладочную информацию, и проверить. Вполне возможно, что там много неиспользуемого кода, который никогда не вызывается, либо подключен код для отладки.
    Я смотрел исходники HAL, ничего криминального в них нету, то что бы сожрало столько памяти.


    1. Amomum
      21.12.2019 15:44

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


    1. towin
      21.12.2019 17:13

      Попробовал сгенерить аналогичный проект для 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


      1. towin
        21.12.2019 18:54

        Также не стоит забывать, что у нас доступно 64 или даже 128 КБ флеш памяти и 20КБ RAM (если брать Blue Pill за 100 руб). Пусть 4КБ займет вся инициализация. Тогда останется 60КБ на пользовательский код, что очень даже немало. Хоть STM32 и позволяет помигать светодиодом, чтобы раскрыть весь его потенциал, еще нужно постараться.


  1. HardWrMan
    21.12.2019 15:36

    А в stm32f1xx_hal_conf.h все модули открыты, да? Там же можно убрать лишнее, оставив только то что используется (и обязательно). Для мырга светиком посредством ногодрыга достаточно TIM_MODULE (при использовании SysTick он тоже не нужен), GPIO_MODULE и обязательные системные CORTEX_MODULE, FLASH_MODULE и RCC_MODULE.


  1. Amomum
    21.12.2019 15:42

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


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


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


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


    Spoiler header

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


    1. av0000
      21.12.2019 20:05

      Не, прозрение не катит :) там по-умолчанию эти опции включены (ну, для 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 байт. Из кода — только дёрганье пином в обработчике прерывания…


      1. Amomum
        21.12.2019 23:59

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

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


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


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

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


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

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


        1. av0000
          22.12.2019 14:07

          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. EddyEm
            22.12.2019 17:32

            > глянул пример «nolib» blink через SysTick
            А ничего, что у меня там не просто «блинк», а псевдоморзянка «SOS» на светодиоде + опрос кнопочек?


            1. av0000
              22.12.2019 20:03

              +1
              Ничего. Плохого :)
              Я как раз о том, что даже «типа-низкий-железный-уровень» и то даёт вдвое оверхеда…
              Попробовал собрать gcc 4.5 (лень было пути прописывать к 7):
              text data bss dec hex filename
              804 336 916 2056 808 mk/blink.elf

              Вот. А с учётом порядка 280 байт «полезного» кода для кнопок и кода SOS, так и втрое!


          1. Amomum
            22.12.2019 23:21

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

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


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


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


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

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


  1. EddyEm
    21.12.2019 19:00

    Крайне плохо, что везде рекламируется хал. Многие новички даже не знают, что STM32 можно программировать правильно — без оверхеда.
    Уныло…


    1. IronHead Автор
      21.12.2019 19:14

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


      1. towin
        21.12.2019 19:24
        -2

        Дело в том что даже не нужно брать контроллер пожирнее.
        Даже обычного BluePill за 100 руб с 60КБ свободной памяти, оставшейся после инициализации, хватит чтобы воплотить все самые смелые желания разработчика. А есть контроллеры и с 1МБ памяти. Просто некоторые застряли в начале 2000х, когда все делали ручками на довольно примитивных контроллерах. Сейчас за программирование регистров STM32 напрямую, я считаю, нужно сразу увольнять человека, потому что это вредительство обойдется значительно дороже в последствии.


      1. EddyEm
        21.12.2019 19:34

        Вот именно! К сожалению, сейчас не модно делать надежно. А если ресурсов не хватает — не беда, возьмем «контроллер пожирнее». Сейчас модно «тяп-ляп и в продакшн». Копроэкономика во всей ее красе!
        Вот так и плодится невежество.


        1. IronHead Автор
          21.12.2019 19:45
          -1

          писать на регистрах != надежно
          С чего вы вообще взяли, что ваш самописный не поддерживаемый код будет работать стабильнее, чем библиотека, которую каждый день используют миллионы разработчиков?
          Правильно выше написал коллега, что есть разработчики застрявшие в 2000.
          Нравится писать долго и самобытно — пожалуйста, но тогда будет правильным отказаться и от других благ человечества. Например от 4G, ведь GPRS надежнее…


          1. EddyEm
            21.12.2019 19:57
            +2

            С того, что я видел исходники этого кала!
            А вы, похоже, в этот индусокод даже не заглядывали…
            Нет, калокуб — это из разряда ардуины. Рассчитано на безмозглых бракоделов.


            1. IronHead Автор
              21.12.2019 20:01

              Отлично.
              Покажите класс, напишите статью как надо делать, почему так надо делать и в чем ваш вариант выигрывает (относительно калокуба).
              А еще желательно, чтобы это был пример боевого проекта, а не ваши домашние игрушки, на которые можно тратить годы жизни бесплатно.
              Такое будет интересно почитать всем «Безмозглым бракоделам»


              1. lamerok
                21.12.2019 20:47
                +1

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


              1. EddyEm
                21.12.2019 21:25
                +1

                Если кому интересно, может ко мне на гитхаб заглянуть. А в этой помойке я ничего писать не буду. Уже был опыт. Только что-нибудь напишешь, налетит школота и вендотролли и все заминусуют.


                1. IronHead Автор
                  21.12.2019 21:28

                  Тогда адрес в студию


                  1. EddyEm
                    21.12.2019 21:34

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


                    1. IronHead Автор
                      21.12.2019 21:41

                      Не судьба


                      1. EddyEm
                        21.12.2019 21:45

                        Странно, а в профиле я данные заполнял:
                        image


        1. towin
          21.12.2019 20:23
          +3

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


          1. EddyEm
            21.12.2019 21:51

            И что хорошего в том, что теперь каждый может оболваниваться? И так образование ниже плинтуса, а с этими гаджетами скоро народ совсем в идиотов превратится!
            Вы посмотрите, какая сейчас ситуация сложилась на рынке трудоустройства: нормальных программистов не найти почти. Сплошные «тяп-ляп» — всякие питонщики,.нетщики и прочая жабоскриптодрянь, совершенно не умеющая делать что-нибудь стоящее. Только копипастить.

            И не надо С называть языком низкого уровня! Что за невежество?


          1. emmibox
            22.12.2019 01:39
            -1

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

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


            1. IronHead Автор
              22.12.2019 02:14

              И где он сейчас, этот R100-XP?
              Где эти дипломы, их обладатели или новые устройства которые они спроектировали?
              Кому сейчас нужен калькулятор, который занимал 1.2к ROM 128 байт RAM?

              ОЗУ вон полтора кб с свистом куда-то делось — но вы как мигали светодиодиком так им и мигаете! Решаете ту же самую скучную, никому не нужную и никого ничему не учащую задачу…

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


              1. emmibox
                22.12.2019 05:23

                Я ноль без палочки.

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

                Ваш — обычный мусор сгенерированый компилятором из чужого однотипного кода, где вашего — 2 строки. В ваших программах через много много лет специалист так и будет видеть «мигание светодиодиком»… Пройдет 2-3 года — выйдет новое IDE, новый HAL, и новые процессоры по еще более мусорной цене — ваша статья к ним будет не применима, потому что единственная вечная тема тут — светодиодик который мигает.


            1. towin
              22.12.2019 07:49

              При всем моем уважении к разработчикам АОНов, таксофонов (там действительно внутри все не просто), если говорить о специализированных процессорах, то компания Sony выпустила свой Playstation еще в далеком 94г. en.wikipedia.org/wiki/PlayStation_technical_specifications
              Там был не просто процессор общего назначения, внутри еще был сопроцессор для ускорения 3D графики. Плюс дополнительные GPU, SPU. Просто космос по сравнению с АОНами.
              Могли бы наверное спрайты на ассемблере продолжать рисовать, но рынок и копроэкономика требовала 3D графику.
              В примере в статье ОЗУ никуда со свистом не делось. Точнее делись только 50 байт, остальное — это пожелания пользователя, который захотел себе сделать стек в 1.5 КБ.


    1. ilya73
      21.12.2019 19:53
      +1

      Таки поколение Ардуино, жи!
      Сплошная копи-паста! Для многих юзверей, переопределить пин для работы с 1-w, это уже «проблема».
      ЗЫ
      Многие и не знают, что есть форк ЯП Forth, для STM32 (MeacrispForth). Где всё возможности контроллера, можно подёргать в интерактивном режиме, а при желании «скомпилировать» и заставить исполнять код «нативно»!


      1. IronHead Автор
        21.12.2019 19:57
        +1

        Мой декан, когда я учился в универе, рассказывал как в своей молодости они делали систему оптического наведения для управляемого снаряда на радиолампах.
        А сейчас программисты без OpenCV не знают как жить.
        Поколение ардуино…


  1. screep123
    21.12.2019 22:00

    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);
         }
    
    



    1. IronHead Автор
      21.12.2019 22:06

      Да, у кубовских либ есть ошибки, но как правило они легко локализуются. В вашем варианте можно было просто посмотреть какие значения в регистрах в отладчике и додумать что тактирование идет не от туда.
      Да и благодаря сообществу — решение находится за 5 секунд github.com/ARMmbed/mbed-os/issues/12090
      ST обещали исправить


      1. screep123
        21.12.2019 22:22
        +1

        В данном случае изучение регистров не дало бы полезной информации т.к. в них находятся правильные значения, но для APB1. А что бы разобраться в чем проблема пришлось лезть в Reference Manual и смотреть куда подключен UART9 т.к. не HAL задает источник тактовой для периферии, а архитектура процессора. А до этого еще некоторое время медитировать над внешне работающим UARTом, который почему-то присылал мусор вместо данных. Ах, да, насчет общества на которое все рассчитывают когда ничего не работает. У меня коммит от 27го ноября :) Другими словами, использование HALа не освобождает он необходимости разбираться в регистрах процессора и вдумчиво (а иногда очень вдумчиво) читать Reference Manual. А это на корню убивает все аргументы выше про «написал и заработало», «написал под один процессор, перенес под другой» и т.д.


        1. IronHead Автор
          21.12.2019 22:30

          Я делал проекты на HAL и на регистрах. Начинал с регистров, когда хала еще не было и в помине.
          Хал (как и регистры) — не панацея от всех бед.
          Нельзя сказать: один раз написал и таскаю туда сюда бездумно
          Нет. Это работает не так.
          Пишу еще раз
          Хал экономит ваше время, когда необходимо сделать довольно сложный проект за короткое время.
          Хал помогает вам, когда надо проверить новую идею руководства сегодня-завтра.
          Хал экономит вам время, когда у вас есть работающий код — который необходимо запустить на плате с отличающимся железом.
          Он не защищает вас от ошибок (ваших или своих)
          Нельзя бездумно делать копипаст, нужно понимать как это работает внутри.
          Я сам много раз сталкивался с ошибками в хале, но эти ошибки нужно устранить один раз — а польза будет всем.
          PS Кстати в вашем варианте устранение ошибки USART9 породило новую скрытую ошибку, надеюсь найдете сами.


          1. EddyEm
            21.12.2019 23:22
            -1

            А можно пример чего-нибудь более-менее сложного на хале? А то я только игрульки какие-то встречал.
            Скажем, одновременно работающие: USB-устройство (да хоть CDC для начала), CAN, SPI через DMA на пару устройств, I2C через DMA, штук 5 таймеров (SysTick как обычно — для счета системного времени под многочисленные КА, пару таймеров на разные ШИМы, таймер на захват, таймер для DMA), эмуляция параллельного 8-битного интерфейса через DMA, штуки 4 канала АЦП через DMA, три UART'а… Еще можно добавить полуаппаратный 1-wire на таймере с DMA или UART+DMA.
            И не надо рассказывать байки о том, что для построения подобного не придется корпеть над RM и даташитом!!!
            Ну и вопрос: а коли все равно нужно очень хорошо изучить RM и даташит, то какой будет профит от хала (ведь дополнительно придется еще и его документацию изучать + внимательно читать исходники в поисках многочисленных багов).

            Эх, ардуинщики… Славно у них светодиодом получается моргать, но лишь только они собираются что-то более-менее сложное сделать, как внезапно оказывается, что надо бы на уровень пониже спуститься…


            1. IronHead Автор
              21.12.2019 23:49
              +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 на плате
              и вишенка на торте — эта штука могла обновить свое ПО по сети, параллельно с основной работой.
              естественно еще была внешняя рамка на плате, чтобы было где разгуляться


            1. FSS1989
              22.12.2019 10:46

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


              1. Ostrovv
                22.12.2019 12:16

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


            1. FSS1989
              22.12.2019 10:52

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


  1. FSS1989
    22.12.2019 00:36

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


    1. NordicEnergy
      22.12.2019 11:01

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

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


      1. Alyoshka1976
        22.12.2019 11:18

        "плюсик" за 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");
            }
        }
        


        1. HardWrMan
          22.12.2019 12:22

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


          1. Alyoshka1976
            22.12.2019 12:29

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


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

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


          1. NordicEnergy
            22.12.2019 12:37

            del


        1. towin
          22.12.2019 12:44

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

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


          1. Alyoshka1976
            22.12.2019 12:52

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


            1. towin
              22.12.2019 12:56

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


              1. Alyoshka1976
                22.12.2019 12:58
                -1

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

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


                1. towin
                  22.12.2019 16:17

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


                  1. Alyoshka1976
                    22.12.2019 17:23

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


      1. towin
        22.12.2019 11:25

        Думаю, что дело тут далеко не в цене контроллера. Пусть контроллер и будет дороже на 300 руб. Но российская печка разве дороже на 300 руб.? В печке, мне кажется, гораздо больше стоит сам корпус, нагревательные элементы, работа по изготовлению и сертификации.
        Опять же, какой функционал? Может быть в китайской печке on-off термостат, а в российской PID. Может в российской графический дисплей с кучей термопрофилей, а в китайской какой-нибудь примитив?
        5КБ флеши много где? На AtTiny2313 — да, много. На копеечном BluePill F103 — около 10%.


        1. NordicEnergy
          22.12.2019 12:41

          тут далеко не в цене контроллера
          Дело в самом подходе при проектирование. Думаете механики не такие же «ардуинщики»? Расточительный подход к проектированию в СНГ повсеместно в железе, т.к. основное производство и деньги завязаны на государственный сектор, а там денег много. Но вот как только надо конкурировать за пределами страны, то все становится плохо из-за низкой оптимизации примененных решений.


      1. tea1975
        23.12.2019 06:52

        Вы хотите сказать, разница 200 рублей между этими МК делает Российские продукты неконкурентоспособными? Я думаю больше на это влияет упаковка, реклама и маркетинг… И тем не менее мы вторые по продаже оружия, боюсь там уже тоже ХАЛы и прочие калы применяют ибо рынок ждать не будет


  1. emmibox
    22.12.2019 02:44

    del


    1. IronHead Автор
      22.12.2019 02:54

      Ответ на ваш комментарий
      habr.com/ru/post/481436/?reply_to=21045638#comment_21045602