Допиливание тулчейна до кондиции

Установить-то тулчейн для ARM-ов/Cortex-ов мы установили, но вот полноценно пользоваться им всё ещё нельзя. Нам понадобится доустановить набор файлов, которые описывают специфику конкретных микроконтроллеров — микроконтроллеры-то все разные, периферия у них отличается. А установленный тулчейн имеет общий набор файлов, которые не затрагивают специфику микроконтроллеров.

Поскольку я работаю исключительно с микроконтроллерами фирмы ST Microelectronics, то я буду устанавливать файлы только для МК этой фирмы. Файлы для других фирм-производителей устанавливаются аналогично.

Вообще я работаю с STM32F100xx, STM32F030xx, но в настоящий момент у меня актуален проект на STM32F101CB. Поэтому я буду вести разговор о STM32F101CB.

Несколько лет назад на сайте st.com лежал сжатый архивный файл стандартной библиотеки периферии STM32. Он назывался stm32f10x_stdperiph_lib.zip. Точно такой же сжатый архив был и для микроконтроллеров STM32F0x. К сожалению, на фирменном сайте я не смог их найти. Возможно, фирма ST их удалила, а может куда-то очень глубоко задвинула… К счастью, у меня на архивном винчестере имеются копии.

К стати, подскажите куда лучше выложить эти файлы, чтобы все желающие имели к ним доступ.

Сжатый архивный файл нужно раскрыть. Вся библиотека нам не нужна, нам нужны всего несколько файлов.

Прежде всего нам понадобится два файла для ядра core-cm3.h и core-cm3.c, которые лежат в директории CoreSupport. Сам директорий лежит тут (после разархивации архива):

STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/CMSIS/CM3/CoreSupport

Нам нужно зайти в директорий, где лежат заголовочные файлы тулчейна, и создать в нем два вложенных поддиректория:

$ cd /usr/include/newlib
$ sudo mkdir -p stm32/cmsis

Затем скопировать в директорий cmsis два упомянутых выше файла.

Не забывайте, что копирование ведется в системный директорий, поэтому копирование нужно выполнять из-под root-a!

Далее идём в поддиректорий (разархивированного архива), который называется

STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x

и копируем из него два файла — stm32f10x.h и system_stm32f10x.h. Копируем из (root-ом!) в директорий

 /usr/include/newlib/stm32

Теперь нам нужно слегка подправить файл stm32f10x.h. Открываем (опять-таки из-под root-а) указанный файл в текстовом редакторе и идём на строку 105. Строку нужно задокументировать:

// #define USE_STDPERIPH_DRIVER

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

Далее идём на строку 478. В этой строке нужно уточнить путь к файлу core_cm3.h. После редактирования строка должна выглядеть так:

#include "cmsis/core_cm3.h"

Сохраняем изменения, выходим.

Но это ещё не все. Мужайтесь!

Теперь нам нужно скопировать из архива стартовый файл startup_stm32f10x_md.s, который находится тут:

STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup/gcc_ride7

Вообще, в этом директории аж восемь файлов для разных линеек микроконтроллеров STM32.

У меня сейчас STM32F101CB. Микроконтроллер относится к семейству Medium-density. Этот факт отражён в названии файла в виде суффикса _md.

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

И наконец, нам остается создать самостоятельно или откуда-то скопировать и поместить в директорий проекта еще два файла — управляющий файл для линковщика и, собственно, управляющий файл для проекта. Последний носит название Makefile.

Файл для линковщика у меня называется stm32f101cb_flash.ld. Изначально это был файл для STM32F100RB. Файл был создан фирмой ST Microelectronics, но откуда, из какого проекта или с какого ресурса я его утянул, я уже не помню.

Этот ld-файл, как и файл Makefile, кочует у меня из проекта в проект. Файл не очень сложный, при желании разобраться в нём можно. В общем, я изменяю его в зависимости от микроконтроллера, используемого для того или иного проекта.

По мере своего существования мои ld-файл и Makefile у меня захламились. Файлы обросли ненужными строками, которые не препятствуют успешной компиляции и сборке проектов, но с другой стороны мешают легко работать с этими файлами. Удалить ненужные для проекта строки — мешает земноводная скотина.

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

Ну вот и всё. Финиш!

Теперь можно поднимать любые проекты.

3 responses to “Допиливание тулчейна до кондиции

  1. Строку нужно задокументировать: ))

  2. Не совсем все понял. Предполагается все же использование SPL ???
    Расскажите, пожалуйста, в следующих статьях, как же создать минимально необходимую заготовку для проекта и при этом не используя ни SPL ни HAL

    • Нет-нет, я не предполагаю использовать SPL.

      Я обращаюсь к периферийным модулям МК через их регистры. Для этого в проектах широко использую пару файлов cmsis.[ch] и файл stm32f10x.h.

      Я прибегаю к вызовам всего нескольких вспомогательных функций типа __enable_irq() и NVIC_EnableIRQ(RTC_IRQn).

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

      Конфигурировать порты-вывода вывода я предпочитаю через регистры CRH:CRL. Я отдаю себе отчет, что писать примерно так

      GPIOB->CRH &= ~(GPIO_CRH_MODE9_0 | GPIO_CRH_MODE8_0);
      GPIOB->CRH |= (GPIO_CRH_MODE9_1 | GPIO_CRH_MODE8_1);
      GPIOB->CRH &= ~(GPIO_CRH_CNF9 | GPIO_CRH_CNF8);

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

      В блоге у Железнякова есть красивые макросы типа

      #define BUTTON A, 0, HIGH, INPUT_FLOATING,

      PIN_CONFIGURATION(BUTTON);

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

      Во многих моих проектах имеется файл (-ы) hal.[ch]. В него я пытался выносить уровень абстрагирования от железа. Но потом понял, что «резать» проект на модули нужно не по уровням абстрагирования, а по линиям функционирования. Иначе говоря, «подвал», в котором кипит взаимодействие с регистрами устройств, обрабатываются прерывания и происходит прочая низкоуровневая суета, — не даёт мне каких-то особых преимуществ.

      Вместо «горизонтальной» разбивки проекта на уровни, я сейчас склоняюсь к вертикальному делению проекта на функциональные модули. Ну, например, в проекте имеется некоторый функциональный модуль, который взаимодействует с компьютером через последовательный порт USART. Я создаю для файла, например, comp.[ch] и прописываю в них весь функционал, который так или иначе относится к этому модулю. В файлы попадают такие функции, как initComp(), SendPacket(), обработчик прерывания USART3_IRQHandler(), разные флаги, буферы передачи и приёма, ну и так далее.

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

      Чем такой подход опасен? Он опасен только тем, что модуль не знает о ресурсах МК, используемых другими модулями. Например, модуль управления LCD знать не знает какие порты МК уже заняты.

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

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

      А все эти эти новомодные библиотеки типа SPL, Cube — это всё от Лукавого. Цель одна — увести вас от истины, подсунуть пустышку, развести на бабло. Как говорят, если в схеме не видно где лох, то лох — это вы.

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

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

      Конкретно по SPL и HAL — я их не использую.

      Что же касается продолжения публикаций… Боюсь что-либо обещать. Времена сейчас не простые — как-то не до песен.

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s