Наилегчайший старт в STM через «одно место»

Уже, наверное, прошло время религиозных войн AVR против STM, но нет-нет да наблюдаются вспышки столкновений двух лагерей. Практически у любой публикации на тему поделок на AVR обязательно будет каммент вроде «Да сколько уже можно лохматить бабушку, давно пора перейти на STM», дальше вариации на тему цены, количества ног и таймеров. Если STMщик более продвинут, обязательно будет указание, что DMA в AVR нет и не будет, по этому AVR должна умереть. Зачем простому блинку-вольтметру-градуснику DMA, гора 16 разрядных таймеров, 100 ног и 12 битный АЦП никто как правило не объясняет. Зачем нужен такой комбайн в устройстве, которое легко вывозит Tiny13, которая при этом не загружена даже на треть своих ресурсов никто не будет разбираться. Просто надо переходить на STM32, и баста. Ибо вот.

И надо сказать, есть у людей тяга к новизне. А действительно, может попробовать? А вдруг понравится? Вот только Референс Мануал на популярный STM32F103C8T6, на котором основана самая массовая Голубая таблетка в 1126 страниц что-то как-то не очень располагает к «быстрому старту». Даже отдельную утилиту, так ненавидимый аксакалами «калокуб», и ту надо изучать, что там к чему. Да и вникнув в Cube, стартовать за 5 минут вряд ли получится, генерируемая им портянка не самое доступное чтиво на ночь, просто «в лоб» врубиться, о чём там речь получится не у каждого.

Отдельной беседы заслуживают многочисленные статьи, похожие на эту, про быстрый и лёгкий старт в STM. У всех подобных статей меня первое время очень смущало одно обстоятельство. Нигде не присутствует подробное объяснение, а что мы тут собственно пишем. Куча скриншотов как создать проект, потом сразу стена кода-делай вот так! А что там, для чего там, почему именно так, откуда взять все эти вроде и понятные слова, никто не вникает, ибо силы кончились при написании мануала по установке Кейла и Куба, и по запуску проекта. Только спустя какое-то время, индивидуальное для каждого, приходит понимание, что происходит и зачем. В свою очередь, я предлагаю способ стартовать не с начала, как все, а с конца. Сейчас мы будем делать всё наоборот, не настраивать контроллер, писать код и дебажить его, а сразу перейдём к дебагу, и запротоколируем наши действия в виде кода.

Итак, устанавливаем Keil, как бесплатную (до 32КБ кода) среду. Описывать сие действо не будем, этого есть в интернетах, да и степ-бай-степ установщика должен осилить человек, который идёт в STM. Запускаем проект: Project-New uVision Project, создаём папку и файл проекта. Открывается окно выбора контроллера, в поиск вводим модель 103C8 и соглашаемся на единственную отобранную модель.

Далее попадаем в окно выбора библиотек:



Здесь ставим три галки: CMSIS-CORE, Device-Startup и Device-GPIO. Этого набора вполне хватит, чтобы подрыгать ножкой, зажигая светодиодик. Дальше придётся-таки понастраивать, никуда от этого не денешься. Alt+F7 запускают окно настроек, расположенное Project-Options for Target, где на вкладке «Output» надо поставить галку «Create HEX-File», чтобы создался файл прошивки, которую мы будем загружать в контроллер. Далее, во вкладке «Debug» мы выберем ST-Link, которым, собственно, и будем загружать прошивку и дебажить:



По кнопке «Setting» рядом с окошком выбора программатора попадаем в окно «Cortex-M Target Driver Setup», где во вкладке «Flash Download» ставим галку «Reset and Run».

В дереве проекта ткнём правой кнопкой в папку «Source Group 1», в открывшемся визарде создадим файл main.c, в который скоро будем писать код. В открывшемся main.c по правой кнопке вставляем самый первый и самый важный инклюд:



Дописываем код, состоящий из main и бесконечного while:

#include "stm32f10x.h"                  // Device header
int main(){
	while(1){
	}
}

Как ни странно, это всё на сей момент, это уже готовая и понятная программа, которая корректно компилируется и загружается в контроллер. Нажимаем F7 и видим, что прошивка удачно собрана, ошибок и варнингов нет.



С этого момента нам полностью доступен контроллер, мы можем войти в него под линии дебага и крутить-вертеть его во все стороны, а он будет откликаться.

Клавиши Ctrl+F5 ведут нас в дебаг, а кнопка «System Viewer Windows» позволяет запустить окошки контроля регистров тактирования и управления ногами GPIO.



Далее предлагаю всё-таки воспользоваться Reference Manual, тем более, что его даже скачивать не надо, он доступен по клику во вкладке «Books» меню «View»:



Теперь предлагаю воспользоваться следующим рассуждением. Из распиновки на Голубую Таблетку видно, что светодиод висит на ноге 13 порта С. Многочисленные инет-ресурсы и обсуждения всегда упоминают, что прежде, чем что-то сделать в STM, это что-то надо включить, иначе-подать тактирование. Не мудрствуя лукаво, пишем в окно поиска pdf-читалки то, что нам надо, а именно-включить порт C: «PORT C CLOCK ENABLE». Получаем во такую картину:



Отсюда можно сделать вывод, что включение тактирования порта С осуществляется в регистре IOPCEN. С этим знанием идём во вкладку RCC в режиме дебага, и вписываем это название в строку поиска:



Помечаем требуемый чекбокс галочкой, и с этого момента считаем порт С включенным.

Теперь, вспомная многострадальный AVR, будем искать настройку собственно пина. Для того, чтобы он заработал, надо объяснить, что именно мы от него хотим. А хотим мы подрыгать ногой номер 13 порта С, для этого надо задать режим её работы. В строке поиска в Referense Manual вбиваем «Port bit configuration», чем выразим своё желание прочитать, где же спрятаны настройки ножки. Поиск приводит нас к таблице, из которой следует, что для того, чтобы назначить ногу выходом, требуется сконфигурировать регистры MODE и CNF:



Из таблицы №20 видно, что для назначения ножки выходом Push-Pull надо сбросить регистры CNF0 и CNF1, а состояние пары MODE0 и MODE1 описано в таблице №21, я выберу верхний вариант, до 10MHz, MODE0=1, MODE1=0. Это я и проделаю в окне GPIOC для регистров CNF13 и MODE13



Теперь у нас настроено тактирование и режим работы порта. Самое время узнать, как именно дрыгнуть ножкой. По английски установить бит порта пишется как «Port bit set», эту фразу и будем искать в мануале:



Поиск приводит нас на страницу с таблицей, из которой явно видно, что за установку состояния ножки порта отвечает регистр BSRR, состоящий из пар BS и BR, Bit set и Bit reset соответственно. Находим эти регистры в окне GPIOC в режиме дебага и наслаждаемся управлением ногой №13 напрямую, тыкая мышкой галки в соответствующие чекбоксы:



Светодиод на плате голубой пилюли висит между ногой и VCC, по этому управление им обратно названию регистров. Bit Set (регистр BS13) тушит его, а Bit Reset (регистр BR13) зажигает. Это регистры атомарных операций, они сбрасываются после установки чекбокса. Есть возможность управлять ногой через регистр ODR, (пункт 9.2.4 Port output data register (GPIOx_ODR) в референс мануале), там наглядно видно, к чему приводит установка и сброс галки.



Горящий и тухнущий зелёный светодиод показывает, что всё работает верно. Остаётся только записать всё это в виде кода в файл main.c. Вот тут и появляется самый изюм, который отличает этот способ постижения контроллера STM через дебаг от остальных, которыми завален весь интернет. Я предлагаю просто переписать то, что видим в окне дебага в код. Пример:



Задали режим работы порта и включили тактирование;



Включили ножку порта, подождали, выключили и так далее:

#include "stm32f10x.h"                  // Device header

int main(){
	RCC->APB2ENR=0x00000010;			// включили тактирование
	GPIOC->CRH=0x44144444;			// задали режим Push-Pull до 10MHz
	int i;								// переменная для задания задержки вкл/выкл светодиода
	while(1){
		GPIOC->ODR=0x00002000;		// выключаем LED, по ламерски дёргая весь порт целиком
		i=2000000;					// взводим переменную для паузы
		while (i) i--;					// ждём
		GPIOC->ODR=0x00000000;		// включаем LED
		i=2000000;					// снова ждём
		while (i) i--;					
	}
}


Само собой, данный способ далеко не лучший и не правильный, но по моему мнению наиболее понятный и простой. К тому же, он приобщает к работе с даташитом (референс мануалом) и не отпугивает, как чтение манов и написание многостраничных портянок кода для Блинка. Да, здесь нет наслоений абстракций, упущено многое, но за элементарность старта я думаю можно это простить. Чтение мана и правильная работа с регистрами это потом, сейчас у нас моргает светодиод и нам в принципе понятно, как и что мы сделали, а самое главное, откуда взялись все эти аббревиатуры. Если бы мне показали такой способ изучения STM раньше, возможно я бы не собирал over 9000 разных программаторов для AVR в которых так и не было дебага, а взялся бы сразу за Кортексы. Ведь в AVR так и нет внятного и доступного дебага, но всё равно, забывать Tiny13 пока рано. Свои задачи она вывозит.
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

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

    –12
    Контроллеры мощнее, а подходы к программированию все те же. Какие-то битики, какие-то регистры. Нафига это все? Следующих шаг от 8-битных МК должен быть переход к более высокому уровню абстракции, когда пофиг сколько там таймеров и есть или нет ДМА. Т.е. к ОС. Без ОС между AVR и ARM нет никакой принципиальной разницы.
      0
      FreeRTOS, mbedOS и иже с ними. Это есть. AVR редко используется(во всяком случае мной), зачастую 32 битный STM.
      И абстракция есть, HAL называется…
        +6
        С такой абстракцией никакие враги не нужны. И человек немного путает ОС и ОСРВ, никакая ОСРВ в обозримом будущем не будет заниматься организацией работы с DMA в независимом от разработчика режиме.
        +1

        Предлагаете для моргания светодиодом использовать Raspberry Pi с каким-нибудь модным фреймворком? :)

          0

          node red

        +1

        В кокосе в свое время можно было выбрать контроллер и создать проект прям в несколько кликов. Если не путаю.
        А сейчас все что может само генерировать проект выдает чудовищные простыни с HAL через которые новичку пробраться к железу гораздо сложнее. Хотя сейчас есть LL но с ним по-умолчанию тоже проект не сгенерируешь, опять hal прицепом.

          +2
          Об этом я и пишу, эта стена кода ради блинка не просто пугает, она сама крестик в правом верхнем углу нажимет и Кейл с Кубом с компа сносит. Вроде хотел всего ничего, Хелловорд написать, а тебе 6 экранов кода выкинуло и дерево проекта на 30+ файлов. Тут любой по старому доброму AVR затоскует, тем более, что реальных задач для STM у домашнего мамкиного программиста как бы и нет. А реально нужного в этой портянке всего 5 строк.
            0

            Кстати, можете мне на пальцах объяснить, почему куб выдаёт стену кода? Возможностей и шаблонов, и даже макросов вполне хватает на то, чтобы пользовательский код был достаточно краток.

              0
              наверное это плата за «универсальность» заготовки кода. Прописано всё на все случаи, нужное-оставить, ненужное-удалить. Как быть с пластами абстракций, если ты нуб? Скорее всего, никак, только терпеть и лопатить.
                0

                STL очень туго обвязана шаблонами, получается, что разработчики куба просто поленились?

                  0

                  Куб генерирует код на Си, а в Си нет шаблонов.

                    0

                    Тогда понятно, на макросах тоже можно писать, но лучше так не делать.

                +2
                Кстати, можете мне на пальцах объяснить, почему куб выдаёт стену кода?
                Да никакой особой стены кода куб не выдаёт. Просто по сути каждый конфигурационный бит процессора в нём записывается как человеко-читаемая строка, например
                htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
                и чтобы понять, что тут происходит, нет необходимости каждую минуту лезть в даташит, выискивая вырвиглазные названия битов в таких же вырвиглазных названиях регистров.
                  0

                  Меня похожий вопрос интересовал, когда я решил попробовать ангуляр — ng init генерит не меньше кода, чем куб

                –1

                Для быстрого перехода на стм32 идеально подходит stm32duino. По мере погружения код будет постепенно превращаться в нативный

                  0

                  stm32duino — это который из двух? Они несовместимы.

                  0

                  Ну тинька и таблетка все же разных весовых категорий, а если сравнивать 328 и стм407 — вообще несравнимы. На тиньке что-то нормальное втиснуть — желателен ассемблер, а не ардуиноиде, на стмках же есть вполне нормальный STMCubeIDE, который содержит в себе все, что надо для разработки. Таки да, достаточно прост, чтобы разобраться, неплохой дебаггер и кейл не нужен при этом. Единственное, что плохо — он на эклипсе, посему любит задумываться даже на неслабых машинках и очень не любит стлинки на клонах китайских, aka cks или как там их.
                  В общем холивар atmel vs stm — изначально глуп, как хищник против человека-паука. Ну вы меня поняли...))

                    0
                    Кубоид пробовал, что-то вообще как-то не зашло. Ну и Эклипс для моей слабенькой машинки неподъёмен, да и тоже не впечатляет
                      0
                      А я с него начал, видимо, поэтому и зашел. А так даже ноут справляется древний, правда, приходится медитировать при разработке ))
                      0
                      А вы с STMH7 сравните. Мег ОЗУ, два мега ПЗУ, в отдельных вариантах полтора процессора… Ну как бы зверь совсем иного класса.
                      0
                      Мне кажется так удобнее периферию смотреть
                      image
                        0

                        К сожалению, такие красивые окошки Кейл умеет рисовать для очень ограниченного количества процов; вероятно, их люди делали "вручную". А регистры рисуются по sfr-файлу, который производитель МК поставляет.

                        0
                        А что делать, если нет 10к$ на Keil? =)
                          0
                          ужаться в 32КБ кода и никому не платить
                            –2
                            А что делать, если нет 10к$ на Keil? =)

                            Тогда можно включить собственные мозговые ресурсы, а не полагаться на статьи хабра. К примеру, зайти на сайт производителя STM32, перейти на «MCU & MPU Eval Tools», выбрать «STM32 Nucleo Boards»
                            www.st.com/content/st_com/en/products/evaluation-tools/product-evaluation-tools/mcu-mpu-eval-tools/stm32-mcu-mpu-eval-tools/stm32-nucleo-boards.html
                            затем прочесть такой текст: «All STM32 Nucleo users have free access to the mbed online resources (compiler, C/C++ SDK, and developer community) at www.mbed.org allowing to build a complete application in only a few minutes.»
                            Другими словами купите за 10 баксов какую-нибудь STM32 Nucleo board и программируйте эту board прямо из браузера на mbed.org, там тонны примеров кода. Это и будет «наилегчайший старт в STM32». Нет особого смысла верить всему, что появляется на хабре, особенно в песочнице.

                              –1
                              это будет «наилегчайший старт в STM за $10+». Да и хотелось бы ссылочку на нуклео за 10 баксов. Не стоит верить всему, что появляется на Хабре, особенно в камментах.
                              +2

                              Фигня жто mbed. Редактор на сайте годится только для запуска примеров. Да и то не всех. Навигации нет, отладки нет, даже нормальных сообщений об ошибках нет. Десктопный редактор еще более убог.

                                +1
                                PlatformIO спасает бедный ембед habr.com/ru/post/358682
                                  0
                                  Спасибо
                                    0
                                    Всегда пожалуйста, есть ещё вариант с Visual Studio и VisualGDB
                                    Правда отладчик платный, но говорят он того стоит. А также можно глянуть на Segger Embedded Studio, есть мнение, что там дебаггер просто божественен
                                    0
                                    Ага, все ждал в комментах, когда про него вспомнят :)
                                    Недавно попробовал, вообще огонь.
                                0
                                Eclipse как IDE на голову выше и бесплатный. Компилятор — gcc для ARM, не сравнивал с Keil по качеству но на больших проектах вполне успешно справляется.
                                  0

                                  Я в QtC вкорячил. Удобно, включая загрузку и отладку с помощью OpenOCD/GDB.

                                  0
                                  Берите IAR за 5 )
                                    0
                                    Мы на gcc собираем. OpenOCD для загрузки, GDB для отладки.
                                      0
                                      Почему бы не попробовать STMCubeIDE? Все в одном — среда разработки, компилятор, программатор, отладчик. В комплекте CubeMX, интегрирован в IDE, не нужно устанавливать/запускать отдельно. Единственный глюк, который я заметил — после обновления (а они случаются) есть вероятность, что при апгрейде файла *.ioc (это основа проекта, файл CubeMX) весь код, который вы написали в соответствующих блоках будет уничтожен. Но своевременные бэкапы проекта спасают в этом случае. Причем потери не обязательны, это происходит при определенных условиях, сейчас не вспомню, каких, уже больше полугода не подходил к МК. Ну и обновления происходят не просто так, STM в каждой обновке решает некоторые проблемы, к примеру, большинство мануалов в инете для запуска USB в качестве serial port предлагают добавлять некий код в обработчики приема-передачи, начиная с некоторой верии IDE они таки включили этот код в шаблоны. Саму IDE можно взять на st.com
                                      Ну и на ту же таблетку можно писать, используя HAL, можно CMSIS, если очень хочется, то можно и SPL подключить. И да не будет холивар, что хал — дерьмо, настоящие пацаны пишут на регистрах )))
                                        0

                                        Я с вами согласен в целом, но все же на следующий Новый год я попрошу Деда мороза повесить каждому менеджеру ST волшебный ошейник. Что бы когда очередной noname_user будет плакать над примерами ST или документацией по волшебном ошейник пробегало вольт 300...


                                        P. S. Самое обидное, что-бы вычистить код примеров нужны копейки, а человеко/лет user тратится порядочно.

                                      0
                                      int i;


                                      volatile int i;
                                        +1

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

                                          –1
                                          Не только. :)
                                          Ничто не помешает компилятору выкинуть пустой цикл, как бесполезный при включении оптимизации.

                                          Локальные переменные

                                          Часто для создания небольших задержек пользуются такими функциями:

                                          void Delay (char D)
                                          {
                                          char i;
                                          for (i = 0; i < D; i++) continue;
                                          }

                                          Однако, некоторые компиляторы видят в этих функциях бесполезный код и вообще не включают его в результирующий объектный код. Если эта задержка применялась для снижения скорости программного i2c (или SPI) под компилятором, например, HT-PICC, то при переносе на ядро AVR с компилятором WinAVR программа перестанет работать, вернее, она будет работать так быстро, что управляемая микросхема не будет успевать обрабатывать сигналы из-за того, что все вызовы функции Delay будут упразднены.

                                          Чтобы этого не происходило, нужно использовать квалификатор volatile:

                                          void Delay (char D)
                                          {
                                          volatile char i;
                                          for (i = 0; i < D; i++) continue;
                                          }
                                            0
                                            ваш пример вообще не самый лучший, так скажем. Строить квадратную шину на таких задержках это далеко не образец программирования, а собственно for сам по себе не самый правильный оператор, есть много программистов, которые им стараются не пользоваться, так как это «синтаксический сахар»
                                              –2
                                              Положим, это фрагмент статьи, на которую указывает ссылка.

                                              Боюсь представить, что с вами будет, если я подключу std::for_each. :)
                                                +2

                                                Так, а что вам не нравиться в цикле for? Любой ваш оператор цикла это по сути if и goto обернутые в красивое название (синтаксический сахар).

                                                  0

                                                  Лично я ничего не имею против, равно как и за. Это сродни предыдущему заявлению, что я был обязан указать volatile, человек считает, что я обязан, и его ничего не волнует.

                                                    +1

                                                    Мне кажется вы слишком резко восприняли критику, volatile, мне кажется, в данном случае нужен, так как эта статья позиционируется как учебный материал и было бы полезно сразу знать о граблях. Я не увидел в словах того заявления принуждения к этому, только совет с объяснением почему.
                                                    Я использую в кейле 6.13 компилятор с настройкой оптимизации balance и подобные циклы порой исчезают.

                                                      0
                                                      Это сродни предыдущему заявлению, что я был обязан указать volatile, человек считает, что я обязан, и его ничего не волнует.


                                                      Меня волнует, что ряды «Не включайте оптимизацию! В компиляторе ошибка — цикл теряется.» пополнятся очередным адептом. И виноваты в этом будете вы со своей статьёй. А вот это уже скверно.
                                                +2

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

                                                0
                                                мы рады, что вам известно назначение volatile, но именно эта минимальная программа здесь и сейчас в нём не нуждается.
                                                  –3
                                                  Блажен, кто верует. ;)
                                                    –1
                                                    мне явлено чудо, задержка работает. Масштабировать и переносить на другой камень в планы не входит
                                                      0
                                                      Ну тут афоризм про трусы и крестик. Либо вы пишете, как надо и с некоторой гарантией переносимости, либо верите своему компилятору и убеждаете себя, что ему не придёт в голову оптимизировать вашу задержку, и этот код не покинет те условия, при которых был собран. Обычно, люди хотят, чтобы их программы не зависели от обстоятельств компиляции, ибо обратно чревато приличным геморроем в случае, когда компилятор возьмётся перекраивать такой код.
                                                        –1
                                                        либо вы пишете всю программу по правилам хорошего тона, здравого смысла и правил программирования и конкретно этого языка, либо отбрасываете вообще всё, что может отвлекать и в конкретных учебных целях оставляете самый минимум. Здесь есть много того, за что можно развести критику до небес, но вы разглядели только volatile. К тому же, эта программа работает в дебаге, этопошаговый режим и эти задержки здесь не нужны вообще. Цель включить вручную тактирование, настроить порт и подрыгать ножкой, ставя галку мышкой.
                                                          0
                                                          Здесь есть много того, за что можно развести критику до небес, но вы разглядели только volatile


                                                          Потому что именно volatile приводит к тому, что люди жалуются, что их код не работает при включении оптимизации и переносе на другой компилятор. И ругают «тупой» компилятор. Я это видел не раз и не два. И потому будет лучше, чтобы те, кто прочитает вашу статью не делали таких весьма необычных ошибок.
                                                          Но к вам вопрос: я что-то сказал неверно про использование в этом фрагменте volatile?
                                                            +1

                                                            При компиляции gcc с ключом -Os (стандарт для МК) volatile не нужен, при -O2 и выше цикл должно выкинуть. Как ведёт себя keil или пиковский компилятор не знаю, документацию на них за ненадобностью не читал.

                                                  0
                                                  Разницы никакой
                                                    0
                                                    Оптимизм — это хорошо. Повышу вам за него карму. :)
                                                  +1
                                                  «Голубая таблетка» это не STM32F103C6T8, это STM32F103C8T6. Исправьте.
                                                    0
                                                    пофиксил
                                                    –1
                                                    Прикольно! Правильно описан ужас вначале разработки на STM, часто нигде не упоминается, откуда берутся операторы и какие они могут быть ещё. А тут по действиям понятно. Я также, когда начинал постигать VBA, включал запись макроса, делал действия, смотрел код.

                                                    По поводу дебага на AVR — зачем? ну есть JTAG-отладчики, но кому это надо? в голове или симуляторе не дебажится? Сколько всего делал на AVR, поэтому недоумеваю.
                                                      +2

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

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

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