Сегодня: 09:06:2025 С добрым утром!

I live ExBB and CMS Limbo!  I live ExBB and CMS Limbo!
Логин :
Пароль :
Регистрация?  Забыли пароль? 
 


 Страниц (1): [1]   

> Без описания

  Супермодератор
Отправлено: 1 июля 2017 — 19:46
ответить цитировать Post Id


 Покинул технарь
Профессионал
Сообщений: 1832
Регистрация: 12.2011

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

Есть такая компания, называется она IAR Systems. Делает много вещей, в том числе и среды разработки и компиляторы для различных архитектур, список которых довольно обширен. Также в числе продуктов компании есть отладчики, наборы разработчиков и т.д. Более подробно со всем этим разнообразием можно ознакомиться на их родном сайте iar.com

Нас же сейчас интересует среда для разработки приложений для архитектуры ARM, в частности Cortex-M3. Есть в их ассортименте и такой продукт и называется он EWARM, что является сокращением от Embedded Workbench for ARM, что в свою очередь, в моем вольном переводе на великий и могучий, звучит примерно как «Среда разработки для встроенных систем на архитектуре ARM», впрочем, за точность я не ручаюсь…

Данная среда поддерживает большое количество микропроцессоров и микроконтроллеров построенных на базе архитектуры ARM разных версий. Полный список можно посмотреть на их сайте Т.к. это серьезная среда разработки, то она поддерживает различные отладочные интерфейсы и средства сопряжения как производства самой IAR так и сторонних компаний, имеет встроенный отладчик, симулятор и т.д.

Но по причине отсутствия у меня какого либо девайса для внутрисхемной отладки рассказать я про все это не могу. А пользоваться симулятором как-то в голову даже не приходило. Я по старинке, пишу, заливаю в контроллер и смотрю что происходит. (Зато их есть у меня. И я вам скоро выдам пример того, какой это рулез. прим. DI HALT)

Есть мнение, что компилятор С/С++ у IAR один из самых лучших, но за это я не ручаюсь, хотя кое какие мои сравнения с Keil uVision v3 показали его превосходство.

В общем, это мощнейшая полноценная среда для разработчика. Кому интересно, изучайте описания на официальном сайте Есть ли версия для линукса я на сайте нигде не углядел, поэтому точно не скажу. (Боюсь, что как всегда ;) Впрочем, там есть могучий и универсальный GCC и обязательно есть поддержка ARM. Так что если есть желающие показать старт проекта под линухом — ждем с распростертыми обьятьями. Пишите на dihalt@dihalt.ru прим. DI HALT)

На момент написания данной статьи доступна версия 6.10 (я же буду рассказывать на примере версии 5.4).

Сколько стоит данное чудо я, к сожалению, на их официальном сайте найти так и не смог, а лазить по сайтам дилеров как-то недосуг… На наше счастье, данный продукт доступен в демо режиме для ознакомления. (Я тоже полазил, не нашел. Кейл стоит около 3 килобаксов. IAR, думаю, в тех же пределах. Вполне подьемно для коммерческого применения прим. DI HALT)

И здесь есть 2 варианта
1. Полнофункциональная версия с ограничением использования в 30 дней.
2. Версия без ограничения по времени использования но генерирующая код не более 32Кб. Под наши ковыряния хватит с лихвой.

Обе версии, кроме того имеют следующие ограничения:
Они не включают исходный код библиотек.
Они не включают поддержку MISRA C (что это такое, к сожалению не знаю).
Имеют ограниченную техническую поддержку.
Версия с ограничением кода в 32Кб не имеет поддержки расширенной отладки (что это такое, к сожалению не знаю)

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

После установки можно приступать к созданию проекта. Запускаем IAR Embedded Workbench и видим следующее окно:



Лирическое отступление.
Если кто-то, как я, привык для копирования/вставки использовать сочетание клавиш Ctr+Insert/Shift+Insert, то его ждет засада! EWARM по умолчанию понимает только Ctrl+C/Ctrl+V и при нажатии Ctr+Insert или Shift+Insert только меняет режим вставки/перезаписи текста. Почти месяц меня это жутко бесило, пока однажды мне не стукнуло что-то в голову и не пришла мысль порыться в настройках… Оказалось, что это легко лечится путем назначения сочетаний клавиш командам! Делается это во вкладке меню Tools->Options, далее Keybindings.

Выбираем в меню:
code:
Project->Create New Project


Открывается окошко создания нового проекта.
На данном этапе можно выбрать из шаблонов, что именно мы хотим создать, но выбор там не велик, а все шаблоны содержат пустые заготовки файлов с нужным расширением и заголовками. Поэтому не ломаем голову а выбираем
code:
C->main


и жмем кнопочку ОК



Появится диалог выбора имени проекта и указания, куда его сохранить. Называем проект милым вашему сердцу названием и сохраняем в укромном месте. Я же назвал его LEDTest, что какбы намекает… В итоге получаем следующую картину:



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

На данном этапе желательно нажать на кнопку с изображением трех дискеток или через меню
code:
File->Save All.

EWARM попросит ввести имя WorkSpace (воркспейс может содержать множество проектов) и не мудрствуя лукаво я назвал его также LEDTest.

В отличие от Keil’a EWARM не попросил указать целевое устройство и все остальное, поэтому лезем в свойства проекта и начинаем его настраивать.

По аналогии с Microsoft Visual Studio EWARM позволяет создавать произвольное число конфигураций и по умолчанию создает в проекте 2 конфигурации Debug и Release, что подразумевает 2 набора параметров, одни для компиляции кода содержащего отладочную информацию и другой для кода без нее. Выбираем наиболее подходящую для себя.

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

Итак, идем в меню
code:
Project->Options

Либо нажимаем Alt+F7, либо тыкаем правой кнопкой мыши на корне дерева слева и выбираем в меню Options. Появляется окно настроек проекта.

Первая категория – General Options
Здесь желательно выбрать ядро для которого нужно откомпилировать код или указать конкретное устройство. По умолчанию указано ядро ARM7TDMI. Переключаем радиобуттон на Device, нажимаем на кнопку справа от поля ввода и в списке выбираем
code:
ST->ST STM32F10xxY


, где Y соответствует семейству имеющегося у вас микроконтроллера. Я выберу ST STM32F10xxE.



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

Output (вывод)
Здесь указываем что мы хотим получить навыходе, исполняемую программу или библиотеку. Оставляем без изменения – Executable. Также здесь можно прописать пути куда ложить откомпилированную программу/библиотеку, объектные файлы и файлы листингов. Меняем, если душа того просит.

Library Configuration (конфигурация runtime библиотеки языка С). Это тема отдельной телепередачи Улыбка но сейчас можно смело поставить None и пройти дальше.

Library options (опции стандартной библиотеки языка С)
Здесь настраивается работа функций printf и scanf. Вернее поддержка различных ключей строки форматирования. Ниже кратко расписано какая опция что поддерживает, а более подробно можно прочитать в документации идущей в комплекте с EWARM. Поддержка более сложных ключей форматирования увеличивает размер кода т.к. обработчики строки форматирования разные по сложности реализации. В данном проекте нам это не важно т.к. данными функциями мы пользоваться не будем. А в последущием я освещу данный вопрос подробнее.

MISRA-C: 2004 и MISRA-C: 1998. Настройки расширений MISRA-C. Что это такое, я честно не знаю. Улыбка

C/C++ Compiler (настройки компилятора С/С++)
Здесь настраивается поддержка расширений языков С/С++, режимы оптимизации компилятора, генерация отладочной информации, пути к инклудам и т.д. Здесь пока можно ничего не трогать.

Assembler
Соответственно настройки языка ассемблера. Здесь пока можно ничего не трогать.

Output Converter (конвертация вывода)
Вот это нам нужно. Дело в том, что по умолчанию EWARM генерирует исполняемый файл в формате ELF, что какбы намекает, что Unix и прочие линуксы IAR’у не чужды.

Но нам то они ни к чему, поэтому смело тыкаем галку Generate additional output (генерировать дополнительный выходной файл) и в списке Output format (формат выходного файла) выбираем подходящий для себя, вернее для используемого вами программатора, формат.

Выбор особо не велик и реально для большинства будет состоять из двух вариантов: Intel extended, в простонародье именуемый HEX или binary. Я лично пользуюсь вариантом binary. Здесь же, если того требуют ваши религиозные убеждения, можно задать имя выходного файла отличающееся от дефолтного.



Custom build (пользовательская сборка)
Здесь можно задать дополнительные утилиты и их параметры которые будут использоваться при сборке проекта, но нам это ни к чему — пропускаем.

Build Actions (действия при сборке)
Здесь можно указать команды которые нужно выполнить перед сборкой или после. Поступаем аналогично предыдущему пункту.

Категория Linker (линковщик)
Вот и добрались до второго, после указания целевого устройства, важного момента! Ибо от линковщика, вернее его настроек, очень сильно зависит запуститься ваш проект в микроконтроллере или нет т.к. именно линковщик располагает код и различные таблицы (например векторов прерываний) по нужным адресам.

Вкладка Config (конфигурация). Здесь содержится ссылка на используемый файл конфигурации линковщика. Это очень важный файл т.к. именно в нем прописана конфигурация нашего микропроцессора в части памяти (ее наличия или отсутствия, адресации и размера), размещения таблицы векторов прерываний, размеры стека и кучи. По умолчанию проставлена ссылка на файл конфигурации идущий в комплекте с EWARM’ом и едином для всех устройств на базе ядра Cortex, что не есть хорошо, т.к. устройства все разные, объемы флеша и ОЗУ у них разные и т.д. К счастью, есть возможность отредактировать этот файл самостоятельно, что дает широчайший простор творчеству, либо с использованием кнопки Edit… находящейся здесь же.



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

Дело в том, что как я уже сказал выше, данный файл является заготовкой для всей архитектуры Cortex, поэтому если вы его измените, а потом захотите создать проект для другого контроллера, того-же NXP LPC17XX, то его опять придется редактировать уже под этот процессор. Тут есть 3 варианта решения:
Сказать себе, что кроме STM32F меня ничего не интересует и отредактировать данный файл.
Скопировать данный файл в той-же папочке где он лежит (а лежит он, как можно догадаться, в папке диск:путь куда установили EWARM\arm\CONFIG\) во что-то типа STM32F10XXX.icf и редактировать его.
Скопировать его в папочку с проектом переименовав во что-то типа STM32F10XXX.icf и редактировать его.

Итак, выбираем вариант себе по душе (я лично пользуюсь 3-им вариантом а путь прописываю так:
code:
$PROJ_DIR$\stm32f103re.icf


Переменная $PROJ_DIR$ разворачивается в путь до папки с проектом автоматически, т.е. путь получается относительным. Таким образом можно папку с проектами копировать потом куда угодно и файл не «потеряется» в отличие от использования жесткого пути), выбираем свой файл отредактировав путь или нажав кнопку выбора файла (кнопка с «…» справа от едита) и нажимаем кнопку Edit…

В появившемся окошке в первой вкладке Vector Table задаем адрес таблицы векторов прерываний. Что это такое, для тех кто не в курсе, я не буду раскрывать. (Я тоже не скажу Улыбка, т.к. все уже сказано в разделе про AVR. Тут все точно также, только векторов больше. прим DI HALT)

Адрес может быть либо 0х00000000 либо 0х08000000. Я предпочитаю ставить 0х08000000 т.к. он указывает на начало внутренней флеш памяти, а адрес 0х00000000 может мэпиться на флешку а может и нет, в зависимости от состояния входов BOOT в момент инициализации контроллера, но это нужно уже курить даташит на устройство.



Вкладка Memory Regions (регионы памяти).
Здесь задается 2 важных для работы контроллера вида памяти ROM (ПЗУ) и RAM (ОЗУ) вернее их адреса начала и окончания. ROM — это наша внутренняя флеш память. Начинается она с адреса 0х08000000, это заложено в архитектуре контроллера. А вот заканчивается у каждого по разному. Зависит от объема который есть в вашем контроллере.

У меня ее 512Кб, а у вас может быть 32, 64, 128, 256. Т.е. адрес окончания этой области памяти вычисляете сами. Для меня он будет равен 0x0807FFFF (адрес начала 0x08000000 + размер флеша (512*1024) – 1 в шестнадцатеричном формате). Для вас это может быть 0x08007FFF, 0x0800FFFF, 0x0801FFFF и т.д. Желательно указывать точный размер чтобы полученная прошивка не превысила этот размер, а так линковщик ругнется в случае чего. Но нам это не грозит пока. Аналогично заполняем поля для RAM, зная из чтения даташита, что она начинается с адреса 0x20000000 и посчитав где она закончится.



Если ошибетесь в этих адресах, особенно начальных, например нолик пропустите или лишний напишите, то программа просто не будет работать.

Вкладка Stack/Heap Sizes (размеры стека и кучи)
Параметры говорящие сами за себя.
Стек нужен для передачи параметров функциям, сохранения точек возврата из них и т.д. Сильно большим его делать не имеет смысла т.к. зря будет расходоваться ОЗУ, а если сделать сильно маленьким, то может не хватить (особенно если будет использоваться много вложенных функций). Поставим его равным 0x200 т.е. 512 байт. В нашем проекте этого более чем достаточно.
Куча – это часть ОЗУ выделенная для функций работы с памятью языка С/С++ таких как malloc, оператор new и т.д. В данном проекте мы их использовать не планируем, поэтому ставим 0.



Все, нажимаем кнопочку Save.

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

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

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

Теперь можно смело нажать кнопку F7 или в меню
code:
Project->Make


и откомпилировать наш проект.

В папочке которую вы указали для выходных файлов программы (если ничего не меняли, то это будет, в зависимости от выбранной конфигурации, папка Debug/exe либо Release/exe в папке с проектом) увидим 2 файла. Один с раширением .out и второй .bin или .hex, в зависимости от того, что вы указали в качестве дополнительного выходного файла.

Все, наша первая программа готова! Можно прошивать ее в контроллер и она заработает! Не верите? А вы попробуйте.

На этом позвольте закончить мою первую статью т.к. она и так получилась не маленькой. А к написанию более функционально насыщенной программы мы перейдем на следующем нашем шаге.

PS:
Хочу еще пару слов сказать о прошивке контроллера. Как я написал в эпиграфе, если ничего нет, но очень хочется… Если у вас нет аппаратного прошивальщика и/или отладчика, то это не большая проблема. Дело в том, что прошить контроллер STM32F можно с использованием обычного интерфейса USART, в простонародье это называется через COM порт. В идеале, если на плате с микроконтроллером распаян преобразователь уровней USART в TTL и заведен на порт USART1 контроллера (ножки PA.8 PA.9). Если нет, то тоже не большая беда. Можно немного распотрошить любой кабель-переходник USB<->COM (в крайнем случае покупается в магазине), там внутри стоит микросхема с TTL уровнями, и пользоваться им подключаясь напрямую к ножкам контроллера. Про выставление уровней BOOT0/1 и как входить в режим бутлоадера можно узнать из даташита. А прошивать можно программой Flash Loader Demo производства самой ST Microelectronics. Я пользуюсь именно ей. Правда почему-то найти ее на сайте ST невозможно, поэтому прикладываю ее к своей статье, спасибо за нее нашим китайским братьям!
 
 Top

  Супермодератор
Отправлено: 1 июля 2017 — 20:01
ответить цитировать Post Id


 Покинул технарь
Профессионал
Сообщений: 1832
Регистрация: 12.2011

Продолжение... Оригинал можно посмотреть здесь.

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

Сей, кажущийся тривиально простым пример (который на самом деле таким и является), на самом деле все-таки несет в себе некий глубинный смысл, т.к. на нем мы научимся подключать в свой проект CMSIS (что это такое, уже рассказал уважаемый Di Halt в своей статье про создание проекта в Keil ) и узнаем о существовании Standard Peripherals Library (стандартной библиотекой работы с периферией), вещью весьма полезной и часто упрощающей жизнь программиста.

Ну что же, приступим. Для начала, хочу сделать небольшое отступление и навести порядок в своем проекте. Дело в том, что я стараюсь всегда делать так, чтобы в проекте был виден некий логический порядок, т.е. исходники и подключаемые файлы (в простонародье инклуды) лежали в папочках с говорящими названиями, а не в корне проекта и чтобы они еще и были структурированы по функциональной нагрузке.
Не сочтите меня педантом, но соблюдение этих простых правил может сильно облегчить вам жизнь в серьезных проектах, поэтому, перефразируя персонажа одного известного мультфильма, лучше 3 минуты потерять на начальном этапе зато потом… Те, кто со мной не согласен могут смело пропускать следующие несколько абзацев (и пить йад! прим. DI HALT).

EWARM в дереве с проектом позволяет создавать логические группы. Что мне особенно в нем понравилось после Keil uVision v3 (может в 4 версии это улучшили) так это то, что группы могут быть вложенными. В uVision v3 вложенные группы у меня создать не получилось.
Первым делом, идем в папку с проектом, создаем там папочку src (вы можете ввести любое, привычное вам, обозначение для папки с исходниками) и перемещаем в нее наш main.c из корня проекта. Затем в EWARM’е тыкаем мышкой на файле main.c и жмем Del на клавиатуре, либо правый клик и в меню Remove. Подтверждаем удаление файла из проекта.
Теперь в дереве проекта, тыкаем правой кнопкой мышки и в меню выбираем
code:
Add->Add Group.


В появившемся окошке нас попросят ввести название группы, вводим src, или как вы там это называете, и нажимаем Ок. В дереве появится «папочка» src.
Тыкаем на ней правой кнопкой мыши и в мею выбираем
code:
Add->Add Files.


В диалоговом окне выбора файлов идем в папочку src и выбираем файл main.c. После этого выбранный файл появится в дереве проекта в «папочке» src.

Теперь настало время подключить CMSIS. Для этого, в принципе, можно воспользоваться файлами любезно предоставленными Di Halt’ом в своей статье. Но я предлагаю вам пройтись на официальный сайт ST Microelectronics и скачать архив содержащий CMSIS и не только.

Дело в том, что данный архив во первых содержит ASM startup файлы, в том числе и для EWARM, а во вторых, он содержите еще и упомянутую в начале статьи Standard Peripherals Library, о ней речь пойдет ниже.

Качаем и распаковываем архив. В нем находим в папочке
code:
STM32F10x_StdPeriph_Lib_V3.4.0\Libraries\CMSIS\CM3\CoreSupport файл core_cm3.c


В своем проекте, в папке с исходниками, создаем папку CMSIS и копируем сюда файл core_cm3.c. Копируем туда же файл
code:
STM32F10x_StdPeriph_Lib_V3.4.0\Project\STM32F10x_StdPeriph_Template\system_stm32f10x.c


Аналогично описанному выше, создаем группу CMSIS в группе src в дереве проекта и добавляем эти файлы в проект в «папочку» src\CMSIS.

В папке с проектом, создаем папку inc и копируем в нее файлы stm32f10x.h и system_stm32f10x.h из папки
code:
STM32F10x_StdPeriph_Lib_V3.4.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x


и файл core_cm3.h из папки
code:
STM32F10x_StdPeriph_Lib_V3.4.0\Libraries\CMSIS\CM3\CoreSupport.


Аналогично добавляем группу и эти файлы в дерево проекта.

И, наконец, создаем в папке с проектом папочку startup, копируем в нее файл startup_stm32f10x_xxx.s из папки
code:
STM32F10x_StdPeriph_Lib_V3.4.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\iar


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

В нем содержится таблица векторов прерываний, инициализация стека, вызов функции SystemInit() из библиотеки CMSIS и последующий вызов функции main() нашей программы.
В указанной папке будет находиться несколько файлов вида startup_stm32f10x_xxx.s Это обусловлено различием микроконтроллеров разных серий по функционалу. Различия в этих файлах минимальны и касаются только таблицы векторов прерываний, т.к. если в вашем микроконтроллере, например, отсутствует ЦАП, то соответственно не будет и прерываний им генерируемых…

ST Microelectronics использует следующую классификацию и обозначения (в моем вольном переводе):
STM32F10X_LD: STM32 Low density devices (устройства низкой плотности интеграции). Это микроконтроллеры серий STM32F101xx, STM32F102xx и STM32F103xx имеющие на борту от 16 до 32Кбайта флеш памяти.
STM32F10X_LD_VL: STM32 Low density Value Line devices (устройства низкой плотности интеграции массового уровня). Это микроконтроллеры серии STM32F100xx имеющие на борту от 16 до 32Кбайта флеш памяти.
STM32F10X_MD: STM32 Medium density devices (устройства средней плотности интеграции). Это микроконтроллеры серий STM32F101xx, STM32F102xx и STM32F103xx имеющие на борту от 64 до 128Кбайта флеш памяти.
STM32F10X_MD_VL: STM32 Medium density Value Line devices (устройства средней плотности интеграции массового уровня). Это микроконтроллеры серии STM32F100xx имеющие на борту от 64 до 128Кбайта флеш памяти.
STM32F10X_HD: STM32 High density devices (устройства высокой плотности интеграции). Это микроконтроллеры серий STM32F101xx и STM32F103xx имеющие на борту от 256 до 512Кбайта флеш памяти.
STM32F10X_HD: STM32 High density value line devices (устройства высокой плотности интеграции массового уровня). Это микроконтроллеры серии STM32F100xx имеющие на борту от 256 до 512Кбайта флеш памяти.
STM32F10X_XL: STM32 XL-density devices (устройства очень высокой плотности интеграции). Это микроконтроллеры серий STM32F101xx и STM32F103xx имеющие на борту от 512 до 1024Кбайта флеш памяти.
STM32F10X_CL: STM32 Connectivity line devices (устройства ориентированные на коммуникации и сфокусированные на реализацию высокопроизводительных вариантов интерфейсов, удовлетворяющих промышленным стандартам). Это микроконтроллеры серий STM32F105xx и STM32F107xx.

Итак, пользуясь данной классификацией, выбираете подходящий вам вариант файла. Для меня это будет startup_stm32f10x_hd.s
В итоге, должна получиться примерно следующая картина:



Если попытаться откомпилировать проект, то компилятор начнет ругаться на то, что он не может найти файл stm32f10x.h Это потому, что мы поместили его в отдельную папочку inc. Укажем эту папку в настройках проекта во вкладке Preprocessor в категории C/C++ Compiler. Здесь есть 2 варианта:
Указать абсолютный путь до своей папки inc.
Указать относительный путь.

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



Пробуем откомпилировать, и появляется другая ошибка:
code:
«Fatal Error[Pe035]: #error directive: "Please select first the target STM32F10x device used in your application бла бла бла».


Эта ошибка генерируется в файле stm32f10x.h и говорит она нам о том, что неплохо бы указать тип микроконтроллера. Это уже просит библиотека CMSIS… Если пройти по ошибке в файл stm32f10x.h и отмотать чуть чуть выше, то мы увидим блок, где можно задефайнить нужный нам тип микроконтроллера, но тут же есть и намек, что, может быть, не стоит это делать жестко. В общем, как обычно у нас 2 пути:
Задефайнить жестко тип микроконтроллера здесь, подойдет, если файл stm32f10x.h, в каждом проекте будет свой или работать планируете только с одним типом контроллеров.
Определить дефайн с типом микроконтроллера в опциях компилятора (там же, где указывали путь к подключаемым файлам, только чуть ниже, едит бокс под названием Defined symbols).

Выбираем способ наиболее подходящий для вас, я воспользуюсь первым вариантом и раскомментирую строчку1
code:
/* #define STM32F10X_HD */ /*!< STM32F10X_HD: STM32 High density devices */



(предварительно сняв в проводнике с файла stm32f10x.h атрибут read only).
Компилируем еще раз, и убеждаемся что на этот раз все компилируется без ошибок. Теперь добавляем код инициализации ножки порта к которой подключен светодиод и в цикле с некоторой задержкой устанавливаем на этой ножке уровень напряжений Vcc или 0, что заставляет мигать наш светодиод. У меня используется 5-я нога порта B. В остальном код практически полностью взят из статьи Di Halt’а.

code:
#include "stm32f10x.h"

//------------------------------------------------------------------------------

void InitAll( void);
void Delay( unsigned int Val);

//------------------------------------------------------------------------------

int main( void) {

InitAll();

while( 1) {
// Set PB.5 bit
GPIOB->BSRR = GPIO_BSRR_BS5;
Delay( 600000);

// Reset PB.5 bit
GPIOB->BSRR = GPIO_BSRR_BR5;
Delay( 600000);
}

}

//------------------------------------------------------------------------------

void InitAll( void) {

// Enable PORTB Periph clock
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;


// Clear PB.5 control register bits
GPIOB->CRL &= ~(GPIO_CRL_MODE5 | GPIO_CRL_CNF5);

// Configure PB.5 as Push Pull output at max 10Mhz
GPIOB->CRL |= GPIO_CRL_MODE5_0;


return;
}

//------------------------------------------------------------------------------

void Delay( unsigned int Val) {
for( ; Val != 0; Val--) {
__NOP();
}
}

//------------------------------------------------------------------------------



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

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

Standard Peripherals Library
На этом, можно было бы закончить данную статью, но хочется еще рассказать о библиотеке Standard Peripherals Library, упомянутой пару раз ранее. Эта библиотека любезно представляется компанией ST Microelectronics для использования со своими микроконтроллерами. Данная библиотека, как следует из ее описания самим производителем, предназначена лишь в качестве руководства к действию, но может облегчить жизнь программисту и сократить время разработки проекта.
Также производитель не несет никакой ответственности если в результате использования этой библиотеки вы чего-то там сломаете себе или кому другому… Но это как обычно Улыбка Истинные последователи дзен буддизма с негодованием могут закончить чтение данной статьи. Библиотека поставляется в исходных кодах, и на данный момент доступна версия 3.4.0 от 15 октября 2010г.

Итак, что же представляет из себя данная библиотека? По сути это просто набор функций, позволяющих намного легче и проще делать какие-то основные моменты. В основном, упор сделан на функции инициализации периферии, ее включения/выключения, опроса состояния и т.д. В комплекте идет небольшой справочник в формате chm (честно говоря весьма убогий т.к. IMHO генерируется автоматически чем-то типа Doxygen т.е. на основе комментариев к коду). Также присутствует папочка с различными примерами, число которых довольно велико и которые тоже могут быть интересны начинающим осваивать данные микроконтроллеры. Примеры разбиты тематически по папочкам с говорящими названиями и неплохо описаны.

В общем, попробуем переписать теперь наш пример используя данную библиотеку.
Для начала нужно опять открыть файл stm32f10x.h и чуть чуть ниже того места, где мы определяли тип используемого микроконтроллера найти условие
code:
#if !defined USE_STDPERIPH_DRIVER.



Далее идет описание, что такое USE_STDPERIPH_DRIVER и закомментированный дефайн. Раскомментируем его, тем самым давая понять, что мы желаем использовать не просто CMSIS а также использовать функционал данной библиотеки. Также, крайне желательно, еще чуть ниже найти строку
code:
#define HSE_VALUE ((uint32_t)8000000)



и указать свое значение кварца, если оно отлично от 8МГц. Если этого не сделать, то потом можно наступить на грабли в виде «неработающего» USART и т.п.

Теперь в наш проект нужно добавить файл stm32f10x_conf.h, который вызывается теперь из файла stm32f10x.h Взять его можно в папочке
code:
STM32F10x_StdPeriph_Lib_V3.4.0\Project\STM32F10x_StdPeriph_Template


Данный файл содержит в себе инклуды на части библиотеки и макрос assert_param предназначенный для проверки правильности передаваемых в функции библиотеки параметров. По умолчанию он пустой. Кому интересно как им пользоваться в полной мере – спрашивайте в комментах. В данном файле можно убрать или закомментировать все не нужные нам инклуды. Мы будем пользоваться только функциями определенными в заголовочных файлах stm32f10x_rcc.h (функции работы с тактовыми генераторами) и stm32f10x_gpio.h (функции работы с портами ввода/вывода).
Также в папочке с проектом создаем папку типа StdPeriphLib, копируем туда файлы stm32f10x_rcc.c и stm32f10x_gpio.c из
code:
STM32F10x_StdPeriph_Lib_V3.4.0\Libraries\STM32F10x_StdPeriph_Driver\src


и добавляем все это добро в наш проект. Теперь переписываем код и заменяем прямую работу с регистрами на вызовы функций билиотеки. В результате получаем следующее:



code:
#include "stm32f10x.h"

//------------------------------------------------------------------------------

void InitAll( void);
void Delay( unsigned int Val);

//------------------------------------------------------------------------------

int main( void) {

InitAll();

while( 1) {
GPIO_SetBits( GPIOB, GPIO_Pin_5);
Delay( 600000);

GPIO_ResetBits( GPIOB, GPIO_Pin_5);
Delay( 600000);
}

}

//------------------------------------------------------------------------------

void InitAll( void) {
GPIO_InitTypeDef GPIO_InitStructure;

// Enable PORTB Periph clock
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);

// Configure PB.5 as Push Pull output at max 10Mhz
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init( GPIOB, &GPIO_InitStructure);

return;
}

//------------------------------------------------------------------------------

void Delay( unsigned int Val) {
for( ; Val != 0; Val--) {
__no_operation();
}
}

//------------------------------------------------------------------------------


Компилируем, прошиваем, убеждаемся, что работает.
Что же мы получили от использования Standard Peripherals Library?

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

Особенно эти пункты становятся видны на более сложном коде.
Есть еще? пишите в комменты.

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

Есть еще? пишите в комменты.

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

И еще, чтобы все время не добавлять нужные C файлы из библиотеки в проект, я просто один раз откомпилировал их в библиотеку, и подключаю ее в свои проекты. Если кому интересно как это сделать – спрашивайте.
Архивы примеров под CMSIS и под SPL

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

PS:
Мистика какая-то! Пару раз специально пытался найти на сайте ST Microelectronics Flash loader demonstrator и не получалось… Сейчас, когда начал писать статью и полез за исходниками библиотеки, сразу же наткнулся и на нее! Причем версия 2.2, еще свежее чем приложенная к прошлой статье. Я так и не понял, толи я раньше тупил, толи подправили сайт. В общем, кому надо, качайте. Улыбка
 
 Top

  Супермодератор
Отправлено: 1 июля 2017 — 20:05
ответить цитировать Post Id


 Покинул технарь
Профессионал
Сообщений: 1832
Регистрация: 12.2011

А это другая статья по тому же вопросу...

С течением времени всегда кажется, что у соседа трава зеленее.

В смысле, компилятор круче, проще, удобней и оптимизирует лучше.

Начнём с IAR Embedded Workbench IDE for AVR - посмотрим, как хотя бы запустить в нем проект.

Будем рассматривать язык С - без плюсов - поэтому уясним, что никаких ссылок "at" и битовых переменных тут не используется.

Теперь наш удел - это выражения типа "portLight |= 1 << _Light;" и "portButton &= ˜(1 << _Button);", где выражение типа "x |= a" заменяет длинную запись "x = x | a".

Ещё тут много всяких кнопочно-галочных настроек, которые не совсем очевидны, но без них не работает >_<
Поэтому щёлкаем "Project -> Options...":

Во вкладке "General options" - "Target" определяем конфигурацию процессора - справа от текстового поля есть кнопочка

В "General options" - "System" есть крайне важная и крайне незаметная галочка "Enable bit definitions in I/O-Include files" - поставим её, и будет нам счастье: компилятор будет понимать не только названия регистров, но и названия битов регистров. То есть можно будет писать примерно так: "GICR |= 1 << INT0; //разрешаем внешнее прерывание INT0", и имена 'GICR' и 'INT0' будут распознаны.

//В "C/C++ Compiler" - "Language 1" ставим галочку "Multi-file Compilation" - поговаривают, что так лучше О_о

Во вкладке "C/C++ Compiler" - "Optimizations" можно поставить высокий уровень оптимизации, и объем выходного файла будет уменьшаться. Теоретически, по крайней мере.

В "Linker" - "Output" ставим галочку "Override default" и в текстовом поле пишем расширение .hex; можно вообще написать "$PROJ_FNAME$.hex" - тогда автоматом будет проставляться название проекта. Ниже, в области "Format" выбираем "Other" - "intel-standard"

После этого все должно быть хорошо)



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

code:
#include <имя_файла.h>
#include "имя_файла.h"



Угловые скобки указывают компилятору, что подключаемые файлы нужно сначала искать в стандартной папке "IAR\avr\inc", а кавычки - что нужно начинать поиск с директории, в которой хранится проект.

При этом для каждого типа микроконтроллера нужно подключать свой заголовочный файл (для ATmega8 - iom8.h, для ATtiny2313 - iotiny2313.h и т.д.), но в принципе, можно подключить общие заголовочные файлы ioavr.h и inavr.h, а препроцессор уже сам разберется, что к чему - в зависимости от настроек программы.

Также в этом компиляторе будет куча define-ов - чтобы переобозвать регистры управления портов (DDRx, PORTx, PINx) - пользоваться указателями на unsigned char, как в MikroC, не получится - и на самом деле непонятно, что даже лучше) Маленький экскурс: в языке Си есть такая вещь, как препроцессор. Он способен изменить код до компиляции и работает с директивами #include, #define, #if, #ifdef и так далее.

Когда мы пишем #define three 3, то дальше препроцессор перед компиляцией заменит в программе все "three" на "3"

О насущном и обычно необходимом: где-то запрятана функция __delay(value), которая работает с миллисекундами - она есть в справке, но найти библиотеку, где она лежит, я так и не смогла - зато есть функция __delay_cycles(unsigned long int), которая работает с тактами - лежит в библиотеке "intrinsics.h" - "inavr.h" тоже на неё ссылается. Чтобы получить нужное количество секунд, надо умножить это количество на частоту в герцах.

code:
#define CPUfreq_MHz 8
#define delayLight_mc 300

//определяем функцию задержки в мс
void delay_ms(unsigned long time)
{
long i;
for(i = 0; i < time; i++)
__delay_cycles(CPUfreq_MHz * 1000);
}



Для примера представлена программа, мигающая светодиодиком:
code:
//программа для attiny2313; светодиод на выводе B.0 мигает (подключаем длинную ножку светодиода к микросхеме, короткую - через резистор на землю)
#include "ioavr.h"
#include "inavr.h"

//частота работы процессора в МГц (!)
#define CPUfreq_MHz 8

//вывод для светодиода B.0
#define ddrLight DDRB
#define portLight PORTB
unsigned char _Light = 0;
#define delayLight_mc 300

//определяем функцию задержки в мс
void delay_ms(unsigned long time)
{
long i;
for(i = 0; i < time; i++)
__delay_cycles(CPUfreq_MHz * 1000);
}

void main(void)
{
//инициализация порта, где будет мигать лампочка
portLight = 0;
ddrLight = 0;
//инициализация светодиодика - на выход и в 1
portLight |= 1 << _Light;
ddrLight |= 1 << _Light;
while(1)
{
delay_ms(delayLight_mc); //задержка
portLight &= ˜(1 << _Light); //ножку в ноль - светодиод не горит
delay_ms(delayLight_mc); //задержка
portLight |= 1 << _Light; //ножку в единицу - светодиод горит
}
}
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 1 (гостей: 1, зарегистрированных: 0)
« Arduino - простая работа с микроконтролером »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Все гости форума могут отвечать на сообщения в этом разделе.
 


> Создание ответа в тему "Embedded Workbench for ARM. Учебный курс. Создание проекта."
Имя: Гость   Вы зарегистрированы?
Помощь по ExBBCodes
С помощью кодов можно очень легко применять различные виды стилей к выделенному тексту.
Смайлики

smilie smilie smilie smilie smilie
smilie smilie smilie smilie smilie
smilie smilie smilie smilie smilie

все смайлики
Опции сообщения Вы хотите разрешить смайлики в этом сообщении?
   

> Темы, похожие на тему "Embedded Workbench for ARM. Учебный курс. Создание проекта."
Темы Форум Информация о теме Обновление
Блокировка рекламы в Adblock Plus
Создание собственных фильтров для Adblock Plus
Всё подряд Ответов: 1
Автор темы: технарь
23 сентября 2018 — 12:59
Автор: технарь
Создание собственного функционала
Пример добавление к форуму собственных функций
SMF Community Ответов: 0
Автор темы: технарь
6 января 2017 — 21:46
Автор: технарь
Создание приватных тем на основе описания темы
Возможность всем создавать приватные темы на основе описания
ExBB Community Ответов: 0
Автор темы: технарь
16 октября 2016 — 11:11
Автор: технарь
 


Powered by ExBB v1.1.180311