Конспект первой лекции по программированию современных микроконтроллеров на примере STM32 и операционной системы RIOT. Лекции читаются в Институте информационных технологий МИРЭА по субботам, с 12:50 в актовом зале на 4 этаже корпуса Д. В занятиях отводится 1,5 часа на саму лекцию и 3 часа на практические занятия в лаборатории IoT Академии Samsung по теме лекции.

Привет, Гиктаймс! Как мы и обещали, начинаем публикацию конспектов лекций, которые сейчас читаются в Институте ИТ МИРЭА. По результатам первой, вводной лекции мы решили немного изменить структуру курса — вместо планировавшихся двух потоков по 5 занятий будет один поток на 7 занятий. Это позволит в более спокойном темпе разобрать ряд вспомогательных вопросов, а также статьи с конспектом будут появляться на GT каждую неделю в течение всего марта и апреля, а не через неделю, как планировалось раньше.

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

Курс рассчитан на студентов второго и третьего курсов, знакомых с языком C и базовыми понятиями электроники и электротехники. Предварительное знакомство с микроконтроллерами не требуется.

Цель курса — освоение навыков, позволяющих свободно работать с микроконтроллерами на ядре ARM Cortex-M на современном уровне и, при наличии такого желания, двигаться в сторону дальнейшего углубления своих знаний.



Сегодняшняя лекция — первая, поэтому на ней будут разбираться общие понятия: что такое вообще микроконтроллер и зачем он нужен, что такое прошивка и как она получается, зачем нам нужна операционная система, и наконец — как работать с git. Результат практического занятия — собственный репозитарий на GitHub с исходными кодами ОС, а также успешно настроенная среда сборки на локальном компьютере.

Микроконтроллер


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



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

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

Микроконтроллеры уже достаточно давно развиваются параллельно с микропроцессорами — так, до сих пор встречающаяся в промышленных изделиях архитектура Intel 8051 была разработана в 1980 году. В каких-то моментах линии их развития начинают пересекаться с микропроцессорами — так, старшие модели микроконтроллеров имеют интерфейсы для внешнего ОЗУ, а производители микропроцессоров интегрируют на кристалл всё больше периферийных устройств (достаточно вспомнить, что на заре «персоналок» даже кэш-память набиралась внешними микросхемами) — но в любом случае они остаются двумя существенно отличающимися ветвями развития.

Собственно, целью создания микроконтроллеров была возможность удешевления и миниатюризации различных устройств, требующих некоторой небольшой вычислительной мощности: использование одного чипа, на который для его работы достаточно просто подать питание, существенно упрощает разработку и производство печатной платы по сравнению с набором из 4-5 отдельных чипов.

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

  • Рабочие частоты редко превышают 200 МГц, а чаще находятся в районе десятков мегагерц.
  • Объём оперативной памяти — в пределах мегабайта, а чаще — в районе десятков килобайт.
  • Объём памяти программ — в пределах мегабайта, а чаще — в районе десятков-сотен килобайт.

Мы в рамках курса будем работать с микроконтроллерами STM32L151CC, имеющими 32 КБ ОЗУ, 256 КБ ПЗУ и максимальную рабочую частоту 32 МГц (на платах Nucleo-L152RE стоят чуть более серьёзные чипы — 80 КБ ОЗУ и 512 КБ ПЗУ).

Память


В общем случае внутри микроконтроллера может быть четыре вида памяти:

  1. Постоянная память (флэш-память) используется для хранения пользовательских программ и, иногда, некоторых настроек самого микроконтроллера. Если при указании на характеристики микроконтроллера пишут объём памяти, не указывая, какой именно — как правило, это про флэш. Содержимое флэша не сбрасывается при пропадании питания, срок хранения информации в нём в нормальных условиях обычно не менее 10 лет.
  2. Оперативная память используется для выполнения пользовательской программы и хранения «сиюминутных» данных. ОЗУ всегда сбрасывается при перезагрузке или выключении питания, а также может не сохраняться при входе в некоторые режимы сна. В микроконтроллерах часто нет чёткого разделения на память программ и память данных — в результате можно встретить термин «выполнение из ОЗУ», означающий, что в ОЗУ находятся не только данные, но и сама программа; впрочем, это достаточно экзотические случаи.
  3. EEPROM. Тоже относится к постоянной памяти, но существенно отличается от флэш-памяти своими характеристиками. У флэша есть два больших недостатка, делающие его очень неудобным для сохранения из программы каких-то текущих данных — во-первых, у флэша ограниченное число перезаписей одной и той же ячейки, во-вторых, с флэшом часто можно работать только целыми страницами, которые имеют размер в сотни байт, даже если вам надо перезаписать всего один байт. EEPROM этих недостатков лишён — срок его службы обычно вдесятеро больше (от 100 тыс. до 1 млн. перезаписей), и работать в нём можно с каждым байтом по отдельности. По этой причине EEPROM используют для постоянного хранения данных, генерируемых самой программой (архивы измерений, настройки программы и т.п.), его типовой объём составляет единицы килобайт, но есть он не во всех контроллерах.
  4. Системная память. Области постоянной памяти, недоступные пользователю для записи, а записывающиеся при производстве микроконтроллера. Обычно в них находится исполняемый код загрузчика (о нём ниже), но могут также храниться какие-либо калибровочные константы, серийные номера или даже вспомогательные библиотеки для работы с периферийными устройствами

Посмотреть на организацию памяти конкретного контроллера можно в его даташите. Вот, например, даташит на STM32L151CC, на странице 51 которого представлена карта памяти этого семейства.

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

Регистры


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

  • прочитать значение по заданному адресу
  • записать значение по заданному адресу

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

Так, например, если мы хотим, чтобы на третьей ножке порта А микроконтроллера (PA2, нумерация идёт с нуля) появилась «1», нам надо записать «1» в третий бит регистра, расположенного по адресу 0x4002014. А если эта ножка настроена как вход и мы, наоборот, хотим узнать, какое на ней значение — нам надо прочитать третий бит регистра по адресу 0x40020010.

Да, чтобы указать контроллеру, входом или выходом является эта ножка — надо записать соответствующие значения в соответствующие биты по адресу 0x40020000.

Это — важный момент в понимании работы микроконтроллера: абсолютно всё, что не является вычислительными операциями, за которые отвечает само ядро процессора, осуществляется с помощью записи или чтения того или иного регистра. Какие бы библиотеки не были наворочены в вашей программе сверху — в конечном итоге всё сводится к регистрам.

Разумеется, работать с числовыми адресами довольно неудобно, поэтому для каждого микроконтроллера на ядре Cortex-M существует библиотека CMSIS (Cortex Microcontroller Software Interface Standard), самый важный компонент которой для нас — заголовочный файл, описывающий имеющиеся в конкретном контроллере регистры и дающий им относительно человекочитаемые имена.

С использованием CMSIS описанные выше операции с ножкой PA будут выглядеть так:

int pin_num = 2; /* PA2*/
GPIOA->MODER &= ~(0b11 << (pin_num*2)); /* сбросили биты настройки ножки PA2 на всякий случай */
GPIOA->MODER |= 0b01 << (pin_num*2); /* установили биты настройки ножки PA2 в 01 — выход */
GPIOA->ODR |= 1 << pin_num; /* установили ножку PA2 в 1 */

GPIOA->MODER &= ~(0b11 << (pin_num*2)); /* сбросили биты настройки ножки PA2, теперь это вход */
uint32_t pa2_value = GPIOA->IDR & (1 << pin_num); /* прочитали состояние ножки PA2 */

Все названия регистров и значения полей в них описаны в документе, который можно считать Библией программиста микроконтроллеров — Reference Manual (он, разумеется, свой для каждого семейства контроллеров, ссылка дана на RM0038, соответствующий семейству STM32L1). Отмечу, что более чем 900 страниц RM0038 — это не очень большой объём информации, легко можно встретить контроллеры с руководствами по 1500-2000 страниц. Вряд ли есть кто-то, помнящий хотя бы треть такого руководства наизусть, но умение быстро в нём ориентироваться — обязательное качество для хорошего программиста.

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

Понимая это, производители контроллеров начали выпускать вспомогательные библиотеки, собирающие наборы обращений к регистрам в функции — например, если при работе с регистрами напрямую для включения какого-либо такового генератора вам надо сделать два действия (поставить в 1 бит, включающий генератор, и подождать, пока в 1 встанет флаг, индицирующий, что генератор вышел на режим), то в функции включения генератора в такой библиотеке они будут объединены.

В случае с STM32 основная библиотека называется Standard Peripherals Library, она же StdPeriphLib, она же SPL. Помимо неё, существует выпускаемая ST библиотека LL, и ряд сторонних библиотек — например, LibOpenCM3. Сторонние библиотеки часто поддерживают и контроллеры других производителей, но в силу распространённости STM32 они обычно оказываются на первом месте.

Так, при использовании SPL обращения к регистрам, которые мы совершали, чтобы зажечь светодиод, превратятся в обращения к функциям GPIO_Init и GPIO_Write.

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

С одной стороны, SPL позволяет значительно быстрее набросать «скелет» проекта, особенно при использовании графических средств конфигурирования контроллера, таких как STM32 CubeMX. При этом код будет довольно хорошо (настолько, насколько у них совпадает набор периферийных устройств и возможностей, которыми вы пользуетесь) переноситься между разными контроллерами семейства STM32.

С другой стороны, как показывает практика, в сложном проекте нет вопроса «что делать, если что-то будет работать не так» — в нём есть вопрос «что делать, когда всё будет работать не так». В SPL, как и в любой библиотеке, могут быть ошибки, кроме того, логика разработчиков SPL может не совпадать с вашим представлением о том, что должно происходить с контроллером при тех или иных действиях — в результате при попадании в такую ситуацию вам всё равно придётся открывать исходники SPL и смотреть, что конкретно там происходит на уровне регистров. На практике это может иногда занять времени не меньше, чем написание нужной вам функциональности с нуля.

Кроме того, библиотеки, выпущенные конкретным производителем чипов, хоть и позволяют в каких-то пределах мигрировать между чипами этого производителя, но перескочить, например, с STM32L1 на ATSAMD21 с кодом, написанным для SPL, у вас не получится при всём желании.

Не всегда помогает SPL и читаемости кода — в программах, написанных с её использованием, нередко можно увидеть простыни размером в полстраницы, состоящие из одних только вызовов SPL.

Наконец, SPL решает лишь одну проблему — абстрагирования от «железа» и работы с регистрами. Однако по мере развития проекта вы столкнётесь ещё с несколькими, например:

  • Виртуализация периферийных устройств. Например, в вашем контроллере есть всего один таймер часов реального времени (RTC), на который можно установить два независимых события — и в то же время в серьёзной программе запросто может оказаться пять-шесть функций, который используют таймер регулярно (для периодического выполнения заданий) или разово (например, для отсчёта задержки), причём другие таймеры им не подходят. В этой ситуации вам потребуется функция-менеджер, которая будет организовывать одновременную работу всех этих процедур с единственным имеющимся таймером.
  • Многозадачность. Любая достаточно сложная система быстро обрастает большим количеством всевозможных процедур, которым надо срабатывать с различной периодичностью или по различным событиями. Знакомый многим по Arduino цикл loop() уже на полудесятке утрамбованных в него разношёрстных процедур начинает выглядеть уродливым монстром, а попытка организовать в его рамках ещё и приоритизацию задач вселяет ужас в сердца людей. В этот момент вы захотите вынести все задачи из loop() в независимые функции, оставив в цикле только планировщик, который будет к указанным задачам обращаться. Это будет первыми зачатками многозадачности (о полной её реализации, типах планировщиков и общении между разными задачами мы поговорим на следующей лекции).
  • Разделение труда. Как только разработка системы выйдет на уровень, на котором её ведут несколько человек, перед вами встанет задача разделения обязанностей — помимо оптимизации разработки, имеющая ещё и чисто практический смысл: в мире довольно мало программистов-универсалов, которые могут с одинаковой эффективностью отлаживать и работу с процессором, и сетевой стек, и пользовательский интерфейс. Со значительно большей вероятностью каждый из членов вашей команды будет лучше других разбираться в какой-то одной области — поэтому вам быстро захочется разделить эти области на уровне кода, чтобы, например, специалист по пользовательскому интерфейсу не был вынужден через строчку сталкиваться с обращением к регистрам контроллера, и наоборот. Это приведёт к разбиению вашего кода на отдельные модули, общающиеся друг с другом через стандартизированные API.

Все эти задачи — и попутно ещё много других — решает операционная система.

Несмотря на то, что ОС требует для своего существования дефицитных ресурсов контроллера (обычно 5-20 КБ постоянной памяти и ещё столько же оперативной), преимущества использования ОС настолько велики, что на данный момент в профессиональной разработке для встраиваемых систем около 70 % проектов используют ту или иную ОС.



Строго говоря, на нижнем уровне ОС может использовать вендорские библиотеки, подобные SPL. Однако в рамках нашего курса мы будем работать с RIOT OS, нижнеуровневый код которой для семейства STM32 написан на регистрах — работу с SPL же мы затрагивать не будем вообще.

Причина этого проста: хотя в целом мы будем изучать работу ОС и контроллера на верхнем уровне, но в тех случаях, когда мы захотим углубиться в детали их функционирования, нам всё равно придётся спускаться на уровень регистров, и прослойка в виде SPL довольно сильно бы этому мешала. Освоив же общие принципы работы с контроллерами, при желании с функционированием SPL вы сможете разобраться самостоятельно, тем более, что абсолютное большинство учебников по STM32, доступных онлайн, построены на её базе.

Операционная система


В виде максимально упрощённой схемы ОС можно представить как набор компонентов, выстроенных в определённую иерархию:



  • нижний уровень — код, непосредственно работающий с микроконтроллером;
  • средний уровень — компоненты, входящие в саму ОС, но уже не зависящие от конкретного контроллера: драйверы различных внешних устройств, планировщик задач, различные вспомогательные службы;
  • верхний уровень — собственно пользовательское приложение.

Одна из причине, почему мы будем работать с RIOT OS и без использования каких-либо средств разработки (IDE) — в получающем в последнее время всё большее распространение магическом мышлении, согласно которому, многие функции реализуются нажатием соответствующих кнопок в IDE, и без этих кнопок невозможны (так, я встречал утверждение, что достоинство Arduino IDE — в возможности собрать один и тот же код под разные аппаратные платформы путём выбора нужной платформы в меню; по мнению рассказчика, другие системы таким функционалом не обладали, так как не имели соответствующего меню).

Точнее, если вспоминать фразу Артура Кларка про технологии, неотличимые от магии, то это мышлении можно скорее назвать псевдомагическим, переформулировав афоризм как «любая технология, достаточно хорошо спрятанная от пользователя, становится неотличима от магии».

На самом деле, разумеется, никакой особенной функции меню в Arduino IDE, как и в любой другой IDE, не несёт — это лишь графическая оболочка для доступа к некоторым совершенно стандартным функциям и особенностям современных программных систем.



Если мы посмотрим на то, как выглядит RIOT OS в виде набора файлов на диске, то без труда опознаем разложенные по папочкам компоненты системы: HAL лежит в папке cpu (и если мы её откроем, то увидим описания для десятков различных микроконтроллеров, от AVR до PIC32), описания построенных на этих контроллерах плат — boards, драйверы внешних устройств — drivers, ядро ОС — core, системные и вспомогательные сервисы ОС — sys, пользовательские приложения — examples.

Один из важных моментов, который отличает микроконтроллеры от больших систем — то, что практически всегда (а в нашем случае совсем всегда) пользовательские приложения существуют не как отдельные файлы, загружаемые независимо от ОС, а компилируются вместе с ОС, всем набором драйверов и модулей в единый файл, загружаемый в память микроконтроллера. Причин этому несколько — начиная с отсутствия необходимости в отдельной загрузке приложений, что позволяет упростить всю систему, и заканчивая наличием необходимости собирать ОС и комплект драйверов и модулей под конкретное устройство ради экономии его отнюдь не бесконечной памяти.

Исходные коды ОС


Мы будем работать с исходными кодами в версии https://github.com/unwireddevices/RIOT/tree/mirea — это ответвление от основной разработки RIOT OS, в котором силами Unwired Devices улучшена поддержка микроконтроллеров STM32L1, а также добавлены некоторые полезные сервисы, например, таймеры на базе часов реального времени, включая миллисекундный таймер.

Исходные коды можно загрузить с Github, выбрав кнопку «Clone/Download» и «Download ZIP», но лучшим вариантом будет создание собственного репозитория. Для этого зарегистрируйтесь на GitHub, после чего вернитесь в указанный выше репозиторий и нажмите кнопку «Fork» — исходные коды будут скопированы в ваш аккаунт, откуда вы сможете уже без проблем работать с ними.

Я не буду описывать здесь детали работы с GitHub и Git — в интернете есть масса отличных пошаговых руководств, повторять которые нет смысла.

Компиляция простейшего приложения


Благодаря тому, что ОС берёт на себя всё взаимодействие с микроконтроллером, простейшее возможное приложение в общем-то ничуть не сложнее, чем традиционный «Hello world» на большом ПК:

#include <stdio.h>
int main(void)
{
    puts("Hello World!");
    printf("You are running RIOT on a(n) %s board.\n", RIOT_BOARD);
    printf("This board features a(n) %s MCU.\n", RIOT_MCU);
    return 0;
}

В структуре нашей ОС это приложение располагается в папке example/hello-world в файле main.c (оно там уже есть).

Однако, очевидно, чтобы его скомпилировать, необходимо сначала настроить среду сборки. Это делается по-разному в разных ОС.

1. Windows 8 и старее. К сожалению, придётся использовать среду MinGW, медленную и неудобную. Процедура установки нужных компонентов достаточно подробно описана здесь. Отмечу, что для работы с Git/GitHub придётся также отдельно поставить Git for Windows, который притащит свою урезанную версию MinGW. При желании всё это можно свести в один терминал MinGW, но проблем с очень низкой скоростью работы MinGW и общим его неудобством это не решит.

В целом, Windows 7 и Windows 8, как можно понять, являются не самым удачным выбором для разработки.

2. Windows 10. Откройте магазин Microsoft Store, найдите в нём Ubuntu и установите. Если при первом запуске Ubuntu будет ругаться на выключенный компонент Windows, откройте системное приложение «Включение или отключение компонентов Windows», найдите там «Поддержка Windows для Linux» и включите.

Вся дальнейшая работа происходит в среде Ubuntu, значительно более комфортной и быстрой, нежели MinGW.

Скачайте компилятор и сопровождающие его утилиты отсюда (внимание: вам нужна 64-битная версия для Linux!), откройте Ubuntu, распакуйте архив и укажите системе пути к нему:

cd /opt
sudo tar xf /mnt/c/Users/vasya/Downloads/gcc-arm-none-eabi-7-2017-q4-major-linux.tar.bz2
export PATH=/opt/gcc-arm-none-eabi-7-2017-q4-major/bin/:$PATH
export PATH=/opt/gcc-arm-none-eabi-7-2017-q4-major/arm-none-eabi/bin/:$PATH
echo "export PATH=/opt/gcc-arm-none-eabi-7-2017-q4-major/bin/:\$PATH" >> ~/.bashrc
echo "export PATH=/opt/gcc-arm-none-eabi-7-2017-q4-major/arm-none-eabi/bin/:\$PATH" >> ~/.bashrc

Последние две команды пропишут установку путей к компилятору и утилитам в файл .bashrc, так что вам не придётся вручную их устанавливать при каждом запуске Ubuntu. Обратите внимание на обратную дробь перед $ и двойную стрелку >> в конце — без первого путь будет записан некорректно, без второго (с одиночной стрелкой) вы сотрёте всё предыдущее содержимое .bashrc.

После этого выполнение в консоли команды arm-none-eabi-gcc --version должно сообщать, что такой компилятор есть, а его версия — 7.2.1 (на текущий момент).

Для работы с Git вам потребуется сгенерировать пару из приватного и публичного ключей командой ssh-keygen, после чего скопировать публичный ключ (в Ubuntu под Windows это можно сделать командой cat ~/.ssh/id_rsa.pub, потом выделить выведенное мышкой и нажать Enter — оно скопируется в буфер обмена) и добавить его в ваш аккаунт GitHub. После этого можно будет работать с GitHub из командной строки командой git.

NB: если вы ранее не работали в командной строке Linux, то обратите внимание на два полезных момента: курсорные стрелки вверх и вниз позволяют листать историю введённых команд, а клавиша Tab дополняет набранный вами путь к файлу или папке до конца (то есть cd /opt/gcc- превратится в строку cd /opt/gcc-arm-none-eabi-7-2017-q4-major). Последнее служит также хорошей проверкой, правильно ли вы набираете путь — если неправильно, дополнен он по очевидной причине не будет. Если возможных вариантов дополнения несколько, то двойное нажатие Tab выведет их все.

NB: в Windows вам будет удобнее работать, если сами исходные коды ОС размещаются в папке, напрямую доступной из Windows, например Documents/git/RIOT. Из-под MinGW она будет доступна по пути /c/Users/vasya/Documents/git/RIOT, из-под Ubuntu — /mnt/c/Users/vasya/Documents/git/RIOT. В этом случае вы сможете свободно пользоваться для работы с кодом, например, текстовыми редакторами, написанными для Windows, такими как Notepad++.

3. Linux. Установка среды сборки ничем не отличается от инструкции для Windows 10, кроме того, что Microsoft Store вам не потребуется. Также не ищите gcc-arm-none-eabi в репозитории вашего дистрибутива — скачайте наиболее свежую версию с его официального сайта.

После установки среды сборки откройте консоль, перейдите в папку с RIOT и в подпапку examples/hello-world, после чего запустите команду make.

Скорее всего, она быстро прервётся ошибкой и сообщением, что у вас не хватает unzip (под Windows 10 по умолчанию он не устанавливается), make или других утилит. В Windows 10 их можно установить командой (перечень недостающего даётся простым списком через пробел):

sudo apt-get install unzip make

После установки попробуйте ещё раз запустить make — точнее, оптимальным вариантом является вызов команды «make clean && make»: первая очищает мусор, оставшийся от предыдущей попытки. Без ней компилятор может ошибочно решить, что какой-то из уже собранных модулей не менялся, и не пересобирать его — в результате вы получите прошивку, собранную из кусков старого и нового кода.

NB: в оригинальном RIOT приложение hello-world собирается для архитектуры native, то есть, в нашем случае ноутбука или десктопа, x86. Однако в нашем коде в параметрах сборки проекта уже указана плата unwd-range-l1-r3, использующая контроллер stm32, поэтому в начале процедуры вы должны увидеть строку

Building application "mirea" for "unwd-range-l1-r3" with MCU "stm32l1".

В случае успеха за ней вы увидите десяток-два строчек, начинающихся с команды make — это сборка отдельных компонентов операционной системы. Закончится всё сообщением об успешном создании файла прошивки mirea.elf с указанием размеров различных типов данных (объёмов используемой флэш-памяти и ОЗУ).

Как-то вот так:



Итак, мы немного разобрались с тем, как выглядит микроконтроллер, скачали исходные коды нашей ОС, настроили среду сборки и убедились, что она работает.

На следующем занятии мы рассмотрим подробнее устройство микроконтроллера, начиная с портов GPIO, и загрузим в него первое приложение — оно, по старой традиции, будет мигать светодиодом — а далее вернёмся к операционной системе и внимательнее изучим, из каких компонентов она состоит и как настраивается её сборка.

P.S. И в качестве дополнения — живая 360-градусная запись лекции (запись семинаров не проводилась по понятной причине: «у доски» там говорится мало, значительная часть работы идёт уже с отдельными студентами, у которых что-то получается или не получается):



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


  1. Neuromantix
    02.04.2018 13:05

    Все, все без исключения уроки по прогрммированию МК «для начинающих» (начинающий — в моем понимании — это человек, никогда не работавший с МК, и не имеющий представления о программировании, типа меня) выглядят так:
    1. У нас есть цифры — это 1, 2, 3, 4 и так далее.
    2. 2+2=4 Это очень просто, не правда ли?
    3. Как очевидно, 6!=720, а lg500=2.699 (что такое! и lg — обычно не объясняется)
    4. Теперь, зная все вышеизложенное вы легко решите (тут идет какое-нить монструозное уравнение в 4 этажа с интегралами, логарифмами, степенями и комплексными значениями).
    5. Урок окончен. В следующем уроке мы рассмотрим решение дифференциальных уравнений в 18-мерном неевклидовом пространстве.

    Примерно так же и тут — начали с регистров, перешли на устройство ОС, а закончили командной строкой линукса — это очень просто, не правда ли?

    Вот именно поэтому я так и не научился программировать МК, хотя много раз начинал — всегда застреваешь где-то между «2+2=4» и «что такое логарифм», не говоря уже о том, что получить готовый результат из рассыпухи выходит быстрее, чем вкуривать все это.


    1. qbertych
      02.04.2018 13:33

      Легендарный курс DIHALT по AVR тоже начинается с дикой смеси из истории контроллеров, архитектуры AVR, тонкостей работы AVR Studio и макроассемблера вперемешку с crash course по Си.


      И, как ни странно, остается лучшим курсом по этой теме на русском языке.


      1. olartamonov Автор
        02.04.2018 13:49
        +2

        Есть два подхода, академический и практический.

        Академический — это постепенное разжёвывание знаний, при котором хоть к какой-то реальной практике на живом микроконтроллере можно перейти через полгода, а до того мы будем на транзисторах и 2И-НЕ работу GPIO и ALU моделировать.

        Практический предполагает, что у каждого занятия есть, собственно, практический результат.

        В нашем случае академический подход не подходит (извиняюсь) в принципе, так как а) всего семь занятий, б) каждое занятие представляет собой пару лекция + лаборатория и в) студенты — с разных направлений и с разным объёмом знаний, есть и электронщики, и программисты, и даже как минимум один человек, который свободно пишет на SPL, но не знаком с RTOS, etc. Если в этой ситуации долго и планомерно давать всю теорию, начиная с азов — у нас через неделю из 40+ студентов останется 20-.

        Кроме того, по моему глубокому убеждению, в практических дисциплинах (а программирование микроконтроллеров — ни разу не фундаментальная) достаточно указать направление движения и ориентиры на этом пути, а уж чего-чего, а недостатка детальной информации для желающих её получить в онлайне в наше время избыток.


        1. qbertych
          02.04.2018 14:56

          Про направление и ориентиры — в точку. Из того же курс DI HALT'а мне (тогда молодому и зеленому) врезались в память простые истины о том, как надо работать:

          — Глюк в простой функции? Открываем скомпилированный код на ассемблере, медленно раскуриваем. Поначалу непонятно и страшно, зато потом можно горы сворачивать.
          — Непонятно, как работает какая-то функция? Лезем в ее исходник, внимательно читаем.
          — Как работать с регистром? Лезем в даташит, ищем. Не нашли? Ищем еще раз, внимательнее. Проблемы с английским? Открываем google translate, переводим.

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


    1. Defaultnickname
      02.04.2018 13:33

      Прочитайте "Цифровая схемотехника и архитектура компьютера". Вам будет куда более понятно, что происходит, начиная от транзисторов и заканчивая кодом на С.


    1. olartamonov Автор
      02.04.2018 13:36

      Человеку, не имеющему представления о программировании, стоит начать собственно с основ программирования. Это совершенно другая тема, никаких микроконтроллеров не требующая.

      В этом же курсе как минимум умение писать на C для «больших» систем предполагается изначально.


    1. SergeyMax
      02.04.2018 14:16

      поэтому я так и не научился программировать МК, хотя много раз начинал — всегда застреваешь где-то между «2+2=4» и «что такое логарифм»

      Скорее всего, вам уже просто слишком много лет.


      1. Mike_soft
        02.04.2018 14:46

        «слишком много лет» — это не приговор. Хотя гибкость мышления после 50 в среднем снижается, это верно. Но видел как 45-50-летних, успешно осваивающих ЦОС и МК, так и 30-летних, которым было «проще сделать на рассыпухе»


      1. SovietTwins
        03.04.2018 12:06

        Не соглашусь с вами. Молодые люди вообще в основном форменные идиоты. И когда писанина кода выходит за рамки языков высокого уровня — начинается нытьё. Никто ничего не хочет искать и учить… Разбираться в коде? Отлаживать код? Оптимизировать? Этим занимается "старая гвардия", те, кто ещё помнит, как в малые ресурсы уместить большие данные. Научиться может и 50 летний. Просто люди после 30-40 вообще мало учатся. А те, кто постоянно изучает что-то новое, молодым фору дать могут.


    1. Mike_soft
      02.04.2018 14:40

      а программировать _не_МК вы пробовали?
      на самом деле, тяжело учиться кататься на коньках, если ты ни разу не видел ни коньков, ни льда…
      попробуйте начать с «программирования вообще», а затем уже переползать на МК. Может, стоит попробовать на «презренной ардуине» — помигать светодиодом, подрыгать ногой, попищать пьезиком, поиграться с АЦП и ШИМом… Чтоб без RTOS, только МК и ваша программа…


      1. Neuromantix
        02.04.2018 14:45

        Светодиодом я моргал, пищал и дрыгал — и на ардуине, и на МК без ардуины. А вот дальше начинается темный лес. Особенно когда начинаешь решать конкретные, хоть и простейшие, задачи, а не абстрактные.


        1. Mike_soft
          02.04.2018 14:48

          т.е. базовые предстваления о программировании, и о внутренней структуре МК (ну, в т.ч. о том, чем он отличается от процессора общего назначения — т.е. GPIO, и т.п. периферия) у вас есть. Это уже хорошо. тогда на каком этапе «затык»?


          1. Neuromantix
            02.04.2018 15:24

            Затык на нескольких сразу. Во-первых после нескольких десятков строк кода я перестаю видеть в нем работающую железку и вижу наборы скобок и знаков препинания. (я когда-то лет 20 назад писал проги для калькуляторов, типа МК-61 — там все было просто и очевидно — грузим в регистры данные, потом делаем с ними нужные манипуляции и выгружаем, а вот с МК так почему-то не воспринимается) Во-вторых меня очень сильно сбивает невозможность делать несколько операций параллельно — почему это мы не можем читать АЦП, пока что-то там перемножается? (В этом отношении верилог оказался куда проще — я за вечер вкурил его куда сильнее, чем МК за несколько попыток, но там я застрял тоже, хоть и дальше, т.к. человек, у которого можно было консультироваться по дурацким и не очень вопросам, внезапно потерялся). И третье — это наверное основное — то, что большинство примеров в интернетах сделаны «чтоб было». Вот из последнего — нужен вольтметр на 4 знака. Пошел копаться в ардуине, что-то сляпал. Измеряет даже не в попугаях, а в килопопугаях. Консультируюсь — оказывается, надо отключать ядро на время измерения, чтоб помех не было. А еще внешний АЦП, внешний опорник (это-то как раз очевидно). А как вот это все слепить — а как хочешь, нигде не найти толком. По крайне мере я за 2 вечера не нашел, плюнул, достал icl7135 и через 2 вечера уже все работало.


            1. Mike_soft
              02.04.2018 15:53

              я, наверное, скажу непонятное — но в «скобках и знаках препинания» тоже очевидно. Это, как вы справедливо заметили, вопрос «восприятия».
              Могу лишь посоветовать довести какой-нибудь проект до конца «через немогу» и через пинки нормального советчика-«учителя». А «примеры в интернете» — ну так на каждый случай жизни их не напасешься. но как вариант — взять готовый проект, и основываясь на готовой схеме — попытаться написать программу, «подглядывая одним глазом» в готовый результат.
              Тут как езда на велосипеде — научившись один раз, трудно разучиться обратно. (хотя МК, в отличие от велосипедов, много разных, и порой сильно отличающихся друг от друга)


            1. DASM
              02.04.2018 15:59

              Ну почему же нельзя, DMA есть для АЦП. Вы же задаете вопрос "почему нельзя что то умножать, когда уже идет умножение" Через DMA ваши данные из АЦП прекрасно отправятся в память без вмешательства АЛУ процессора. Ну а именно "читать" придется потом, если мы обсуждаем одноядерные МК


            1. olartamonov Автор
              02.04.2018 17:01
              +2

              У вас в голове сейчас странная смесь из программирования вообще, программирования микроконтроллеров и вообще не программирования.

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

              «Невозможно делать несколько операций параллельно» не имеет никакого особенного отношения к микроконтроллерам — абсолютное большинство языков программирования, которыми пользуются на больших ПК, точно так же не имеют встроенных средств организации многопоточности. Возьмите банальный Delphi, напишите на нём приложение так, как вы его сейчас пишете для MCU — и на Core i7 на три гигагерца у вас в нём кнопки нажиматься не будут, пока оно внутри что-нибудь перемножает.

              Точно так же работа с аналоговыми сигналами и АЦП не имеет никакого особо прямого отношения к микроконтроллеру. Взяв внешний АЦП, вы можете совершенно спокойно прострелить себе ногу несколькими разными способами. Собственно, даже с тупой как пробка ICL7135 у вас есть отличный получить чушь вместо измерений, если не вдумываться, что, как и зачем вы измеряете.


            1. Alexeyslav
              02.04.2018 21:58

              Абстрактного мышления вам не хватает. Пробуйте решать задачу с двух концов, и научиться правильно сделать техзадание. «Вольтметр на 4 знака» это вообще цель а не задача, а путей достижения цели — неисчислимое множество, даже в таком ограниченном контроллере. Вам надо найти любой из удовлетворяющих задаче путей решения поставленной задачи, и если готового решения нет(а его с большей долей вероятности нет) то смотреть как эту проблему решают другие — смотреть нужные части и строить свои мостики. Это не сложно когда хорошо работает абстрактное решение. Потом по найденному пути написать программу — дело времени.
              Соответственно, надо знать и схемотехнику поскольку у вас есть и аналоговый сигнал. На практике, вы уже набили шишку с влиянием ядра на АЦП, и больше такую не сделаете. Но тут в принципе и другой выход мог быть — «шум» можно было победить математически усреднением методом скользящего окна(обычное усреднение в данном случае неэффективно) — ведь результат нам не нужен слишком быстро — человек всеравно не воспримет мельтешение цифр чаще чем 1/10 секунды а АЦП за это время может сделать 1000 измерений. В аналоговой части этого АЦП нужен фильтр НЧ высокого порядка на частоту найквиста — НЕ БОЛЕЕ 5кГц(для данных услоовий), а лучше всего ближе к характеристикам измеряемого сигнала вплоть до 100Гц и меньше иначе у вас пролезет другая проблема если в измеряемом сигнале есть ВЧ составляющая.


            1. Vanellope
              03.04.2018 10:44

              ПМСМ, чтобы разобраться в микроконтроллерах, надо начинать с уровня с минимальной абстракцией. Понять, как работает железо — надо смотреть на уровне ассемблера, как биты и байты обрабатываются в процессе решения поставленной задачи. Я вот худо-бедно разобралась без всяких лекций и онлайн-курсов, обложившись книжками и даташитами. А, да, в универе какое-то убожество советское программировали на ассемблере, но это не считается :)


              1. Mike_soft
                03.04.2018 10:59

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


                1. Vanellope
                  03.04.2018 12:13

                  Не считается, потому что современное образование в моей реальности, как морская свинка — ни к современности, ни к образованию не имеет отношения. В 21 веке, программировать советский микропроцессор! На бумажке по таблицам опкодов! Вводить программу в Нех-кодах! На кривоколенной поделке времен молодости отцов «учебном микропроцессорном комплекте»! А не работает правильно — либо светодиодные индикаторы сгорели, либо микросхемы сбоят, либо программа и вправду кривая. Когда пол группы про Нех и слышать не слышала. Компиляторов нет, есть только эмулятор этого самого УМК на компе — студенческая поделка. Не было бы интересно с железом возиться — и в памяти не осталось бы.
                  Снизу вверх — у вопрошающего проблема — не видит работающего железа за уровнями абстракций, а вот МК-61 в регистрах программировал, значит надо идти снизу вверх, от простого к сложному. Да и ассемблеры все похожи ;) Переносить принципы с одного типа на другой — легко, когда принципы понятны. А за абстрагированием мелочи теряются, для работы полезно — скорость, для обучения — не очень.


                  1. Mike_soft
                    03.04.2018 12:49

                    Да какая разница, советский процессор или не советский (расово советских вообще не было, все они цельнотянутые были).
                    «по таблицам опкодов» — ну а почему бы и нет? чтоб задумались, попытались найти в опкодах логику. я уже рассказывал про товарища, который в армии по памяти (опираясь, естественно, на логику), восстановил таблицу команд 80-го проца, и дизассемблировал вручную бейсик из журнала Радио (для Радио-Микро80), отсылая получившийся текст письмами домой… так что это весьма неплохой способ изучения.
                    И запускали мы, кстати, перекомпилированный бейсик на СПМ-80 (ну, это почти тот же УМК, только больше для отладки «железа»), «Система Проектирования Микропроцессорных устройств для 80 процессора».
                    А на ассемблер мы «спустились» с фортрана…
                    то, что половина группы не знает про хекс — так это либо вина учебного плана, либо преподов (ну, если они объясняли, а пол-группы не поняло — вина этой половины группы). но никак не советского проца или эмулятора. Нет компиляторов — прекрасно: вот вам и задача. хороший курсовой для 3 курса.


                    1. Alexeyslav
                      03.04.2018 13:30

                      Надоело мне с опкодами возится для Z80 взял и написал свой компилятор…
                      Кстати для Z80 было два ассембера — один изначальный отражающий суть системы команд и другой адаптированный под стандарты из которого нельзя понять что происходит т.к. команды LD и MOV не различались и была только одна команда MOV… типа, меньше разных слов быстрее студенты язык выучат? Довелось мне пообщаться с этой самой УМК, ну так игрушка. Лабораторку сделал за 15 минут из двух часов, но остальные 28 человек из класса парились до конца так и не поняв что к чему. Всёравно потом списывали.


                      1. Mike_soft
                        03.04.2018 13:49

                        так везде. и на всех предметах. и, наверное, во все времена — часть студентов усваивает, часть списывает.
                        УМК — ну, а чего там волшебного ожидать? 580-й с обвязкой, 55й в/в. пару килобайт памяти. для обучения достаточно.
                        у нас еще были аналоги на 584 серии (это секционники).
                        а вот под 51/48 мы уже делали комплекс на Корветах (нечто отдаленно похожее на то, что потом назовут IDE -редактор, ассемблер, эмулятор-отладчик, эмулятор ПЗУ)


                    1. Vanellope
                      03.04.2018 15:10

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


                      1. Mike_soft
                        03.04.2018 15:39

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


                        1. Vanellope
                          03.04.2018 16:18

                          Вот положа руку на сердце, чему может К580 научить кроме как мыслить на ассемблере? Периферии и современных интерфейсов — 0. На том же AVR все это изучается и на железе и в симуляторах разных.


                          1. Alexeyslav
                            03.04.2018 16:40

                            Как же ноль? К нему целый набор микросхем идёт — те же таймеры 580ВИ53, УВВ — КР580ВВ55, UART — 580ВВ51. В отличие от контролера в систему на наборе микросхем К580 их можно добавить столько сколько нужно, лишь бы адресного пространства хватило и бюджета электричества(ВВ55 за просто так пол ватта потребляет). Кстати заодно и упражнение на синтез схемы дешифратора адреса и сигналов выбора микросхем можно организовать и на практике выяснить ограничения сложных каскадных схем на логике по быстродействию. С одним каналом таймера ВИ53 и регистром сдвига 155ИР13 можно организовать SPI.


                            1. Mike_soft
                              03.04.2018 16:44

                              ну ты загнул!©
                              «организовать» :-) читаем даташит — нет SPI. Нет — значит НЕТ!
                              :-)))


                              1. Alexeyslav
                                05.04.2018 06:38

                                В даташите на что? на 580ВМ80? Так это только ядро, а рабочая система на его основе требует платы с периферией — вот на неё и нужно даташит искать или самому делать и написать даташит, а там уже и SPI можно реализовать.


                                1. Mike_soft
                                  05.04.2018 07:33

                                  да, в даташите на процессор :-)
                                  вы ж SPI, I2C, ADC, таймеры в даташите на STM32F103 видите? видите… значит, там они есть. а в 8080 — нет.
                                  но если серьезно, то 580 процессор и 580 комплект — совершенно разные вещи, совершенно разный подход и т.п. И сравнивать с микроконтроллерами их, имхо, не стоит. Хотя для учебных целей 580 вполне может подойти (а может и не подойти — смотря на кого учат)


                                  1. Alexeyslav
                                    05.04.2018 11:00

                                    так дело в том что STM32F103 это SOC, а 580 процессор это только ядро, систему мы формируем сами — значит за нами же и даташит на систему. Вот системы и надо сравнивать.
                                    В первом случае мы получаем уже готовую систему изменить конфигурацию которой мы не можем, но там как правило периферии больше чем нужно. Но когда нам надо будет организовать 10 штук UART тогда придётся долго думать КАК это сделать на МК(хотя, наверно есть внешние модули UART но я таких не видел). В случае своей системы мы просто ставим нужное количество микросхем на общую открытую шину и разводим их в адресном пространстве. Конечно, энергопотребление микросхем технологии 30-летней давности и их быстродействие оставляет желать лучшего… но если вопрос обучения там такие вещи не критичны. Заодно это можно совместить со схемотехникой, разработкой необходимой логики(дешифратор адреса, формирование управляющих сигналов) и т.д.
                                    С точки зрения коммерческой практики, конечно, STM контроллер гораздо предпочтительней.


                                    1. olartamonov Автор
                                      05.04.2018 11:47

                                      Но когда нам надо будет организовать 10 штук UART тогда придётся долго думать КАК это сделать на МК(хотя, наверно есть внешние модули UART но я таких не видел)


                                      Я не очень понимаю эту логику.

                                      А на 580 нам думать не придётся, там как в ардуине — знай себе на Али шилды заказывай?

                                      Или «долго» — это один запрос в гугль, первой строчкой выдающий «MAX3107 SPI/I?C UART with 128-Word FIFOs»?


                                    1. Mike_soft
                                      05.04.2018 11:49

                                      да я прекрасно понимаю различия и между современностью и тем, на чем я когда-то начинал. :-)
                                      И несмотря на то, я б не стал использовать 580 более чем для учебных целей, да и то как частный случай (ага, «страшилку»)
                                      что касается 10 UARTов — дык нонче модно поставить три STM8AL по три UARTа в каждом, запрячь их по SPI/I2C, плюс свой внутреннний- и вуаля. по цене будет не сильно отличаться, а вот по гибкости


                                      1. olartamonov Автор
                                        05.04.2018 12:19

                                        По цене изделия это почти всегда будет существенно дешевле, чем специализированный контроллер :)

                                        Микроконтроллеры мелкие сейчас как грязь стоят.

                                        Но вылезает ещё вопрос разработки и прошивки (в т.ч. в готовых изделиях), поэтому на практике жизнеспособны оба варианта.


                                        1. Mike_soft
                                          05.04.2018 13:06

                                          Иногда это почему-то (видимо, в силу вбитой в советские времена экономии) жутко бесит. знаю, что это глупо, но то, что «процессор+3*uart+2*adc*12*timer+spi+i2c» стоит на треть дешевле просто uart+spi вызывает внутренний протест… так же как бесят нынешние xml-файлы для обмена данными, и тому подобное.


                          1. Mike_soft
                            03.04.2018 16:42

                            этому и может (архитектура, соотвествующий ассемблер, соотв. подходы). Кроме того, как пример процессора общего назначения.
                            хотя я б учил на 51/48 вместо 580 (хоть и древнее — но выпускается, и судя по всему будет долго), чонить атмеловское-микрочиповское, и чонить STM32/LPC. хотя бы «галопом по европам».
                            ну а интефейсы — отдельно.
                            Но это опять же курс не для программистов как таковых, а для близких к эмбеддингу (11.03.02 Инфокоммуникационные технологии и системы связи, 11.05.01 Радиоэлектронные системы и комплексы, возможно 11.03.03 Конструирование и технология электронных средств и 27.03.04 Управление в технических системах)


            1. Barbaresk
              03.04.2018 11:07

              Чтобы не путаться в скобках и подобном — пишите на языке ассемблера. Год назад, когда в универе было программирование на микроконтроллерах, нам сказали писать всё именно на нём, чтобы «прочувствовать» микроконтроллер, понять сколько там памяти, регистров, и т.д. Правда микроконтроллеры были клонами MCS-51, но думаю не суть.


  1. Andrey_Dolg
    02.04.2018 13:34

    Лепота.


  1. golf2109
    02.04.2018 13:55
    +1

    STElectronics давно уже «забила» на SPL, а тут она не к месту упоминается.
    И почему выбрана RIOT OS, а не FreeRTOS?


    1. olartamonov Автор
      02.04.2018 13:59

      Удивительно, что сама ST об этом не в курсе.

      Наша разработка идёт на RIOT, и в рамках основных занятий в Лаборатории студенты работают с модулями с готовыми прошивками на RIOT.


      1. golf2109
        02.04.2018 14:27

        А дайте ссылочку где можно скачать SPL например для серии STM32L0, ...L4, STM32F7 или STM32H7.
        … вопрос преимущества RIOT перед FreeRTOS не раскрыт…


        1. olartamonov Автор
          02.04.2018 15:36

          А дайте ссылочку где можно скачать SPL например для серии STM32L0, ...L4, STM32F7 или STM32H7


          А почему сразу не для Microchip или TI? Мы работаем с STM32L1, для STM32L1 SPL существует, официально считается активным и широчайше используется в реальной жизни.

          вопрос преимущества RIOT перед FreeRTOS не раскрыт


          Первая проблема в том, что FreeRTOS — это вообще не ОС, а только ядро. На которое далее надо ещё навесить BSP, расширения, драйверы и всё прочее, что из ядра делает полноценную ОС.

          Кроме того, в рамках учебного курса подходит любая достаточно современная и логично выглядящая ОС. Почему, собственно, это должна быть именно FreeRTOS?


          1. golf2109
            02.04.2018 15:43

            А почему сразу не для Microchip или TI?

            это типа «ответ»? (из серии «сам дурак»?)
            Почему, собственно, это должна быть именно FreeRTOS?

            попробуйте погуглить FreeRTOS & RIOT…


            1. olartamonov Автор
              02.04.2018 15:45

              попробуйте погуглить FreeRTOS & RIOT…


              У меня они обе на ноутбуке, с которого я пишу этот комментарий, есть, с какой целью мне их «гуглить»?


              1. golf2109
                02.04.2018 15:50
                -1

                чтобы сравнить количество ссылок для FreeRTOS & RIOT


                1. olartamonov Автор
                  02.04.2018 16:13
                  +1

                  Если вы планируете меряться количеством ссылок, то я вас сразу огорчу: исходя из них, микроконтроллеры и программирование вообще не нужны, ни на каком языке и ни на какой ОС. На менеджеров по продажам и специалистов холодных звонков спрос выше минимум на порядок.

                  Если же вы всё-таки хотите почему-то научиться программировать микроконтроллеры, то конкретная RTOS в принципе неважна, а конкретно RIOT удобен тем, что это готовое решение, а не голое ядро, вокруг которого ОС ещё собрать надо.


                  1. golf2109
                    02.04.2018 16:30

                    Программировать на микроконтроллерах я умею уже лет 30 и исходя из своего опыта удивляюсь сумбурности и непоследовательности изложения материала в ваших «лекциях»
                    А относительно FreeRTOS — посмотрите примеры проектов от производителя (STElectronics) с использованием RTOS — они все сделаны на FreeRTOS. Спрашивается зачем «забивать» мозги студенту малопопулярными вещами типа RIOT?


                    1. olartamonov Автор
                      02.04.2018 16:45
                      +4

                      Ещё раз:

                      * FreeRTOS — это вообще не RTOS.
                      * Если вы хотите учить студентов тому, на что больше всего ссылок — то это «менеджер по продажам».
                      * Обучение в вузе — это не вбивание навыков работы руками на конкретном станке, для этого ПТУ есть.


                      1. golf2109
                        02.04.2018 17:01
                        -1

                        FreeRTOS — это вообще не RTOS

                        сочувствую студентам…
                        Обучение в вузе — это не вбивание навыков работы руками на конкретном станке, для этого ПТУ есть

                        а разве RIOT — это не «конкретный станок»? (причем еще и малораспостраненный)


                        1. olartamonov Автор
                          02.04.2018 18:31

                          сочувствую студентам…


                          Посмотрите как-нибудь в википедии, чем ядро ОС отличается от ОС, и почему, например, Linux — это не ОС, а GNU/Linux — ОС.


    1. ks0
      02.04.2018 14:47

      А я вот тоже про SPL спросить хотел. Для новых контроллеров ее же вроде и нет даже.


      1. golf2109
        02.04.2018 14:58

        один из хороших курсов по STM32 в сети на русском языке
        narodstream.ru/programmirovanie-mk-stm32


      1. olartamonov Автор
        02.04.2018 15:39

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


        1. golf2109
          02.04.2018 15:55

          SPL давно успешно заменена на HAL именно самой STElectronics. Яркий пример использования HAL — CubeMX — без которого проблематично сконфигурировать более менее приличный проект (например ног так на 176 или 208 с десятком интерфейсов).


          1. olartamonov Автор
            02.04.2018 16:21

            Откройте статьи на том же GT с использованием STM32 и посмотрите, в каком проценте из них висят SPL'овские простынки. Про всевозможные «учебники» в интернетах я уж не говорю — их чаще всего пишут люди минимум с несколькими годами опыта с STM32, которые сидят на SPL и никуда особо слезать не планируют. Ну и на сайте ST Micro библиотека имеет статус «Active», несмотря ни на что.

            Более того, последнее веяние моды (после того, как HAL, который должен был стать всем тем, чем не стал SPL, получил свою кучу бурчания со стороны пользователей) — это «как с SPL перейти на LL». Я не знаю, в каком мире SPL «давно успешно заменена», но разжёвывания, как наконец с неё перейти на LL, ST по сию пору выпускает.

            P.S. В скобках также замечу, что абсолютно никакой проблемы сконфигурировать десяток интерфейсов без CubeMX нет. Неумение это делать — может быть, а проблемы — нет.


            1. golf2109
              02.04.2018 16:36

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

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


              1. olartamonov Автор
                02.04.2018 16:49
                -1

                Сколько времени вы теряете на том, чтобы пролистать табличку функций GPIO в даташите вместо натыкивания мышкой в CubeMX? Минут пятнадцать?


                1. golf2109
                  02.04.2018 16:54

                  Встречный вопрос — а вы много реальных проектов для TQFP208 без CubeMX сделали, «пролистывая странички»?


                  1. olartamonov Автор
                    02.04.2018 17:18

                    Достаточно.

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

                    Открываете даташит, там таблица «Alternate function input/output», смотрите, на каких ногах может висеть условный USART1, со схемотехником обсуждаете, на каких ногах вам его удобнее повесить, схемотехник идёт вешать, а вы в условном board.h или где там у вас в используемой ОС описывается плата долистываете до секции с USART'ами и вписываете туда условный .tx = GPIO_PIN(PORT_A, 10), .rx = GPIO_PIN(PORT_A, 9).

                    И?

                    Где здесь проблема-то?

                    TQFP208 — это вообще даже головная боль схемотехника в первую очередь, а не программиста. Вот только схемотехник CubeMX использует исключительно как визуальную подсказку, на какие ноги что можно вывести, HAL ему при этом нужен примерно как рыбе зонтик.


                    1. golf2109
                      02.04.2018 17:24
                      +3

                      головная боль схемотехника в первую очередь, а не программиста

                      о чем это вы?
                      я сам лично и схемотехник и программист и сборщик и настройщик и тестировщик и снабженец немножко в одном лице, поэтому про «рыбу, зонтик» это вы рыбам и раскажите


                      1. olartamonov Автор
                        02.04.2018 17:48

                        о чем это вы?


                        Наверное, о том, что если бы вы изначально писали не «проблема есть», а «лично у меня с этим проблема, потому что я и швец, и жнец, и на дуде игрец», то и вопросов бы не было?..


                      1. NordicEnergy
                        02.04.2018 18:51
                        +1

                        я сам лично и схемотехник и программист и сборщик и настройщик и тестировщик и снабженец немножко в одном лице

                        А вы в закупке так же мало соображаете, как и в разработке ПО? Зачем вообще использовать cube? Это для школьников придумано. Проект в TFBGA-216 с ОЗУ и LTDC настраиваю регистрами (о да, регистры!) минут за 5-7 с нуля, а учитывая, что у меня куча наработок, то вся настройка сводится к подключению собственной обертки функции настройки и прописыванию ног дефайнами. В итоге первая в жизни настройка «даташитиком+регистрами» занимает минут 5-7, последующие минуту.

                        Вы тут рассказываете о «огромных» проектах, но пугаетесь элементарных вещей. Про freeRTOS совсем смешно кстати… В нормальных компаниях обычно вообще пишут свою rtos, а в той же Финляндии студенты вообще про freeRTOS не в курсе и успешно любят ChibiOS и прочие. Вот блин темные же люди!

                        P.S. Вы случайно не преподаете в ВУЗе? Это бы объяснило ущербность студентов, которые после 6 лет обучения на собеседовании максимум могут сгенерировать проект в кубе на HAL и не понимать как оно работает…


                    1. DASM
                      02.04.2018 17:39
                      +1

                      Простите, не верю о 15 мин. Вам чтобы юарт запустить вначале придется разобраться хотя бы как кварц запустить, а зачастую и отключить встроенный dcdc преобразователь. Потом повозюкаться с ремэппингом ножек. И если после этого получится именно uart, а не spi (что тоже самое, пара битов в настройках) — то хорошо. И никак не 15 минут


                      1. olartamonov Автор
                        02.04.2018 17:46

                        У меня ощущение, что часть комментаторов сочла статью слишком длинной и сразу промотала до комментариев.

                        Мы работаем с ОС. В ней всё это уже сделано. 2018 год на дворе, люди не пишут код с нуля каждый раз.


                        1. DASM
                          02.04.2018 17:59
                          +1

                          Так зачем Вы выбранный вами путь советуете как истинный? Вы выбрали редкую ОС, редкую spl прослойку… это ваше право. Но "мы так работаем" и курс начинающих разные вещи


                          1. olartamonov Автор
                            02.04.2018 18:12

                            Простите, а у вас в «частой» ОС в контексте принципов работы в ОС отличается что конкретно?

                            То есть я вот понимаю, что, например, в Contiki — там многозадачность с инвалидностью третьей группы, там надо в треде либо без switch-case, либо без сообщений жить. Этому в университете всех учить не надо, кому в жизни не посчастливится — сами научатся.

                            А в RIOT чего конкретно такого нет, без чего студентов научить работать с микроконтроллерной ОС нельзя?

                            редкую spl прослойку


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

                            Печально, что вы его не прочитали.

                            Во-вторых, про редкость — процентов проектов под STM32, написанных с HAL, против процента написанных с SPL, сможете привести?


                            1. DASM
                              02.04.2018 18:20

                              Каюсь, прочитал через слово, извините. Просто я считаю, что МК в наших реалиях сильно тяготеют к электронике, чем к программированию. Уверен, что phyton или java программисту МК — несложно. Но вот чтобы запустить его — понадобятся некоторые знание из хоровица и хила. По процентам не скажу, все что брал с гитхаба — все НАL


                              1. olartamonov Автор
                                02.04.2018 18:30

                                Вот с питоном и явой вы совсем лишка хватили.

                                Понимаете ли, проблема у программиста МК — она не с тем, чтобы hello world написать.

                                Она с тем, что там, например, работа с памятью такая, что по сравнению с ней не то что питон — по сравнению с ней C на винде сказкой покажется. Потому что MMU тупо нет, зато есть пятнадцать способов прострелить себе ногу так, что пуля сначала будет пять минут зигзагом летать. И после того, как она таки долетит, вы будете не сегфолт и аккуратный дамп памяти иметь, а какой-нибудь Configurable Fault Status Register, из которого извлечь что-то разумное обычно тупо невозможно.


                                1. Uzix
                                  03.04.2018 13:12

                                  На Cortex M во многих случаях может помочь навешивание на *Fault_Handler обработчика, выводящего в, например, UART содержимое различных регистров (например, при применении MPU очень удобно видеть SCB->MMFAR), или даже полного дампа SRAM. Не панацея, но зачастую помогает ловить пулю «на подлёте».


  1. Nick_Shl
    02.04.2018 16:46

    HAL имеет баги. Они правятся, но они есть. Главная проблема HAL — его разработчики не умеют думать "многопоточно". Простейший пример: функция приема по I2C. Если байта нет, проверяем конец передачи — если конец — выходим и возвращаем ошибку. Вроде все логично, но… в реальности, после проверки RTOS может переключить задачу, байт примется, выставиться флаг конца передачи и когда управление вернётся в задачу работающую с I2C получим лажу. А всего-то надо после проверки на окончание проверить "А приняли ли мы байт?" и если приняли — все в порядке. И это не первый раз когда я наступаю на подобные "грабли" заботливо разложенные разработчиками HAL.


    1. olartamonov Автор
      02.04.2018 17:21
      +2

      У меня от ST'шных аппнотов ощущение, что они получившегося из HAL сами немного стыдятся — и теперь тихо подменивают его на LL :)

      Что в общем правильно, из всего этого зоопарка LL представляется наиболее разумным балансом между простотой, надёжностью и универсальностью.


    1. DASM
      02.04.2018 17:23

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


      1. olartamonov Автор
        02.04.2018 17:50

        При чём здесь тормоза, дёргание пина и критические секции?

        Выше описан не только баг, но и его решение, которое добавляет аж целую строчку кода, выполняющуюся… сколько там, пару тактов?


      1. Nick_Shl
        02.04.2018 18:09

        Я выше разве говорил про критическую секцию? Тут нет совместного доступа что бы обвешиваться критическими секциями/семафорами/мьютексами. Кроме того, всего этого не будет, если не используется RTOS… а проблема банально вылезет когда произойдет прерывание в этом месте и задержит исполнение HAL'овского кода.
        Ещё пример с SPI: цикл, в цикле два if'а: если готов к передаче — отправляем, если принят байт — читаем. И как результат получалось отправлять два байта подряд без чтения. А все потому, что должно быть не условие, а ожидание приема.
        В последующем они этот баг поправили. И на том спасибо.


        1. olartamonov Автор
          02.04.2018 18:17

          а проблема банально вылезет когда произойдет прерывание в этом месте и задержит исполнение HAL'овского кода


          Это, кстати, вообще отличная засада — когда увеличение частоты какого-нибудь постороннего прерывания переводит проблему из гипотетической (т.е. с настолько низкой вероятностью, что если с ней кто-то и встретится, посчитает за случайный глюк, ну мало ли, космический луч пролетел, свет Венеры отразился) в практическую.

          А это может быть вообще какая-нибудь обработка GPIO, частота дёргания которого зависит от того, какую железку эксплуатант в разъём на этот раз воткнул.


        1. DASM
          02.04.2018 18:25

          Прерывание это и есть многозадочность. Может мы о разном?


          1. Nick_Shl
            02.04.2018 19:02
            +1

            Т.е. вы хотите сказать, что использовать прерывания совместно с HAL нельзя???


    1. golf2109
      02.04.2018 17:34
      +1

      «многопоточно» должен думать пользователь HAL, CMSIS, SPL, а не разработчики этих надстроек


      1. olartamonov Автор
        02.04.2018 17:53
        +1

        Это, извините, как?

        Если у вас библиотека не thread-safe/interrupt-safe в вашем окружении, то вы можете думать как угодно, но пока вы в неё не залезете руками, она безопасной не станет. Максимум, что вы можете «думать» — это каждый относящийся к ней чих завернуть в многослойную прокладку: запретить вложенные прерывания, запретить тики шедулера в ОС с вытесняющей многозадачностью, etc.

        То есть, «думать» вы можете в этой ситуации не «многопоточно», а ровно наоборот.


      1. Nick_Shl
        02.04.2018 18:19
        +1

        Думать о чем? О том, что бы их вообще не использовать? Шикарно!
        Я не говорю, что они должны делать совсем уж thread-safe код. Но при использование переферии монопольно одной задачей результат не должен зависеть от задержек вносимых переключением задач/вызовом прерываний. Или хотя бы все ограничения должны быть описаны в документации/заголовке функции.


  1. GarryC
    02.04.2018 17:18

    Ну все таки, почему сразу начинать учить плохому? Это я про

    GPIOA->MODER &= ~(0b11 << (pin_num*2))

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


    1. olartamonov Автор
      02.04.2018 17:22

      В смысле — студентам НЕ надо знать, что у микроконтроллера есть регистры, CMSIS и вот это всё?..


      1. GarryC
        02.04.2018 17:55

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

        GPIOA->MODER &= ~(0b11 << (pin_num*2));
        GPIOA->MODER |= 0b01 << (pin_num*2);
        и тут же альтернативу
        BitClear(GPIOA->MODER,(0b11<<(pin_num*2)));
        BitSet(GPIOA->MODER,(0b01<<(pin_num*2)));
        и следующую альтернативу
        GPIOMode(GPIOA,pin_num,0b01);
        и следующую альтернативу
        GPIOA->MODE.PORT4=OUT;
        и объяснить, что все это приведет к (почти) одинаковым командам и показать, к каким именно.
        А пусть студенты дальше сами решают, что удобнее и чем пользоваться.


        1. olartamonov Автор
          02.04.2018 18:07

          Ок, а статью вы читали?


          1. GarryC
            02.04.2018 18:25

            Ну в общем то, да, читал. Хотя не очень понял вопрос. Я просто о том, что регистры — это крайний случай и обертки, как правило, удобнее.


            1. olartamonov Автор
              02.04.2018 18:33

              Читали ли вы, в частности, фразу о том, что по причине крайнего неудобства работы с регистрами напрямую мы будем использовать ОС, а не работать с регистрами напрямую, кроме случаев, когда нам захочется посмотреть, что происходит внутри ОС?

              Если да, то зачем вы мне рассказываете, что работать с регистрами напрямую — неудобно?


    1. DASM
      02.04.2018 17:23
      +2

      Ой, только не надо макросов. Это Ад. Особенно когда они становятся вложенными. Поглядев на такие «упрощалки» с досадой выкидываю это, и по старинке *(volatile uint16_t*) reg_address = myVal;


  1. saw_tooth
    02.04.2018 17:53
    +1

    Одна из причине, почему мы будем работать с RIOT OS и без использования каких-либо средств разработки (IDE) — в получающем в последнее время всё большее распространение магическом мышлении.

    Перевернули с ног на голову. IDE — это плохо, будем корячиться в cmd. ОС это хорошо нам же не важно что там внутри МК.
    (Собеседование на хардварщика)
    — здравствуйте, реализуйте пожалуйста минимальный невытесняющий диспетчер задач для МК, используя только один аппаратный счетчик.
    — хз о чем вы, я только умею использовать тип Tasks из <name_os> и программный таймер.


    1. olartamonov Автор
      02.04.2018 17:58

      «Корячиться» — это вы так назвали единственный вызов make и ручное редактирование одного Makefile и пары заголовочных вместо натыкивания мышкой в красивых менюшках?

      здравствуйте, реализуйте пожалуйста минимальный невытесняющий диспетчер задач для МК, используя только один аппаратный счетчик


      — Здравствуйте, у вас отличный невытесняющий диспетчер задач на одном аппаратном счётчике. А теперь реализуйте мне на нём, пожалуйста, парсер протокола вот этих датчиков избыточного давления на Modbus RTU с автоматическим опросом, передачей почасового инкрементального архива с привязкой к реальному времени по радиосети с гарантированной доставкой и имитозащитой сообщений. В смысле — «полгода»? Что вы там полгода делать собрались?!

      Говоря короче, не думали ли вы, что задачи и программисты бывают разные, и что не всем, работающим с микроконтроллерами, приходится реализовывать свой невытесняющий диспетчер задач?


      1. DASM
        02.04.2018 18:03

        То, что вы тут написали вообще непонятно какое отношение к эмбеддед имеет. Вроде курс для начинающих, регистры там всякие. А то, что вы тут написали — это и на пентиуме времени достаточно займет.


        1. olartamonov Автор
          02.04.2018 18:06

          «На пентиуме» — это как, на голом x86 ассемблере? Тогда да, более чем достаточно.

          Но мы вроде как про ОС, вы правда первый прототип этого на винде или линуксе не сможете за вечер-два набросать?


      1. saw_tooth
        02.04.2018 18:19

        это вы так назвали единственный вызов make и ручное редактирование одного Makefile

        И вызов MakeFile и какой то дебаг (ну да, он же не нужен), а завтра студент захочет вынести свой модуль в отдельный файл и опять редактируй файлы. Зачем заранее ограничивать людей в инструментах?
        И в тоже время: Вот вам абстрактная ОС, зачем вам знать что такое цикл обработки, и программные счетчики?
        Я в меньшей мере хочу показать насколько, уж простите, ущербный данный курс. Я пытаюсь у Вас (именно у Вас) спросить — чему вы хотите обучить студентов?
        Использование ОС не обучит студентов грамотному подходу к работе с МК и его периферией. Более того, приняв это за догму, они будут отрицать все нормальные подходы.
        И тогда: Если работа под ОС на МК не отличается, от обычного прикладного программирования, зачем тогда по сути вобще нужны эти контроллеры? Просто обучайте людей программировать… хотите ножек/светодиодов. Дайте людям Raspberry и обучайте — суть от этого не изменится, знания будут эквивалентны.
        По поводу «практичности» (в противовес академичности) вашего курса, мне кажется, куда более лучше научить студентов использовать периферию в связи ADC+DMA, SPI+кольцевые буферы, и все это в контексте вашего МК (L151). Таким образои, они поймут в каких задача и что нужно использовать, а главное ПОЧЕМУ. И вот тогда, венцом вашей работы будет.."… теперь мы подошли к тому моменту, когда у нас 100500 обработчиков аппаратных и программных, куча вложенных прерываний и шанс что мы в этом запутаемся, поэтому давайте ознакомимся с ОС и проблемами которые они решают".
        Людям, не нужна как вы выразились практичность, людям нужна доступность, и понимание «зачем это все» (вспомните себя на уроках геометрии/математики в школе), и вот когда они поймут зачем, они без вас смогут это использовать на практике.
        ЗЫ. Выше подметили статьи от ДиХальта: посмотрите с чгео он начинает — с проблематики, и только потом решение.


        1. olartamonov Автор
          02.04.2018 18:22

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


          Вот ровно за этим.

          Чтобы завтра студент знал, что всё, вообще всё, что у него тут происходит — это всего лишь текст в файлах, которые можно редактировать обычным текстовым редактором, а не магия волшебной кнопочки в IDE.


          1. saw_tooth
            02.04.2018 18:23

            В контексте «изучение микроконтроллеров» IDE и все ее инструменты, таки должны быть как можно проще… Вы же при чтении книг не начинаете со статей «устройство печатного станка»?
            В целом, я никоим образом не говорю что против данных курсов, просто их ценность очень близка к «Курсам программиста/тестировщика за 10 дней в твоем городе».
            Даже за 8 занятий, можно очень грамотно изложить материал: в меньшей мере настройка блокнота и make, в большей — целевой материал.


            1. olartamonov Автор
              02.04.2018 18:34

              А что именно вы обычно настраиваете в блокноте и make?..

              Я как-то теряюсь в догадках.


  1. DASM
    02.04.2018 17:54

    Все же выскажусь. Начинал я, как и многие, с Z80 (ни разу ни микроконтроллер, только принципы те же). Потом появился замечательный AT89c2051, 2 кб флеша и 128 байт озу. Но шить неудобно — паралелльно. Потом глоток воздуха at90s1200 глючный, но вот его последователь 90s2313 уже удобен. Ну а потом поехало, 16 бит фуджитсу, арм7тдми, кортексы 3, 4, 7. Разницы особой нет ни у кого. А для быстрого старта, с учетом того, что молодые с Линуксом знакомы… советую распберри пи. Удобно, знакомые тулзы, вот не предоставляю человека который хорошо управляется с малинкой, но несчастный кортекс3 вводит в ступор


    1. olartamonov Автор
      02.04.2018 18:04

      Во-первых, зачем вы советуете Raspberry Pi, когда можно просто под винду поставить из магазина Ubuntu — будет тот же линукс.

      Во-вторых, на последнем занятии показывал студентам, что бывает при переполнении стека.

      Когда, например, процедура, вылезшая за границы своего стека в два раза от его размера, совершенно спокойно работает неограниченно долгое время (sic!), но вторая процедура, совершенно не зависящая от первой и запускающаяся в какой-то произвольный момент времени, мгновенно рушит всю систему в хардфолт.

      Сможете это в линуксе показать?


      1. DASM
        02.04.2018 18:12

        Распберри дает навык с gpio (а часто и spi, uart). Этого достаточно, чтобы понять архитектуру любого мк. Чем по вашему распберри отличается от мк? Озу отдельное и флешка. Это мелочи. По большому счету программеру с распберри надо только очень хорошо понять смысл слова volatile. В остальном программирование под МК особенностей не имеет (как бы я этого не хотел, ведь всегда хочется иметь редкую специальность). Другое дело что эмбеддерщики берут свое, когда знают, что в сеансе радиоприема или считывания АЦП надо ядро усыпить, или что резисторы проходные нужны, дабы снизить скорость нарастания фронтов и убрать помехи. Но это с опытом


        1. olartamonov Автор
          02.04.2018 18:20
          +1

          Какие, простите, «навыки gpio»? Там GPIO — это echo «10» > /sys/class/gpio/export, оно на микроконтроллер даже близко не похоже.

          И я всё ещё жду, как вы на любом линуксе мне покажете распространённейшую проблему с переполнением стека в исполнении микроконтроллера без MMU.


          1. DASM
            02.04.2018 18:32

            Поясните, что за проблема? Исчерпать память? Я это и на пентиуме покажу. А что не так gpio? Это memory mapped device, он везде такой. Я просто не понимаю, почему много эмбеддеров пишут такие курсы и считают это сокровенным знанием. Это примитив. Очень жду курсы Haskell for embedders, вот там да, взрыв моего мозга и понимание, что это-совсем не то, к чему привык. А эти ваши микроконтроллеры, простите, просто несложное ядро с большьой перифирией, не более


            1. olartamonov Автор
              02.04.2018 18:39

              Я это и на пентиуме покажу.


              В линуксе? Нет, в линуксе не покажете. Спросите у гугля, что такое Memory Management Unit и зачем он нужен.

              Это memory mapped device, он везде такой


              Простите, где именно в /sys/class/gpio у вас есть хотя бы маленький шанс увидеть «memory mapped», и на каком конкретно микроконтроллере у вас есть хотя бы маленький шанс увидеть /sys/class/gpio?

              Или вы всем рекомендуете из-под линукса с GPIO работать обращениями напрямую по 0x20200000?


              1. DASM
                02.04.2018 18:49

                Причем тут линукс вообще? Да, рекомедую 0х20200000 чем разбираться в бреде писателей библиотек. Ладно, давайте остынем, статью написали — хорошо. Может кому-то полезно. В чем отличие линусового мемори мэппед от даташитов с описанием регистров — да ни в чем.


                1. olartamonov Автор
                  02.04.2018 18:55
                  +1

                  Причем тут линукс вообще?


                  А для быстрого старта, с учетом того, что молодые с Линуксом знакомы… советую распберри пи


                  Обе фразы — ваши.


                1. wigneddoom
                  04.04.2018 16:24

                  Поясните, вы про Linux на уровне ядра программировать предполагаете?


  1. maybe_im_a_leo
    02.04.2018 20:20
    +1

    Мне кажется что STM32 надо начинать с STM32CubeMX и генерации кода из него. Чтобы абстрагироваться от того как это прописывать в коде, а сосредоточиться на возможностях микроконтроллера.


    1. olartamonov Автор
      02.04.2018 20:47

      Зачем?

      Чтобы не тратить время на страницу кода только на запуск всего хозяйства, есть ОС, в которой эта страница кода уже написана. Чтобы потом посмотреть, как оно работает внутри — та же ОС значительно удобнее, т.к. SPL/HAL/LL довольно трудны для чтения из-за размазывания на десятки мелких подфункций, а производимый кодогенератором код хуже структурирован, чем код ОС.


      1. maybe_im_a_leo
        02.04.2018 21:35
        +1

        Я не ставлю под сомнение что RIOT — возможно хорошая вещь, особенно IoT. И вы сделали большую работу по подготовке презентации этого дела под STM32L1.
        Но Cube — это официально поддерживаемая и рекомендуемая ST система. Если рассматривать именно STM32 то несомненно надо начинать со средств от самого разработчика.
        (Хороши они или плохи — это уже второй вопрос. Как по мне то Cube — оК. По крайне мере регулярно фиксится и обновляется, в HAL есть какая-то логика. Но это мое IMHO, в такой же степени как ваша оценка HAL в коменте :) )


        1. olartamonov Автор
          02.04.2018 21:42

          Если рассматривать именно STM32 то несомненно надо начинать со средств от самого разработчика


          Обоснуйте.

          В контексте учебного процесса.

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


          1. maybe_im_a_leo
            02.04.2018 21:55
            +1

            Средства от разработчика обычно оказываются самыми долгоживущими/поддерживаемыми/с наибольшей базой пользователя. Поэтому этот тезис имеет смысл с точки зрения долгосрочной полезности изученного материала. Далеко не везде где используют STM32 вообще слышали от RIOT, а вот от Cube/HAL/SPL слышали (как плохое так и хорошее — но по крайне мере слышали об его существовании).
            пс: Если что, это сугубо мое личное мнение, но основанное на 7-и летнем опыте использования STM32 в разных компаниях и четырех разных странах (в том числе и в Самсунге и Корее).


            1. olartamonov Автор
              02.04.2018 22:39
              +1

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

              Кроме того, никакой долгосрочной полезности у Cube/HAL/SPL нет, не было и не будет. Это всего лишь инструмент, использованию которого можно обучиться за неделю максимум.


              1. Mike_soft
                03.04.2018 16:46

                Добавлю, что если есть понимание, как конфигурировать руками — то Сube работу может ускорить. но если есть только навыки работы с Cube — можно сильно вляпаться.


          1. HomoLuden
            03.04.2018 16:41

            Обоснуйте.


            Вот я запущу CubeMX. Настрою ножки, быть может кристалл выбиру тот, что я впаял вместо штатного на китайской борте STM32F103C8T6, настрою ножки, добавлю WatchDog, FreeRTOS да сгенерирую код для «кокоса» или для связки Visual Studio + VisualGDB.

            А вот с RIOT мне надо будет разобраться что и на что изменить в конфиге от NucleoF103 (самое близкое что нашел на ГитХаб). Это если мне повезет и конфиги совместимы.

            PS: я еще не пробовал портировать RIOT на ширпотреб китайский вроде STM32F103C8T6… может это и не так страшно, но визуальные средства конфигурации не помешали бы.


            1. olartamonov Автор
              03.04.2018 17:05

              То есть в контексте учебного процесса вы обосновываете использование Cube тем, что с ним не надо разбираться, а можно быстренько натыкать мышкой чего хочется?

              Как вы относитесь к отмене уроков алгебры в связи с тем, что на калькуляторе считать удобнее?


              1. Nick_Shl
                03.04.2018 18:39

                Так забавно читать про то, что "FreeRTOS это не ОС, а всего лишь ядро" и тут же читать про "мышкой натыкать". Что бы натыкать, нужно знать что происходит при каждом "тычке". А GUI всего лишь ускоряет процесс. Кроме того, весь код сгенерированный CubeMX открыт — всегда можно посмотреть что конкретно там происходит и в случае чего подправить.


                1. olartamonov Автор
                  03.04.2018 19:17

                  Что бы натыкать, нужно знать что происходит при каждом «тычке»


                  Нет, не нужно. И для того, чтобы на автомобиле ездить, про цикл Карно знать не обязательно.

                  Кроме того, весь код сгенерированный CubeMX открыт — всегда можно посмотреть что конкретно там происходит и в случае чего подправить


                  Вот только если вы всю жизнь в него только мышкой тыкали — первая встреча с реальным кодом (тем более, с кодом HAL) принесёт вам много удивительных, но не очень приятных моментов.


                  1. Nick_Shl
                    03.04.2018 21:28

                    Момент об "настоящей ОСи в которой есть все из коробки" сознательно опущен?
                    Если мне нужен пин как выход, то нет никакой разницы сконфигурирую я его вручную или мышкой. Если мне нужна подтяжка на этом пине — тоже самое. Можно вручную конфигурировать все частоты тактовых сигналов(а их в том же STM32 могут быть десятки), а можно рутину оставить CubeMX. Главное знать что ты делаешь и зачем. И в результате все равно получается код(причем довольно низкого уровня абстракции) который доступен программисту. CubeMX — это вспомогательная тулзина берущая на себя рутину, не более. У нее нет задачи спрятать все внутрь как у «настоящей ОС».


                    1. olartamonov Автор
                      04.04.2018 14:43

                      Фраза «чтобы натыкать, нужно знать, что происходит при тычке» неверна даже с позиции формальной логики.

                      Нет, не нужно. И вокруг ходят толпы погромистов, которые могут натыкать мышкой в CubeMX и впадают в ступор при виде регистра.

                      При чём тут вообще ОС? Какая ОС и куда у вас что прячет? В файлы *.c и *.h, что ли?


                      1. Nick_Shl
                        04.04.2018 17:31

                        CubeMX тоже прячет регистры в файлы *.c и *.h. Мне надоело с вами спорить.
                        Мне жаль, что вам встречались только такие программисты, которые тыкают и не знают.
                        Впрочем я не удивлен. Качество разработок в Самсунге то ещё… причем во всем. Что у телефона жены аккумулятор два раза вздувался а потом он стал тормозить так, что использовать невозможно, что даже стиралку нормальную сделать не могут — поищите на Ютюбе "Samsung washer spyder"… и судя по критике в комментариях, это не изменится.


                        1. olartamonov Автор
                          04.04.2018 17:44
                          +1

                          Самсунг, жена, телефон, бузина, Киев, дядька…

                          Что вы вообще несёте?

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

                          Можете проверить, оно работает.

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


  1. nomadmoon
    03.04.2018 07:02

    int pin_num = 2; /* PA2*/
    GPIOA->MODER &= ~(0b11 << (pin_num*2)); /* сбросили биты настройки ножки PA2 на всякий случай */
    GPIOA->MODER |= 0b01 << (pin_num*2); /* установили биты настройки ножки PA2 в 01 — выход */
    GPIOA->ODR |= 1 << pin_num; /* установили ножку PA2 в 1 */
    
    GPIOA->MODER &= ~(0b11 << (pin_num*2)); /* сбросили биты настройки ножки PA2, теперь это вход */
    uint32_t pa2_value = GPIOA->IDR & (1 << pin_num); /* прочитали состояние ножки PA2 */


    Объясните пожалуйста на пальцах что здесь происходит. Что делают операции смещения (это же они, да?), что за ~, почему 0b11 и 0b01? Почему где то И где то ИЛИ?


    1. GarryC
      03.04.2018 09:20

      Это такая уличная магия — в нее надо верить.


      1. olartamonov Автор
        03.04.2018 11:12

        Нет, уличная магия — это когда битовые операции меняют на BitSet(address, bit), «потому что так понятнее», а потом человек смотрит на собственно простейшие битовые операции как на неведомого зверя.


    1. Alexeyslav
      03.04.2018 09:26

      Это всё элементарная логика. По сути, мы формируем константы. Есть такое понятие — битовые поля, регистры например 32-разрядные и отдельные биты могут управлять совершенно разной частью периферии и нам крайне важно менять только эти биты не трогая остальные — вот здесь и приходит на помощь математика. Удобно записать в исходнике состояние нужных бит(например два бита — 0 и 1), но в реальном регистре они находятся на 8 и 9 бите. Что нам надо сделать? Сдвинуть эти два бита на 8 бит, чтобы в результате они отразились на 8 и 9 в 32-битном регистре. в итоге имеем запись вроде (0b11 << 8).
      Теперь нам надо сбросить указанные биты, т.е. там где мы запишем «1» в маске в регистре бит должен сбросится. Для этого нам надо… сделать операцию «И» (& в выражении) с инверсной(~ символ) маской(там где у нас были до этого 1 стали 0 и наоборот).
      Чтобы установить какие-то биты в регистре, нам надо сделать операцию OR с константой в которой установлены только нужные биты в «1».
      Вот собственно и весь секрет.
      п.с. иногда логика регистров обратная, например, чтобы сбросить признак прерывания(читается как «1» в регистре) нужно в регистр записать «1» в нужный бит. Это должно быть записано в даташите.


      1. Mogwaika
        03.04.2018 23:22

        А просто операции присваивания не существует?
        Если нельзя биты, то прочитать что было и записать что было с изменениями нельзя?
        Типа GPIOA[9:8] <= 2'b01 или GPIOA <= {GPIOA[31:10],2'b01,GPIOA[7:0]}


        1. Alexeyslav
          04.04.2018 08:42

          Именно это и происходит. Читаем-изменяем-записываем(R-M-W). Иногда, такой подход имеет побочные эффекты, если например регистр меняется после того как мы его прочитали но ещё не записали результат.
          Есть конечно команды работающие конкретно с битами, но там свои заморочки и их почему-то не используют так широко как хотелось бы. Наверно потому, что изменять отдельный бит порта требуется крайне редко а меняют их обычно группами и часто требуется менять синхронно.
          Работать с отдельными группами битов КОНТРОЛЛЕР НЕ УМЕЕТ АППАРАТНО в любом случае работа ведется минимальными порциями по 32 бита, даже если требуется изменить 3 бита затрагиваются все 32 т.к. контроллер умеет оперировать только целыми регистрами. Даже если у вас и получится реализовать что-то вроде GPIOA[9:8] <= 2'b01 то дёргать оно будет всеравно целый 32-битный регистр.
          Да, обратите внимание что есть ещё такая логическая операция как XOR — исключающее ИЛИ, которое позволяет инвертировать указанные в маске биты. Многие почему-то забывают про такую операцию и начинают городить сложные конструкции if-then-else.


          1. Mogwaika
            04.04.2018 10:53

            Т.е. чтобы заведомо ничего не изменилось нужно сделать ассемблерную вставку, которая отработает за два такта и это для динамической замены, когда нужно прочитать регистр, который менял кто-нибудь ещё кроме нас.
            А для начальной конфигурации, когда мы сами все биты выставляем не проще ли сразу писать все биты (т.е. если мы настраиваем в нескольких местах меняем биты в переменной а в конце фигачим все настройки в один регистр одной записью, без чтения и логических операций с масками, т.е. свалить все сложности на компилятор, чтобы он не делал кучу отдельных команд ассемблера с and, or и константами)?
            А какие например проблемы с битовыми операциями бывают?


            1. Mike_soft
              04.04.2018 11:10

              а зачем нужна ассемблерная вставка? в конце концов, гляньте код, генерированный этой инструкцией — он не будет ничем отличаться от вашей вставки.
              Для начальной конфигурации — можно и писать сразу целиком одним словом. (такое часто называют «волшебное число», «magic value»). Но гораздо лучше показать, как и откуда это волшебное число берется. все эти операции (int pin_num = 2;GPIOA->MODER &= ~(0b11 << (pin_num*2));) оптимизирующий компилятор вполне вычислит на этапе компиляции.
              и помните — вы пишете программу, которую будет читать человек. вот и пишите так, чтобы любой человек понял, что и зачем вы написали.

              Выдержки из книги Денни Ван Тассела
              1. Стиль программирования

              Цель программирования — не создание программы, а получение результатов вычисления.

              Кодирование, увы, само по себе ничего не стоит — существенны результаты!

              Помните: программы читаются людьми.
              Делайте комментариев больше, чем это кажется необходимым.
              Используйте вводные комментарии.
              Делайте оглавление в больших программах.
              Комментарии должны содержать дополнительную информацию, а не перефразировать программу.
              Располагайте комментарии таким образом, чтобы это не делало программу менее наглядной.
              Неправильные комментарии хуже, чем их отсутствие.
              Делайте пробелы для улучшения читаемости программы.
              Используйте имена с подходящей мнемоникой.
              При наименовании файлов используйте определенный префикс или суффикс.
              Одного оператора в строке достаточно.
              Упорядочивайте списки по алфавиту.
              Скобки обходятся дешевле, чем ошибки.
              Для выявления структуры программы используйте отступы.
              Для выявления структуры данных используйте отступы.

              2. Проектирование программ.

              Большие программы подобны спагетти на тарелке: тянешь с одной стороны — что-то движется с другой.

              Хорошее правило — ожидать всегда наихудшего; это относится и к программам.

              Я не программирую и наполовину своих возможностей.

              Стремитесь к простоте.
              Добивайтесь точности при определении задачи.
              Выбирайте алгоритм задачи самым тщательным образом.
              Выбирайте представление данных, соответствующее задаче.
              Используйте в качестве параметров переменные, а не константы.
              Создавайте универсальные программы.
              Не перепрограммируйте функцию квадратного корня.
              Устанавливайте цели проекта заблаговременно и точно.
              Сначала напишите программу на естественном языке.
              Разрабатывайте тестовые данные заранее.
              Прежде, чем начать программировать, разработайте проект.
              Исключайте ошибки с самого начала.
              Короткие модули предпочтительнее длинных.
              Стремитесь к минмиальному использованию операторов GOTO.
              Прежде, чем программировать, запишите программу в псевдокодах.
              Планируйте возможные изменения в программе.
              Начинайте документирование на стадии разработки программы.
              Не бойтесь начинать программирование сначала.

              3. Эффективность программ.

              Отчего у нас никогда нет времени сделать что-либо хорошо, но всегда находится время на переделку.

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

              Если программа неправильна, не имеет значения, какова ее эффективность.
              Определяйте требования к эффективности программы на стадии проектирования.
              Удобочитаемость программы обычно более важна, чем эффективность.
              Используйте оптимизирующий компилятор.
              Профилируйте ваши программы.
              Инициируйте переменные во время компилирования.
              Избегайте смешанных типов данных.
              Оптимизируйте сначала внутренние циклы.
              Используйте для индексации наиболее предпочтительный тип данных.
              Группируйте записи в эффективные блоки для ввода-вывода.
              Используйте загрузочные модули.

              4. Отладка программ.

              … Возмездье
              Рукой бесстрастной чашу с нашим ядом
              Подносит нам же…
              Шекспир. Макбет

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

              Программа, свободная от ошибок, есть абстрактное теоретическое понятие.

              Применяйте отладочный компилятор.
              Первым делом проверяйте программу за столом.
              Выполняйте эхо-проверку вводимых данных.
              Вводите средства отладки как можно раньше.
              Контролируйте правдоподобность вводимых данных.
              Используйте доступные для вас средства отладки.
              Делайте программу правильной с самого начала.

              5. Тестирование (испытание) программ.

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

              О тестировании необходимо думать на протяжении всего периода разработки программы.

              Обходитесь минимальным количеством контрольных примеров.
              Учитывая, что исчерпывающее тестирование невозможно, испытывайте программу разумно.
              Начинайте тестирование как можно раньше.
              Прежде всего проводите ручную проверку.
              Старайтесь проверять правильность принципов построения системы на ее простом варианте.
              Старайтесь применять тестирование по методу сверху вниз.
              В каждом следующем тесте должен использоваться класс данных, отличный от предыдущего.
              Испытывайте программу в нормальных, экстремальных и исключительных условиях.
              Подготавливайте тестовые данные для проверки каждой ветви алгоритма.
              Повторяйте тестирование после каждого случая внесения изменений в программу.
              © www.delphikingdom.com/asp/viewitem.asp?catalogid=528


              1. Mogwaika
                04.04.2018 12:20

                Может и не будет, а может и будет, а ассемблер должен однозначнее по тактам разложить (хотя наверное и это окажется не так).
                А про просто битовые операции не расскажете?


                1. Mike_soft
                  04.04.2018 12:34

                  ассемблер это (вычисление выражения) сделает на этапе компиляции (а то и препроцессинга), без всякого «раскладывания по тактам».
                  (вообще, сейчас написать на ассемблере оптимальнее оптимизирующего компилятора весьма сложно. )
                  что вы хотите узнать про битовые операции — я не совсем понял.


                  1. Mogwaika
                    04.04.2018 16:53

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


                    1. Mike_soft
                      04.04.2018 17:23

                      Нет, чистый си не умеет. Есть макросы, в C++ есть класс.
                      но опять же, чем это поможет? либо у вас номера битов станут «волшебными числами», либо вы все равно станете их вычислять, и в итоге получите то же самое в двойном количестве :-)


                      1. Mogwaika
                        04.04.2018 19:59

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


                        1. Mike_soft
                          04.04.2018 20:48

                          Будет одна строчка вместо одной. Или две вместо одной. А вот что такое "аналитически заданные" — я не понимаю… Заданные числом (константой), или заданные выражением? Если константой — упирается в "волшебные числа". Если выражением — то выражений потребуется как минимум не меньше.


                          1. Mogwaika
                            04.04.2018 23:45

                            Тут две строчки, одна зануляет через И, другая делает ИЛИ с нужными значениями.
                            xxx[pin_num*2+1:pin_num*2] И это повезёт, если настройки в регистре так равномерно красиво разложены, наверняка бывает и по другому и тут уже без «волшебных таблиц», где хранятся нужные адреса не обойтись и со сдвигами так красиво не получится.


                            1. Mike_soft
                              05.04.2018 07:45

                              в таком ключе — согласен, строчек будет одна вместо двух «сбросить все-установить нужное». хотя выражений для адресов все равно два («pin_num*2+1» и «pin_num*2»). если три управляющих бита — выражений будет три…
                              Да, я посмотрел на этот ассемблер — в нем есть работа с битовыми полями, и весьма неплохая.


                            1. olartamonov Автор
                              05.04.2018 11:11

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


                              Для конфигурационных регистров (CR) и регистров статуса (SR), в которых лежит куча разнотипных и разноразмерных кусочков, в CMSIS определны константы, соответствующие конкретным битам.

                              Так что там операции выглядят так примерно (пишу названия наобум):

                              RCC->CR &= ~RCC_CR_MSIRANGE_Msk;
                              RCC->CR |= RCC_CR_MSIRANGE_6;

                              while (!(RCC->SR & RCC_SR_MSIREADY)) {}


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

                              P.S. Бывают ещё случаи, когда настройки одного порта размазаны по двум регистрам, тогда вычисления сложнее, конечно, но тоже возможны.

                              В совсем клиническом случае они выглядят как-то так (это реальный код из cpu/stm32_common/periph/gpio.c):

                              /* enable specific pin as exti sources */
                              SYSCFG->EXTICR[pin_num >> 2] &= ~(0xf << ((pin_num & 0x03) * 4));
                              SYSCFG->EXTICR[pin_num >> 2] |= (port_num << ((pin_num & 0x03) * 4));


                              Здесь EXTICR — это несколько регистров, но т.к. они идут один за другим, с ними удобно работать как с массивом, через индексы.


            1. olartamonov Автор
              04.04.2018 11:11

              А для начальной конфигурации, когда мы сами все биты выставляем не проще ли сразу писать все биты


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


              1. Mogwaika
                04.04.2018 12:22

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


                1. Mike_soft
                  04.04.2018 12:46

                  этот код как раз и обеспечивает понятное и очевидное поведение вместо использования «волшебных чисел».
                  и что не менее важно — он формирует привычку к такому стилю. (иначе привыкнете везде числа пихать)
                  Другое дело, что — возможно — это было нужно объяснить. с другой стороны, в требованиях с студентам вроде как ясно сказано: «знакомых с языком C и базовыми понятиями электроники и электротехники». а вся строка — это как раз базовые понятия языка.
                  Я, конечно, постараюсь посмотреть запись лекции, чтоб «быть на одной волне», но…


            1. Alexeyslav
              04.04.2018 13:21

              Ассемблерная вставка не поможет, т.к. заменить выражение одной ассемблерной вставкой часто бывает невозможным. Кроме того, бывает такая бяка что записать константу в регистр непосредственно одной командой нельзя — сначала загрузить константу во временный регистр(ячейку памяти), потом передать значение в РЕГИСТР(тот что с устройствами связан). И между этими командами внезапно возникает прерывание на 2000 команд…

              Одной записью в регистр установить всё можно, но не всегда. Это если регистр статический тогда без проблем… А бывает так что надо сделать целый обряд — сначала установить одни биты, подождать и потом установить другие. Как пример можно взять настройку вач-дог таймера из программы. Включить/выключить одной командой его нельзя и сделано это для того чтобы он не дергался от «помех» в момент подачи питания на контроллер. Такая же история с EEPROM — защита от затирания ячейки «случайной» командой записи в момент подачи напряжения когда дешифратор команд находится в неопределённом состоянии.


    1. Mike_soft
      03.04.2018 09:53

      GPIOA->MODER &= ~(0b11 << (pin_num*2));
      1)поле настройки (каждой) ноги — 2 бита.
      2)0b11 — это слово, в котором установлено только 2 бита
      3)pin_num*2 — это на столько позиций нужно сдвинуться от начала слово, чтоб попасть в биты настройки ноги номер pin_num (т.к. см. п.1), остальные позиции нулевые
      4) ~(0b11 << (pin_num*2)) — это мы инвертировали наше слово. на месте единичек, стоящих в позиции настройки нужной нам ноги (см. п 3.), оказались нули (на остальных позициях единички)
      5) GPIOA->MODER &= — делаем «логическое И» текущего состояния GPIOA->MODER, и аргумента, и результат пишем в GPIOA->MODER. в аргументе у нас слово из единичек кроме двух нулей, стоящих на позиции настройки нужной ноги (см. п.4.). таким образом, в результате мы сбросим два бита на позиции нужной нам ноги, а остальные биты оставим в текущем состоянии.
      — GPIOA->MODER |= 0b01 << (pin_num*2) — мы установим «01» на позиции нужной нам ноги.
      ну и т.д.


      1. GarryC
        03.04.2018 10:01

        Еще раз попытаюсь донести свою позицию — Вам НЕ НУЖНО устанавливать биты на позиции, Вам НУЖНО настроить режим работы пина и внешняя сторона программы ДОЛЖНА быть сосредоточена именно на этом, а особенности реализации ДОЛЖНЫ быть скрыты под капотом.


        1. Mike_soft
          03.04.2018 10:16

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


        1. olartamonov Автор
          03.04.2018 11:16
          +1

          Да-да.

          А потом эти люди приходят ко мне и рассказывают — реальный случай, и это был ни разу не студент на собеседовании, а практически государев человек, на большой и важной должности — цитирую, «только Arduino позволяет запускать один и тот же код на разных процессорах».

          А почему они это рассказывают?

          А потому что у них только в Arduino есть менюшка, в которую можно ткнуть мышкой и выбрать процессор.

          А что там внутри после тыкания мышкой происходит — ну понятно что, магия. Вам про неё знать не надо, вам надо знать, куда мышкой тыкать.


          1. Mike_soft
            03.04.2018 11:24

            Для определенного уровня абстракции этого может быть вполне достаточно.


            1. olartamonov Автор
              03.04.2018 11:47

              Этого достаточно в одном из двух случаев:

              1) человек знает, что происходит ниже
              2) человек не рассуждает о том, что происходит ниже

              По факту же мы имеем вокруг всё больше низкоквалифицированных высокомотированных людей, которые не знают, но рассуждают. Если это вчерашний студент, который просто завалит собеседование — это одно, а если это какой-нибудь замдиректора вуза, подписывающий финансирование учебных программ в нём?

              Ну, мы будем иметь вуз, в котором на четвёртом курсе учат ардуину, потому что она «уникальна по своим возможностям».


              1. Mike_soft
                03.04.2018 12:56

                замдиректора ВУЗа и не обязан знать все тонкости учебных программ. и декан факультета. Боюсь, что даже зав кафедрой может (в смысле «имеет полное право») не иметь об этом представления (если это не его учебный профиль).
                с другой стороны, если выбор между изучением *дуйни, и изучением, как написали выше, УМК на 580м с программированием с пульта в хексе — я проголосую за дуйню.
                зы. «Ректор университета просмотрел смету, которую ему принес декан физического факультета, и, вздохнув, сказал:
                — Почему это физики всегда требуют такое дорогое оборудование? Вот, например, математики просят лишь деньги на бумагу, карандаши и ластики!
                Подумав, добавил:
                — а философы, те ещё лучше, им даже ластики не нужны… „©


    1. olartamonov Автор
      03.04.2018 11:44

      «Так, например, если мы хотим, чтобы на третьей ножке порта А микроконтроллера (PA2, нумерация идёт с нуля) появилась «1», нам надо записать «1» в третий бит регистра, расположенного по адресу 0x4002014»

      Собственно, пляшем от этого тезиса.

      Нужный адрес у нас задаётся дефайнами в CMSIS, чтобы не вбивать его руками, в примере выше это GPIOA->MODER (GPIOA указывает на базовый адрес блока регистров порта A, а MODER задаёт смещение от него до нужного регистра).

      Теперь нам надо поменять в нём третий бит. Мы можем для каждой ножки (биты от 0 до 15) записывать константу с 1 на месте нужного бита, но это громоздко и бессмысленно — проще взять 1 и сдвинуть вправо на нужное число бит: 1 << N.

      С местом бита определились, но с одиночным битом у нас могут быть две операции — либо установить его в единицу, либо сбросить в ноль.

      Чтобы сбросить один бит в 0, надо провести операцию И с этим битом и нулём — тогда что бы в нём ни было, на выходе будет ноль.

      Чтобы установить бит в 1, надо провести операцию ИЛИ с ним и единицей — тогда что бы в нём ни было, на выходе будет ноль.

      Чтобы не поменять значение остальных битов в регистре (мы же дёргаем только одну ножку), нужно в первом случае их все поставить в 1 (1 & 1 = 1, 0 & 1 = 0, значение сохранили), а во втором — их все поставить в ноль.

      У нас есть полученное сдвигом число 0000 0000 0000 0000 0000 0000 0000 0100. Для ИЛИ (установка третьего бита в 1) мы его применяем как есть, для И его надо инвертировать.

      Собственно, вот и получили:

      * сброс бита в ноль: GPIOA->MODER &= ~(1 << N)
      * установка бита в единицу: GPIOA->MODER |= (1 << N)

      С этим всё хорошо, пока у нас бит один — но есть масса настроек, задающихся двумя-тремя-четырьмя битами, часть из которых нам надо поставить в ноль, а часть — в единицу. При этом мы заранее не знаем, в каком значении они сейчас (мало ли кто и где их в другой части программы под себя менял), поэтому сначала их надо привести к известному значению.

      Обычно это делают, сбрасывая их в ноль:

      REG &= ~(0b111 << N)

      Теперь мы знаем, что все три бита точно в нуле, и можно нужные из них установить в 1:

      REG |= (0b010 << N)

      Собственно, всё.

      Дальше случаются всякие нюансы:

      * биты, отвечающие за флаги разных событий, устанавливаемых микроконтроллером самостоятельно (аппаратные ошибки, например), часто сбрасываются в 0 записью в них 1

      * сброс блока битов в регистре с последующей записью нужного значения не есть атомарная операция, поэтому часто это делают через промежуточную переменную: читают в неё регистр, переставляют нужные битики, а потом одни куском кладут её обратно в регистр

      * ну и там уже совсем тонкие нюансы со спецификой синхронизации шин, возможностью немгновенного изменения состояния регистра после записи в него и т.п.


  1. r1000ru
    03.04.2018 09:36
    -1

    Контроллеры не программирую, но в контексте статьи возникло несколько вопросов. Буду благодарен за пояснения:
    1. RIOT OS ориентирована исключительно на dev-платы? (не нашел никаких упоминаний драйверов периферии в коде, за исключением i2c, uart, adc, причем без DMA, и со стартом на фиксированных частотах без ориентирования на энергопотребление).
    2. В комментариях указывается об информации о регистрах из Datasheet`ов. Но ее там нет. Для понимания расположения регистров, их значения, примеров использования в МК STM32 — необходимо читать Reference Manual. Вы считаете данную неточность мелочью, которая начинающим разработчикам никак не помешает?
    3. Увидел много кода файловых систем, консоли и прочих не специфичных для МК вещей. Я правильно понимаю, что данная ОС больше ориентирована на то, чтобы сделать из МК полноценный слабенький, но универсальный компьютер, нежели на выполнение заранее заложенных алгоритмов?


    1. olartamonov Автор
      03.04.2018 11:25

      1. Нет, никакой привязки к платам нет вообще. На третьей лекции будет немного про то, как ОС конфигурируется под разные платы и разные процессоры (и написать там профиль какой-то вообще своей платы — это дело от силы двадцати минут).

      Не очень понял, какой периферии вы не нашли в коде. Для L1 поддерживаются GPIO во всех вариантах, ADC, DAC, I2C, SPI, UART, RTC, ШИМ на таймерах, EEPROM. Собственно, из коробки нет только контроллера ЖК и узкоспециального функционала тех же таймеров или компараторов, который применяется не шибко часто.

      Что такое «старт на фиксированных частотах»? Динамически менять частоту работы периферии в 999 случаях из 1000 нет вообще никакого смысла, а статическую можно в конфигурации платы задать.

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

      3. Чем файловая система не специфична для МК — вы никогда не писали с МК на SD-карту? Что такое «заранее заложенный алгоритм»? Если у устройства есть одна кнопка управления — это заранее заложенный алгоритм или уже нет? А если у него десять кнопок? Сто?


  1. mpa4b
    03.04.2018 19:52

    Подскажите пожалуйста, как в RIOT OS обстоят дела с поддержкой fat32? Есть ли из коробки, например, порт FATfs? А для stm32f105/7 есть ли, например, поддержка OTG USB (и хост и девайс)?


    1. olartamonov Автор
      03.04.2018 19:53

      Да, FatFS есть в виде пристёгнутого стороннего пакета.

      USB вроде кто-то пилил, но в релизах пока нет.


  1. batman12345
    04.04.2018 15:19

    Полностью согласен с первым комментарием. Лекция хуже чем «ниочом» — это просто откровенное мошенничество (ну или ловкость рук, если угодно).
    Вот это вот:
    «Сегодняшняя лекция — первая, поэтому на ней будут разбираться общие понятия: что такое вообще микроконтроллер и зачем он нужен, что такое прошивка и как она получается, зачем нам нужна операционная система, и наконец — как работать с git. Результат практического занятия — собственный репозитарий на GitHub с исходными кодами ОС, а также успешно настроенная среда сборки на локальном компьютере.»
    Как согласутся с:
    «Я не буду описывать здесь детали работы с GitHub и Git — в интернете есть масса отличных пошаговых руководств, повторять которые нет смысла.»
    ???
    Так вы бы и написали тогда уж — вот есть фирма ST, она выпускает микроконтроллеры, а вот ещё есть RIOT. Остальное нагуглите сами, лекция окончена.
    Впрочем, наивно было с моей стороны чего-то ожидать от МИРЭА.


    1. olartamonov Автор
      04.04.2018 16:23
      +1

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

      Ну или что вот там видео висит, можно в него мышкой ткнуть?

      Впрочем, вижу, не приходила.

      Только негодование, что вам кашицу разжёванную в рот не положили.


      1. batman12345
        04.04.2018 16:31
        -1

        Допустим, занятия от текста могут отличаться. Тогда у меня только один вопрос — зачем это здесь? Если оно не даёт ничего, кроме информационного шума и отнимает безценное время читателей.
        И таки вот это: «Результат практического занятия — собственный репозитарий на GitHub с исходными кодами ОС, а также успешно настроенная среда сборки на локальном компьютере.» — это публичная оферта? Или дайте мне это знание или пишите статьи так, чтобы было понятно, что читатель этого не получит.


        1. olartamonov Автор
          04.04.2018 16:38

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

          Я боюсь спрашивать, а если в следующей лекции встретятся слова «самостоятельно посмотреть в даташите»? А через одну — «самостоятельно написать три строчки кода»?


  1. wigneddoom
    04.04.2018 16:43

    А я поддержу автора. Нормальная лекция. В тысячу раз пережеванный «Hello world» с использованием SPl, HAL и т. д., как раз и не нужен.

    Выбор RIOT OS может и не очевидный, но правильный в плане того, что это нормальная ОС. На её примере хоть научатся использовать нормальные абстракции.

    Отказ от IDE тоже поддерживаю. Любой нормальный сишник сначала должен понимать этапы сборки и сборочные средства типа make, cmake и т.д Дальше пусть уже натсраивает IDE по вкусу.

    GPIOA->MODER &= ~(0b11 << (pin_num*2));


    Бинарных литералов нет в стандарте Си, плохому лучше не учить.


  1. electro_mozg
    05.04.2018 11:41
    +1

    Не понимаю все же, зачем учить студентов писать под RIOT OS. Да может быть это и крутая штука и удобная, но тот же FreeRTOS на много популярнее. И тут встает вопрос коллективной работы. Большинство из ваших студентов придут уже в готовый коллектив, где с большой долей вероятности больше будут знать про FreeRTOS (CubeMX и достаточно информации по ней в интернете тому помогли). Да к тому же, как я понял из вашей лекции, у вашей ОС еще и сопутствующее программное обеспечение свое. Если я скажу своему руководителю, а давайте вы будете не в привычном вам кейле а в каком то не понятном редакторе проверять мой код, да и еще на OC про которую он мало что слышал, меня закидают помидорами. Выглядит так, будто я привык работать так, значит учитесь так. Уж если учить так уж сразу с низов, на чистом CMSIS(все равно практика показывает что не куда ты от этого не уйдешь), а уж потом продвигать в массы ОС.
    PS: Буду рад если в будущих лекциях будет больше уделено внимания именно CMSIS. После прихода все возможных библиотек от ST, обучающие ресурсы положили большой болт то на чем STM жили, живут и будут жить. А зря)


    1. olartamonov Автор
      05.04.2018 11:44

      С тем же успехом студенты могут придти в коллектив, в котором вообще не будет пользоваться STM32 и FreeRTOS, а будет, например, MSP432 и TI RTOS (один из крупнейших производителей электроники в России, Инкотекс, например, плотно сидит на TI).

      Поэтому я надеюсь, что они заранее поймут, что ценность специалиста по закручиванию гаек с левой резьбой — она очень сомнительная независимо от распространённости в мире гаек с левой резьбой.

      Если я скажу своему руководителю, а давайте вы будете не в привычном вам кейле а в каком то не понятном редакторе проверять мой код


      Если вы придёте ко мне на собеседование и скажете, что работать вы умеете только в Keil, а всё остальное для вас тёмный лес и что там делать, вы не понимаете, то собеседование на этом и закончится.