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

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

И надо сказать, есть у людей тяга к новизне. А действительно, может попробовать? А вдруг понравится? Вот только Референс Мануал на популярный STM32F103C6T8, на котором основана самая массовая Голубая таблетка в 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 пока рано. Свои задачи она вывозит.
Источник: habr.ru