Оглавление

Сборка.

Два типа сборки: управляемая (GUI) и не управляемая (make).

Свойства процесса сборки.

Анализатор построения.

Линковка.

Анализ.

Ссылки проекта (Referring Project)

Отключение ненужных предупреждений (Treat Linker Warnings as Errors).

Настройка.

Размещение с помощью malloc (Page Size Allocation for Malloc).

Удаление «мертвого» кода (Dead Code Removal).

Подключение дополнительных объектных файлов (Include Additional Object Files).

Правка линкер-скрипта.

Создать новый.(Generate a New Linker Script)

Изменение существующего линкер-скрипта (Modify Existing Linker Script).

Размещение переменных по определенному адресу (Place variables at specific addresses).

map файл.

Смена скрипта линкера.

Закрепление кода в произвольном месте.

Сообщения компилятора. Разбор частых событий.

Отладка.

Настройка отладки.

Установка STLink Utility – внешняя утилита отладки.

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

Восстановление отладочной конфигурации STLink Utility из расшареных файлов настроек.

Останов, пересбор, запуск — в один кликл. Цепочка: остановить, пересобрать и перезапустить.

Отладка без загрузки. Присоединение к работающей прошивке МК.

Элементы отладки.

Окно со значениями переменных.

Выражения.

Живые выражения.

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

Регистры.

Точки останова.

Останов по условию.

Окно дизасемблера. Disassemble listing

Анализатор неисправностей.

Отладка программы в RAM.

SWV.

Процесс отладки.

Сообщения отладчика. Разбор частых событий.

Error_Handler откуда перешли.

Причины перезагрузок.

Флаг RCC_CSR.

Известные решения некоторых проблем.


Сборка.

Два типа сборки: управляемая (GUI) и не управляемая (make).

Немного важной теории.


Проекты бывают управляемые и не управляемые. Управляемые полностью настраиваются в GUI — всяческих окнах настроек. Не управляемые должны получать настойку из make-файлов. Настройки сборки проекта, относящиеся как к проектам в управляемом режиме, так и к проектам в неуправляемом режиме собираются на панели Target Settings.


@C/C++ Build – Setting - Target Settings

$CONFIGURING THE PROJECT’S BUILD SETTINGS


Любые изменения на вкладке Target Settings будут отражаться в настройках создания проекта, так же будут причиной нового линкер скрипта. Однако библиотеки, заголовки и прочее требуется добавлять вручную. Каждый проект может иметь любое количество конфигураций построения. Это удобно, например, для сжатия или защиты кода в релизной конфигурации. А вот отлаживаться с такой настройкой не всегда возможно.


Открыть проект.

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

$Using an existing project


make-файл можно создать из проекта.

$ Creating a Makefile Project From Existing Code



elf файл откуда появляется

Основным результатом сборки является .elf файл. Этот файл используется для создания файлов прошивок типа .hex и .bin. В каком-то смысле, .elf это тот же бинарник что и .hex, но в формате unix. В частности, STLinkUtility его шить не хочет. Из вторичных целей его бытия, .elf используется для создания красивых полосок и полезных циферок в Build Analiser, Static Stack Analiser и возможно каких то других. В сухом остатке имеем равенство - «сделать прошивку = сделать .elf файл».

$Create a New Build Configuration for Release



.h файлы внешних библиотек не пересканируются,

так как считается что они сторонние и меняться не будут.

$ Include Libraries



Уровень оптимизации.


Его можно задать как отдельно для функций или блоков кода так для файлов или проекта в целом. Выбрать вид оптимизации для блока кода, можно применив такую конструкцию
void __attribute__((optimize("O1"))) myFunc(unsigned char data) {

// The code the needs to have the –O1 optimizing

где O1 — уровень «без оптимизации»

У меня это один из самых спасительных действий в случае глюков отладки. А именно:


$Compiler Optimization


Версия toolchane когда проектом пользуются из разных версий Atollic-a.


При работе с системой контроля версий в команде вариант - «Fixed TrueSTUDIO version» рекомендуется для проекта. Таким образом, все разработчики будут использовать один и тот же набор инструментов, даже если используются разные версии Atollic TrueSTUDIO.

$Changing Toolchain Version



Свойства процесса сборки.

Подключение внешних библиотек.

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


Порядок включения библиотеки в проект. Правой мышью нажать на проекте в который библиотека должна быть включена:


О сборке и пересборке.


Параллельная сборка сильно снижает время сборки.

Количество потоков нужно делать равным количеству ядер на компьютере. Проверил это утверждение — получил 1.5-кратный рост скорости построения.

$Enable Parallel Build



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


Безголовая сборка.

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

$Headless Build


Логи сборок.

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

"D:\PROJECTS\Atollic\01 CEmbProj\.metadata\.plugins\org.eclipse.cdt.ui\CEmbPrj.build.log"

лог последней сборки — то, что видим в окне консоль

"D:\PROJECTS\Atollic\01 CEmbProj\.metadata\.plugins\org.eclipse.cdt.ui\global-build.log"

логи всех сборок

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

$Logging


Для каждого файла можно посмотреть размер его объектного файла

$The Build Size


Сборка одного файла.

Полезная штука — сборка одного файла. В IAR постоянно этим пользовался.

$Building One File


.h файлы внешних библиотек не пересканируются,

так как считается что они сторонние и меняться не будут.

Анализатор построения.

Место, начало, размер блоков памяти, функций, переменных.

Этот вид получается из .elf файла. Если в той же папке лежит еще и .map файл то и из него. Этом случае будет дополнительная информация о чем то.

В анализаторе есть две вкладки.

Чтобы обновить данные в виде, можно кликнуть любой файл и сбилдить проект или выбрать .ela или .o файл в проекте. Инфа не обновляется для PC проектов.


$Build Analyzer


Линковка.

Анализ.

Ссылки проекта (Referring Project)

Иерархия вызовов (Стек).

Можно щелкать на функции и смотреть иерархию вызовов Ctrl+Alt+H. Клевая удобная фича.

Добавлять сторонние библиотеки лучше на вкладке References. Тогда будут верно работать фишки вроде построения иерархии вызовов, поиска и прочее.

$Referring Project

Отключение ненужных предупреждений (Treat Linker Warnings as Errors).

Отключение предупреждений.

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

Настройка.

Размещение с помощью malloc (Page Size Allocation for Malloc).

Размер «куска» для malloc.

Размер «куска» в байтах для функции malloc(). т.е. когда вызываем эту функцию и передаем ей число, то выделяется место именно под N * «размер куска». Доступны, например, 128 или 4096 байт на один «кусок».

Удаление «мертвого» кода (Dead Code Removal).

Штатно он удаляется. По умолчанию галка выставлена и происходит игнорирование не задействованного кода. Мертвый — тот, что есть в исходниках, но не задействован по разным причинам. Например из-за не активных дефайнов.

Подключение дополнительных объектных файлов (Include Additional Object Files).

Подключение внешних объектников без сырцов.

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

Правка линкер-скрипта.

Создать новый.(Generate a New Linker Script)

Связь .ld и .startup.

Содержимое линкер скрипта и его связь со стартап файлом отдельный большой вопрос. Пометим, что создать его можно, как указано в этой главе руководства - Generate a New Linker Script.

Изменение существующего линкер-скрипта (Modify Existing Linker Script).

.ld как, когда создается.

Линкер файл может быть создан двумя путями:

  1. При смене камня спросят об этом и создадут.

  2. Можно принудительно, как в пункте выше.

Размещение переменных по определенному адресу (Place variables at specific addresses).

Размещаем переменные по произвольным адресам.

Первым шагом при размещении переменных по произвольным адресам памяти является создание нового региона памяти с помощью линкер скрипта .ld. Посмотрите пример скрипта содержащего как раз такие регионы


MEMORY

{

FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K

RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 16K

MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K

}


Новый регион можно добавить поправив этот файл. В нашем примере мы добавляем MYVARS регион.


MEMORY

{

FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K

MYVARS (x) : ORIGIN = 0x08010000, LENGTH = 64K

RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K

MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K

}


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


Теперь добавим секцию памяти. Размещаем следующий кусок далее внизу в скрипте, между .data{..} и .bss{..} секциями.


.myvars :

{

*(.myvars*);

} > MYVARS


Это вызовы линкера для размещения всех секций с названиями .myvars* из входящих в .nyvars выходной секции в регионе MYVARS, которые определят стартовый адрес памяти 0x8010000.


Теперь переменные нужно положить в регион.


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

Карта порядка переменных в линкер скрипте.


Вот пример, код может быть такой:


__attribute__((section(".myvars.VERSION_NUMBER"))) uint32_tVERSION_NUMBER;

__attribute__((section(".myvars.CRC"))) uint32_t CRC;

__attribute__((section(".myvars.BUILD_ID"))) uint16_t BUILD_ID;

__attribute__((section(".myvars.OTHER_VAR"))) uint8_t OTHER_VAR;


А затем решить порядок в линкер скрипте при добавлении определенных именованных секций типа:


.myvars :

{

*(.myvars.VERSION_NUMBER)

*(.myvars.CRC)

*(.myvars.BUILD_ID)

*(.myvars*);

} > MYVARS

map файл.

Формируется по умолчанию. Вроде бы считается более полным, чем elf.

В блоке Linker script and memory map содержится разбивка памяти для каждого файла.


Разберем на примере.

.text           0x00000000     0xf080
 *(.text*)
 .text          0x00000000      0x310 /cygdrive/c/Program Files (x86)/FTDI/FT90x Toolchain/Toolchain/tools/bin/../lib/gcc/ft32-elf/5.0.0/crti-hw.o
                0x00000000                _start
                0x00000090                _exithook
                0x000000fc                _exit
                0x0000030c                nullvector
                0x00000310                __gxx_personality_sj0
 .text.StaticFunc
                0x00000310       0x20 ./main.o
 .text.GlobalFunc
                0x00000330       0x20 ./main.o
                0x00000330                GlobalFunc
 .text.main     0x00000350       0x44 ./main.o
                0x00000350                main
 .text.StaticFunc
                0x00000394       0x38 ./test.o
 .text.Test     0x000003cc       0x14 ./test.o
                0x000003cc                Test
                ....

.text начинается с 0x00000000 и длина его 0xF080 байт.

Первый модуль — это файл ctri-hw.o и в нем есть 4 глобальные функции.

Команда --ffunction-sections удостоверится что каждая функция скомпилирована в раздельные секции, которые позволяют линкеру (ia -Wl,--gc-sections) позднее удалить некоторые функции которые не используются.


Некоторая информация о .data и .bss сегментах. Однако статичные символы в bss сегментах отсутствуют.





Смена скрипта линкера.



Закрепление кода в произвольном месте.

Закрепляет код в определенной части памяти программ.

Поможет, например, при работе с загрузчиком. Опция компилятора fPIE включает этот режим. Удостоверится в указателе стека.

$Position Independent Code

Сообщения компилятора. Разбор частых событий.

сообщение

перевод

Значение и описание. Когда может возникнуть.

Безобидные но иногда докучные

unused variable 'NameOfFunction'

Переменная не используется

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

Problems encountered during text search.

Проблемы, возникшие во время текстового поиска.

Обычно в расшифровке повторяющиеся причины

File 'name_file.c' has been skipped, problem while reading:

для решения можно попробовать

  • В окне Project Explorer может видна папка которой в реальности нет — удалить её




опасные

expected declaration or statement at end of input

ожидаемое объявление или утверждение в конце ввода

ожидается?


  • Не хватает закрывающей скобки. Указывает на строку гораздо ниже места «авварии»

object has been skipped, problem while reading

объект был пропущен, проблема при чтении


implicit declaration of function 'NameOfFunction'

неявное объявление функции NameOfFoonctions

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

incompatible types when assigning to type 'SPI_HandleTypeDef * {aka struct __SPI_HandleTypeDef *}' from type 'SPIDrv {aka struct <anonymous>}' Driver.c

несовместимые типы при назначении этого типа.(он же вот какой тип) из типа

Когда тупо пытаемся присвоить значение из переменной одного типа в переменную другого типа.

passing argument 1 of 'SPIInit' from incompatible pointer type [-Wincompatible-pointer-types] my_main.c

передача аргумента 1 'SPIInit' из несовместимого типа указателя [-Wincompatible-pointer-types] my_main.c / имя_какойто_папки / Users / Src / common line 102 Проблема C / C ++


passing argument 2 of [NameFunction] discards 'const' qualifier from pointer target type

при передаче аргумента 2 из функции такой то отбрасывается квалификатор 'const' из целевого типа указателя





уровень опасности не ясен

assignment makes integer from pointer without a cast

присвоение делает целое число из указателя без приведения


критичные — без них не собирается

error: duplicate case value

Повторяющееся значение кейса


pointer targets in passing argument 2 of 'strcat' differ in signedness

вt

целевые объекты указателя при передаче аргумента 2 'strcat' отличаются по знаку
вm
целевые указатели при передаче аргумента 2 функции отличаются по значению

передавался тип uint8_t в параметр с типом char[]

Отладка.

Настройка отладки.

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

__attribute__((optimize("O0")))

Установка STLink Utility – внешняя утилита отладки.

В больших проектах перестает работать предустановленный отладчик. В Atollic-e это правило работает всегда, только мелкие проекты удается отлаживать. В CUBE IDE не сталкивался с подобными проблемами.


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


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

Например может понадобиться после формирования дефолтной конфигурации кубом. В этом случае создается файл формата NameProject.elf.launch — это и есть отладочная конфигурация. Она содержит настройки и ссылки на .elf файл.

Восстановление отладочной конфигурации STLink Utility из расшареных файлов настроек.

Сохранение настроек в файл.

Восстановление.

Останов, пересбор, запуск — в один кликл. Цепочка: остановить, пересобрать и перезапустить.

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

$Terminate, Rebuild and Re-launch

Отладка без загрузки. Присоединение к работающей прошивке МК.

Элементы отладки.

Окно со значениями переменных.


Выражения.

Смотрим переменные.

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


$ Expressions

Живые выражения.

Смотрим переменные в реальном времени.

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


$ Live Expressions

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

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


$ Local Variables

Регистры.

В этом виде показаны регистры железа. Можно использовать фильтр по имени. Можно переключать системы счислений. Удобная маска для отображения битов. Кнопка RD активирует силовое чтение, если ReadAction атрибут активен все равно прочитает.

Содержимое и структура вида зависит от файла .svd. Чтобы все работало должен быть хороший Device File. По умолчанию он такой есть. Рекомендуют использовать самый свежий.

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


$ SFRs

Точки останова.

Точки останова делятся на железные и софтовые. Железные зависят от реализации. ARM 7/9 = 2 штуки, Cortex M = 4 для 6? штук. ST-Link GDB сервер может использовать только железные точки останова и их количество ограничено шестью.

$Breakpoints

Останов по условию.

Поставьте точку останова и правой мышью откройте свойства. Breakpoint Properties – Common. В поле Conditiotion: поставить выражения типа [название переменной] == [значение останова]


Можно использовать даже в RTOS если в его ядре есть переменная на которой можно проверять условие точки останова. Перейти можно нажав правой мышью по полосе точек останова и выбрав Breakpoint Properties


$Conditional Breakpoint


Окно дизасемблера. Disassemble listing

Обычно, при отладке можно ходить только по окну редактора. Для того чтобы ходить по дизассемблеру нужно нажать спецкнопку i→

$Disassembly View


Открывает окно ассемблерного кода

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


$Disassemble/List Object and Elf Files


Анализатор неисправностей.

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


обращение к неправильному месту в памяти

• обращение к ячейкам памяти на смещенных границах (не понял чем отличается от предыдущего)

• выполнение неизвестной инструкции

• деление на ноль


$ Fault Analyzer



Отладка программы в RAM.

Можно производить любым HW отладчиком, правда есть два ограничения.

• Обычно в МК рам меньше флеша, поэтому всю прогу не сохранишь в нем.

• Cortex M0 Не возможно использовать прерывания когда весь код лежит в рам.

• Надо править gdb script.


$Debugging Code in RAM

SWV.

Дополнительные моменты.


Для использования системного анализа и отладки в реальном времени процессоров совместимых с ARM, взаимодействуют несколько технологий. SWV последовательный проводной обзор, SWD последовательная проводная отладка и SWO последовательный проводной вывод. Эти технологии являются частью ядра отладчика ARM и будут освещены ниже.


SWD это порт отладки подобный JTAG, и позволяющий выполнять отладочные операции (запуск, останов,однократный останов), но с несколькими точками. Он заменяет разъем JTAG на 2-контактный интерфейс (один тактовый вывод и один двунаправленный вывод данных). SWD порт сам не обеспечивает трассировку в реальном времени, таким образом расширая отладочный интерфейс на 3 ноги. Сочетание ног SWD и SWO включает SWV отладку реального времени в случае ARM процессора.


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


SWO нога может быть задействована в сочетании с SWD и использована процессором для отдачи данных уже в реальном времени

Процесс отладки.

Сообщения отладчика. Разбор частых событий.

сообщение

перевод

Значение и описание. Когда может возникнуть.

Program received signal SIGTRAP, Trace/breakpoint trap.


При запуске ПО через отладку.

Это описание https://stackoverflow.com/questions/9809413/program-received-signal-sigtrap-trace-breakpoint-trap оказалось правдивым. PC просто достиг некоей точки останова. Перед этим баловался с точками останова по значению в переменных.

  • Лечится

    • Полная замена воркспейса помогла

    • Снятием галки/удалнием виновной точки остаова.

Error in initializing ST-Link device.

Reason: (1) Failed to connect to device. Please check power and cabling to target.


При установленной защите от чтения прошивки.



При внезапной остановке отладки, реально gdb сервер может ее продолжать. в этом случае все последующие операции с отладчиком могут приводить к глюкам. для проверки такого состоянии удостовериться что нет запущенного процесса « arm-atollic-eabi-gdb.exe»



Error_Handler откуда перешли.

?

смотрим lr.

Адрес в disassembly

Причины перезагрузок.

Флаг RCC_CSR.

Флаг RCC_CSR нужно чистить т. к. он может сохранять старые значения.


Для того, чтобы понять что перезагрузка произошла по срабатыванию IWDG (да и WWDG) нужно следить за регистром Control/status register (RCC_CSR). Там есть биты IWDG RSTF (WWDG RSTF). Если он выставлен в 1, то перезагрузка произошла по нему. Чтобы его сбросить нужно в этом же регистре в бит RMVF записать 1 (как я понял, она обнуляет весь регистр).



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

Читать можно как можно быстрее сразу после заупска, до инициализации какойто другой перифирии.

Известные решения некоторых проблем.



кроме выбора оптимизации для проекта или файлов можно выбрать оптимизацию для блока кода применив такую конструкцию:
void __attribute__((optimize("O1"))) myFunc(unsigned char data) {

// The code the needs to have the –O1 optimizing




v2.