Вы находитесь на странице: 1из 890

Руководство разработчика

по семейству
процессоров Cortex-M
Эта страница, намеренно
оставленная незаполненный
Руководство разработчика
по семейству
процессоров Cortex-M
Второй выпуск

Trevor Martin

АМСТЕРДАМ • БОСТОН • ГЕЙДЕЛЬБЕРГ • ЛОНДОН


НЬЮ-ЙОРК • ОКСФОРД • ПАРИЖ • САН-ДИЕГО
САН-ФРАНЦИСКО • СИНГАПУР • СИДНЕЙ • ТОКИО
Newnes является отпечатком Elsevier
Newnes является отпечатком Elsevier
Бульвар, Langford Lane, Кидлингтон, Оксфорд OX5 1GB,
Великобритания Хэмпшир Street, 50, 5-й этаж, Cambridge,
Массачусетс 02139, США
Авторское право r 2016, 2013 Elsevier Ltd. Все права защищены.

Никакая часть этой публикации не может быть воспроизведена или передана в любой форме или каким-либо образом,
электронная или механическая, включая фотокопирование, запись, или любую систему хранения информации и
поисковую систему, без разрешения в письменной форме от издателя. Детали о том, как искать разрешение,
дополнительную информацию о политиках полномочий Издателя и наших расположениях с организациями, такими
как Центр по проверке авторских прав и Агентство по Лицензированию Авторского права, могут быть найдены в
нашем веб-сайте: www.elsevier.com/permissions.

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

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

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

Данные каталогизации в публикации Библиотеки Конгресса


Запись каталога для этой книги доступна из Библиотеки Конгресса.

ISBN: 978-0-08-100629-0

Для получения информации обо всем


Newnes публикации посещают наш веб-
сайт в https://www.elsevier.com/

Издатель: Joe Hayton


Редактор приобретения: Tim Pitts
Редакционный менеджер проектов: Charlotte Kent
Производственный менеджер проектов: Julie-Ann Stansfield
Разработчик: Mark Rogers
Набранный MPS Limited, Ченнаи, Индия
Моей жене Sarah и моим родителям Ann и
Maurice
Эта страница, намеренно
оставленная незаполненный
Содержание
Предисловие ..................................................................................................... xvii
Предисловие ...................................................................................................... xix
Список благодарностей .................................................................................... xxi

Глава 1: введение в семейство процессоров Cortex-M ............................... 1


Профили коры..................................................................................................... 1
Кора-M3 ............................................................................................................. 3
Усовершенствованные архитектурные функции ................................................... 7
Кора-M0 ............................................................................................................ 10
Кора-M01 .......................................................................................................... 13
Кора-M4 ............................................................................................................ 16
Инструкции по DSP ............................................................................................ 18
Кора-M7 ............................................................................................................ 19
Заключение ........................................................................................................ 21

Глава 2: разработка программного обеспечения для семейства Cortex-M


...............................................................................................................................23
Введение ............................................................................................................ 23
Комплект разработчика микроконтроллера Keil .................................................. 23
Программные пакеты ......................................................................................... 24
Учебные упражнения ......................................................................................... 24
Установка .......................................................................................................... 25
Упражнение 2.1 Создание первой программы ..................................................... 27
Проект Blinky..................................................................................................... 28
Конфигурация проекта ....................................................................................... 52
Упражнение 2.2 Аппаратная отладка .................................................................. 65
Заключение ........................................................................................................ 69

Глава 3: архитектура Cortex-M.........................................................................71


Введение ............................................................................................................ 71
Система команд Cortex-M................................................................................... 71
Модель программиста и регистры ЦП ................................................................. 72
Регистр состояния программы ............................................................................ 74

vii
Содержание
viii

Q бит и влажные инструкции по математике ....................................................... 75


Прерывания и инструкции по мультициклу ......................................................... 76
Условное выполнение — если затем блоки.......................................................... 76
Упражнение 3.1 Влажная математика и условное выполнение ............................. 78
Карта распределения памяти Cortex-M и шины ................................................... 84
Буфер записи ...................................................................................................... 87
Инструкции по барьеру памяти ........................................................................... 87
Системный блок управления ............................................................................... 87
Побитовая обработка .......................................................................................... 89
Осуществите соединение на 3,2 бита ................................................................... 91
Специализированные инструкции по побитовой обработке ................................. 92
Таймер SysTick................................................................................................... 93
Контроллер прерываний вложенного вектора ...................................................... 94
Рабочие режимы................................................................................................. 94
Обработка прерываний — запись ........................................................................ 95
Обработка прерываний — выход ........................................................................ 96
Обработка прерываний — важный выход! .......................................................... 97
Упражнение 3.3 Прерывание SysTick .................................................................. 97
Исключения процессора Cortex-M .................................................................... 102
Отказ использования ................................................................................. 103
Отказ шины .............................................................................................. 103
Отказ диспетчера памяти........................................................................... 104
Серьезный отказ........................................................................................ 104
Включение исключений отказа .................................................................. 104
Приоритет и вытеснение ................................................................................... 104
Группы и подгруппа ......................................................................................... 106
Управление приоритетами во время выполнения ............................................... 107
Модель исключения ......................................................................................... 107
Объединение в цепочку хвоста NVIC......................................................... 108
NVIC, поздно прибывающий ..................................................................... 109
NVIC вытеснение POP .............................................................................. 110
Упражнение 3.3 Работа с несколькими прерываниями ....................................... 110
Поддержка загрузчика ...................................................................................... 115
Упражнение 3.4 Загрузчик ................................................................................ 116
Управление питанием ....................................................................................... 121
Переход к режимам низкой мощности ....................................................... 123
Конфигурирование режимов низкой мощности .......................................... 123
Упражнение 3.3 Режимы низкой мощности................................................ 124
Содержание ix

Перемещение от коры-M3 ................................................................................ 126


Кора-M4 .......................................................................................................... 127
Кора-M0 .......................................................................................................... 127
Кора-M01 ........................................................................................................ 129
Заключение ...................................................................................................... 130

Глава 4: стандарт программного интерфейса микроконтроллера коры


............................................................................................................................ 131
Введение .......................................................................................................... 131
Спецификации CMSIS ...................................................................................... 133
CMSIS-ядро ..................................................................................................... 134
CMSIS-RTOS ................................................................................................... 134
CMSIS-DSP ...................................................................................................... 135
CMSIS-драйвер ................................................................................................ 135
CMSIS-SVD и DAP .......................................................................................... 135
CMSIS-пакет .................................................................................................... 136
Основы CMSIS ................................................................................................. 136
Кодирование правил......................................................................................... 137
MISRA-C ......................................................................................................... 137
CMSIS-базовая структура ................................................................................. 139
Код запуска ...................................................................................................... 140
Системный код................................................................................................. 141
Заголовочный файл устройства ......................................................................... 141
CMSIS-базовые заголовочные файлы ................................................................ 143
Прерывания и исключения ............................................................................... 144
Упражнение 4.1 CMSIS и пользовательское сравнение кода .............................. 147
CMSIS-базовый доступ регистра ............................................................... 148
CMSIS-ядро-процессора внутренние инструкции .............................................. 149
Упражнение 4.2 Внутренняя побитовая обработка............................................. 150
CMSIS-SIMD Intrinsics ..................................................................................... 151
CMSIS-базовые функции отладки ..................................................................... 152
Аппаратная точка останова ....................................................................... 152
Трассировка инструментария .................................................................... 152
CMSIS-базовые функции для Corex-M7 ............................................................ 153
Заключение ...................................................................................................... 153

Глава 5: функции передовой архитектуры ................................................. 155


Введение .......................................................................................................... 155
Рабочие режимы процессора коры .................................................................... 155
x
Содержан
ие

Упражнение 5.1 Конфигурация стека ................................................................ 158


Вызов контролера............................................................................................. 161
Упражнение 5.2 Вызов контролера.................................................................... 163
Исключение PEND_SV ..................................................................................... 166
Пример Pend_SV .............................................................................................. 167
Межпроцессорные события .............................................................................. 169
Эксклюзивный доступ ...................................................................................... 169
Упражнение 5.4 Эксклюзивный доступ ............................................................. 172
Единица защиты памяти ................................................................................... 173
Конфигурирование MPU................................................................................... 175
Упражнение 5.5 Конфигурация MPU ................................................................ 178
Подобласти MPU.............................................................................................. 184
Ограничения MPU ............................................................................................ 185
AHB облегченный шинный интерфейс .............................................................. 185
Заключение ...................................................................................................... 187

Глава 6: процессор коры-M7 ......................................................................... 189


Суперскалярная архитектура ............................................................................ 190
Предсказание ветвлений ................................................................................... 191
Упражнение 6.1 Простой цикл .......................................................................... 191
Структура шины............................................................................................... 193
Иерархия памяти .............................................................................................. 195
Упражнение 6.2 Определение местоположения кода и данных в TCM ............... 197
Блоки кэш-памяти ............................................................................................ 199
Операция кэша ................................................................................................. 200
Кэш инструкции ............................................................................................... 203
Упражнение 6.3 Кэш инструкции ...................................................................... 203
Кэш данных ..................................................................................................... 204
Барьеры памяти ................................................................................................ 205
Упражнение 6.4 Кэш данных в качестве примера .............................................. 206
Единица защиты памяти и конфигурация кэша.................................................. 206
Политика кэша ................................................................................................. 207
Управление кэшем данных ............................................................................... 209
Выключите кэш ........................................................................................ 209
Отключите кэширование по региону системной памяти ............................. 209
Измените политику кэша для региона системной памяти ........................... 209
Используйте функции управления кэшем для гарантии когерентности ....... 209
Кси содержания

Упражнение 6.5 Конфигурация кэша данных .................................................... 209


Сопроцессор для операций с плавающей точкой двойной точности ................... 213
Функциональная безопасность.......................................................................... 214
Функции безопасности коры-M7....................................................................... 215
Документация безопасности ............................................................................. 215
Средства разработки ......................................................................................... 216
Заключение ...................................................................................................... 216

Глава 7: отладка с CoreSight ......................................................................... 217


Введение .......................................................................................................... 217
Аппаратные средства CoreSight ........................................................................ 219
Аппаратные средства отладчика ....................................................................... 220
Архитектура отладки CoreSight......................................................................... 221
Упражнение 7.1 Отладка CoreSight ................................................................... 221
Аппаратная конфигурация ................................................................................ 222
Конфигурация программного обеспечения ........................................................ 223
Ограничения отладки ....................................................................................... 229
Трассировка инструментария............................................................................ 229
Упражнение 7.2 Установка ITM ........................................................................ 230
Системная поддержка отладки блока управления .............................................. 233
Отслеживание отказов ...................................................................................... 234
Упражнение 7.3 Исключения отказа процессора................................................ 235
Трассировка инструкции со встроенной макроячейкой трассировки .................. 239
Упражнение 7.4 Использование трассировки ETM ............................................ 241
CMSIS-DAP ..................................................................................................... 244
Кора-M01 MTB................................................................................................ 245
Упражнение 7.5 Микро буфер трассировки ....................................................... 246
Системное описание средства просмотра CMSIS ............................................... 248
Упражнение 7.6 CMSIS-SVD ............................................................................ 249
Сводка функций отладки заключения ............................................................... 254

Глава 8: практический DSP для коры-M4 и коры-M7 ................................ 255


Введение .......................................................................................................... 255
Аппаратные средства FPU ................................................................................ 255
Интеграция FPU ............................................................................................... 256
Регистры FPU................................................................................................... 257
Кора-M7 FPU ................................................................................................... 258
Содержани
е xii

Включение FPU................................................................................................ 258


Исключения и FPU ........................................................................................... 258
Использование FPU .......................................................................................... 259
Упражнение 8.1 Сопроцессор для операций с плавающей точкой ...................... 259
Cortex-M4/M7 DSP и Инструкции SIMD ........................................................... 265
Упражнение 8.2 Инструкции SIMD ................................................................... 269
Упражнение 8.3 Оптимизация алгоритмов DSP ................................................. 272
Библиотека CMSIS-DSP.................................................................................... 279
Библиотечные функции CMSIS-DSP ................................................................. 279
Упражнение 8.3 Пользование библиотекой CMSIS-DSP .................................... 280
Методы обработки данных DSP ........................................................................ 285
Упражнение 8.4 Фильтр FIR с обработкой блока ............................................... 286
DSP фиксированной точки с числами Q ............................................................ 289
Упражнение 8.5 Фиксированная точка FFT преобразовывает ............................. 290
Заключение ...................................................................................................... 292

Глава 9: стандартное реальное время программного интерфейса


микроконтроллера коры
Операционная система ................................................................................... 293
Введение .......................................................................................................... 293
Первые шаги с CMSIS-RTOS ............................................................................ 294
Доступ к API CMSIS-RTOS .............................................................................. 294
Потоки ............................................................................................................. 295
Запуск RTOS .................................................................................................... 296
Упражнение 9.1 первый проект CMSIS-RTOS ................................................... 297
Создание потоков ............................................................................................. 306
Упражнение 9.2 Создание и управление потоками............................................. 307
Управление потоком и приоритет ..................................................................... 310
Упражнение 9.3 Создание и управление потоками II ......................................... 311
Несколько экземпляров .................................................................................... 312
Упражнение 9.4 Несколько экземпляров потока ................................................ 313
Тайм-менеджмент ............................................................................................ 314
Задержка .......................................................................................................... 314
Ожидание события ........................................................................................... 315
Упражнение 9.5 Тайм-менеджмент ................................................................... 315
Виртуальные таймеры ...................................................................................... 316
Упражнение 9.6 Виртуальный таймер ............................................................... 317
Задержки подмиллисекунды ............................................................................. 319
Неактивный демон ........................................................................................... 319
Содержание xiii

Упражнение 9.7 Неактивный поток ................................................................... 320


Коммуникация межпотока ................................................................................ 323
Сигналы ........................................................................................................... 323
Сигналы упражнения 9.8 .................................................................................. 324
Семафоры ........................................................................................................ 325
Упражнение 9.9 Семафорная передача сигналов................................................ 326
Использование семафоров ................................................................................ 328
Передача сигналов ........................................................................................... 328
Мультиплексирование ...................................................................................... 329
Упражнение 9.10 Мультиплексирование ........................................................... 329
Рандеву ............................................................................................................ 330
Упражнение 9.11 Рандеву ................................................................................. 330
Турникет барьера ............................................................................................. 331
Упражнение 9.12 Семафорный барьер............................................................... 332
Семафорные протесты ...................................................................................... 332
Взаимное исключение ...................................................................................... 333
Упражнение 9.13 Взаимное исключение ........................................................... 333
Взаимоисключающие протесты ........................................................................ 335
Обмен данными ............................................................................................... 335
Очередь сообщений .......................................................................................... 337
Упражнение 9.14 Очередь сообщений ............................................................... 338
Пул памяти ...................................................................................................... 339
Упражнение 9.15 Пул памяти ........................................................................... 340
Почтовая очередь ............................................................................................. 341
Упражнение 9.16 Почтовый ящик ..................................................................... 342
Конфигурация .................................................................................................. 343
Определение потока ......................................................................................... 344
Поддержка отладки ядра................................................................................... 344
Системная конфигурация таймера .................................................................... 346
Конфигурация интервала .................................................................................. 346
Планирование опций ........................................................................................ 346
Упреждающее планирование..................................................................... 347
Циклическое планирование ....................................................................... 347
Циклическое упреждающее планирование ................................................. 348
Кооперативная многозадачность ............................................................... 348
Исходный код RTX .......................................................................................... 348
Лицензия RTX.................................................................................................. 349
Заключение ...................................................................................................... 350
Содержани
е xiv

Глава 10: методы RTOS ................................................................................. 351


Введение .......................................................................................................... 351
RTOS и прерывания.......................................................................................... 351
Обработка прерываний RTOS ........................................................................... 352
Упражнение 10.1 Обработка осуществления прерывания RTOS ......................... 354
Пользовательские функции супервизора ........................................................... 355
Упражнение 10.2 RTOS и пользователь исключения SVC .................................. 356
Управление питанием ....................................................................................... 358
Первые шаги управления питанием................................................................... 358
Стратегия управления питанием ....................................................................... 360
Сторожевое управление .................................................................................... 362
Интеграция ISRs............................................................................................... 363
Упражнение 10.3 Питание и сторожевое управление ......................................... 364
Барьер запуска.................................................................................................. 369
Разработка в течение реального времени ........................................................... 370
Буферизация методов — двойной или кольцевой буфер ............................. 370
Буферизация очереди сообщений FIFO методов ......................................... 371
Балансировка загрузки .............................................................................. 375
Упражнение 10.4 Реальное время RTX .............................................................. 375
Взваливание на себя загрузки, контроллера прямого доступа к памяти............... 380
Разработка для отладки..................................................................................... 381
Упражнение 10.5 Диагностика во время выполнения ......................................... 382
Заключение ...................................................................................................... 385

Глава 11: разработка через тестирование ................................................. 387


Введение .......................................................................................................... 387
Цикл разработки TDD ............................................................................... 389
Среда тестирования................................................................................... 389
Автоматизация тестирования..................................................................... 389
Установка платформы единицы ........................................................................ 390
Упражнение 11.1 Разработка через тестирование............................................... 390
Добавление среды тестирования единицы.................................................. 391
Конфигурирование целей сборки проекта .................................................. 393
Добавление тестов .................................................................................... 397
Автоматизация цикла TDD ........................................................................ 399
Тестирование потоков RTOS ............................................................................ 402
Упражнение 11.2 Тестирование потоков RTOS.................................................. 404
Отделение низкоуровневых функций ......................................................... 405
Тестирование прерываний ......................................................................... 406
Содержание xv

Упражнение 11.3 Тестирование с прерываниями ............................................... 407


Заключение ...................................................................................................... 409

Глава 12: компоненты программного обеспечения .................................. 411


Введение .......................................................................................................... 411
Драйвер CMSIS ................................................................................................ 412
Драйвер CMSIS API .................................................................................. 413
Упражнение 12.1 CMSIS-драйвер .............................................................. 414
Проверка драйвера ........................................................................................... 419
Упражнение 12.2 Проверка драйвера ......................................................... 419
Разработка компонента программного обеспечения........................................... 424
Упражнение 12.3 Компонент GPS.............................................................. 424
Создание программного пакета ......................................................................... 427
Структура программного пакета ................................................................ 427
Software Pack Utilities ................................................................................ 428
Мастер конфигурации ...................................................................................... 439
Упражнение 12.4 Мастер конфигурации .................................................... 440
Развертывание компонентов программного обеспечения ................................... 443
Заключение ...................................................................................................... 444

Глава 13: ARMv8-M ......................................................................................... 445


Введение .......................................................................................................... 445
Общие архитектурные улучшения .................................................................... 446
Базовые улучшения ARMv8.............................................................................. 446
Улучшения магистрали ARMv8-M.................................................................... 447
TrustZone ......................................................................................................... 448
Прерывания и исключения ........................................................................ 451
Разработка программного обеспечения ............................................................. 454
Компилятор .............................................................................................. 454
Операционная система реального времени................................................. 454
Отладчик .................................................................................................. 454
Стандарт программного интерфейса микроконтроллера коры .................... 455
Заключение ...................................................................................................... 455

Приложение ...................................................................................................... 457


Индекс................................................................................................................ 461
Эта страница, намеренно
оставленная незаполненный
Предисловие

Когда эта книга была сначала опубликована в 2013, ARM питал тихий оборот
во встроенной промышленности. Во время запуска второго выпуска ARM является
ясно архитектурой победы с более чем 3 000 Коры ARM основанные на процессоре
микроконтроллеры на рынке и непараллельном росте.

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


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

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


программного обеспечения в последние годы, была сложностью. Требование для
лучшей возможности соединения, графических интерфейсов, и выше
вычислительная мощность в оконечном приложении была подобрана увеличенной
функциональностью в самих микроконтроллерах, и конечно, в размере программного
обеспечения, работающего на них. Чтобы помочь разработчикам справиться с этим
Cortex-M сложности, процессоры включают усовершенствованную отладку и
прослеживают возможности, которые используются профессиональными средствами
разработки, такими как Keil MDK. Однако это недостаточно: для хранения затрат на
разработку программного обеспечения при повторном использовании программного
обеспечения управления, стал обязательным. Поэтому ARM сотрудничал со своей
экосистемой инструментов и поставщиков RTOS для создания стандарта CMSIS,
который включает эффективное портирование стандартного промежуточного
программного обеспечения и заказного программного обеспечения между
несколькими наборами инструментальных средств и микроконтроллерами.

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


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

xvii
Предисловие
xviii

Ядра ARM. Еще раз методология программного обеспечения, средства разработки


и стандарты имеют решающую роль для проигрывания.

Я знал Trevor в течение прошлых 10 лет, в течение которых он помог сотням


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

Javier Orensanz
Предисловие
ARM сначала представил семейство процессоров Cortex-M в 2004. С тех пор
процессор Cortex-M получил широкое принятие как хорошо масштабируемый
процессор общего назначения для маленьких микроконтроллеров. Во время записи
существует хорошо более чем 3 000 стандартных устройств, которые показывают
процессор Cortex-M. Они доступны от многих ведущих полупроводниковых
поставщиков, и темп разработки не показывает знака замедления. Семейство
процессоров Cortex-M теперь установило себя как промышленный стандарт. Как
таковой знание того, как использовать его, становится необходимым навыком для
профессиональных разработчиков. Эта книга предназначается, поскольку и введение
в процессор Cortex-M и руководство по методам раньше разрабатывали прикладное
программное обеспечение для работы ее. Книга записана как учебное руководство, и
главы предназначаются, чтобы работаться через в порядке. Каждая глава содержит
много примеров, которые представляют ключевые принципы, обрисованные в общих
чертах в этой книге с помощью минимального объема кода. Каждый пример
разработан, чтобы быть созданным с пробной версией Комплекта разработчика
Микроконтроллера для ARM. Эти примеры разработаны для выполнения в средстве
моделирования, таким образом, можно использовать большинство рук на примеры в
этой книге без потребности в любых дополнительных аппаратных средствах.

Глава 1 “Введение в Семейство процессоров Cortex-M”: Обеспечивает введение и


обзор функции каждого процессора в семействе Cortex-M.

Глава 2 “Разработка программного обеспечения для Семейства Cortex-M”:


Представляет Вас основам создания проекта “C” для процессора Cortex-M.

Глава 3 “Архитектура Cortex-M”: Предоставляет архитектурное описание Коры-M3 и


ее различий к другим процессорам Cortex-M.

Глава 4 “Стандарт Программного интерфейса Микроконтроллера Коры”:


Представляет Стандарт программного интерфейса микроконтроллера коры
(CMSIS), программируя спецификации для процессоров Cortex-M.

Глава 5 “Функции Передовой архитектуры”: Расширяет Главу 3 “Архитектура


Cortex-M” путем представления большего количества расширенных функций
архитектуры Cortex-M.

Глава 6 “Процессор Коры-M7”: В этой главе мы смотрим на процессор Cortex-


M7, который представляет более сложную модель памяти и структуру шины.
xix
Предислов
ие xx

Глава 7 “Отладка с CoreSight”: Предоставляет описание системы отладки


CoreSight и ее функций в реальном времени.

Глава 8 “Практический DSP для Коры-M4 и Коры-M7”: Смотрят математика и


поддержка обработки цифровых сигналов (DSP), доступная на Коре-M4 и как
разработать приложения DSP в реальном времени.

Глава 9 “Стандартная Операционная система реального времени Программного


интерфейса Микроконтроллера Коры”: Представляет использование
операционной системы реального времени (RTOS) на процессоре Cortex-M.

Глава 10 “Методы RTOS”: Эта глава исследует некоторые реальные методы,


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

Глава 11 "Test Driven Development": В этой главе мы смотрим на то, как использовать
среду тестирования разработчика под названием Единица с Основанным на Cortex-M
микроконтроллером.

Глава 12 "Software Components": стандарты CMSIS, представленные в Главе 4


“Стандарт Программного интерфейса Микроконтроллера Коры”, помогают
стандартизировать, как код “C” написан для микроконтроллера Cortex-M. Эта глава
смотрит на то, как разработать компоненты программного обеспечения и как
упаковать их так, они могут быть легко распределены и снова использованы.

Глава 13 "ARMv8-M": последняя глава представляет введение в новую архитектуру


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

Эта книга полезна для студентов, новичков и опытных и опытных разработчиков


одинаково. Однако предполагается, что у Вас есть элементарные знания того, как
использовать микроконтроллеры и что Вы знакомы с программированием на языке
“C”. Кроме того, полезно иметь элементарные знания о том, как использовать
отладчик µVision и IDE.
Список благодарностей
Я хотел бы благодарить Charlotte Kent, и Tim Pitts из Elsevier для помощи производят
книгу и Joseph Yui, Richard York и Ian Johnson ARM для их сотрудничества. Я также
хотел бы быть благодарным за то, что Tanya Wrycraft корректирует и полезный совет.

xxi
Эта страница, намеренно
оставленная незаполненный
CHPTER1

Введение в Cortex-M
Семейство процессоров

Так как первый выпуск этой книги был опубликован в 2013, число Кремниевых
Поставщиков, обеспечивающих Основанные на Cortex-M устройства, почти удвоилось, и
число вариантов микроконтроллера - теперь хорошо более чем 3 000 и продолжает
увеличиваться. Десятилетие назад я был знаком с основными характеристиками всех
основных используемых микроконтроллеров Cortex-M. Сегодня я изо всех сил пытаюсь не
отставать от диапазона доступных устройств, могла быть старость, конечно, но Вы
получаете изображение. В этой книге мы собираемся узнать о самом процессоре Cortex-M
и также методах программного обеспечения, требуемых разработать эффективный и
эффективный код приложения. Эта книга расположена как учебное руководство и лучше
работать через него глава главой. Каждая глава содержит много рук на примеры, и Вы
будете учиться намного больше путем фактического выполнения примеров.

Профили коры
В 2004 ARM представил свое новое семейство Коры процессоров. Семейство
процессоров Коры подразделено на три различных профиля. Каждый профиль
оптимизирован для различных сегментов приложений встроенных систем (Рис. 1.1).

Рисунок 1.1
Семейство процессоров Коры имеет три Приложения профилей, Реальное время и
Микроконтроллер.
Руководство разработчика по семейству процессоров Cortex-M.
DOI: http://dx.doi.org/10.1016/B978-0-08-100629-0.00001-3 1
© 2016 Elsevier Ltd. Все права защищены.
2 Главы 1

Профиль Коры-A был разработан как процессор приложения высшего класса.


Процессоры коры-A способны к выполнению многофункциональных операционных
систем, таких как Победа RT и Linux. Ключевые приложения для Коры-A являются
бытовой электроникой, такой как смартфоны, планшетные компьютеры и абонентские
установки. Вторым профилем Коры является Cortex-R. Это - профиль в реальном
времени, который поставляет высокоэффективный процессор, который является
основой специализированного устройства. Очень часто процессор Cortex-R является
частью дизайна “системы на микросхеме”, который фокусируется на определенной
задаче, такой как управление жестким диском (HDD), автомобильное управление
механизмом и медицинские устройства. Заключительным профилем является Cortex-M
или профиль микроконтроллера. В отличие от более ранних центральных процессоров
ARM, семейство процессоров Cortex-M было специально разработано для
использования в маленьком микроконтроллере. Процессор Cortex-M в настоящее
время прибывает в шесть вариантов: кора-M0, Кора-M01, Кора-M1, Кора-M3, Кора-
M4 и Кора-M7. Кора-M0 и Кора-M01 являются самыми маленькими процессорами в
семействе. Они позволяют кремниевым производителям разрабатывать недорогие
устройства низкой мощности, которые могут заменить существующие 8-разрядные
микроконтроллеры при тихом предложении 32-разрядной производительности. Кора-
M1 имеет большую часть тех же функций как Кора-M0, но была разработана как
“мягкое ядро” для выполнения в устройстве Программируемой пользователем
вентильной матрицы (FPGA). Кора-M3 является оплотом семейства Cortex-M и была
первым вариантом Cortex-M, который будет запущен. Это включило новое поколение
высокоэффективных 32-разрядных микроконтроллеров, которые могут быть
произведены по очень низкой цене. Сегодня, существует много микроконтроллеров
Cortex-M3-based, доступных от большого разнообразия кремниевых производителей.
Это представляет сейсмический сдвиг, где Основанные на Cortex-M
микроконтроллеры начинают заменять традиционное 8-/16-bit микроконтроллеры и
даже другие 32-разрядные микроконтроллеры. Следующим самым высоким
участником выполнения семейства Cortex-M является Кора-M4. Это имеет все
функции Коры-M3 и добавляет поддержку обработки цифровых сигналов (DSP). Кора-
M4 также включает аппаратную поддержку плавающей точки вычислений одинарной
точности. Corex-M7 является процессором Cortex-M с высшим уровнем
производительности, все еще поддерживая модель программистов Cortex-M. Кора-M7
была также разработана для использования в высокой надежности и безопасности
критические системы (Рис. 1.2).
Введение в семейство процессоров Cortex-M 3

Рисунок 1.2
Профиль Cortex-M имеет пять различных вариантов с общей моделью
программистов.

В конце 1990-х, различные производители произвели микроконтроллеры на основе ARM7


и центральных процессоров ARM9. В то время как эти микроконтроллеры были
огромным прыжком в производительности и конкурировали в цене с существующим 8-
/16-bit архитектура, они были не всегда просты в использовании. Разработчик должен был
бы сначала изучить, как использовать ЦП ARM и затем иметь, чтобы понять, как
определенный производитель интегрировал ЦП ARM в их систему микроконтроллера.
Если Вы переместились в другой основанный на ARM микроконтроллер, Вы, возможно,
прошли другую кривую обучения системы микроконтроллера, прежде чем Вы могли
уверенно запустить разработку. Cortex-M изменяет все это; это - полный
Микроконтроллер (MCU) архитектура, не только ядро процессора. Это обеспечивает
стандартизированный шинный интерфейс, архитектуру отладки, ядро процессора,
структуру прерывания, управление питанием и защиту памяти. Что еще более важно,
каждый процессор Cortex-M является тем же через всех производителей, поэтому после
того как Вы учились использовать один процессор Cortex-M-based, можно снова
использовать это знание с любыми другими производителями микроконтроллеров Cortex-
M. Также в семействе Cortex-M, после того как Вы изучили основы того, как использовать
Кору-M3, затем можно использовать этот опыт разработать использование любого
другого процессора Cortex-M. Через эту книгу мы будем использовать Кору-M3 в
качестве эталонного устройства и затем смотреть на различия между Корой-M3 и Корой-
M0, Корой-M01 и Корой-M4. Кора-M7 имеет более усовершенствованную систему
памяти, которая представляет функции, такие как Сильно связанные Памяти и Кэши, мы
бросим подробный взгляд на Кору-M7 отдельно так к концу этой книги, у Вас будут
практические знания всех процессоров Cortex-M.

Кора-M3
Сегодня, Кора-M3 наиболее широко используется из всех процессоров Cortex-M. Это
частично, потому что это было доступно не только в течение самого долгого
промежутка времени, но также и это отвечает требованиям для микроконтроллера
общего назначения. Это обычно означает, что имеет хороший баланс между высокой
производительностью, низкой потребляемой мощностью и низкой стоимостью (Рис.
1.3).
4 Главы 1

Рисунок 1.3
Кора-M3 была первым доступным устройством Cortex-M. Это - полный процессор
для микроконтроллера общего назначения.

Основой Коры-M3 является высокоэффективный 32-разрядный ЦП. Как ARM7 это


- компьютер с сокращенной системой команд, где большинство инструкций
выполнится в единственном цикле (Рис. 1.4).

Рисунок 1.4
Кора-M3 ЦП имеет трехэтапный конвейер с предсказанием ветвлений.

Это частично сделано возможным трехэтапным конвейером с отдельной


выборкой, декодируют и выполняют единицы (Рис. 1.5).

Рисунок 1.5
Кора-M3 ЦП может выполнить большинство инструкций в единственном цикле. Это
достигается конвейером, выполняющим одну инструкцию, декодируя
следующую, и выбирающую одну треть.
Введение в семейство процессоров Cortex-M 5

Так, в то время как одна инструкция выполняется, секунда декодируется, и одна


треть выбирается. Тот же подход использовался на ARM7. Здорово, когда код входит
в прямую линию, однако, когда программа переходит, конвейер должен быть
сброшен и снова наполнен новыми инструкциями, прежде чем выполнение сможет
продолжиться. Это сделало ответвления по довольно дорогому ARM7 с точки зрения
вычислительной мощности. Однако Кора-M3 и Кора-M4 включают инструкцию
выбрать единицу, которая может обработать спекулятивные целевые выборки
ответвления, которые могут уменьшить штраф места размещения. Кора-M7
включает полный Целевой блок кэш-памяти Адреса Ответвления, который еще более
эффективен. Это помогает Коре-M3 и Коре-M4 иметь длительную вычислительную
мощность 1.25 DMIPS/MHz, в то время как Кора-M7 достигает 2.14 DMIPS/MHz.
Кроме того, процессор Cortex-M3 имеет аппаратную целочисленную математическую
единицу с аппаратными средствами, делятся, и единственный цикл умножаются.
Процессор Cortex-M3 также включает контроллер прерываний вложенного вектора
(NVIC), который может обслужить до 240 источников прерывания. NVIC
обеспечивает быстро детерминированную обработку прерываний, и от прерывания,
повышаемого до достижения первой строки “C” в процедуре обработки прерывания,
берет всего 12 циклов каждый раз. NVIC также содержит стандартный таймер,
названный таймером SysTick. Это - 24-разрядный таймер обратного отсчета с
автоматической перезагрузкой. Этот таймер присутствует на всех различных
процессорах Cortex-M. Таймер SysTick используется для обеспечения регулярных
периодических прерываний. Типичное использование этого таймера должно
обеспечить галочку таймера для маленьких операционных систем реального времени
(RTOS) места. Мы взглянем на такой RTOS в Главе 9 “CMSIS-RTOS” Также рядом с
NVIC, контроллер прерываний пробуждения (WIC); это - небольшая площадь
процессора Cortex-M, который поддерживается, когда процессор находится в режиме
низкой мощности. WIC может использовать сигналы прерывания от периферийных
устройств микроконтроллера до пробуждения процессор Cortex-M от режима низкой
мощности. WIC может быть реализован различными способами и в некоторых
случаях не требует, чтобы часы функционировали; также, это может быть в
отдельном энергетическом регионе от основного процессора Cortex-M. Это позволяет
99% процессора Cortex-M быть помещенными в режим низкой мощности только с
минимальным током, используемым WIC.
6 Глав 1

Рисунок 1.6
Архитектура отладки Cortex-M независима от ЦП и содержит до трех единиц
трассировки в реальном времени в дополнение к блоку
управления выполнения.

Семейство Cortex-M также имеет очень усовершенствованную архитектуру отладки


под названием CoreSight
(Рис. 1.6). Более ранние процессоры ARM7/9 могли быть отлажены через “Joint Test
Action Group” (JTAG) интерфейс отладки. Это обеспечило средство загрузить код
приложения во флэш-память на микросхеме и затем осуществить код с основной
отладкой выполнения/остановки.
В то время как отладчик JTAG обеспечил недорогой способ отладить, он имел две
основных проблемы. Первым было ограниченное количество точек останова, обычно
два с одной требуемой для единственного ступающего кода и во-вторых, когда ЦП
выполнял код, микроконтроллер стал черным квадратом с отладчиком, имеющим
видимость к ЦП, памяти или периферийным устройствам, пока микроконтроллер не
был остановлен. Архитектура отладки CoreSight в процессорах Cortex-M намного
более сложна, чем старые процессоры ARM7 или ARM9. Это позволяет до восьми
аппаратных точек останова быть помещенными в регионы данных или код. CoreSight
также обеспечивает три отдельных единицы трассировки, которые поддерживают
усовершенствованные функции отладки, не внедряя на выполнении Коры ЦП. Кора-
M3 и Кора-M4 всегда оснащены контрольной точкой данных и прослеживают единицу
(DWT) и единицу макроячейки трассировки инструментария (ITM). Интерфейс
отладки позволяет недорогому отладчику просматривать содержание памяти, и
периферийное устройство регистрируется “на лету”, не останавливая ЦП, и DWT
может
Введение в семейство процессоров Cortex-M 7

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


не используя ресурсов процессора. Вторую единицу трассировки называют
трассировкой инструментария. Эта единица трассировки обеспечивает способ связи
отладки между под управлением кодом и пользовательским интерфейсом отладчика.
Во время разработки стандартный канал IO может быть перенаправлен к консоли в
отладчике. Это позволяет Вам оснащать свой код с printf () сообщения отладки,
которые могут затем быть прочитаны в отладчике, в то время как код работает. Это
может быть полезно для захвата сложных проблем во время выполнения. Трассировка
инструментария также очень полезна во время программного обеспечения,
тестирующего, поскольку благодаря этому тестовая обвязка вывела данные к ПК, не
нуждаясь ни в каких определенных аппаратных средствах на цели. Трассировка
инструментария на самом деле более сложна, чем простой Универсальный
асинхронный приемопередатчик (UART), поскольку она обеспечивает 32 канала
передачи, которые могут использоваться различными ресурсами в рамках кода
приложения. Например, мы можем обеспечить расширенную отладочную
информацию о производительности RTOS путем размещения кода в ядро RTOS,
которое использует канал трассировки инструментария для общения с отладчиком.
Заключительную единицу трассировки называют встроенной макроячейкой
трассировки (ETM). Эта единица трассировки является дополнительным
соответствием и не присутствует на всех устройствах Cortex-M. Обычно
производитель будет соответствовать ETM на их высокопроизводительных
микроконтроллерах для обеспечения расширенных возможностей отладки. ETM
обеспечивает трассировочную информацию инструкции, которая позволяет отладчику
создавать список трассировок ассемблерного и Высокоуровневого языка
выполненного кода. ETM также включает более усовершенствованные инструменты,
такие как покрытие кода контролирующий и синхронизирующий анализ
производительности. Этими функциями отладки часто является требование для очень
важной безопасности и разработка кода высокой целостности.

Усовершенствованные архитектурные функции


Кора-M3 и Кора-M4 могут также быть оснащены другой единицей для помощи
выполнению кода высокой целостности. Единица защиты памяти (MPU) позволяет
разработчикам сегментировать карту распределения памяти Cortex-M на регионы с
различными правами доступа. Мы посмотрим на рабочие режимы процессора Cortex-
M в Главе 5 “Функции Передовой архитектуры”, но помещать его простыми словами,
Кора ЦП может выполнить код в привилегированном режиме или более строгом
непривилегированном режиме. MPU может определить привилегированные и
непривилегированные регионы по 4 ГБ адресного пространства (т.е., код, RAM и
периферийное устройство). Если ЦП будет работать в непривилегированном режиме,
и он пытается получить доступ к привилегированному региону памяти, то MPU
повысит исключение, и выполнение векторизует к служебной программе отказа MPU.
MPU обеспечивает поддержку оборудования для более усовершенствованных
разработок программного обеспечения. Например, можно настроить код приложения
так, чтобы RTOS и драйверы устройств низкого уровня имели полный
привилегированный доступ ко всем функциям микроконтроллера, в то время как код
приложения ограничивается своим собственным регионом кода и данных. Как ETM,
MPU является дополнительной единицей, которая может быть приспособлена
производителями во время дизайна микроконтроллера. MPU обычно находится на
высокопроизводительных устройствах, которые имеют большой объем Флэш-памяти и
8 Глав 1

SRAM. Наконец, с Корой-M3 и Корой-M4 соединяют интерфейсом к остальной


части микроконтроллера через шинную архитектуру Гарварда. Это означает, что у
них есть порт для выбирающих инструкций и констант от памяти кода и второй
порт для доступа к SRAM и периферийным устройствам. Мы посмотрим на
шинный интерфейс более тесно в Главе 5 “Функции Передовой архитектуры”, но в
сущности, шинная архитектура Гарварда увеличивает производительность
процессора Cortex-M, но не представляет дополнительной сложности для
программиста.

Более ранние центральные процессоры ARM, ARM7 и ARM9, поддерживали две


системы команд. Этот код мог быть скомпилирован или как 32-разрядный код ARM
или как 16-разрядный код Ползунка. Система команд ARM позволила бы коду быть
записанным для максимальной производительности, в то время как код Ползунка
достигнет большей плотности кода (Рис. 1.7). Во время разработки должен был
решить программист, какая функция должна быть скомпилирована с ARM 32-
разрядная система команд и который должен быть создан с помощью Ползунка 16-
разрядная система команд. Компоновщик затем взаимодействовал бы эти две системы
команд вместе. В то время как процессоры Cortex-M являются кодом, совместимым с
исходной системой команд Ползунка, они разработаны для выполнения расширенной
версии системы команд Ползунка под названием Ползунок 2. Ползунок 2 является
смешением 16-и 32-разрядные инструкции, который был разработан, чтобы быть
очень C дружественный и эффективен. Даже для наименьшего проекта Cortex-M весь
код может быть написан на высокоуровневом языке, обычно C, без любой
потребности использовать ассемблер.

Рисунок 1.7
Более ранний ARM ЦП имел две системы команд ARM (32 бита) и Ползунок (16
битов). Процессоры Cortex-M имеют систему команд под названием Ползунок 2,
который является смешением 16-разрядных и 32-разрядных инструкций.

С Ползунком 2 системы команд Кора-M3 обеспечивает 1.25 DMIPS/MHz, в то время как


ЦП ARM7 с помощью ARM, 32-разрядная система команд достигает 0.95 DMIPS/MHz и
Ползунка 16-разрядная система команд на ARM7, является 0.7 DMIPS/MHz (Рис. 1.8). ЦП
Cortex-M имеет много аппаратных акселераторов, таких как единственный цикл,
умножаются, аппаратное деление и инструкции по управлению битовым полем что
повышение справки ее производительность по сравнению с основанными на ARM7
устройствами.
Введение в семейство процессоров Cortex-M 9

Рисунок 1.8
Кора-M3 и Ползунок M4 2 системы команд достигают более высоких уровней
производительности или, чем Ползунок или, чем система команд
ARM, работающая на ARM7.

Ползунок 2 системы команд также могут достигнуть превосходной плотности кода,


которая сопоставима с исходной 16-разрядной системой команд Ползунка при
обеспечении большего количества производительности обработки, чем ARM 32-
разрядная система команд (Рис. 1.9).

Рисунок 1.9
Ползунок 2 системы команд Коры-M3 и-M4 достигает той же плотности кода как
Ползунок ARM7 (16 битов) система команд.
10 Глав 1

Все процессоры Cortex-M используют Ползунок 2 системы команд (Рис. 1.10). Кора-
M0 использует подмножество всего 56 инструкций, и Кора-M4 добавляет DSP,
единственную инструкцию несколько данных (SIMD) и инструкции с плавающей
точкой.

Рисунок 1.10
Ползунок 2 масштаба системы команд из 56 инструкций относительно Коры-M0,-
M01 до 169 инструкций относительно Коры-M4.

Кора-M0
Кора-M0 была представлена спустя несколько лет после того, как Кора-M3 была
выпущена и была во всеобщем употреблении. Кора-M0 является намного меньшим
процессором, чем Кора-M3 и может быть всего 12 логическими элементами K в
минимальной конфигурации. Кора-M0 обычно разрабатывается в микроконтроллеры,
которые предназначаются, чтобы быть очень недорогими устройствами и/или
предназначаются для операции низкой мощности. Однако важная вещь состоит в том,
что, после того как Вы понимаете Кору-M3, у Вас не будет проблемы с помощью
Коры-M0; различия главным образом очевидны для высокоуровневых языков (Рис.
1.11).
Введение в семейство процессоров Cortex-M 11

Рисунок 1.11
Кора-M0 является уменьшенной версией Коры-M3, все еще сохраняя ту же модель программистов.

Процессор Cortex-M0 имеет ЦП, который может выполнить подмножество Ползунка


2 системы команд. Как Кора-M3, это имеет трехэтапный конвейер, но никакая
выборка предположения ответвления, поэтому не переходит и переходит в рамках
кода, заставит конвейер сбрасывать и снова наполнять, прежде чем выполнение
сможет возобновиться. Кора-M0 также имеет шинную архитектуру Von Neumann,
таким образом, существует единственный путь для кода и данных. В то время как это
делает для простого дизайна, это может стать узким местом и уменьшить
производительность. По сравнению с Корой-M3 Кора-M0 достигает 0.84 DMIPS/MHz,
который, в то время как меньше, чем Кора-M3 все еще о том же как ARM7, который
имеет три раза количество логического элемента. Так, в то время как Кора-M0 в
заднем конце семейства Cortex-M, это все еще упаковывает большую
вычислительную мощность. Процессор Cortex-M0 имеет тот же NVIC как Кора-M3,
но это ограничено максимумом 32 линий прерывания от периферийных устройств
микроконтроллера. NVIC также содержит таймер SysTick, который полностью
совместим с Корой-M3. Большинство RTOS, которые работают на Коре-M3 и Коре-
M4, будет также работать на Коре-M0, хотя поставщик должен будет сделать
выделенный порт и перекомпилировать код RTOS. Как разработчик, самое большое
различие Вы найдете между использованием Коры-M0, и Кора-M3 является своими
возможностями отладки. В то время как на Коре-M3 и Коре-M4 там обширная
поддержка отладки в реальном времени, Кора-M0 имеет более скромную архитектуру
отладки. На Коре-M0 единица DWT не поддерживает трассировку данных, и ITM не
приспособлен, таким образом, нас оставляют с основным управлением выполнением
(т.е., выполняют, останавливаемся, единственное продвижение и точки останова и
контрольные точки), и непрерывные доступы памяти/периферийного устройства. Это
- все еще улучшение от поддержки JTAG, оказанной на ARM7 и центральных
процессорах ARM9.

В то время как Кора-M0 разработана, чтобы быть высокоэффективным процессором


микроконтроллера, она имеет относительно низкое количество логического элемента.
Это делает это идеальным и для устройств недорогой и для низкой мощности.
12 Глав 1

Потребление типичного питания Коры-M0 составляет 16 мкВт/МГц при выполнении,


и почти обнулите когда в ее режиме ожидания низкой мощности. В то время как
другие 8-и 16-разрядная архитектура могут также достигнуть подобных чисел низкой
мощности, они должны выполнить намного больше инструкций, чем Кора-M0 для
достижения того же конечного результата (Рис. 1.12). Это означает дополнительные
циклы, и дополнительные циклы означали бы больше потребляемой мощности. Если
мы выбираем хороший пример для Коры-M0 такой, когда 16 3 16 умножаются, то
Кора-M0 может выполнить это вычисление в 1 цикле. В сравнении для 8-разрядной
типичной архитектуры как эти 8051 будут нужны по крайней мере 48 циклов, и 16-
разрядной архитектуре будут нужны 8 циклов. Это не только преимущество
производительности, но также и преимущество энергоэффективности также (Таблица
1.1).

Рисунок 1.12
Кора-M0 разработана для поддержки дежурных режимов низкой мощности. По
сравнению с 8-разрядным или 16-разрядным MCU это может остаться в режиме
ожидания в течение намного более длительного времени, потому что это должно
выполнить меньше инструкций, чем 8-/16-bit устройство для достижения того же
результата.

Таблица 1.1: Количество циклов, взятых для 16 3 16, умножается


против типичных 8-и 16-разрядной
архитектуры
8-разрядный Пример
(8051) 16-разрядный Пример ARM Cortex-M
MOV A, R7
MOV B (0xF0), R5 MOV R1, &MulOp1 MULS r0, r1, r0
MUL AB MOV R2, &MulOp2
MOV R0, B (0xF0) MOV SumLo, R3
XCH A, R7 MOV SumHi, R4
MOV B (0xF0), R4
(С отображенной памятью умножают
MUL AB единицу),
ADD A, R0
XCH A, R6
MOV B (0xF0), R5
MUL AB
ADD A, R6
MOV R6, A
RET
Время: 336 тактов Время: 8 тактов Время: 1 такт
Размер кода: 18 Размер кода: 2
байтов Размер кода: 8 байтов байта
Введение в семейство процессоров Cortex-M 13

Как Кора-M3, Кора-M0 также имеет функцию WIC. В то время как WIC связан с
процессором Cortex-M0, он может быть помещен в другой домен питания в
микроконтроллере (Рис. 1.13).

Рисунок 1.13
Процессор Cortex-M разработан для перехода к режимам низкой мощности. WIC
может быть помещен в отдельный домен питания.

Это позволяет производителю микроконтроллеров использовать их экспертные


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

Кора-M01
Процессор Cortex-M01 является вторым поколением сверхнизкое питание ядро
Cortex-M. Это имеет полную совместимость системы команд с Корой-M0,
разрешающей Вам использовать тот же компилятор и отладчики. Как Вы могли бы
ожидать, Кора-M01 имеет некоторые важные улучшения по Коре-M0 (Рис. 1.14).
14 Глав 1

Рисунок 1.14
Кора-M01 полностью совместима с Корой-M0. Это имеет больше расширенных
функций, больше вычислительной мощности и более низкой
потребляемой мощности.

Функцией определения Коры-M01 является своя потребляемая мощность, которая


является всего 9.8 МГц µW/по сравнению с 16 мкВт/МГц для Коры-M0 и 32
мкВт/МГц для Коры-M3. Одно из изменений в архитектуре ключа Коры-M01 является
перемещением к двухэтапному конвейеру. Когда Кора-M0 и Кора-M01 выполняют
условный переход, инструкции в конвейере больше не действительны. Это означает,
что конвейер должен быть сброшен каждый раз, когда существует ответвление. После
того как ответвление было взято, конвейер должен быть снова наполнен для
возобновления выполнения. В то время как это влияет на производительность, это
также означает получать доступ к Флэш-памяти, и каждый доступ стоит энергии, а
также время. Путем перемещения в двухэтапный конвейер количество доступов
Флэш-памяти и следовательно также уменьшается потребление энергии во время
выполнения
(Рис. 1.15).
Рисунок 1.15
Кора-M0 1 имеет двухэтапный конвейер по сравнению с трехэтапным конвейером,
используемым в других процессорах Cortex-M.
Введение в семейство процессоров Cortex-M 15

Другой важной опцией, добавленной к Коре-M01, является новый периферийный


интерфейс I/O, который поддерживает выборку в течение одного цикла к
периферийным регистрам. Единственный интерфейс I/O цикла является стандартным
компонентом карты распределения памяти Коры-M01 и не использует специальных
инструкций или разбитого на страницы обращения. К регистрам, расположенным в
интерфейсе I/O, могут получить доступ нормальные указатели “C” из Вашего кода
приложения. Интерфейс I/O предоставляет более быстрый доступ к периферийным
регистрам с меньшим количеством использования энергии будучи очевидным для
кода приложения. Единственный интерфейс I/O цикла является отдельным от
усовершенствованной высокоскоростной шины (AHB) облегченный интерфейс
внешней шины, таким образом, для процессора возможно выбрать инструкции через
облегченный интерфейс AHB при создании доступа к данным к периферийным
регистрам расположенным в интерфейсе I/O.

Кора-M01 разработана для поддержки выбирающих инструкций от 16-разрядной


Флэш-памяти. Так как большинство инструкций Коры-M01 является 16-разрядным,
это не оказывает основное влияние на производительность, но действительно делает
получающийся дизайн микроконтроллера более простым, меньшим, и следовательно
более дешевым. Кора-M01 имеет некоторые функции Cortex-M3, отсутствующие на
исходной Коре-M0. Это включает MPU, на который мы посмотрим в Главе 5
“Функции Передовой архитектуры” и способность переместить таблицу векторов к
другой позиции в памяти. Эти две функции оказывают улучшенную поддержку
операционной системы (OS) и поддержку более сложных разработок программного
обеспечения с несколькими задачами приложения на едином устройстве (Рис. 1.16).

Рисунок 1.16
Порт I/O позволяет выборку в течение одного цикла к GPIO и
периферийным регистрам.
Кора-M01 также имеет улучшенную архитектуру отладки по сравнению с Корой-M0.
Поскольку мы будем видеть в Главе 7 “Отладку с CoreSight”, это поддерживает тот же
доступ в режиме реального времени к периферийным регистрам и SRAM как Кора-M3
и Кора-M4. Кроме того, Кора-M01 имеет новую функцию отладки, названную “Микро
Буфером трассировки” (MTB) (Рис. 1.17). MTB
16 Глав 1

Рисунок 1.17
Микро Буфер трассировки может быть настроен для записи выполняемых инструкций в
раздел пользователя SRAM. Это может быть считано и отображено как
трассировка инструкции в отладчике ПК.

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


регион установки SRAM программистом во время разработки. Когда код
останавливается, эта трассировка инструкции может быть загружена и отображена в
отладчике. Это обеспечивает снимок выполнения кода сразу, прежде чем код был
остановлен. В то время как это - ограниченный буфер трассировки, это чрезвычайно
полезно для разыскивания неуловимых ошибок. К MTB могут получить доступ
стандартные аппаратные средства адаптера отладки провода JTAG/Serial, для которых
Вам не нужен дорогой инструмент трассировки.

Кора-M4
В то время как Кора-M0 может считаться Корой-M3 минус некоторые функции, Кора-
M4 является расширенной версией Коры-M3 (Рис. 1.18). Дополнительные функции на
Коре-M4 фокусируются на поддержке алгоритмов DSP. Типичные алгоритмы
являются преобразованиями, такими как быстрое преобразование Фурье (FFT),
цифровые фильтры, такие как конечная импульсная характеристика (FIR) фильтрует, и
алгоритмы управления, такие как контур управления Пропорционального внутреннего
дифференциала (PID). С ее функциями DSP Кора-M4 создала новое поколение
основанных на ARM устройств, которые могут быть названы контроллерами
цифрового сигнала (DSC). Эти устройства позволяют Вам разрабатывать устройства,
которые комбинируют функции типа микроконтроллера с обработкой сигналов в
реальном времени. В Главе 8 “Практический DSP для Коры-M4 и Коры-M7” мы
посмотрим на расширения DSP Коры-M4 более подробно и также как создать
программное обеспечение, которое комбинирует обработку сигналов в реальном
времени с типичным событийно-ориентированным кодом микроконтроллера.

Кора-M4 имеет ту же базовую структуру как Кора-M3 с теми же режимами


программистов ЦП, NVIC, архитектурой отладки CoreSight, MPU и шинным
интерфейсом. Улучшения по Коре-M3 частично к системе команд, где Кора-M4 имеет
Введение в семейство процессоров Cortex-M 17

Рисунок 1.18
Кора-M4 полностью совместима с Корой-M3, но представляет аппаратный
сопроцессор для операций с плавающей точкой и
дополнительные инструкции по DSP.

дополнительные инструкции по DSP в форме инструкций SIMD. Аппаратные


средства умножаются, накапливаются (MAC) был также улучшен так, чтобы
многие из 32 3 32 арифметических инструкции были единственным циклом
(Таблица 1.2).

Таблица 1.2: Единственный цикл инструкции MAC относительно Коры-


M4

Операция Инструкция
16 316 5 32 SMULBB, SMULBT, SMULTB, SMULTT
16 316 1 32 5 32 SMLABB, SMLABT, SMLATB, SMLATT
16 316 1 64 5 64 SMLALBB, SMLALBT, SMLALTB, SMLALTT
16 332 5 32 SMULWB, SMULWT
(16 3 32) 1 32 5 32 SMLAWB, SMLAWT
(16 3 16) 6 (16 3 16) 532 SMUAD, SMUADX, SMUSD, SMUSDX
(16 3 16) 6 (16 3 16) 1 32 5 32 SMLAD, SMLADX, SMLSD, SMLSDX
(16 3 16) 6 (16 3 16) 1 64 5 64 SMLALD, SMLALDX, SMLSLD, SMLSLDX
32 3 32 5 32 MUL
32 6 (32 3 32) 532 MLA, MLS
32 3 32 5 64 SMULL, UMULL
(32 3 32) 1 64 564 SMLAL, UMLAL
(32 3 32) 1 32 132 564 UMAAL
32 6 (32 3 32) 532 (верхний) SMMLA, SMMLAR, SMMLS, SMMLSR
(32 3 32) 5 32 (верхний) SMMUL, SMMULR
18 Глав 1

Инструкции по DSP
Кора-M4 имеет ряд инструкций SIMD, нацеленных на поддержку алгоритмов DSP.
Эти инструкции позволяют много параллельных арифметических операций в
единственном цикле процессора (Рис. 1.19).

Рисунок 1.19
Инструкции SIMD могут выполнить несколько вычислений в единственном
цикле.

Инструкции SIMD работают с 16-или 8-разрядные данные, которые были упакованы в


32-разрядные количества слова. Так, например, мы можем выполнить, два 16-
разрядных умножается, и суммируйте результат в 64-разрядное слово. Также
возможно упаковать 32-разрядные работы 8-разрядными данными и выполнить
квадратическое 8-разрядное дополнение или вычитание. Как мы будем видеть в Главе
8, инструкции SIMD могут использоваться для обширного улучшения
производительности алгоритмов DSP, таких как цифровые фильтры, которые в
основном работают, много из умножает и суммирует вычисления на конвейере
данных. Процессор Cortex-M4 может также быть оснащен аппаратными средствами
FPU. Этот выбор сделан в стадии проектирования поставщиком микроконтроллера,
так как ETM и MPU, который необходимо будет проверить таблицу данных
микроконтроллера, чтобы видеть, присутствует ли это. FPU поддерживает плавающую
точку одинарной точности арифметические вычисления с помощью стандарта IEEE
754 (Таблица 1.3).

Таблица 1.3: время цикла сопроцессора для операций с


плавающей точкой коры-M4

Операция Количество цикла


Добавить/Вычесть 1
Разделиться 14
Умножиться 1
Умножьтесь накапливаются (MAC) 3
Сплавленный MAC 3
Квадратный корень 14
На маленьких микроконтроллерах математические операции с плавающей точкой
всегда выполнялись библиотеками программного обеспечения, обеспеченными
инструментом компилятора. Как правило, такие библиотеки могут взять сотни
инструкций работать, плавающая точка умножаются. Так, добавление аппаратных
средств вычислений с плавающей точкой, которые могут сделать то же вычисление в
единственном цикле, дает беспрецедентную производительность
Введение в семейство процессоров Cortex-M 19

повышение. FPU может считаться сопроцессором, который находится вместе с


Корой-M4 ЦП. Когда вычисление выполняется, значения с плавающей точкой
передаются непосредственно от регистров FPU до и от хранилища памяти SRAM без
потребности использовать регистры ЦП. В то время как это может звучать
включенным, вся транзакция FPU организована компилятором. Когда Вы создаете
приложение для Коры-M4, можно скомпилировать код для автоматического
использования библиотек программного обеспечения, а не FPU. Затем любые
вычисления с плавающей точкой в Вашем коде “C” будут выполнены на FPU.

С оптимизированным кодом Кора-M4 может выполнить алгоритмы DSP намного


быстрее, чем стандартные микроконтроллеры и даже некоторые выделенные
устройства DSP (Рис. 1.20). Конечно, слово ласки здесь “оптимизировано”, это
означает иметь хорошее знание процессора и алгоритма DSP, который Вы реализуете
и затем рука, кодирующая алгоритм, использующий компилятор intrinsics для
получения лучшего уровня производительности. К счастью, ARM обеспечивает
полную библиотеку DSP с открытым исходным кодом, которая реализует много
обычно необходимых алгоритмов DSP как простые в использовании библиотечные
функции. Мы посмотрим на пользование этой библиотекой в Главе 8 “Практический
DSP для Коры-M4 и Коры-M7”

Рисунок 1.20
MP3 декодирует сравнительный тест.

Кора-M7
Во время записи последнего процессора Cortex-M, который будет выпущен ARM,
Кора-M7. Кора-M7 является самым высоким в настоящее время доступным
процессором Cortex-M7 производительности. Это - на самом деле что-то вроде
преуменьшения. Числа сравнительного теста для Коры-M7 по сравнению с Корой-M4
показывают ниже. Обратите внимание на то, что эти числа показывают на МГц
частоты ЦП. А также значительно превзойдя Кору-M4 по характеристикам Кора-M7
может работать при очень верхних частотах. Короче говоря это оставляет Кору-M4 в
пыли. Однако Кора-M7 все еще поддерживает модель программиста Cortex-M
поэтому при использовании более раннего процессора Cortex-M, перемещающегося в
Кору-M7, не основная проблема (Рис. 1.21).
20 Глав 1

Рисунок 1.21
Кора-M4 по сравнению со сравнительным тестом Коры-M7.

Кора-M7 достигает этого повышения уровней производительности с некоторыми


архитектурными улучшениями и более сложной системой памяти. Кора-M7 ЦП имеет
суперскалярную архитектуру; это означает, что имеет два, параллельны трехэтапным
конвейерам, которые могут двойные инструкции по проблеме. ЦП также способен к
обработке различных групп инструкций параллельно. ЦП также имеет “Целевой Кэш
Адреса Ответвления”, который улучшает производительность высокоуровневых
операторов, таких как условные переходы и что еще более важно циклы. Когда тот же
исходный код будет скомпилирован для Коры-M4 и Коры-M7, значительно
потребуется меньше циклов для работы Коры-M7 (Рис. 1.22).

Рисунок 1.22
Процессор коры-M7.
Введение в семейство процессоров Cortex-M 21

Кора-M7 также представляет более сложную структуру шины. Первые основанные на


ARM микроконтроллеры использовали процессор ARM7, который использовал шину,
названную Усовершенствованной Высокоэффективной шиной (AHB). Поскольку
сложность микроконтроллеров выросла, эта шина стала узким местом, когда было
несколько устройств управления шиной (ЦП и единицы DMA) в микроконтроллере. С
введением семейства Cortex-M AHB был обновлен до облегченной матрицы AHB. Это
в действительности - ряд параллельных шин, которые позволяют нескольким
устройствам управления шиной получать доступ к памяти параллельно. Арбитраж
внутренней шины только происходит, если два устройства управления шиной
пытаются получить доступ к той же группе периферийных устройств или блоку
памяти. Кора-M7 представляет Усовершенствованный Расширяемый Интерфейс (AXI-
M). AXI-M является высокоэффективным 64-разрядным интерфейсом, который
поддерживает несколько выдающихся транзакций памяти. Это также открывает много
возможностей для кремниевых разработчиков разработать многоядерные системы и
является шагом к проектам сети на микросхеме (NoC).

Для Разработчика старшим значащим различием между Корой-M4 и Корой-M7


является более сложная система памяти. Для процессора Cortex-M7 для достижения
очень высоких уровней производительности это имеет иерархию памяти. ЦП имеет
два региона памяти, названной Сильно связанными памятями (TCM) Инструкции и
Данных. I-TCM и D-TCM являются блоками памяти состояния с нулевым временем
ожидания, которая может быть до 16K в размере. Это гарантирует, что к любым
критическим стандартным программам или данным может получить доступ процессор
без любых задержек. Процессор может также включать два кэша до 64K. Эти единицы
обеспечивают до 64K кэша Инструкции и Данных для системной памяти, которая
расположена на шине AXI-M. При разработке приложения, необходимо понять и
управлять этой системой памяти. Как Кора-M4 Кора-M7 имеет дополнительную
возможность DSP в форме инструкций SIMD и может быть оснащена единственным
или двойным Сопроцессором для операций с плавающей точкой прецессии. Кора-M7
может также быть пригодна для важных приложений безопасности. Процессор Cortex-
M7 может быть синтезирован с дополнительной функцией безопасности, такой как
“Коды с коррекцией ошибок” на ее шинных интерфейсах и “Созданный В Сам Тест”
единица. Кора-M7 является также первым процессором Cortex-M, который будет
иметь полный пакет документации безопасности, чтобы позволить Кремниевым
Поставщикам производить полностью, безопасность квалифицировала устройство.

Заключение
Эта книга действительно затрагивает две темы. Введение в аппаратные средства
процессора Cortex-M и также во введении в разработку программного обеспечения
для Основанных на Cortex-M микроконтроллеров. С введением процессора Cortex-M у
нас теперь есть недорогая аппаратная платформа, которая способна к поддержке более
сложной разработки программного обеспечения и в прошлое десятилетие видела
принятие RTOSs, и библиотеки промежуточного программного обеспечения должны
были поддерживать более сложные периферийные устройства, найденные на
устройствах Cortex-M. Таким образом вместе с пониманием функций низкого уровня
процессоров Cortex-M мы также должны использовать более сложные методы
проектирования (Рис. 1.23).
22 Главы 1

Рисунок 1.23
Производительность и питание фигурируют для семейства
процессоров Cortex-M.
CHPTER2

Разработка программного
обеспечения для
Семейство Cortex-M

Введение
Одно из больших преимуществ использования процессора Cortex-M - то, что оно
имеет широкую и растущую поддержку средства разработки диапазона. Существуют
наборы инструментальных средств, доступные максимум на уровне нулевых
нескольких тысяч долларов стоимости в зависимости от глубины Ваших карманов и
типа приложения, которое Вы разрабатываете. Сегодня существует пять основных
наборов инструментальных средств, которые используются для разработки Cortex-M
(Таблица 2.1).

Таблица 2.1: наборы инструментальных средств процессора


Cortex-M
Средство разработки
GNU GCC со свободным и коммерческим IDE
Greenhills
IAR встроенные инструментальные средства для ARM
Комплект разработчика микроконтроллера Keil для ARM (MDK-ARM)
Управление задачами для набора инструментов VX для ARM

Строго говоря GCC GNU является набором инструментальных средств


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

Комплект разработчика микроконтроллера Keil


В этом учебном руководстве мы собираемся использовать MDK-ARM Keil (Комплект
разработчика микроконтроллера для ARM) набор инструментальных средств. MDK-
ARM Keil обеспечивает полную среду разработки для всех Основанных на Cortex-M
микроконтроллеров (Рис. 2.1).

Руководство разработчика по семейству процессоров Cortex-M.


DOI: http://dx.doi.org/10.1016/B978-0-08-100629-0.00002-5 23
© 2016 Elsevier Ltd. Все права защищены.
24 Главы 2

Рисунок 2.1
Установка Ядра MDK-ARM содержит IDE, компилятор и отладчик.
Поддержка устройства и промежуточного программного
обеспечения добавляется через программные пакеты.

MDK-ARM включает его собственную среду разработки по имени µVision (Микро


Видение), который действует как менеджер проектов редактора и отладчик. Одни из
больших преимуществ MDK-ARM - то, что это использует ARM “C” компилятор. Это -
очень широко используемый компилятор “C\C11”, который непрерывно разрабатывался
ARM, так как их первый ЦП был создан. MDK-ARM также включает интегрированную
Операционную систему реального времени (RTOS) под названием RTX. Все процессоры
Cortex-M способны к выполнению операционной системы, и мы посмотрим на
использование RTOS в Главе 9 “CMSIS-RTOS”. А также включая RTOS, MDK-ARM
включает библиотеку DSP, которой можно пользоваться на Коре-M4 и также Коре-M3. Мы
посмотрим на эту библиотеку в Главе 8 “Практический DSP для Коры-M4 и Коры-M7”.

Программные пакеты
MDK-ARM установлен как базовый набор инструментальных средств. Это состоит из
IDE µVision, компилятора и отладчика плюс утилита, названная установщиком
пакета. Базовый набор инструментальных средств не содержит поддержки
определенных микроконтроллеров Cortex-M. Поддержка определенного семейства
микроконтроллеров Cortex-M установлена через систему программного пакета.
Установщик пакета позволяет Вам выбирать и устанавливать поддержку семейства
микроконтроллеров. После того, как выбранный,
“Пакет Семейства Устройств” будет загружен с веб-сайта Репозитория Пакета и
установлен в набор инструментальных средств. Эта система программного пакета
может также использоваться для распределения библиотек программного
обеспечения и других компонентов программного обеспечения. Мы посмотрим на
то, как сделать компонент программного обеспечения для повторного использования
кода в Главе 12 "Software Components".

Учебные упражнения
Существует несколько основных причин для использования MDK-ARM как среда
разработки для этой книги. Во-первых, это включает ARM “C” компилятор, который
является промышленным ссылочным компилятором для процессоров ARM. Во-
вторых, это включает средство моделирования программного обеспечения который
модели каждый из процессоров Cortex-M и периферийных устройств для диапазона
Основанных на Cortex-M микроконтроллеров. Это позволяет Вам выполнять
большинство учебных примеров в этой книге без потребности в аппаратном
отладчике или оценочной плате. Средство моделирования является очень хорошим
путем к
Разработка программного обеспечения для семейства Cortex-M 25

изучите, как каждый процессор Cortex-M работает, поскольку можно получить так же
очень подробную отладочную информацию от средства моделирования как от
аппаратного отладчика. MDK-ARM также включает первый RTOS для поддержки
спецификации CMSIS-RTOS. Мы будем видеть больше из этого в Главе 9 “CMSIS-
RTOS”, но это - в основном универсальный API для Cortex-M RTOS. В то время как
мы можем использовать средство моделирования для экспериментирования с
различными процессорами Cortex-M, там прибывает точка, когда Вы захотите
выполнить свой код некоторых реальных аппаратных средств. Теперь существует
много очень недорогих модулей, которые включают аппаратные средства отладчика.
Приложение предоставляет URL веб-сайтам, где эти платы могут быть куплены. В
Главе 6 “Процессор Коры-M7”, мы посмотрим на Кору-M7, и практические примеры
будут выполнены на плате исследования STM32F7. Это - недорогая оценочная плата и
широко доступно от большинства поставщиков каталога электроники (Рис. 2.2).

Рисунок 2.2
Недорогие модули Cortex-M включают плату Исследования ST32F7. Мы будем
использовать это управление по Коре-M7 и аппаратному
осуществлению отладки.

Учебные упражнения, описанные в этой книге, приспособлены к использованию


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

Установка
Для практических упражнений в этой книге мы должны установить MDK-ARM
облегченный набор инструментальных средств и “пакеты” Поддержки Семейства
Устройств для микроконтроллеров, которые мы будем использовать и учебный пакет
в качестве примера.
26 Глав 2

Первая Загрузка MDK-ARM Keil, облегченный с www.keil.com.

Облегченный MKD-ARM является бесплатной версией полного набора инструментальных


средств, который позволяет Вам создавать код приложения до 32K размера изображения.
Это включает полностью рабочий компилятор, RTOS и средство моделирования и
работает с совместимыми аппаратными отладчиками. Прямая ссылка для загрузки:
https://www.keil.com/arm/demo/eval/arm.htm.

Если это изменяется со временем, посетите основную веб-страницу Keil и перейдите


по ссылке к инструментам MDK-ARM.
Выполните загруженный исполняемый файл для установки MDK-ARM на ПК.

Запустите IDE µVision

Откройте установщик пакета

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


Микроэлектронике ST Ряд STM32F1 (Рис. 2.3).

Рисунок 2.3
Используйте установщик пакета для загрузки файлов поддержки для семейства
STM32F1 микроконтроллеров.
Разработка программного обеспечения для семейства Cortex-M 27

На вкладке Packs выберите Keil:: STM32F1xx_DFP и нажатие кнопка Install.


Повторите этот процесс для установки поддержки следующих семейств устройств
(Таблица 2.2).

Таблица 2.2: семейство Выбранных устройств поддерживает


пакеты
Кремниевый Пакет
поставщик Устройство устройства
Микроэлектроника ST Ряд STM32F7 Keil:: STM32F7xx_DFP
NXP Ряд LPC1700 Keil:: LPC1700_DFP

В разделе Generic Pack окно выбирает и установка или обновляет следующие


пакеты (Таблица 2.3).

Таблица 2.3: Необходимые универсальные программные


пакеты
Универсальный пакет
РУКА:: CMSIS
ARM:: CMIS-Driver_Validation
Keil:: ARM_Compiler

Загрузите пакет в качестве примера для практических упражнений.


Учебные примеры могут быть найдены по http://booksite.elsevier.com/9780081006290.

Загрузите Учебный файл В качестве примера и сохраните его на Вашем жестком


диске. Удостоверьтесь, что это имеет .pack расширение; некоторые браузеры могут
переименовать файл путем предоставления ему .zip расширения.

На веб-сайте страниц Tutorial существует также пакет Утилит. Загрузите этот


пакет на свой жесткий диск и проверьте, что он имеет .pack расширение.

После того как Вы загрузили Учебный Пакет В качестве примера, и Утилиты


упаковывают, двойной щелчок по каждому файлу в свою очередь для установки их
содержания в Набор инструментальных средств MDK-ARM.
Для просмотра примеров откройте установщик пакета.
Выберите вкладку Boards и выберите “Учебное руководство Руководства
Разработчиков”.
Теперь нажмите на вкладку Examples для наблюдения учебных примеров.
Чтобы показать им в порядке, нажмите на серый блок во главе столбца.
Упражнение 2.1 Создание первой программы
Теперь, когда набор инструментальных средств и примеры установлены, мы можем
посмотреть на установку a
проект для типичного маленького Основанного на Cortex-M микроконтроллера.
После того как проект настроен,
28 Глав 2

мы можем познакомиться с IDE µVision, создать код и сделать наши первые


шаги с отладчиком.

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

Жидкокристаллический дисплей

Микро
Напряжение на
ADC1 channel1

8 светодиодов на GPIO B

Рисунок 2.4
Аппаратные средства проекта Blinky состоят из аналогового источника
напряжения, внешнего жидкокристаллического
дисплея и банка светодиодов.

Код также высвечивает группу светодиодов в последовательности. Существует


восемь светодиодов, присоединенных к контактам порта на порте GPIO B. Скорость,
на которой светодиодная флэш-память установлена значением ADC.
Запустите IDE µVision путем нажатия на значок UV4.

Откройте установщик пакета.


Нажмите на вкладку Boards и выбор “Учебная запись” Руководства Разработчиков
В качестве примера.
Разработка программного обеспечения для семейства Cortex-M 29

Выберите вкладку Examples и нажмите кнопку копирования для “Исключая 1.1


Первыми Проектами”.

Установите каталог установки на подходящее место на Вашем жестком диске.


В следующих инструкциях это местоположение назовут, путь. Проект \First.

В этом осуществлении мы пройдем шаги, необходимые для воссоздания этого


проекта с нуля.
В µVision, близко текущий проект путем выбора project\close проекта из строки
главного меню (Рис. 2.5).

Рисунок 2.5
Закройте любой открытый проект.

Запустите новый проект путем выбора проекта Project\new µVision (Рис. 2.6).

Рисунок 2.6
Создайте новый проект и сохраните его в Первый Каталог проекта.
30 Глав 2

Это откроет меню, просящее название проекта и каталог.

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


выбираете, путь. Каталог проекта \First.
Этот каталог содержит файлы исходного кода “C”, которые мы будем использовать в
нашем проекте.
Введите свое название проекта и нажмите Save.
Затем, выберите микроконтроллер для использования в проекте (Рис. 2.7).

Рисунок 2.7
Выберите STM32F103RB из базы данных устройства.

После того как Вы выбрали каталог проекта и сохранили название проекта, новое
диалоговое окно с базой данных устройства будет запущено. Здесь, мы должны
выбрать микроконтроллер, который мы собираемся использовать для этого проекта.
Переместитесь по базе данных устройства и выберите Микроэлектронику ST, “Ряд
STM32F103” и затем STM32F103RB и нажмите "OK". Это настроит проект для этого
устройства; это включает установку корректных параметров компилятора, файла
сценария компоновщика, имитационной модели, соединения отладчика и алгоритмов
программирования Flash.
При выборе STM32F103RB нажать "OK".

Теперь, IDE отобразит “Среду выполнения” (RTE) менеджер. RTE позволяет Вам
выбирать компоненты программного обеспечения, которые были установлены через
систему пакета и добавляют их к нашему проекту. Это позволяет Вам создавать
сложные программные платформы очень быстро. Для справки на любом из
компонентов программного обеспечения нажмите на синюю ссылку в столбце
описания (Рис. 2.8).
Разработка программного обеспечения для семейства Cortex-M 31

Рисунок 2.8
Менеджер по Среде выполнения позволяет Вам добавлять компоненты
программного обеспечения к своему проекту быстро
создать разработку “платформа”.

На данный момент мы должны добавить минимальную поддержку нашего


первоначального проекта (Рис. 2.9).

Рисунок 2.9
Выберите компоненты “Ядра” и “Запуска”.
32 Главы 2

В RTE отметьте поле “CMSIS:: Core” и “Устройство:: поле Startup”.


Это добавляет первоначальный код Запуска и также функции поддержки для
процессора Cortex-M.

Этот пример также использует некоторые функции микроконтроллера, таким


образом, мы сможем использовать его в некоторых файлах поддержки платы. Этот
пример разработан для работы с оценочной платой, названной MCBSTM32E.
Удостоверьтесь, что это - плата, выбранная в столбце Board Support\Variant.
Отметьте поле “Board Support:: ADC” и “Поддержку Совета:: поле LED” (Рис. 2.10).

Рисунок 2.10
Компоненты поддержки платы требуют, чтобы субкомпоненты работали. Пока это не
разрешено, “sel”. Столбец будет окрашен в Оранжевый (Темно-Серый
в печатных версиях).

Окно вывода проверки теперь показывает нам, что компоненты поддержки платы
требуют некоторых дополнительных субкомпонентов (Рис. 2.11).
Рисунок 2.11
Функции светодиодного индикатора требуют, чтобы драйвер GPIO был
добавлен к проекту.
Разработка программного обеспечения для семейства Cortex-M 33

Для добавления в драйвере GPIO, можно или открыть раздел Device RTE и вручную
добавить в драйвере GPIO или просто нажать кнопку твердости RTE, и все
зависимости компонента будут разрешены автоматически (Рис. 2.12).

Рисунок 2.12
Выберите файл поддержки GPIO вручную или нажмите кнопку твердости для
добавления необходимых компонентов
автоматически.

Теперь, когда мы выбрали все компоненты, требуемые нашим проектом, нажмите


кнопку OK, и файлы поддержки будут добавлены к окну проекта (Рис. 2.13).

Рисунок 2.13
Первоначальный проект с выбранными компонентами
программного обеспечения.

Дважды щелкните по startup_stm32F10x.md.s файлу для открытия его в редакторе.


Нажмите на вкладку мастера конфигурации у основания окна редактора (Рис. 2.14).

Рисунок 2.14
Конфигурационные файлы могут быть просмотрены как текст или как
мастера конфигурации.
34 Главы 2

Это преобразовывает исходный файл простого текста в представление, которое


показывает параметры конфигурации в файле (Рис. 2.15).

Рисунок 2.15
Мастер конфигурации позволяет Вам просматривать и изменять #defines в заголовочном
или исходном файле.

Это представление создается XML-тэгами в комментариях исходного файла.


Изменение значений в мастере конфигурации изменяет базовый исходный код. В
этом случае мы можем установить размер стекового пространства и пространства
"кучи".
В представлении проекта нажмите вкладку Books у основания окна (Рис. 2.16).

Рисунок 2.16
Справка набора инструментальных средств.
Разработка программного обеспечения для семейства Cortex-M 35

В окне Books “Полное Пользовательское Руководство” открывает систему


справочной информации для µVision и руководств компилятора (Рис. 2.17).

Рисунок 2.17
Справка компонента программного обеспечения.

В RTE синие гиперссылки в Описании открывают справочные файлы для


определенного компонента программного обеспечения.
Переключитесь назад на представление проекта и добавьте исходные файлы проекта
"C".

Выделите папку “Source Group” в окне проекта, щелкните правой кнопкой и


выберите, “Добавьте Существующие файлы к Group Source Group 1” (Рис. 2.18).

Рисунок 2.18
Добавьте существующий файл к исходной группе проекта.
36 Глав 2

Это откроет диалоговое окно “Add files to Group”. В диалоговом окне добавьте файл
проекта Blinky.c (Рис. 2.19).

Рисунок 2.19
Добавьте Blinky.c.

Проект должен теперь содержать Blinky.c и компоненты RTE (Рис. 2.20).

Рисунок 2.20
Завершенный проект.
Разработка программного обеспечения для семейства Cortex-M 37

Разработайте проект путем выбора project\build цели (Рис. 2.21).

Рисунок 2.21
Разработайте проект.

Это скомпилирует каждый из “.c” модулей в свою очередь и затем соединит их для
создания заключительной прикладной программы. Окно вывода показывает
результат процесса сборки и сообщает о любых ошибках или предупреждениях
(Рис. 2.22).

Рисунок 2.22
О заключительном размере программы сообщают в Окне вывода
Сборки.

О размере программы также сообщают (Таблица 2.4).

Таблица 2.4: использование памяти раздела


Linker

Раздел Описание
Код Размер исполняемого изображения
Данные RO Размер кодовых констант во Флэш-памяти
Размер инициализированной переменной
Данные RW в SRAM
Размер на неинициализированных
Данные ZI переменных в SRAM
Если об ошибках или предупреждениях сообщат в окне сборки, нажимающем на них,
то возьмет Вас к строке кода в окне редактора.
38 Глав 2

Откройте Опции для Целевого диалогового окна (Рис. 2.23).

Рисунок 2.23
Откройте глобальные опции проекта.

Это может быть сделано в меню проектов путем щелчка правой кнопкой по названию
проекта и выбора “Опций для Цели” или путем выбора той же опции в меню проектов из
основной панели инструментов (Рис. 2.24).

Рисунок 2.24
Целевое меню определяет карту распределения памяти проекта.

“Опции для Целевого” диалогового окна содержат все глобальные


настройки проекта.
Разработка программного обеспечения для семейства Cortex-M 39

Теперь выберите вкладку Debug (Рис. 2.25).

Рисунок 2.25
Выберите средство моделирования и имитационную модель
STM32F103RB.

Меню Debug разделяется на две половины. Опции средства моделирования


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

Проверьте, что Диалоговое окно Средства моделирования, DLL установлен на


DARMRM.DLL и параметр, является pSTM32F103RB.
Теперь мы можем добавить сценарий моделирования для обеспечения некоторых
входных значений ADC (Рис. 2.26).

Рисунок 2.26
Откройте файловый менеджер для выбора сценария
моделирования.
40 Глав 2

Нажмите кнопку Файлового менеджера и добавьте файл Dbg_sim.ini, который


находится в первом каталоге проекта как файл инициализации отладчика (Рис. 2.27).

Рисунок 2.27
Добавьте сценарий моделирования.

Файл сценария использует “C” - как язык для моделирования внешнего


оборудования. Весь моделируемый микроконтроллер “контакты” появляется как
виртуальные регистры, которые могут быть считаны из и записаны в сценарием.
Сценарий отладки генерирует моделируемое напряжение для ADC, сценарий для
этого показывают ниже. Это генерирует сигнал, который растет и вниз и он
применяется к виртуальному регистру ADC1_IN1, который является каналом 1
преобразователя ADC 1. Функция twatch читает моделируемые часы процессора и
останавливает сценарий для конкретного количества циклов.
Пустой Аналог сигнала (пускают в ход
предел) {вольты плавающие;

printf ("Аналог (%f) вводимый \n", предел); в то


время как (1) {/* навсегда */
вольты 5 0;
в то время как (вольты, 5 пределов) {
ADC1_IN1 5 вольт; аналоговый вход/* 2 */
twatch (250000);/* 250 000 Повреждений Времени Циклов */
вольты 1 5 0.1; /* увеличивают напряжение */
}
вольты 5 пределов;
в то время как (вольты.5 0.0)
{ADC1_IN1 5 вольт;
Разработка программного обеспечения для семейства Cortex-M 41

twatch (250000);/* 250 000 Повреждений Времени Циклов


*/вольты - 5 0.1;/* уменьшают напряжение */
}
}
}

Нажмите "OK" для закрытия опций для Целевого диалогового окна.


Теперь запустите Отладчик и выполните код (Рис. 2.28).

Рисунок 2.28
Запустите отладчик.

Это подключит µVision к Имитационной модели и загрузит изображение проекта в


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

Рисунок 2.29
Представление отладки.

Отладчик µVision разделен на многие окна, которые позволяют Вам исследовать и


управлять выполнением своего кода. Ключевые окна показывают в Фигах. 2.30 2.35.
42 Главы 2

Рисунок 2.30
Окно Register.

Окно Register отображает текущее содержание регистрового файла ЦП (R0-R15).


Регистр состояния Программы (xPSR) и также Основной указатель вершины стека (MSP)
и Указатель стека процесса (PSP). Мы посмотрим на все эти регистры в следующей главе
(Рис. 2.31).

Рисунок 2.31
Окно Disassembly.

Поскольку его имя подразумевает, окно Disassembly покажет Вам список ассемблеров
низкого уровня, чередованный с высокоуровневым "C" листингом кода. Одна из
больших достопримечательностей семейства Cortex-M - то, что весь Ваш код проекта
может быть написан на высокоуровневом языке, таком как “C\C11”. Вы никогда или
очень редко не должны писать ассемблерные подпрограммы низкого уровня. Однако
полезно смочь “прочитать” ассемблерный код низкого уровня для наблюдения то, что
делает компилятор. Окно дизассемблирования показывает абсолютный адрес текущей
команды, затем, это показывает Код операции, это - или 16-разрядная инструкция или
32-разрядная инструкция. Необработанный OP
Разработка программного обеспечения для семейства Cortex-M 43

Код затем отображен как ассемблерная мнемосхема. Текущее местоположение


счетчика команд показывает желтая стрелка в левом поле. Темно-серые блоки
указывают на местоположение исполняемых строк кода (Рис. 2.32).

Рисунок 2.32
Окно Editor.

Окно исходного кода имеет подобное расположение окно дизассемблирования. Это окно
просто отображает высокоуровневый "C" исходный код. Текущее местоположение
счетчика команд показывает желтая стрелка в левом поле. Blue Arrow показывает
местоположение курсора. Как окно дизассемблирования, темно-серые блоки указывают на
местоположение исполняемых строк кода. Исходное окно позволяет Вам иметь много
открытых модулей проекта. Каждый исходный модуль может быть достигнут путем
нажатия на вкладку наверху окна.

Командное окно позволяет Вам вводить команды отладчика, чтобы


непосредственно настроить и управлять функциями отладчика. Эти команды могут
также быть сохранены в текстовом файле и выполнены как сценарий, когда
отладчик запускается (Рис. 2.33).
Рисунок 2.33
Командная строка отладчика.
44 Главы 2

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

Рисунок 2.34
Переменное окно часов.

Можно управлять выполнением кода через значки на панели инструментов (Рис.


2.35). Код может быть единственным, ступил “C” или собрал строку за один раз или
работал в полной скорости и остановился. Те же команды доступны через меню
отладки, которое также показывает ярлыки функциональной клавиши, которые
можно предпочесть.

Рисунок 2.35
Панель инструментов Debugger.

Установите точку останова на основном цикле с условием


продолжения в Blinky.c (Рис. 2.36).
Разработка программного обеспечения для семейства Cortex-M 45

Рисунок 2.36
Точка останова отображена как красная точка (Рядом со строкой
53).

Можно установить точку останова путем перемещения курсора мыши в темно-


серый блок рядом с номером строки и щелчком левой кнопкой. Точка останова
отмечена красной точкой.
Запустите выполнение кода.

Со сценарием моделирования на месте мы сможем выполниться, весь


жидкокристаллический дисплей кодирует и достигает точки останова (Рис. 2.37).

Рисунок 2.37
Установите точку останова на основном цикле с условием продолжения. Если Вы
добираетесь здесь, код инициализации работал успешно.

Теперь проведите несколько минут, исследуя отладчик выполненное управление (Рис.


2.38).

Рисунок 2.38
Панель инструментов одноэтапные опции.
Используйте одноэтапные команды, установите точку останова и запустите
средство моделирования, работающее в полной скорости. Если Вы теряете то,
что продолжается, выйдите, отладчик выбором
отлаживают/начинают/останавливают отладчик и затем перезапускают снова.
46 Глав 2

Добавьте переменную к окну Watch.

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


в отладчике, определяют местоположение основного () функция в Blinky.c. Чуть
выше основного () объявление для переменной под названием ADC_DbgValue.
Выделите эту переменную, щелкните правой кнопкой, и выбор, “Добавьте
ADC_DbgValue” для Наблюдения 1 (Рис. 2.39).

Рисунок 2.39
Добавьте ADC_DbgValue для наблюдения 1.

Теперь запустите выполнение кода, и Вы сможете видеть переменное обновление


ADC_DbgValue в окне часов.

Сценарий моделирования подает напряжение к моделируемому


микроконтроллеру, который в свою очередь предоставляет преобразованные
результаты коду приложения.
Теперь добавьте ту же переменную к окну Logic Trace.
Отладчик µVision также имеет логическую функцию трассировки, которая
позволяет Вам визуализировать исторические ценности данной глобальной
переменной. В окне часов (или окне исходного кода), выделите имя переменной
AD_DbgValue, щелкните правой кнопкой, и выбор добавляет AD_DbgValue к
Анализатору логики (Рис. 2.40).
Рисунок 2.40
Добавление переменной к Анализатору логики.
Разработка программного обеспечения для семейства Cortex-M 47

Если окно Logic Analyzer не открывается автоматически избранный это от


панели инструментов (Рис. 2.41).

Рисунок 2.41
Открытие анализатора логики.

Теперь с выполнением кода, нажмите кнопку Min\Max Auto, которая установит


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

Рисунок 2.42
Анализатор логики.

Представление Now состояние пользовательских периферийных устройств.

Средство моделирования имеет модель целого микроконтроллера не только процессор


Cortex-M, таким образом, возможно исследовать состояние периферийных устройств
микроконтроллера непосредственно.
Выберите peripherals\General цель IO\GPIOB (Рис. 2.43).
48 Глав 2

Рисунок 2.43
Периферийное окно GPIO B.

Это откроет окно, которое отображает текущее состояние порта GPIO


микроконтроллера B. Когда моделирование работает, мы видим состояние контактов
порта. Если контакты настроены как исходные данные, мы можем вручную
установить и очистить их путем нажатия на отдельные поля “Pins”.
Можно сделать то же для ADC путем выбора ADC1 (Рис. 2.44).

Рисунок 2.44
Открытие периферийного устройства ADC просматривает
окно.
Разработка программного обеспечения для семейства Cortex-M 49

Когда код работает, возможно видеть текущую конфигурацию ADC и результатов


преобразования. Можно также вручную установить входное напряжение путем ввода
нового значения в поля Analog Inputs (Рис. 2.45).

Рисунок 2.45
Периферийное окно ADC.

Средство моделирования также включает терминал, который обеспечивает канал I\O


для микроконтроллеров UARTS.
50 Глав 2

Выберите view\serial windows\UART окно № 1.

Это открывает консольное окно типа, которое отображает вывод от выбранного


UART и также позволяет Вам входным значениям (Рис. 2.46).

Рисунок 2.46
Окно консоли UART.

Средство моделирования также имеет некоторые усовершенствованные


аналитические инструменты включая трассировку, покрытие кода и анализ
производительности.
Откройте меню View\Trace и выберите Данные Трассировки и Включите Запись
Трассировки (Рис. 2.47).

Рисунок 2.47
Включение инструкции Трассировки.

Это откроет окно Trace инструкции. Трассировка записывает историю каждой


инструкции, выполняемой (Рис. 2.48).
Разработка программного обеспечения для семейства Cortex-M 51

Рисунок 2.48
Трассировка инструкции.

Теперь откройте окна View\Analysis\Code Coverage и View\Analysis\Performance


Analyzer (Рис. 2.49).

Рисунок 2.49
Выбор анализатора производительности.

Окно “Performance Analysis” показывает количество вызовов к функции и ее


кумулятивное время выполнения (Рис. 2.50).

Рисунок 2.50
Окно Performance Analyzer.

Окно покрытия кода предоставляет обзор количества выполняемых строк и частично


выполняемых в каждой функции (Рис. 2.51).
52 Главы 2

Рисунок 2.51
Окно Code Coverage.

И “Покрытие Кода” и “Анализ Производительности” важны для проверки и


тестирования программного обеспечения. В Главе 7 “Отладка с CoreSight” мы будем
видеть, как эта информация может быть получена из реального микроконтроллера.

Конфигурация проекта
Теперь, когда Вы знакомы с основными характеристиками отладчика, мы можем
посмотреть более подробно на то, как код проекта создается.
Сначала выйдите из отладчика путем выбора сеанса отладки Debug\Start\Stop (Рис.
2.52).

Рисунок 2.52
Выйдите из отладчика.

Откройте диалоговое окно “Options for Target”.


Все ключевые глобальные настройки проекта могут быть найдены в “Опциях для
Целевого” диалогового окна (Рис. 2.53).
Разработка программного обеспечения для семейства Cortex-M 53

Рисунок 2.53
Опции для Целевого диалогового окна.

Вкладка Target определяет расположение памяти проекта. Основной шаблон


определяется при создании проекта. На этом микроконтроллере существует 128K
внутренней Флэш-памяти и 20K SRAM. Если необходимо определить более сложное
расположение памяти, возможно создать дополнительные регионы памяти для
подразделения энергозависимой и энергонезависимой памяти (Рис. 2.54).

Рисунок 2.54
Меню Target определяет карту распределения памяти проекта.

Чем более сложная карта распределения памяти выше разделила внутренний Flash на
два блока и определила, тем более низкий блок Flash как регион по умолчанию для
кода и постоянных данных. Ничто не будет помещено в верхний блок, если Вы явно
не скажете компоновщику делать это. Точно так же SRAM был разделен на два
региона, и верхний регион не использован, если Вы явно не говорите компоновщику
использовать его. Когда компоновщик разрабатывает проект, он ищет маркировку
кода “СБРОСА”. Компоновщик затем помещает код сброса в базе в регионе кода,
определяемом как регион Запуска. Первоначальный код Запуска запишет все
внутренние SRAM для обнуления, если Вы не отметите поле NoInit для данного
региона SRAM. Затем SRAM оставят с его значениями мусора запуска. Это может
быть полезно, если Вы хотите допускать мягкую перезагрузку, где некоторые
системные данные сохраняются.
54 Главы 2

Если Вы хотите поместить объекты (код или данные) в неиспользованный регион


памяти, выберите модуль проекта, щелкните правой кнопкой и откройте его
локальные опции (Рис. 2.55).

Рисунок 2.55
Открытие локальных опций проекта.

В его локальных опциях поля присвоения памяти позволяют Вам вызывать


различные объекты памяти в модуле в определенный регион кода (Рис. 2.56).

Рисунок 2.56
Выбор регионов памяти для модуля. Это переопределяет глобальные
настройки.

Назад в основных опциях для меню Target существует опция установить


Внешнюю Кристаллическую частоту, используемую микроконтроллером (Рис.
2.57).
Разработка программного обеспечения для семейства Cortex-M 55

Рисунок 2.57
Кристалл (Xtal) частота только используется средством
моделирования.

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


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

MDK-ARM Keil идет с двумя наборами библиотеки ANSI (Рис. 2.58). Первой является
стандартная библиотека, которая идет с компилятором ARM. Это полностью совместимо с
текущим ANSI, стандартным, и как таковым имеет большое место кода для использования
микроконтроллера. Вторая библиотека установила, Keil MicroLIB, эта библиотека была
записана в более ранний стандарт ANSI, стандарт C99. Эта версия стандарта ANSI больше
соответствует потребностям пользователей микроконтроллера (Таблица 2.5).

Рисунок 2.58
Выбор библиотеки MicroLIB.

Таблица 2.5: сравнение Размера между стандартными библиотеками ARM ISO и


библиотекой Keil MicroLIB
Сохранение
Процессор Объект Стандарт MicroLIB (%)
Библиотека
Кора-M0 (1) Ползунок otal 16,452 5996 64
Общее
количество
RO 19,472 9016 54
Общее
количество
Кора-M3\M4 Ползунок 2 библиотеки 15,018 5796 63
Общее
количество
RO 18,616 8976 54

Путем выбора MicroLIB Вы сохраните по крайней мере 50% стихов места кода
библиотеки ANSI библиотеки компилятора ARM. Так попытайтесь использовать
MicroLIB по мере возможности. Однако это имеет некоторые ограничения прежде
всего, это не поддерживает все функции в standardlib и вычислениях плавающей точки
двойной точности. В большом количестве приложений можно жить с этим.
56 Глав 2

“Поле галочки” Оптимизации перекрестного Модуля Использования включает


многопроходный процесс соединения, который полностью оптимизирует Ваш код
(Рис. 2.59). При использовании этой опции генерация кода изменяется, и выполнение
кода больше не может отображаться непосредственно на исходный код “C”. Не
используйте эту опцию, когда Вы тестируете и отлаживаете код, поскольку Вы не
сможете точно следовать за ним в окне исходного кода отладчика. Мы посмотрим на
другие опции, системное средство просмотра файловая и операционная система
позже в более поздних главах.

Рисунок 2.59
Оптимизация перекрестного модуля включает многопроходный процесс компиляции
для лучшей генерации кода.

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


(Рис. 2.60). Здесь, мы можем выбрать между генерацией автономной программы выбором,
“Создают Исполняемый файл”, или мы можем создать библиотеку, которая может быть
добавлена к другому проекту. Значение по умолчанию должно создать автономный
проект с отладочной информацией. Когда Вы доберетесь к концу проекта, Вы должны
будете
Рисунок 2.60
Выходное диалоговое окно.
Разработка программного обеспечения для семейства Cortex-M 57

выберите, “создают шестнадцатеричный файл” опция генерировать файл HEX32, который


может использоваться с производственным программистом. Если Вы хотите разработать
проект за пределами µVision, выбор Создают Пакетный файл, и это произведет a, Проект
name..bat пакетный файл DOS, который может быть выполнен из другой программы для
восстановления проекта за пределами IDE. По умолчанию название заключительного
изображения всегда является тем же как Вашим названием проекта. Если Вы хотите
измениться, это просто изменяет поле “Name of Executable”. Можно также выбрать
каталог для хранения всего проекта, компилятора, и компоновщик генерировал файлы.
Это гарантирует, что исходный каталог проекта только содержит Ваш код
первоисточника. Это может сделать жизнь легче при архивации проектов.

Вкладка Listing позволяет Вам включать списки компиляторов и файлы карты


компоновщика (Рис. 2.61). По умолчанию файл карты компоновщика включен.
Быстрый способ открыть файл карты состоит в том, чтобы выбрать окно проекта и
двойной щелчок по корню проекта. Файл карты компоновщика содержит большую
информацию, которая может казаться непостижимой сначала, но существует
несколько важных разделов, которые необходимо учиться читать и следить при
разработке реального проекта. Первой является “карта распределения памяти
изображения”. Это показывает Вам подробное расположение памяти Вашего проекта.
Каждый сегмент памяти показывают против его абсолютного местоположения в
памяти. Здесь можно отследить, какие объекты были расположены к который регион
памяти. Можно также видеть
Рисунок 2.61
Диалоговое окно Списка.
58 Глав 2

общая сумма ресурсов памяти выделила, местоположение стека, и также если этому
включают местоположение памяти "кучи" (Рис. 2.62).

Рисунок 2.62
Список символов файла карты компоновщика.

Второй раздел дает Вам обзор ресурсов памяти, требуемых каждым модулем и
библиотекой в проекте вместе с деталями полного требования к памяти.
Использование памяти изображений разломано на размер кода. Размер данных кода
является объемом энергонезависимой памяти, используемой для хранения значений
инициализации, которые будут загружены в переменные RAM на запуске. В простых
проектах эти данные инициализации сохранены как простая таблица ROM, которая
записана в корректные местоположения RAM кодом запуска. Однако в проектах с
большим объемом инициализируемых данных, компилятор будет переключать
стратегии и использовать алгоритм сжатия для уменьшения размера данных
инициализации.
Разработка программного обеспечения для семейства Cortex-M 59

На запуске распаковывается эта таблица, прежде чем данные записаны в переменные


местоположения в памяти. Ввод данных RO перечисляет объем энергонезависимой
памяти, используемой для хранения литералов кода. Использование SRAM
разделяется на инициализированные данные RW и деинициализирует данные ZI
(Рис. 2.63).

Рисунок 2.63
Список разделов файлов карты компоновщика.

Следующая вкладка является вкладкой User. Это позволяет Вам добавлять внешние
утилиты к процессу сборки. Меню позволяет Вам выполнять утилиту к пред - или
постобрабатывать файлы в проекте.
Утилита может также быть выполнена, прежде чем каждый модуль компилируется.
Дополнительно, можно также запустить отладчик, после того как процесс сборки
закончился (Рис. 2.64).
60 Глав 2

Рисунок 2.64
Пользовательское диалоговое окно.

Кодом, сгенерированным компилятором, управляет вкладка C\C11. Это управляет


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

Рисунок 2.65
Отсчитайте поля могут иметь три состояния.
Разработка программного обеспечения для семейства Cortex-M 61

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


согласованы серый
галочка. Здесь, серая галочка означает, “наследовали глобальные опции”, и это -
состояние по умолчанию.

Самая важная опция в этом меню является управлением оптимизацией (Рис. 2.66). Во
время разработки и отладки Вас должен оставить уровень оптимизации в нуле. Затем
сгенерированные кодированные карты непосредственно к высокоуровневому "C"
исходному коду и легко отладить. Поскольку Вы увеличиваете уровень оптимизации,
компилятор будет использовать все более агрессивные методы для оптимизации кода.
На высоком уровне оптимизации, сгенерированном коде
больше карты тесно к коду первоисточника, который затем делает использование
отладчика очень трудным. Например, когда Вы одноэтапный код, его выполнение
больше не будет следовать за ожидаемым путем через исходный код. Установка
точки останова может также быть бессистемной, поскольку сгенерированный код не
может существовать на той же строке как исходный код. По умолчанию компилятор
генерирует наименьшее изображение. Если необходимо получить максимальную
производительность, можно выбрать опцию “Optimize for Time”. Затем стратегия
компилятора будет изменена для генерации самого быстрого исполняемого файла
код (Рис. 2.67).

Рисунок 2.66
Локальные опции модуля.
62 Главы 2

Рисунок 2.67
Диалоговое окно C\C11.

Меню компилятора также позволяет Вам вводить любой #defines, который Вы хотите
передать исходному модулю, когда это компилируется. При структурировании
проекта по нескольким каталогам, можно также добавить локальный, включают пути
к каталогам с заголовочными файлами проекта. Текстовое поле Misc Controls
позволяет Вам добавлять любые переключатели компилятора, которые
непосредственно не поддерживаются в главном меню. Наконец, полная строка
управления компилятором отображена, это включает опции CPU, проект включает
пути и пути к библиотеке и сделать файлы зависимости.
Разработка программного обеспечения для семейства Cortex-M 63

Существует также ассемблерное Окно настроек, которое включает многие из тех же


опций как меню “C\C11” (Рис. 2.68). Однако большая часть проекта Cortex-M записана
полностью в “C \C11”, таким образом, с удачей Вы никогда не должны будете
использовать это меню!.

Рисунок 2.68
Ассемблерное диалоговое окно.
64 Главы 2

Рисунок 2.69
Диалоговое окно Компоновщика.

По умолчанию меню Linker импортирует расположение памяти из меню Target (Рис.


2.69). Это расположение памяти преобразовывается в “точечный” файл
компоновщика. Точечный файл предоставляет текстовое описание расположения
памяти компоновщику, таким образом, это может создать заключительное
изображение. Пример точечного файла показывают ниже.
*************************************************************
Файл Описания Загрузки вразброс *** сгенерирован uVision ***
*************************************************************
LR_IROM1 0x00000000 0x00040000 {; регион загрузки size_region
ER_IROM1 0x00000000 0x00040000 {; загрузитесь обращаются к 5 адресам
выполнения *.o (СБРОС, 1 Первое)
* ($Sections InRoot$)
.ANY (1RO)
}
RW_IRAM1 0x10000000 0x00004000 {; данные RW
.ANY (1RW 1 ZI)
}
RW_IRAM2 0x2007C000 0x00008000 {
.ANY (1RW 1 ZI)
}
}
Разработка программного обеспечения для семейства Cortex-M 65

Точечный файл определяет ROM и регионы RAM и сегменты программы, которые


должны быть помещены в каждый сегмент. Точечный файл в качестве примера
сначала определяет регион ROM 256K. Вся эта память выделяется в одном банке.
Точечный файл также говорит компоновщику помещать сегмент сброса, содержащий
таблицу векторов в начале этого раздела. Затем, точечный файл говорит
компоновщику помещать все остающиеся энергонезависимые сегменты в этот регион.
Точечный файл также определяет два банка SRAM 16K и 32K. Компоновщику затем
разрешают использовать и страницы SRAM для инициализированных и
неинициализированных переменных. Это - простое расположение памяти, которое
отображается непосредственно на память микроконтроллеров. Если необходимо
использовать более сложное расположение памяти, можно добавить регионы
дополнительной памяти в меню Target, и это будет отражено в точечном файле.
Однако, при необходимости в сложной карте распределения памяти, которая не может
быть определена через меню Target затем, необходимо будет записать собственный
точечный файл. Прием здесь должен стать настолько близким, как Вы можете с меню
Target и затем вручать редактированию точечный файл.

При использовании собственного точечного файла необходимо затем снять флажок с


“Расположением Памяти использования от Целевого Диалогового окна” и затем
вручную выбрать новый точечный файл с помощью текстового поля Scatter File (Рис.
2.70).

Рисунок 2.70
Используя пользовательский точечный файл.

Упражнение 2.2 Аппаратная отладка


В этом разделе мы посмотрим на конфигурирование отладчика для использования
аппаратного интерфейса отладки, а не внутреннего средства моделирования. В этом
осуществлении мы будем использовать плату Исследования STM32F7, но
инструкции ниже могут быть применены к любой другой аппаратной установке
отладки. При использовании другой платы, необходимо установить пакет семейства
устройств для микроконтроллера, используемого на плате. В примерах пакета
устройства обычно будет проект Blinky.
66 Глав 2

Откройте установщик пакета.


Выберите вкладку Boards и “Учебные Примеры Руководства Разработчиков”.
Выберите вкладку Example и Копию “Исключая 2.2 Аппаратными
Отладками”.
Проект, показанный здесь, для платы Исследования STM32F7.
Подключите плату Исследования к ПК с помощью USB мини-коннектор.
Разработайте проект.
Проект создается и создает точно таким же образом как версия средства
моделирования.
Откройте Опции для Целевого диалогового окна и вкладки Debug (Рис. 2.71).

Рисунок 2.71
Выбор аппаратных средств отлаживает интерфейс.

В меню Debug опция “Use” была переключена для выбора аппаратного


отладчика, а не средства моделирования. Мы можем также выбрать аппаратный
интерфейс отладки. Для платы Исследования используется отладчик Ссылки ST.
Разработка программного обеспечения для семейства Cortex-M 67

Рисунок 2.72
Установка алгоритма программирования Flash от диалогового окна Настроек
Утилит.
Теперь откройте меню утилит (Рис. 2.72).

Когда проект будет создан, меню Utilities отметят поле “Use Debug Driver”. Это
вынудит программиста Flash использовать тот же аппаратный интерфейс, выбранный
в меню Debug. Однако меню Utilities позволяет Вам выбирать инструмент для
программирования Флэш-памяти микроконтроллера. Это может быть другим
интерфейсом отладки или внешним инструментом, таким как инструмент Silicon
Vendor Bootloader.
Наиболее распространенные проблемы программирования Flash упоминаются ниже
(Рис. 2.73).
Рисунок 2.73
Цель обновления должна быть выбрана для автоматического программирования Flash, когда
отладчик запускается.
68 Глав 2

Одна точка, которую стоит отметить в меню Utilities, является “Целью обновления
перед Отладкой” поля галочки.

Когда эта опция будет отмечена, Флэш-память будет повторно запрограммирована,


когда отладчик запускается. Если это не проверяется затем, необходимо вручную
повторно программировать Flash путем выбора Flash \Download от основной панели
инструментов (Рис. 2.74).

Рисунок 2.74
Вручную загрузка программы отображает к Flash.

Если будет программирование задач, Флэш-память, то Вы получите следующее


ошибочное всплывающее окно окна (Рис. 2.75).

Рисунок 2.75
Программная ошибка Flash.

Окно вывода сборки сообщит о дальнейших сообщениях диагностики. Наиболее


распространенная ошибка является недостающим алгоритмом Flash. Если Вы видите,
что следующее сообщение проверяет, что “опции для target\utilities” меню настроены
правильно.
Никакой Алгоритм, найденный для: 00000000-й 000032A3H
Стирание пропускается!

Когда отладчик запустится, он проверит содержание Flash против изображения


программы. Если Flash не соответствует, текущее изображение, Вы получите ошибку
несоответствия памяти, и отладчик не запустится. Это означает, что изображение
Flash устарело, и текущая версия должна быть загружена во Флэш-память (Рис. 2.76).
Разработка программного обеспечения для семейства Cortex-M 69

Рисунок 2.76
Ошибка проверки Flash.

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

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


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

Вы заметите, что некоторые функции, доступные в средстве моделирования, не


присутствуют при использовании аппаратного модуля. Это Трассировка
Инструкции, Покрытие Кода и окна Performance Analysis. Эти функции доступны с
аппаратной отладкой, но Вам нужно больше интерфейса передового оборудования
для получения их. У нас будет более глубокий взгляд на систему отладки CoreSight в
Главе 7 “Отладкой с CoreSight”.

Заключение
К концу этой главы необходимо смочь установить основной проект Cortex-M, создать
код и смочь отладить его в средстве моделирования или на подходящем аппаратном
модуле. В следующей главе мы начнем смотреть на семейство Cortex-M процессоров
более подробно и затем продолжать смотреть на некоторые практические проблемы,
вовлеченные в разработку программного обеспечения для работы их.
Эта страница, намеренно
оставленная незаполненный
CHPTER3

Архитектура Cortex-M

Введение
В этой главе мы более внимательно рассмотрим в архитектуре процессора Cortex-
M. Объем этой главы сконцентрируется на процессоре Cortex-M3. После того как у
нас есть твердое понимание Коры-M3, мы посмотрим на основные отличия в Коре-
M0, Коре-M01 и Коре-M4. Существуют некоторые значительные дополнения в
процессоре Cortex-M7, и мы посмотрим на них в Главе 6 “Процессор Cortex-M7”.
Через главу существует много упражнений. Они дадут Вам более глубокое
понимание каждой темы и могут использоваться в качестве ссылки при разработке
собственного кода.

Система команд Cortex-M


Поскольку мы видели в Главе 1 “Введение в семейство процессоров Cortex-M”,
процессоры Cortex-M являются основанными на RISC процессорами, и как таковой
имеют маленький набор инструкций.
Кора-M0 имеет всего 56 инструкций, Кора-M3 имеет 74, и Кора-M4 имеет 137 с
опцией дополнительных 32 для сопроцессора для операций с плавающей точкой.
Центральные процессоры ARM ARM7 и ARM9, которые первоначально
использовались в микроконтроллерах, имеют две системы команд ARM (32 бита)
система команд и Ползунок (16 битов) система команд. Система команд ARM была
разработана для получения максимальной производительности от ЦП, в то время
как система команд Ползунка дала хорошую плотность кода, чтобы позволить
программам вписываться в ресурсы ограниченной памяти маленького
микроконтроллера. Разработчик должен был решить, какая функция была
скомпилирована с системой команд ARM и который был скомпилирован с
системой команд Ползунка. Затем две группы функций могли
“взаимодействоваться” вместе для создания заключительной программы. Система
команд Cortex-M основана на более ранней 16-разрядной системе команд Ползунка,
найденной в процессорах ARM, но расширяет инструкцию по Ползунку создать
объединенную систему команд со смешением 16-и 32-разрядные инструкции (Рис.
3.1).
Руководство разработчика по семейству процессоров Cortex-M.
DOI: http://dx.doi.org/10.1016/B978-0-08-100629-0.00003-7 71
© 2016 Elsevier Ltd. Все права защищены.
72 Главы 3

Рисунок 3.1
ARM7 и ЦП ARM9 имели отдельные 32-разрядные и 16-разрядные
системы команд. Процессор Cortex-M имеет единственную систему команд,
которая является смешением 16-и 32-разрядный
инструкции.

Система команд Cortex-M, названная Ползунком 2, разработана, чтобы быть


хорошей целью для инструментов компилятора. Хорошие новости - то, что Ваш
целый проект Cortex-M может быть кодирован на высокоуровневом языке, таком
как “C/C11” без потребности в кодированном ассемблере любой руки. Полезно
смочь “считать” Ползунок 2 ассемблерных кода через отладчик
Окно Disassembly для проверки то, что составил компилятор, но необходимо будет
крайне редко записать ассемблерную подпрограмму. Существует некоторый
полезный Ползунок 2 инструкции, которые не являются достижимым
использованием языка “C”, но большинство наборов инструментальных средств
компилятора предоставляет внутренние инструкции, которые могут
использоваться для доступа к этим инструкциям из кода “C”.

Модель программиста и регистры ЦП


Процессоры Cortex-M наследовали RISC ARM, загрузку, и хранят принцип действия.
Это означает, что, чтобы сделать любой вид обработки данных, инструкция, такая как
ADD или ВЫЧЕСТЬ данные должна сначала быть загружена в регистры ЦП;
инструкция по обработке данных выполняется, и результат затем хранится назад в
оперативной памяти. Это означает это
код, выполняющийся на процессоре Cortex-M, вращается вокруг центральных
регистров ЦП (Рис. 3.2).
Архитектура Cortex-M 73

Рисунок 3.2
Регистры ЦП Cortex-M состоят из 16 регистров данных, регистра состояния
программы и четырех специальных функциональных регистров. R13 R15 используется
в качестве указателя вершины стека, регистра ссылки и счетчика команд. R13 является
окруженным валом регистром, который позволяет ЦП Cortex-M работать с двойными
стеками.

На всех процессорах Cortex-M регистровый файл ЦП состоит из 16 регистров данных,


сопровождаемых Регистром состояния программы (PSR) и группой регистров
конфигурации. Все регистры данных (R0 R15) 32 бита шириной и могут быть
получены доступ всем Ползунком 2 загрузки и инструкции по хранилищу. К
остающимся регистрам ЦП могут только получить доступ две специализированных
инструкции, Регистр Перемещения к Специальному Регистру (MRS) и Перемещение
Специальные Регистры для Регистрации (MSR). R0 R12 Регистров является
регистрами обычного пользователя и используется компилятором, как он считает
целесообразным. R13 R15 регистров имеет специальные функции. R13 используется
компилятором в качестве указателя вершины стека, это - на самом деле окруженный
валом регистр с двумя регистрами R13. Когда процессор Cortex-M выходит из сброса,
второй регистр R13 не включен и выполнения процессора в “простом” режиме с
одним указателем вершины стека, называемым Основным указателем вершины стека
(MSP). Возможно включить второй регистр R13 путем записи в Регистр управления
затем, процессор будет настроен для выполнения с двумя стеками. Мы посмотрим на
это более подробно в Главе 5 “Функции Передовой архитектуры”, но на данный
момент мы будем использовать процессор Cortex-M в его режиме по умолчанию.
После указателя вершины стека у нас есть R14 регистр ссылки. Когда процедуру
называют, обратный адрес автоматически хранится в R14, регистре ссылки. Начиная с
Ползунка 2 системы команд не содержат инструкцию по ВОЗВРАТУ, когда процессор
достигает конца процедуры, это использует команду перехода на R14 для возврата.
Наконец, R15 является счетчиком команд, можно воздействовать на этот регистр
точно так же, как все другие, но Вы не должны будете делать этого во время
нормального выполнения программы. Регистры ЦП
74 Главы 3

PRIMASK, FAULTMASK и BASEPRI используются для временного


отключения обработки прерываний, и мы посмотрим на них далее в этой
главе.

Регистр состояния программы


PSR как его имя подразумевает, содержит весь (Рис. 3.3) флагов состояния ЦП.

Рисунок 3.3
Регистр состояния Программы содержит несколько групп флагов ЦП. Они включают
коды условий (NZCVQ), биты состояния Прерывания инструкции Continuable (ICI),
Если флаг Then и текущее число исключения.

PSR имеет много полей псевдонима, которые являются версиями маскированными


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

Рисунок 3.4
Регистр состояния Программы имеет три регистра псевдонима, которые обеспечивают доступ
к определенным подобластям или Регистру состояния Программы. Следовательно, родовое
название для регистра состояния программы является xPSR.

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

Старшие значащие четыре бита xPSR являются битами кода условия,


Отрицательными, Нуль, Несут, и переполнение. Они будут установлены и очищены
в зависимости от результатов инструкции по обработке данных. Результат Ползунка
2 инструкции по обработке данных может установить или очистить эти флаги.
Однако обновление этих флагов является дополнительным.
Архитектура Cortex-M 75

SUB R8, R6, № 240 Выполняет вычитание и не обновляет НИЖНИЕ ИНДЕКСЫ флагов кода условия
R8, R6, № 240 Выполняет вычитание и обновляет флаги кода условия

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


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

Q бит и влажные инструкции по математике


Q укусил, флаг насыщенности, процессоры Cortex-M3/M4 и Cortex-M7 имеют
специальный набор инструкций, названных влажными инструкциями по математике.
Если нормальная переменная достигнет своего максимального значения, и Вы
увеличиваете ее далее, то она прокрутится вокруг для обнуления. Точно так же, если
переменная достигнет своего минимального значения и будет затем постепенно
уменьшена, то она прокрутится вокруг к максимальному значению (Рис. 3.5).

Рисунок 3.5
Нормальная переменная будет трансформация для обнуления, когда она поразит
свое максимальное значение. Это очень опасно в алгоритме управления. ЦП Cortex-
M поддерживает насыщаемые инструкции по математике, которые упорно
продолжают их максимальные и минимальные значения.

В то время как это - проблема для большинства приложений, это особенно серьезно
для приложений, таких как важные приложения безопасности и блок управления
приводом. Cortex-M3/M4 и насыщаемые инструкции по математике M7
предотвращают этот вид “списка вокруг”. При использовании влажных инструкций по
математике если переменная достигнет своего максимального или минимального
значения, то она будет придерживаться (насыщают) в том значении. После того как
переменная насыщала бит Q, будет установлен. Q укусил, “липкий” бит и должен
быть очищен кодом приложения. Стандартные инструкции по математике не
используются компилятором “C” по умолчанию. Если Вы хотите использовать
влажные инструкции по математике, необходимо получить доступ к ним при помощи
компилятора intrinsics или CMSIS-базовых функций.

uint32_t __ SSAT (uint32_t значение, uint32_t находился)


uint32_t __ USAT (uint32_t значение, uint32_t находился),
76 Глав 3

Прерывания и инструкции по мультициклу


Следующее поле в PSR является “Прерыванием Инструкция Continuable” (ICI) и,
“Если Затем” (IT) инструкция отмечает. Большинство инструкций по процессору
Cortex-M выполняется в единственном цикле. Однако некоторые инструкции, такие
как Хранилище Загрузки Несколько, Умножьтесь и Разделитесь, берут несколько
циклов. Если прерывание происходит, в то время как эти инструкции выполняются,
они должны быть приостановлены, в то время как прерывание подается. После того
как прерывание было подано, мы должны возобновить инструкцию по мультициклу.
Полем ICI управляет процессор Cortex-M, таким образом, Вы не должны делать
ничего специального в своем коде приложения. Это действительно означает, что,
когда исключение повышено, много банка инструкции по циклу будет
приостановлена, поле ICI будет обновлено, и достижение запуска Вашей процедуры
прерывания будет всегда брать то же количество циклов независимо от инструкции, в
настоящее время выполняемой ЦП.

Условное выполнение — если затем блоки


Поскольку мы видели в Главе 1 “Введение в Семейство процессоров Cortex-M”,
большинство процессоров Cortex-M имеет трехэтапный конвейер. Это позволяет
ВЫБОРКУ, ДЕКОДИРУЮТ
и ВЫПОЛНИТЕ единицы для работы параллельно значительно улучшением
производительности процессора. Однако существует недостаток, что каждый раз
процессор делает переход, конвейер должен быть сброшен и снова наполнен. Это
представляет большой хит на производительности, поскольку конвейер должен быть
снова наполнен, прежде чем выполнение инструкций может возобновиться. Кора-M3
и-M4 уменьшают штраф ответвления при наличии единицы вызова команды, которая
может выполнить спекулятивные целевые выборки ответвления из возможного адреса
ответвления, таким образом, выполнение целей ответвления может запуститься ранее.
Однако для маленьких условных переходов процессор Cortex-M имеет другой прием
его рукав. Для маленького условного перехода, например

Если (Y 55 0x12C)
{I11;
} еще
{я —;}

который компилирует меньше чем в 4 инструкции, процессор Cortex-M может


скомпилировать код как ЕСЛИ ЗАТЕМ блок условия. Инструкции в, ЕСЛИ ЗАТЕМ
блок расширяется с помощью Таблицы 3.1 кода условия. Этот код условия
сравнивается с состоянием Флагов Кода условия в PSR. Если условие будет
соответствовать состоянию флагов, то инструкция будет выполняться, если это не
сделает и инструкция все еще введет конвейер, но не будет выполняться как “Никакая
Операция” (только для указанных целей) инструкция. Эта техника устраняет
ответвление и следовательно избегает потребности сбросить и снова наполнить
конвейер. Даже при том, что мы вставляем инструкции по NOP, мы все еще
добираемся, лучшие уровни производительности, чем при помощи более стандартного
выдерживают сравнение и переходят подход.
Архитектура Cortex-M 77
Таблица 3.1: коды условий
Инструкции

Код условия Протестированные Флаги xPSR Значение


EQ Z51 Равный
NE Z50 Не равный
Выше или то же
CS или HS C51 (Неподписанное)
CC или LO C50 Ниже (Неподписанный)
MI N51 Отрицательный
МН N50 Положительный или нуль
VS V51 Переполнение
VC V50 Никакое переполнение
Привет! C 5 1 и Z 50 Выше (Неподписанный)
Ниже или то же
LS C 5 0 или Z 51 (Неподписанное)
Больше, чем или равный (Со
GE N5В знаком)
LT N! 5 В Менее, чем (Со знаком)
GT Z50и5ВN Больше, чем (Со знаком)
Меньше чем или равный
LE Z 5 1 и N! 5 В (Со знаком)
AL Ничего Всегда выполняйтесь

Инициировать, ЕСЛИ ЗАТЕМ блок, мы используем инструкции по обработке данных


обновить коды условий PSR. По умолчанию большинство инструкций не обновляет
коды условий, если у них нет суффикса S, добавленного к ассемблерному коду
операции. Это дает компилятору большую гибкость в применении ЕСЛИ ЗАТЕМ
условие.

ADDS R1, R2, R3 //выполняют и добавляют и устанавливают флаги xPSR


ADD R2, R4, R5//Делают некоторые другие инструкции, но не изменяют xPSR ADD R5, R6,
R7

IT VS//, ЕСЛИ ЗАТЕМ условное выражение блока на первой инструкции ADD SUBVS R3,
R2, R4

Так, наш “C”, ЕСЛИ оператор THEN ELSE может быть скомпилирован в четыре
инструкции.

CMP r6, #0x12C


ITE EQ
STREQ r4, [r0, #0x08]
STRNE r5, [r0, #0x04]

CMP выдерживают сравнение, инструкция используется для выполнения теста и


установит или очистит флаг Zero Z в PSR. ЕСЛИ ЗАТЕМ блок создается
инструкцией по Если затем (IT). Инструкциям IT всегда следуют одна условно
исполняемая инструкция и дополнительно до четырех условно исполняемых
инструкций. Формат инструкции IT следующие:
IT x y z
конусовидный
78 Глав 3

X, y, и z параметры включают вторым, третьим, и четвертым инструкциям быть


частью условного блока. Может быть далее ЗАТЕМ ИЛИ ИНАЧЕ инструкции.
Конусовидный параметр является условием, относился к первой инструкции. Так,
NE ITTTE четыре инструкции, Если Затем блок с три ЗАТЕМ инструкции, которые выполняются
когда Z 5 1, сопровождаемый ЕЩЕ инструкцией, которая выполняется когда Z51
ITE GE Две инструкции, ЕСЛИ ЗАТЕМ блок с одним ЗАТЕМ инструкция, которая выполняется когда
N 5 В и один ЕЩЕ инструкция, которая выполняется когда N! 5 В

Использование условного исполняемого файла, ЕСЛИ ЗАТЕМ блоки оставлен до


компилятора. Обычно на низких уровнях оптимизации, ЕСЛИ ЗАТЕМ блоки не
используются, это высказывает хорошее мнение отладки. Однако на высоких
уровнях оптимизации, компилятор использует ЕСЛИ ЗАТЕМ блоки. Так, обычно не
будет никаких странных побочных эффектов, представленных условным методом
выполнения, но существует несколько правил принять во внимание.

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

В-третьих, единственное время, Вы действительно заметите выполнение, ЕСЛИ


ЗАТЕМ блок условия будет во время отладки. Если Вы одноэтапный отладчик через
условный оператор, условный код, будет казаться, выполнится, даже если условие
будет ложью. Если Вы
не знают о блоках кода условия Cortex-M, это может быть большой причиной
беспорядка!

Следующий бит в PSR является T, или Ползунок укусил. Это - бит прежней версии от
более раннего ARM ЦП и установлено на один при очистке этого бита он вызовет
исключение отказа. В предыдущих центральных процессорах T укусил,
использовался, чтобы указать, что Ползунок 16-разрядная система команд работал.
Это включено в PSR Cortex-M, чтобы поддержать совместимость с более ранними
центральными процессорами ARM и позволить 16-разрядному коду Ползунка
прежней версии выполняться на процессорах Cortex-M. Поле Final в PSR является
числовым полем Исключения. Единица Прерывания Вложенного вектора Коры
может поддерживать до 256 источников исключения. Когда исключение
обрабатывается, число исключения хранится здесь. Поскольку мы будем видеть
позже, что это поле не используется кодом приложения при обработке прерывания,
хотя это может быть полезная ссылка при отладке.
Упражнение 3.1 Влажная математика и условное выполнение
В этом осуществлении мы будем использовать простую программу, чтобы
исследовать регистры ЦП и использовать влажные инструкции по математике. Мы
также восстановим проект использовать условное выполнение.
Архитектура Cortex-M 79

Откройте установщик пакета.


Выберите вкладку Boards и “Учебные Примеры Руководства Разработчиков”.
Выберите вкладку Example и Копию “Исключая 3.1 Насыщенностью и Условным
Выполнением”.
интервал a, range5300; символ
c; международное основное
(пустота) {
в то время как (1) {
для (50; a, диапазон; a11) {c 5
a;

}}

Эта программа увеличивает целочисленную переменную от 0 до 300 и копирует


ее в символьную переменную “c”.
Создайте программу и запустите отладчик.
Добавьте эти две переменные к Анализатору логики и запустите программу (Рис. 3.6).

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

В окне Logic Analyzer мы видим, что, в то время как целочисленная переменная


работает как ожидалось, символ насыщает, когда это достигает 255 и
“переворачивается” к нулю и начинает увеличивать снова.
Остановите отладчик и измените код как показано ниже для использования
насыщаемой математики.
Интервал #define Q_FLAG
0x08000000 a, расположитесь 5
300;
символ c;
неподписанный
международный
APSR; международное
основное (пустота) {в
то время как (1) {

для (a50; a, диапазон; a11) {c


5 __ SSAT (a, 9);
}
}}
80 Глав 3

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


на девятом бите целочисленного значения. Это позволяет значениям 0 255 быть
записанными в значение байта, любые другие значения будут насыщать в
максимальном допустимом значении 255.
Разработайте проект и запустите отладчик.
Выполните код и просмотрите содержание переменных в Анализаторе логики (Рис.
3.7).

Рисунок 3.7
Используя инструкции по насыщенности, переменная cal “насыщает” на
выбранной разрядной границе.

Теперь символьная переменная насыщает, а не “rollingover”. Это все еще


неправильно, но не так потенциально катастрофически неправильно как
динамический случай. При изменении разрядного граничного значения “c” будет
насыщать в нижних значениях.
В окне Registers нажмите на регистр xPSR для просмотра флагов (Рис. 3.8).

Рисунок 3.8
То, когда переменная насыщает, Q укусил в xPSR, будет
установлено.

В дополнение к нормальным флагам кода условия NVCZ установлена


насыщенность Q бит.
Архитектура Cortex-M 81

Остановите отладчик и измените код как показано ниже.


#define Q_FLAG 0x08000000
интервал a, диапазон 5 300; символ c; неподписанный
международный APSR; зарегистрируйте неподписанный
интервал apsr __ asm ("apsr");
международное
основное (пустота)
{в то время как (1) {
для (a50; a, диапазон; a11) {c
5 __ SSAT (a, 9);
}
APSR 5 __ get_APSR ();
если (APSR&Q_FLAG) {
range22;
}
apsr 5 apsr&BQ_FLAG;
}}

После того как мы записали в символьную переменную, возможно считать APSR


(псевдоним приложения xPSR) и проверка, если Q укусил, установлен. Если
переменная насыщала, мы можем принять некоторые меры по ликвидации
последствий и затем очиститься, Q укусил для следующего повторения.
Разработайте проект и запустите отладчик.
Выполните код и наблюдайте переменные в окне Watch.

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


постепенно код будет корректировать переменную диапазона, пока выходные данные
не впишутся в символьную переменную.
Набор устанавливает контрольные точки на строках 19 и 22 для включения контроля
битов Q (Рис. 3.9).

Рисунок 3.9
Точки останова на строках 19 и 22.

Сбросьте программу и затем выполните код, пока первая точка останова не будет
достигнута.
Откройте окно Disassembly и исследуйте код, сгенерированный на контроль битов Q.
если
(xPSR&Q_FLAG)
{MOV r0, r1
LDR r0, [r0, #0x00] TST
r0, #0x8000000 BEQ
0x080003E0
20: range22;
82 Главы 3

} еще {
LDR r0, [ПК, #44]; @0x08000400
LDR r0, [r0, #0x00]
SUB r0, r0, #0x01
LDR r1, [ПК, #36]; @0x08000400
STR r0, [r1, #0x00]
B 0x080003E8
заблокированный 5 1;
}
MOV r0, #0x01
LDR r1, [ПК, #32]; @0x08000408
STR r0, [r1, #0x00]

Также обратите внимание на значение в счетчике состояния, это - количество


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

Рисунок 3.10
Значение состояний противостоит в первой точке останова.

Теперь выполните код, пока он не поражает следующую точку останова, и


снова обратите внимание на счетчик состояния (Рис. 3.11).

Рисунок 3.11
Значение состояний противостоит во второй точке останова.

Остановите отладчик и откройте вкладку “Options for Target/C” (Рис.


3.12).
Архитектура Cortex-M 83

Рисунок 3.12
Измените уровень оптимизации, и также “выбор оптимизирует для
скорости”.

Измените уровень оптимизации от Уровня 0 до Уровня 3 и установите флажок


“Optimize for speed”.
Закройте Опции для Цели и восстановите проект.
Теперь повторите измерение количества цикла путем выполнения к двум точкам
останова
(Рис. 3.13).

Рисунок 3.13
Цикл значит первую и вторую точку останова.
84 Главы 3

Теперь контроль битов Q берет 7 циклов в противоположность оригиналу 14.


Исследуйте дизассемблированный код на контроль битов Q.
если (xPSR&Q_FLAG) {
F0116F00 TST 0x08000336 r1, #0x8000000
диапазон-;
} еще {
ITTE NE
STRNE r1, [r0, #0x08]
заблокированный 5 1;
}
STREQ r4, [r0, #0x04]

В более высоких уровнях оптимизации компилятор переключился от теста и


команд перехода к условным инструкциям по выполнению. Здесь, ассемблер
выполняет поразрядное И тест на R1, который содержит текущее значение xPSR.
Это установит или очистит флаг Z в xPSR. Системы команд ITT условный блок с
двумя инструкциями. Инструкции в этом блоке выполняют вычитание и
хранилище, если флаг Z является нулем; иначе они проходят через конвейер как
только для указанных целей инструкции.
Удалите точки останова. Работайте код в течение нескольких секунд затем
останавливают его.
Установите точку останова на одной из условных инструкций (Рис. 3.14).

Рисунок 3.14
ЕСЛИ ЗАТЕМ инструкции, следовавшие условными инструкциями.

Запустите код, работающий снова.

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

Карта распределения памяти Cortex-M и шины


В то время как устройство Cortex-M каждого производителя имеет различные
периферийные устройства и емкости памяти, ARM определил шаблон основной
памяти, которого должны придерживаться все устройства. Это обеспечивает a
Архитектура Cortex-M 85

стандартное расположение так весь поставщик, если память и периферийные


устройства расположены в тех же блоках памяти (Рис. 3.15).

Рисунок 3.15
Карта распределения памяти Cortex-M имеет стандартный шаблон, который разделяет
диапазон адресов на 4 ГБ на определенные регионы памяти. Этот шаблон памяти
характерен для всех устройств Cortex-M.

Шаблон памяти Cortex-M определяет восемь регионов, которые покрывают 4 ГБ


адресного пространства процессора Cortex-M. Первые три региона - каждый 0,5 ГБ в
размере и выделены пространству исполняемого кода, внутреннему SRAM и
внутренним периферийным устройствам. Следующие два региона выделены внешней
памяти и устройствам с отображенной памятью, оба региона составляют 1 ГБ в
размере. Заключительные три региона составляют пространство памяти процессора
Cortex-M и содержат регистры конфигурации для процессора Cortex-M и любых
определенных для поставщика регистров (Рис. 3.16).
86 Глав 3

Рисунок 3.16
В то время как процессор Cortex-M имеет много внутренних шин, они чрезвычайно
невидимы для разработчика программного обеспечения. Память
появляется как плоские 4 ГБ адресного пространства.

В то время как карта распределения памяти Cortex-M составляет линейных 4 ГБ


адресного пространства без разбитых на страницы регионов или сложных способов
адресации, память микроконтроллера и периферийные устройства подключены к
процессору Cortex-M многими различными шинами. Первые 0,5 ГБ адресного
пространства резервируются для исполняемого кода и кодовых констант. Этот регион
имеет два специализированных шин, шина ICODE используется для выборки
инструкций по коду, и шина DCODE используется для выборки кодовых констант. К
остающимся пространствам пользовательской памяти (внутренний SRAM и
периферийные устройства плюс внешний SRAM и периферийные устройства)
получает доступ отдельная системная шина. Пространство памяти процессора Cortex-
M имеет дополнительную частную периферийную шину. В то время как это может
выглядеть сложным, что касается Вашего кода приложения, что у Вас есть одно
бесшовное пространство памяти. Процессор Cortex-M имеет отдельные внутренние
шины для оптимизации его доступа к различным регионам памяти.

Как отмечалось ранее, большинство инструкций в Ползунке, 2 системы команд


выполняются в единственном цикле и Коре-M3, может дойти до 200 МГц, и на самом
деле некоторым проектам системы на микросхеме (SoC) удается получить процессор,
работающий еще быстрее. Однако текущая Флэш-память, используемая для хранения
программы, имеет время доступа приблизительно 50 МГц. Таким образом, существует
основная проблема вытаскивания инструкций из Флэш-памяти достаточно быстро для
питания процессора Cortex-M. При выборе микроконтроллера Cortex-M, важно
изучить таблицу данных, чтобы видеть, как Кремниевый Поставщик решил эту
проблему. Как правило, Флэш-память будет расположена как 64-или 128-разрядная
широкая память, таким образом, одно чтение от Флэш-памяти сможет загрузить
многоадресные команды. Эти инструкции затем сохранены в “единице” акселератора
памяти, которая затем подает инструкции к процессору Cortex-M как
Архитектура Cortex-M 87

необходимый. Акселератор памяти является формой простого блока кэш-памяти,


который разработан Кремниевым Поставщиком. Обычно, эта единица отключена,
после того, как сброшено, таким образом, необходимо будет включить ее, или
процессор Cortex-M будет работать непосредственно от Флэш-памяти. Общая
производительность процессора Cortex-M будет зависеть от того, как успешно эта
единица была реализована разработчиками микроконтроллера.

Буфер записи
Кора-M3 и Кора-M4 содержат однократный буфер записи данных. Это позволяет ЦП
превращать запись в буфер записи и продолжаться на следующую инструкцию, в то
время как буфер записи завершает запись к реальному SRAM. Это старается не
останавливать процессор, в то время как он ожидает записи для завершения. Если
буфер записи полон, ЦП вынужден ожидать, пока он не закончил свою текущую
запись. В то время как это обычно - прозрачный процесс к коду приложения,
существуют некоторые случаи, где необходимо ожидать, пока запись не закончилась
перед продолжающимся выполнением программы. Например, если мы включаем
внешнюю шину на микроконтроллере, необходимо ожидать, пока буфер записи не
закончил писать в периферийный регистр, и шина включена прежде, чем попытаться
получить доступ к памяти, расположенной на внешней шине. Процессор Cortex-M
предоставляет некоторые инструкции по барьеру памяти справиться с этими
ситуациями.

Инструкции по барьеру памяти


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

Таблица 3.2: инструкции по барьеру памяти

Инструкция Описание
Гарантирует, что все доступы памяти закончены, прежде чем новый доступ к
DMB памяти сделан
Гарантирует, что все доступы памяти закончены, прежде чем следующая
DSB инструкция выполняется
Гарантирует, что все предыдущие инструкции завершаются, прежде чем
ISB следующая инструкция
выполняемый. Это также сбрасывает конвейер ЦП
Системный блок управления
В дополнение к регистрам ЦП процессоры Cortex-M имеют группу конфигурации с
отображенной памятью и регистров состояния, расположенных около верхней части
карты распределения памяти, запускающейся в 0xE000 E008.
88 Глав 3

Мы посмотрим на основные функции, поддерживавшие этими регистрами в


остальной части этой книги, но сводка дана ниже (Таблицы 3.3).

Таблица 3.3: процессор Cortex имеет конфигурацию с отображенной памятью и


расположенные регистры состояния
в системном блоке управления
Разме
рв
Зарегистрироваться Слова Описание
Вспомогательное Позволяет Вам настраивать, как выполняются некоторые
управление 1 функции процессора
Зашитый идентификатор и числа пересмотра от ARM и
ИДЕНТИФИКАТОР ЦП 1 кремния
производитель
Управление
прерыванием и Обеспечивает Ожидают биты для SysTick и прерываний NMI
состояние 1 и
расширенное прерывание информация о Pending\active
Таблица векторов Программируемое смещение адреса для перемещения
смещается 1 Таблицы векторов в новое
местоположение в Flash или памяти SRAM
Прерывание приложения Позволяет Вам настраивать PRIGROUP и генерировать ЦП
и 1 и
управление сбросом сброс микроконтроллера
Конфигурация средств управления режимов ожидания
Системное управление 1 процессора
Конфигурация и Настраивает рабочий режим ЦП и некоторые исключения
управление 1 отказа
Приоритет обработчика Эти регистры содержат 8-разрядные приоритетные поля
систем 3 для настраиваемого
исключения процессора
Управление Показывает причину шины, управления памятью или отказа
обработчиком систем и 1 использования
состояние
Настраиваемое Показывает причину шины, управления памятью или отказа
состояние отказа 1 использования
Состояние серьезного
отказа 1 Шоу, какое событие вызвало серьезный отказ
Отказ диспетчера
памяти 1 Содержит адрес ячейки памяти, которая генерировала
адрес отказ памяти
Адрес отказа шины 1 Содержит адрес ячейки памяти, которая генерировала
отказ памяти

Система команд Cortex-M имеет инструкции по обращению, которые позволяют Вам


загружать и хранить 8-, 16-, и 32-разрядные количества. В отличие от ARM7 и ARM9,
16-и 32-разрядные количества не должны быть выровненные на границах слова или
полуслова (Рис. 3.17). Это дает компилятор и гибкость максимума компоновщика,
чтобы полностью упаковать память SRAM. Однако существует штраф, который будет
оплачен эту гибкость, потому что невыровненные передачи занимают больше времени
для выполнения. Система команд Cortex-M содержит загрузку и многоадресные
команды хранилища, которые могут передать несколько регистров и из памяти в
одной инструкции. Это берет несколько циклов процессора, но использует только
один 2 байта или 4 байтовых команды. Это допускает очень эффективное управление
стеком, копия памяти блока и т.д. Загрузка и многоадресные команды хранилища
только работают на выровненные данные слова. Так, при использовании
невыровненных данных компилятор вынужден использовать несколько отдельная
загрузка и инструкции по хранилищу достигнуть того же самого. В то время как Вы
полностью используете ценный внутренний SRAM, Вы потенциально увеличиваете
размер инструкции по приложению. Невыровненные данные для пользовательских
данных только, необходимо удостовериться, что стеки являются выровненным словом.
Начальное значение MSP определяется компоновщиком,
Архитектура Cortex-M 89

но второй указатель вершины стека Указатель стека процесса (PSP) включен и


инициализирован пользователем, так Вам решать для разбираний в нем. Мы
посмотрим на использование PSP в Главе 5 “Функции Передовой архитектуры”.

Рисунок 3.17
В отличие от этого, ранее ARM7 и центральных процессоров ARM9, процессор Cortex
может сделать невыровненные доступы памяти. Это позволяет компилятору и
компоновщику лучше всего использовать устройство SRAM.

Побитовая обработка
В маленькой встроенной системе часто необходимо установить и очистить отдельные
биты в SRAM и периферийных регистрах. При помощи стандартных инструкций по
обращению мы можем установить и очистить отдельные биты при помощи языка “C”
поразрядно И и ИЛИ команды, в то время как это работает хорошо, процессоры
Cortex-M предоставляют более эффективный метод побитовой обработки.

Процессор Cortex-M предоставляет метод, названный “соединение бита”, которое


позволяет отдельному SRAM и периферийным битам регистра быть
установленным и очищенными очень эффективным способом
(Рис. 3.18).

Рисунок 3.18
Разрядное соединение является техникой, которая позволяет первому 1 МБ
региона SRAM и первому 1 МБ периферийного региона
быть обращенным битом.
90 Глав 3

Первый 1 МБ или регион SRAM и первый 1 МБ периферийного региона определяются


как разрядные регионы полосы. Это означает, что каждая ячейка памяти в этих
регионах с побитовой адресацией. Так, на практике для сегодняшних
микроконтроллеров, все их внутренние SRAM и периферийные регистры с побитовой
адресацией. Соединение бита работает путем создания адреса слова псевдонима для
каждого бита реальной памяти или периферийного бита регистра. Так, 1 МБ реального
SRAM искажается к 32 МБ виртуального (Рис. 3.19) адресов слова.

Рисунок 3.19
Каждый бит в реальной памяти отображается на адресе слова в памяти
псевдонима.

Это означает, что каждый бит реального SRAM или периферийного регистра
отображается на адресе слова в разрядном регионе псевдонима полосы и путем
записи 1 с и 0s к адресу слова псевдонима, мы можем установить и очистить
местоположение бита реальной памяти. Точно так же, если мы пишем слово в
местоположение реальной памяти, мы можем считать разрядный адрес псевдонима
полосы для проверки текущего состояния немного в том слове. Для использования
разрядного соединения просто необходимо вычислить адрес слова в разрядном
регионе полосы, который отображается на местоположение бита в реальной памяти,
которую Вы хотите изменить. Затем создайте указатель на адрес слова в разрядном
регионе полосы. После того как это сделано, можно управлять реальной разрядной
ячейкой памяти путем чтения и записи в регион псевдонима через указатель.
Вычисление для адреса слова в разрядном регионе псевдонима полосы следующие:
Разрядное слово полосы обращается к основе полосы на 5 битов 1 (байтовое
смещение 3 32) 1 (разрядный номер 3 4)

Так, например, мы хотели считать и записать в бит 8 из регистра порта GPIO B на


типичном микроконтроллере Cortex-M, мы можем вычислить разрядный адрес
псевдонима полосы следующим образом:

GPIO B адрес регистра данных 5 0x40010C0C


Зарегистрируйте байтовое смещение от периферийного базового адреса 5
0x40010C0C 2 0x40000000
5 0x00010C0C

Разрядное слово полосы обращается к 5 ¦ 0x42000000 1 ¦ 0x000010C0C


0x20ÞÞ 1 ¦ 0x8 0x4Þ
5 0x422181A0

Мы можем определить указатель на этот адрес.


#define GPIO_PORTB_BIT8 5 (* ((энергозависимый неподписанный длинный *)
0x422181A0))
Архитектура Cortex-M 91

Теперь путем чтения и записи в этот адрес слова, мы можем непосредственно


управлять битом отдельного порта.
GPIO_PORTB_BIT8 5 1//установил контакт порта

Это скомпилирует в следующие ассемблерные инструкции:


Код операции Assembler
F04F0001 MOV r0, #0x01
4927 LDR r1, [ПК, #156]; @0x080002A8
6008 STR r0, [r1, #0x00]

Эта последовательность использует одну 32-разрядную инструкцию и две 16-


разрядных инструкции или в общей сложности 8 байтов. Если мы сравниваем это с
установкой контакта порта при помощи логического ИЛИ записать непосредственно в
регистр порта.
GPIOB-.ODR | 5 0x00000100;//Вовлек

Мы затем получаем следующую кодовую последовательность:


Код
операции Ассемблер
481E LDR r0, [ПК, #120]; @0x080002AC
6800 LDR r0, [r0, #0x00]
F4407080 ОРР r0, r0, #0x100
491C LDR r1, [ПК, #112]; @0x080002AC
6008 STR r0, [r1, #0x00]

Это использует четыре 16-разрядных инструкции и одну 32-разрядную инструкцию


или 12 байтов.

Использование разрядного соединения дает нам взаимовыгодную ситуацию, меньший


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

Можно найти некоторые инструменты компилятора, или библиотеки


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

Осуществите соединение на 3,2 бита


В этом осуществлении мы посмотрим на определение небольшой переменной
полосы, чтобы переключить контакт порта и сравнить его использование с
поразрядным И и ИЛИ инструкции.
Откройте установщик пакета.
Выберите вкладку Boards и “Учебные Примеры Руководства Разработчиков”.
Выберите вкладку Example и копию “Исключая Соединением 3,2 битов”.
92 Главы 3

В этом осуществлении мы хотим переключить контакт отдельного порта. Мы будем


использовать Порт B, укусил 8 контактов, поскольку мы уже сделали вычисление
для адреса слова псевдонима.
Так, теперь в коде “C” мы можем определить указатель на разрядный адрес полосы.
#define PortB_Bit8 (* ((энергозависимый неподписанный длинный *) 0x422181A0))

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


этот указатель.
PortB_Bit8 5 1;
PortB_Bit8 5 0;

Разработайте проект и запустите отладчик.


Включите временной анализ с debug\execution profiling\Show меню Time
(Рис. 3.20).

Рисунок 3.20
Позвольте профилю синхронизации показать время выполнения на
строку кода.

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


выполнения для каждой строки. Сравните время выполнения для разрядной
инструкции по полосе по сравнению с И и ИЛИ инструкций.

Откройте окно Disassemble и исследуйте код, сгенерированный на каждый метод


установки контакта порта.

Инструкции по соединению бита являются лучшим способом установить и


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

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


В дополнение к разрядной поддержке полосы Ползунок 2 системы команд имеют
ориентируемые инструкции некоторого специализированного бита. Некоторые из
этих инструкций не непосредственно доступны с языка “C” и поддерживаются
компилятором “внутренние” вызовы (Таблица 3.4).
Архитектура Cortex-M 93

Таблица 3.4: В дополнение к разрядному


соединению процессор Cortex-M3 имеет
некоторую специализированную побитовую
обработку
инструкции

BFC Ясное битовое поле


BFI Битовое поле вставляет
Извлечение битового поля
SBFX со знаком
SXTB Знак расширяет байт
SXTH Знак расширяет полуслово
Неподписанное
UBFX извлечение битового поля
UXTB Нуль расширяет байт
Нуль расширяет
UXTH полуслово

Таймер SysTick
Все процессоры Cortex-M содержат стандартный таймер. Это называют таймером
SysTick и является 24-разрядным таймером обратного отсчета с автоперезагрузкой
(Рис. 3.21). После того, как запущенный, таймер SysTick будет обратный отсчет от
своего начального значения, после того как он достигает нуля, он повысит
прерывание, и новое значение количества будет загружено из регистра
перезагрузки. Основная цель этого таймера состоит в том, чтобы генерировать
периодическое прерывание для операционной системы реального времени (RTOS)
или другого управляемого событиями программного обеспечения. Если Вы не
выполняете RTOS, можно также использовать его в качестве простого
периферийного устройства таймера.

Рисунок 3.21
Таймер SysTick является 24-разрядным таймером обратного отсчета с
автоперезагрузкой. Это обычно используется для
обеспечения периодического прерывания для
планировщика RTOS.
Источник часов по умолчанию для таймера SysTick является тактовой частотой ЦП
Cortex-M. Может быть возможно переключиться на другой источник часов, но это
будет варьироваться в зависимости от фактического микроконтроллера, который Вы
используете. В то время как таймер SysTick характерен для всех процессоров Cortex-
M, его регистры занимают те же ячейки памяти в Cortex-M3/-M4 и-M7. В Коре-M0 и
Коре-M01, регистры SysTick расположены в системном блоке управления и имеют
различные символьные имена для предотвращения беспорядка. Строка прерывания
по таймеру SysTick и все периферийные строки микроконтроллера подключены к
Контроллеру прерываний вложенного вектора (NVIC).
94 Главы 3

Контроллер прерываний вложенного вектора


Кроме ЦП Cortex-M, следующая главная единица в процессоре Cortex-M является
NVIC. NVIC является тем же для использования между всеми процессорами Cortex-
M, после того как Вы настроили прерывание на Коре-M3, процесс является тем же
для Коры-M0 к Коре-M7. NVIC разработан для быстрой и эффективной обработки
прерываний, на Коре-M3 Вы достигнете первой строки кода “C” в Вашей процедуре
прерывания после 12 циклов для системы памяти состояния с нулевым временем
ожидания. Эта задержка прерывания полностью детерминирована так от любой
точки в фоновом режиме (непрерывание) код, Вы введете прерывание с той же
задержкой. Поскольку мы видели, что инструкции по мультициклу могут быть
остановлены без издержек и затем возобновлены, после того как прерывание
закончилось. На Cortex-M3/M4 и Кора-M7 NVIC поддерживает до 240 источников
прерывания, Кора-M0 может поддерживать до 32. NVIC поддерживает до 256
уровней приоритета прерываний на Коре-M3 и-M4 и четырех приоритетных уровнях
на Коре-M0 (Таблица 3.5).

Таблица 3.5: Контроллер прерываний Вложенного вектора состоит из семи групп


регистров, который позволяет Вам включать, устанавливать приоритетные уровни и
контролировать, пользователь прерывают периферийные каналы
Максимальный
размер в
Зарегистриров
a
аться Слова Описание
Набор Обеспечивает разрешение прерывания укусило для
включает 8 каждого источника прерывания
Ясный Обеспечивает запрет прерывания укусил для каждого
включают 8 источника прерывания
Ожидание Обеспечивает набор, ожидающий бит для каждого
набора 8 источника прерывания
Четкое Обеспечивает ясный незаконченный бит для каждого
ожидание 8 источника прерывания
Предоставляет прерыванию активный бит для каждого
Активный 8 источника прерывания
Обеспечивает 8-разрядное приоритетное поле для
Приоритет 60 каждого источника прерывания
Триггер
программного Запишите номер канала прерывания для генерации
обеспечения 1 программного обеспечения
прерывание
a
Фактическое количество используемых слов будет зависеть от количества каналов прерывания,
реализованных производителем микроконтроллеров

Рабочие режимы
В то время как ЦП Cortex-M выполняет фон (код непрерывания), ЦП находится в
рабочем режиме, названном режимом потока. Когда прерывание будет повышено,
NVIC заставит процессор переходить к соответствующей процедуре обработки
прерывания (ISR). Когда это происходит, изменения ЦП в новом рабочем режиме,
названном режимом обработчика. В простых приложениях без ОС можно
использовать конфигурацию по умолчанию процессора Cortex-M из сброса и нет
никакого главного функционального различия в этих рабочих режимах, и они могут
быть проигнорированы. Процессоры Cortex-M могут быть настроены с более сложной
операционной моделью, которая представляет операционные различия между
потоком и режимом обработчика, и мы посмотрим на это в Главе 5 “Функции
Передовой архитектуры”.
Архитектура Cortex-M 95

Обработка прерываний — запись


Когда периферийное устройство микроконтроллера повысит линию прерывания,
NVIC вызовет две вещи произойти параллельно. Во-первых, вектор исключения
выбирается по шине ICODE. Это - адрес точки входа в ISR. Этот адрес продвинут в
R15, счетчик команд, вынуждающий ЦП переходить к запуску процедуры
прерывания. Параллельно с этим ЦП автоматически продвинет ключевые регистры на
стек. Этот стековый фрейм состоит из следующих регистров, xPSR, ПК, LR, R12, R3,
R2, R1 и R0. Этот стековый фрейм сохраняет состояние процессора и обеспечивает
R0 R3 для использования ISR. Если ISR должен использовать больше регистров ЦП,
он должен ПРОДВИНУТЬ их на стек и POP их на выходе (Рис. 3.22).

Рисунок 3.22
Когда прерывание или исключение произойдут, ЦП автоматически продвинет
стековый фрейм. Это состоит из xPSR, ПК, LR, R12 и регистрирует R0 R3. В конце
прерывания или исключения, автоматически не сложен стековый фрейм.

Процесс записи прерывания берет на себя 12 циклов Cortex-M3/M4/M7 и 16 циклов


на Коре-M0. Все эти действия обрабатываются микрокодом в ЦП и не требуют
никаких специализированных инструкций по записи как LJMP или ПРОДВИГАЮТ,
чтобы быть частью кода приложения.

Векторы исключения хранятся в таблице векторов прерываний. Таблица векторов


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

значение будет автоматически загружено в R13 как часть сброса ЦП. Таблица
векторов прерываний затем имеет местоположения адреса каждые 4 байта, растущие
вверх через адресное пространство. Таблица векторов содержит адрес ISR для
каждого из возможных источников прерывания в микроконтроллере. Таблица
векторов для каждого микроконтроллера стала предопределенная частью кода
запуска, как мы будем видеть в следующей главе. Маркировка для каждого ISR
хранится в каждом местоположении вектора прерывания. Для создания ISR, просто
необходимо объявить пустоту “C” функция с помощью того же имени в качестве
маркировки вектора прерывания.
СБРОС ОБЛАСТИ, ДАННЫЕ,
ТОЛЬКО ДЛЯ ЧТЕНИЯ
ЭКСПОРТИРУЙТЕ __ Векторы
__ Векторы DCD __ initial_sp ; Вершина стека
DCD Reset_Handler ; Обработчик сброса
; Внешние прерывания
DCD WWDG_IRQHandler ; Сторожевой таймер окна
; PVD через Строку EXTI
DCD PVD_IRQHandler обнаруживают
DCD TAMPER_IRQHandler ; Трамбовка
DCD RTC_IRQHandler ; RTC
DCD FLASH_IRQHandler ; Flash
DCD RCC_IRQHandler ; RCC

Так, для создания стандартной программы “C” для обработки прерывания от час
реального времени мы создаем функцию “C”, названную следующим образом:
освободите RTC_IRQHandler (пусто) {
. . .. . ..
}

Когда проект будет разработан, компоновщик разрешит адрес стандартной


программы “C” и определит местоположение его в таблице векторов вместо
маркировки. Если Вы не используете это конкретное прерывание в своем проекте,
маркировка все еще, как должны объявлять, поддерживает порядок таблицы векторов.
После таблицы векторов прерываний существует вторая таблица, которая
объявляет все адреса ISR. Они объявляются как СЛАБЫЕ маркировки. Это
означает, что это объявление может быть перезаписано, если маркировка
объявляется в другом месте в проекте. В этом случае они действуют как
“поддержка” для предотвращения любых ошибок компоновщика, если процедура
прерывания официально не объявляется в исходном коде проекта.
СЛАБ
WWDG_IRQHandler ЭКСПОРТА ЫЙ]
ЭКСПОР [СЛАБ
Т PVD_IRQHandler ЫЙ]
ЭКСПОР [СЛАБ
Т TAMPER_IRQHandler ЫЙ]
Обработка прерываний — выход
После того как ISR закончил свою задачу, он вызовет возврат от прерывания до
точки, в фоновом режиме кодируют от того, где он кончил. Однако Ползунок 2
системы команд не имеет возврата или возвращается из инструкции по прерыванию.
ISR будет использовать тот же метод возврата
Архитектура Cortex-M 97

как стандартная программа непрерывания а именно, ответвление по R14 регистр


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

Таблица 3.6: В начале исключения или прерывания R14 (Регистр Ссылки)


продвинут на стек. ЦП затем помещает управляющее слово в R14. В конце
прерывания код перейдет на R14. Управляющее слово не является допустимым
обратным адресом и заставит ЦП получать стековый фрейм и возвращаться к
корректному рабочему режиму

Значение возврата из прерывания Значение


Возвратитесь к режиму Thread и используйте Основной
0xFFFFFFF9 Указатель вершины стека
Возвратитесь к режиму Thread и используйте Указатель
0xFFFFFFFD Стека процесса
0xFFFFFFF1 Возвратитесь к режиму Handler

Обработка прерываний — важный выход!


Линии прерывания, которые подключают пользовательские источники прерывания
ввода-вывода к каналам прерывания NVIC, могут находиться на одном уровне
чувствительные или чувствительный край. Во многих микроконтроллерах значение по
умолчанию находится на одном уровне чувствительное, после того как прерывание
было повышено, оно будет утверждаться на NVIC, пока оно не будет очищено. Это
означает, что при выходе из ISR с прерыванием, все еще утверждаемым на NVIC,
новое прерывание будет повышено. Для отмены прерывания, необходимо очистить
флаги состояния прерывания в пользовательском периферийном устройстве прежде,
чем выйти из ISR. Если периферийное устройство генерирует другое прерывание, в то
время как его линия прерывания утверждается, дальнейшее прерывание не будет
повышено. При очистке флагов состояния прерывания в начале процедуры
прерывания затем, дальнейшие прерывания от периферийного устройства будут
подаваться. Для дальнейшего усложнения вещей, некоторые периферийные
устройства автоматически очистят некоторые свои флаги состояния. Например,
полный флаг преобразования ADC может быть автоматически очищен, когда регистр
результатов ADC читается. Имейте это в виду при чтении руководства пользователя
Микроконтроллера.
Упражнение 3.3 Прерывание SysTick
Этот проект демонстрирует установку первого прерывания с помощью таймера
SysTick.
Откройте установщик пакета.
Выберите вкладку Boards и “Учебные Примеры Руководства Разработчиков”.
Выберите вкладку Example и копию “Исключая 3.2 Прерываниями SysTick” (Рис.
3.23).
98 Глав 3

Рисунок 3.23
SysTick прерывают расположение проекта.

Это приложение состоит из минимального объема кода, необходимого, чтобы


получить выполнение процессора Cortex-M и генерировать прерывание SysTick.
Откройте main.c файл
#include "stm32f10x.h"
#define SYSTICK_COUNT_ENABLE 1
#define SYSTICK_INTERRUPT_ENABLE 2
международное основное (пустота)
{
GPIOB-.CRH 5 0x33333333;
SysTick-.VAL 5 0x9000;
SysTick-.LOAD 5 0x9000;
SysTick-.CTRL 5 SYSTICK_INTERRUPT_ENABLE | SYSTICK_COUNT_ENABLE; в
то время как (1);
}

Основная функция настраивает банк контактов порта как выводы. Затем, мы


загружаем таймер SysTick и перезагружаем регистр и затем включаем таймер и его
линию прерывания к NVIC. После того как это сделано, фоновый код находится в
некоторое время () цикл, делающий ничто.
Когда таймер будет считать в обратном порядке для обнуления, он генерирует
прерывание, которое выполнит SysTick ISR.
освободите SysTick_Handler (пусто)
{
статическое неподписанное символьное количество 5 0,
ledZero 5 0x0F; если (count11.0x60)
{
ledZero 5 ledZero ^ 0xFF;
LED_SetOut (ledZero);
количество 5 0;
}
}
Архитектура Cortex-M 99

Процедура прерывания затем используется для периодического переключения строк


GPIO.
Откройте Устройство:: файл STM32F10x.s и определяет местоположение таблицы
векторов.
SysTick_Handler PROC
SysTick_Handler ЭКСПОРТА [СЛАБЫЙ]
B .
ENDP

Таблица векторов обеспечивает стандартные маркировки для каждого источника прерывания,


созданного как “слабые” объявления. Для создания ISR “C” мы просто должны использовать
имя маркировки в качестве названия пустой функции. Функция “C” затем переопределит
собранный тупик и будет вызвана, когда прерывание будет повышено.

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

Не выполняя код, откройте окно Register и исследуйте состояние регистров (Рис.


3.24).
Рисунок 3.24
Регистр ЦП оценивает в начале кода.
100 Глав 3

В частности, отметьте значение указателя вершины стека (R13) регистр ссылки (R14)
и PSR.
Установите точку останова в процедуре прерывания и запустите код, выполняющий
(Рис. 3.25).

Рисунок 3.25
Набор точки останова на записи в прерывание.

Когда код совершает нападки, точка останова снова исследуют окно Register (Рис.
3.26).

Рисунок 3.26
Регистр ссылки (R14) теперь содержит код возврата, который вынуждает ЦП
возвратиться из прерывания в конце служебной функции
прерывания.

Теперь, R14 имеет код возврата из прерывания вместо нормального обратного


адреса, и указатель вершины стека был постепенно уменьшен 32 словами.
Откройте Окно памяти в 0x20000248 и декодируйте стековый фрейм (Рис. 3.27).

Рисунок 3.27
Просмотрите стековый фрейм в окне памяти.

Теперь откройте peripherals\core peripherals\NVIC (Рис.


3.28).
Архитектура Cortex-M 101

Рисунок 3.28
Периферийное окно NVIC и регистр xPSR просматривают, оба показывают таймер
SysTick активным прерыванием.

Периферийное окно NVIC показывает состояние каждой линии прерывания. Строка


15 является таймером SysTick, и этому включают (E) и активному (A) (Ожидание P
5). idx столбец указывает на номер канала NVIC и объединяется с номером канала
ISR в PSR.
Теперь установите точку останова на закрывающей фигурной скобке функции
обработки прерываний и выполните код
(Рис. 3.29).

Рисунок 3.29
Точки останова на точках входа и выхода ISR.
Теперь откройте окно дизассемблирования и просмотрите инструкцию по
возврату (Рис. 3.30).
102 Главы 3

Рисунок 3.30
Возврат из прерывания является нормальной командой перехода.

Инструкция по возврату является командой перехода, то же, как будто Вы


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

Исключения процессора Cortex-M


В дополнение к строкам прерывания ввода-вывода процессор Cortex-M имеет
некоторые внутренние исключительные ситуации, и они занимают первые 15
мест таблицы векторов (Рис. 3.31).

Рисунок 3.31
Первые 4 байта памяти содержат начальное значение стека. Таблица векторов начинает с
0x00000004. Первые 10 векторов для процессора Cortex, в то время как остаток для
пользовательских периферийных устройств.
Первое местоположение в таблице векторов является обработчиком Сброса. Когда
процессор Cortex-M будет сброшен, адрес, сохраненный здесь, будет загружен в
счетчик команд Cortex-M
Архитектура Cortex-M 103

принуждение перехода к запуску кода приложения. Следующее местоположение в


таблице векторов для немаскируемого прерывания. То, как это реализовано, будет
зависеть от определенного микроконтроллера, который Вы используете. Это может,
например, быть подключено к внешнему контакту на микроконтроллере или к
периферийному устройству, такому как сторожевой таймер в микроконтроллере.
Следующие четыре исключения для обработки отказов, которые могут произойти во
время выполнения кода приложения. Все эти исключения присутствуют на Cortex-
M3/M4 и Коре-M7, но только обработчик серьезных отказов реализован на Коре-M0.
Тип отказов, которые могут быть обнаружены процессором, является отказом
использования, соединяет шиной отказ, отказ диспетчера памяти и серьезный отказ.

Отказ использования

Отказ использования происходит, когда код приложения неправильно использовал


процессор Cortex-M. Типичная причина состоит в том, когда процессору дали
недопустимый код операции для выполнения. Большинство компиляторов ARM
может сгенерировать код для диапазона ядер процессора ARM. Так, возможно
неправильно настроить компилятор и произвести код, который не будет работать
на процессоре Cortex-M. Другие причины отказа использования показывают ниже
(Таблицы 3.7).

Таблица 3.7: Возможные причины исключения отказа


использования

Неопределенная инструкция
Недопустимый адрес возврата из прерывания
Невыровненный доступ к памяти с помощью загрузки и многоадресных команд
хранилища
a
Разделитесь на нуль
a
Невыровненный доступ к памяти
a
Эта опция должна быть активирована в системном блоке управления настраиваемый регистр
использования отказа.

Отказ шины

Отказ шины повышен, когда ошибка обнаруживается на матрице шины AHB (больше
о матрице шины в Главе 5 “Функции Передовой архитектуры”). Потенциальные
причины этого отказа следующим образом (Таблица 3.8).
Таблица 3.8: Возможные причины исключения отказа шины

Недопустимый регион памяти


Неправильный размер передачи, то есть, побайтовой записи к
слову только периферийное устройство регистрирует уровень
полномочий процессора Wrong (Мы посмотрим на уровни
полномочий в Главе 5 “Функции Передовой архитектуры”),
104 Главы 3

Отказ диспетчера памяти

Единица защиты памяти (MPU) является дополнительным периферийным


устройством процессора Cortex-M, которое может быть добавлено, когда
микроконтроллер разработан. Это доступно на всех вариантах кроме Коры-M0. MPU
используется для управления доступом к различным регионам адресного
пространства Cortex-M в зависимости от рабочего режима процессора. На это
посмотрят более подробно в Главе 5 “Функции Передовой архитектуры”. MPU
повысит исключение в следующих случаях (Таблица 3.9).

Таблица 3.9: Возможные причины исключения отказа диспетчера памяти


Доступ к региону MPU с неправильным уровнем полномочий
Запись в регион только для чтения
Доступ к ячейке памяти за пределами определенных регионов MPU
Выполнение программы из памяти регион, который определяется как неисполняемый
файл

Серьезный отказ

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

Включение исключений отказа

Обработчик серьезных отказов всегда включается и может только быть отключен


путем установки регистра FAULTMASK ЦП. Другие исключения отказа должны быть
включены в Системном Блоке управления, “Управление Обработчиком систем и”
регистр состояния (SCB-. SHCSR). SCB-. Регистр SHCSR также содержит, Ожидают и
Активные биты для каждого исключения отказа.

Мы посмотрим на исключения отказа и отслеживающие отказы в Главе 5


“Функции Передовой архитектуры”.

Приоритет и вытеснение
NVIC содержит группу приоритетных регистров с 8-разрядным полем для каждого
источника прерывания. В его конфигурации по умолчанию лучшие 7 битов
приоритетного регистра позволяют Вам определять
Архитектура Cortex-M 105

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

Рисунок 3.32
Каждый периферийный приоритетный регистр состоит из настраиваемого поля вытеснения
и подприоритетного поля.

Младший значащий бит (LSB) является подприоритетным битом. Если два


прерывания будут повышены с тем же уровнем вытеснения, то прерывание с
самым низким подприоритетным уровнем будет подаваться сначала. Это означает,
что у нас есть 128 уровней вытеснения каждый с двумя подприоритетными
уровнями
(Рис. 3.33).

Рисунок 3.33
Каждый приоритетный регистр 8 битов шириной. Однако кремниевый производитель не
может реализовать все приоритетные биты. Реализованные биты всегда
расширяются от MSB к LSB.

Когда микроконтроллер разработан, производитель может определить число


активных битов в приоритетном регистре. Для Cortex-M3/M4 и Кора-M7, это может
быть минимумом три и максимум до восемь. Для Коры-M0 и M0 1 это всегда - 2 бита.
Сокращение количества активных приоритетных битов уменьшает количество
логического элемента NVIC и следовательно его потребляемую мощность. Если
производитель не реализует полные 8 битов приоритетного регистра, то LSBs будет
отключен, это делает более безопасным портировать код между микроконтроллерами
с различными числами активных приоритетных битов. Необходимо будет проверить
таблицу данных производителя для наблюдения, сколько битов приоритетного
регистра активно.
106 Глав 3

Группы и подгруппа
После сброса процессора первые 7 битов приоритетных регистров определяют
уровень вытеснения, и LSB определяет подприоритетный уровень. Это разделение
между группой вытеснения и приоритетной подгруппой может быть изменено путем
записи в поле “NVIC priority group” в “Регистре” Управления Прерыванием и Сбросом
приложения. Этот регистр позволяет нам изменять размер поля группы вытеснения и
приоритетной подгруппы. На сбросе, этот регистр значения по умолчанию к
приоритетному нулю группы (Таблица 3.10).

Таблица 3.10: Приоритетная группа и значения подгруппы


Приоритетная Вытесните биты Подприоритетные
группа группы биты группы
0 71 0
1 72 10
2 73 20
3 74 30
4 75 40
5 76 50
6 7 60
7 Ничего 70

Так, например, если бы наш микроконтроллер имеет четыре активных приоритетных


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

Рисунок 3.34
Приоритетный регистр с четырьмя активными битами и приоритетной группой 5.
Это уступает четыре, вытесняют уровни и четыре
приоритетных уровня.

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


нулем, однако, некоторые исключения процессора Cortex-M имеют отрицательные
приоритетные уровни, таким образом, они будут всегда вытеснять пользовательское
прерывание ввода-вывода (Рис. 3.35).
Архитектура Cortex-M 107

Рисунок 3.35
Исключения процессора Cortex-M и возможные приоритетные
уровни.

Управление приоритетами во время выполнения


Существует три регистра ЦП, которые могут использоваться для динамичного отключения
источников прерывания в NVIC. Это PRIMASK, FAULTMASK и регистры BASEPRI
(Таблица 3.11).

Таблица 3.11: PRIMASK ЦП, FAULTMASK и регистры BASEPRI используются для


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

Регистр маски ЦП Описание


PRIMASK Отключает все исключения кроме серьезного отказа и NMI
FAULTMASK Отключает все исключения кроме NMI
Отключает все исключения на выбранном уровне Вытеснения, и ниже
BASEPRI вытесните уровень

Эти регистры не с отображенной памятью, они - регистры ЦП и могут только быть


получены доступ с MRS и инструкциями MSR. При программировании в “C” к ним
может получить доступ специализированный компилятор внутренние инструкции,
мы посмотрим на эти intrinsics более тесно в Главе 4 “Стандарт Программного
интерфейса Микроконтроллера Коры”.

Модель исключения
Когда NVIC служит единственному прерыванию, существует задержка 12 циклов,
пока мы не достигаем ISR и еще 10 циклов в конце ISR до резюме процессора
Cortex-M
108 Глав 3

выполнение фонового кода. Это дает нам быстро детерминированную обработку


прерываний в системе, которая может иметь только один или два активных
источника прерывания (Рис. 3.36).

Рисунок 3.36
Когда исключение повышено, стековый фрейм продвинут параллельно с адресом
ISR, выбираемым от таблицы векторов. На Коре-M3 и Коре-M4 это всегда - 12
циклов. На Коре-M0 требуется 16 циклов. Кора-M01 берет 15 циклов.

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

Объединение в цепочку хвоста NVIC

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


как ЦП служит высокоприоритетному прерыванию, более низкое приоритетное
прерывание также находится на рассмотрении. В более ранних центральных
процессорах ARM и многих других процессорах, было необходимо возвратить из
прерывания POPing контекст ЦП от стека назад в регистры ЦП и затем выполнение
нового стека PUSH прежде, чем выполнить незаконченный ISR. Это довольно
расточительно с точки зрения циклов ЦП, поскольку это выполняет две избыточных
операции стека (Рис. 3.37).
Рисунок 3.37
Если ISR будет работать, и более низкое приоритетное прерывание повышено, то
это автоматически “выследит объединенный в цепочку” для
выполнения 6 циклов после того, как начальное прерывание
завершилось.
Архитектура Cortex-M 109

Когда эта ситуация происходит на процессоре Cortex-M, NVIC использует технику,


названную объединением в цепочку хвоста для устранения ненужных операций
стека. Когда процессор Cortex-M достигает конца активного ISR и существует
незаконченное прерывание затем, NVIC просто вызывает процессор к вектору к
незаконченному ISR. Это берет фиксированные шесть циклы для выборки начального
адреса незаконченной процедуры прерывания, и затем выполнение следующего ISR
может начаться. Дальше с незаконченными прерываниями имеют дело в том же пути.
Когда не будет никакого дальнейшего ожидания прерываний, стековый фрейм будет
POPed назад к регистрам процессора, и ЦП возобновит выполнение фонового кода.
Как Вы видите из Рис. 3.37, объединение в цепочку хвоста может значительно
улучшить задержку между процедурами прерывания.

NVIC, поздно прибывающий

Другая ситуация, которая может произойти, является “последним прибывающим”


первоочередным прерыванием. В этой ситуации низкоприоритетное прерывание
повышено сопровождаемое почти сразу первоочередным прерыванием. Большинство
микроконтроллеров обработает это путем вытеснения начального прерывания. Это -
нежелательный, потому что он заставит два стековых фрейма быть продвинутыми и
задержит первоочередное прерывание (Рис. 3.38).

Рисунок 3.38
Если процессор Cortex-M войдет и ISR, и более высокое приоритетное прерывание
повышено, то NVIC автоматически переключится для обслуживания
первоочередного прерывания. Это только произойдет, если начальное прерывание
будет в своих первых 12 циклах.

Если эта ситуация произойдет на процессоре Cortex-M, и первоочередное прерывание


прибывает в рамках начальных 12 НАЖАТИЙ цикла низкоприоритетного стекового
фрейма, то NVIC переключится на обслуживание первоочередного прерывания, и
низкоприоритетное прерывание будет хвостом, объединенным в цепочку для
выполнения, после того как первоочередное прерывание закончено. Чтобы
“последний прибывающий” переключатель произошел, первоочередное прерывание
должно произойти в начальный период с 12 циклами низкоприоритетного
прерывания. Если это произойдет немного позже, чем это, то это вытеснит
низкоприоритетное прерывание, которое требует нормального стека PUSH и
НАСЕЛЕНИЯ.
110 Глав 3

NVIC вытеснение POP

Заключительный метод оптимизации, используемый NVIC, является названным


вытеснением POP (Рис. 3.39). Это - своего рода реверсирование последней
прибывающей техники, обсужденной выше.

Рисунок 3.39
Если прерывание будет повышено, в то время как находится в его выходе из 12
циклов, процессор будет “перематывать” стек и служить новому
прерыванию с минимальной задержкой 6 циклов.

Когда типичный микроконтроллер достиг конца ISR, он всегда должен


восстанавливать стековый фрейм независимо от любых незаконченных прерываний.
Как мы видели выше, NVIC будет использовать объединение в цепочку хвоста для
эффективного контакта с любыми в настоящее время незаконченными прерываниями.
Однако, если не будет никаких незаконченных прерываний, то стековый фрейм будет
восстановлен регистрам ЦП в стандартных 10 циклах. Если в течение этого периода с
12 циклами новое прерывание будет повышено, то POPing стекового фрейма будет
остановлен, и указатель вершины стека будет раной назад к началу стекового фрейма.
Затем, новый вектор прерывания будет выбран, и новый ISR будет выполняться. В
конце новой процедуры прерывания мы возвращаемся к фоновому коду посредством
обычного процесса POP с 10 циклами. Важно помнить, что эти три метода,
Объединение в цепочку Хвоста, Поздно Прибывая и Поп-Вытеснение все
обрабатываются NVIC без любых инструкций, добавляемых к Вашему коду
приложения.

Упражнение 3.3 Работа с несколькими прерываниями


Это осуществление расширяет наше исходное осуществление исключения SysTick для
включения второго прерывания ADC. Мы можем использовать эти два прерывания
для исследования поведения NVIC, когда это имеет несколько источников
прерывания.
Откройте установщик пакета.
Выберите вкладку Boards и “Учебные Примеры Руководства Разработчиков”.
Выберите вкладку Example и Копию “Исключая 3,3 Несколько Прерываний”.
Откройте main.c и найдите основное () функция.
Архитектура Cortex-M
111
неподписанный символьный ФОН 5 0; неподписанный символьный ADC 5 0; неподписанный символьный
SYSTICK 5 0;
международное основное (пустота) {
интервал i;
GPIOB-.CRH 5 0x33333333; //Настройте Порт B светодиодные контакты
SysTick-.VAL 5 0x9000; //Запустите значение для счетчика Галочки sys
SysTick-.LOAD 5 0x9000; //Значение перезагрузки
SysTick-.CTRL 5 SYSTICK_INTERRUPT_ENABLE | SYSTICK_COUNT_ENABLE;
init_ADC (); //установите периферийное устройство ADC
ADC1-.CR1 | 5 (1UL, 5); //включите для Прерывания EOC
NVIC-.ISER [0] 5 (1UL, 18); //включите Прерывание ADC
ADC1-.CR2 | 5 (1UL, 0); //ADC включает
в то время как
(1) {
ФОН 5 1;
}}

Мы инициализируем таймер SysTick то же как прежде. Кроме того, периферийное


устройство ADC также настроено. Для включения прерывания ввода-вывода
необходимо включить источник прерывания в периферийном устройстве и также
включить его канал прерывания в NVIC путем установки корректного бита в
регистрах NVIC ISER. В этом примере пишем мы непосредственно в NVIC-. ISER [0]
регистр. В следующей главе мы будем видеть лучший более “стандартный” способ
сделать это.

Мы также добавили три переменные: ФОН, ADC и SYSTICK. Они будут установлены
на логический, когда регион соответствия кода выполнится, и обнулите в других
случаях. Это позволяет нам отслеживать казнь каждого региона кода с помощью
Анализатора логики отладчика.
освободите ADC_IRQHandler (пусто) {
интервал i;
ФОН 5 0;
SYSTICK 5 0;
для (я 5 0; я, 0x1000; i11) {
ADC 5 1;
}
ADC1-.SR и 5 B (1, 1); /* очищают прерывание EOC */
ADC 5 0;
}

Обработчик прерываний ADC устанавливает переменные региона выполнения, затем


находится в цикле задержки. Прежде, чем выйти из него также пишет в регистр
состояния ADC для очистки конца флага преобразования. Этот deasserts запрос на
прерывание ADC к NVIC.
освободите SysTick_Handler (пусто)
{интервал i;

ФОН 5 0; ADC 5 0;
ADC1-.CR2 | 5 (1UL, 22); для (я 5
0; я, 0x1000; i11) {
SYSTICK 5 1;
}
SYSTICK 5 0;
}
112 Глав 3

Обработчик прерываний SysTick подобен обработчику ADC. Это устанавливает


переменные казни региона и находится в цикле задержки перед выходом. Это также
пишет в регистр управления ADC для инициирования единственного
преобразования ADC.
Разработайте проект и запустите средство моделирования.
Добавьте каждую из переменных выполнения к Анализатору логики и запустите
выполнение кода
(Рис. 3.40).

Рисунок 3.40
Прерывание SysTick выполняется (логика высоко) затем, прерывание ADC является
объединенным в цепочку хвостом и будет работать,
когда SysTick заканчивается.

Прерывание SysTick повышено, который запускает преобразование ADC. ADC


заканчивает преобразование и повышает его прерывание, прежде чем прерывание
SysTick завершится так, это вводит Незаконченное состояние. Когда прерывание
SysTick завершается, прерывание ADC является объединенным в цепочку хвостом и
начинает выполнение, не возвращаясь к фоновому коду.

Выйдите из отладчика и закомментируйте строку кода, которая очищает конец


ADC флага преобразования.
//ADC1-.SR И 5 B (1, 1);

Создайте код и перезапустите отладчик и наблюдайте выполнение прерываний в окне


Logic Analyzer (Рис. 3.41).

Рисунок 3.41
Хвост ADC объединяет SysTick в цепочку и работает многократно, потому что
флаг состояния ADC не был очищен.
После того, как первое прерывание ADC было повышено, флаг состояния прерывания не
был очищен, и линия прерывания ADC к NVIC остается утверждаемой. Это вызывает
непрерывные прерывания ADC к
Архитектура Cortex-M 113

будьте повышены NVIC блокирование действия фонового кода. Прерывание


SysTick имеет тот же приоритет как ADC, таким образом, это будет хвост,
объединенный в цепочку для погони за текущим прерыванием ADC, закончился.
Пренебрежение очистить флаги состояния прерывания является наиболее
распространенной ошибкой, сделанной, сначала начиная работать с прерываниями и
процессорами Cortex-M.
Выйдите из отладчика и не прокомментируйте конец кода преобразования.
ADC1-.SR И 5 B (1, 1);

Добавьте следующие строки к фоновому коду инициализации.


NVIC-.IP[18] 5 (2, 4);
SCB-.SHP[11] 5 (3, 4);

Это программирует пользовательское периферийное устройство приоритетные регистры


прерывания NVIC для установки приоритетного уровня ADC и “Приоритетных
регистров” Обработчика Систем для установки приоритетного уровня SysTick. Это оба
массивы байтов, которые покрывают 8-разрядное приоритетное поле для каждого
источника исключения. Однако на этом микроконтроллере производитель реализовал
четыре приоритетных бита из возможных восьми. Приоритетные биты расположены в
верхнем откусывании каждого байта. На сбросе обнуляется PRIGROUP, который создает
7-разрядное поле вытеснения и 1-разрядное приоритетное поле (Рис. 3.42).

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

На нашем устройстве все доступные приоритетные биты расположены в поле


вытеснения, дающем нам 16 уровней приоритетного вытеснения.

Создайте код, перезапустите отладчик и наблюдайте выполнение прерываний в окне


Logic Analyzer (Рис. 3.43).
Рисунок 3.43
ADC в более высоком приоритете, чем SysTick, таким образом, он
предвосхищает прерывание SysTick.
114 Глав 3

ADC теперь имеет самое высокое на значение emption поэтому, как только его
прерывание повышено, это вытеснит прерывание SysTick. Когда это завершится,
прерывание SysTick возобновится и завершится прежде, чем возвратиться к
фоновому коду.

Выйдите из отладчика и не прокомментируйте следующие строки в фоновом режиме


код инициализации.

Регистр AIRC не может быть записан в свободно. Это защищено полем ключа,
которое должно быть запрограммировано со значением 0x5FA, прежде чем запись
будет успешна.
работайте временно 5 SCB-.AIRCR;
работайте временно и 5 B (SCB_AIRCR_VECTKEY_Msk |
SCB_AIRCR_PRIGROUP_Msk); работайте временно 5 (временный файл |
(uint32_t) 0x5FA, 16) | (0x05, 8)); временный файл SCB-.AIRCR 5;

Это программирует поле PRIGROUP в регистре AIRC к значению 5, что означает 2-


разрядное поле вытеснения и 6-разрядное приоритетное поле. Это отображается на
доступное 4-разрядное приоритетное поле, дающее четыре уровня вытеснения
каждый с четырьмя уровнями приоритета (Рис. 3.44).

Рисунок 3.44
PRI Group установлена определить 2-разрядное поле вытеснения и 2-
разрядное приоритетное поле.

Создайте код и перезапустите отладчик и наблюдайте выполнение прерываний в окне


Logic Analyzer (Рис. 3.45).
Рисунок 3.45
SysTick и ADC имеют различные приоритетные уровни, но то же вытесняет
уровень. Теперь, ADC не может вытеснить SysTick.
Архитектура Cortex-M 115

Прерывание ADC больше не вытесняет таймер SysTick несмотря на них имеющий


различные значения в их приоритетных регистрах. Это вызвано тем, что у них теперь
есть различные значения в приоритетном поле, но то же вытесняет значение.
Выйдите из отладчика и измените приоритеты прерывания как показано ниже.
NVIC-.IP[18] 5 (2, 6 | 2, 4);
SCB-.SHP[11] 5 (1, 6 | 3, 4);

Установите регистр базового приоритета для блокирования, ADC вытесняют группу.


__ set_BASEPRI (2, 6);

Создайте код, перезапустите отладчик и наблюдайте выполнение прерываний в окне


Logic Analyzer (Рис. 3.46).

Рисунок 3.46
Установка регистра Базового приоритета отключает прерывание ADC.

Установка регистра BASEPRI отключила прерывание ADC и любые другие


прерывания, которые находятся на том же уровне, вытесняют группу или ниже.

Поддержка загрузчика
В то время как таблица векторов прерываний расположена в начале памяти, когда
процессор Cortex-M сбрасывается, возможно переместить таблицу векторов к другому
местоположению в памяти. Поскольку программное обеспечение, встроенное в
маленькие микроконтроллеры, становится более сложным существует
увеличивающаяся потребность разработать системы с постоянной программой
начальной загрузки, которая может проверить целостность кода главного приложения,
прежде чем это будет работать и проверка на обновление программы, которое может
быть поставлено различными последовательными интерфейсами (например, Ethernet,
USB, UART) или SD / мультимедийную карту (Рис. 3.47).
116 Глав 3

Рисунок 3.47
Программа начальной загрузки может быть помещена в первый сектор во Флэш-
памяти. Это проверит, существует ли обновление кода приложения прежде, чем
запустить программу главного приложения.

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

Рисунок 3.48
Когда код приложения начинает работать, он должен переместить таблицу
векторов к запуску кода приложения путем программирования регистра
Смещения таблицы векторов NVIC.

Таблица векторов может быть перемещена путем записи в регистр в системном блоке
управления, названном “регистром” Смещения Таблицы векторов. Этот регистр
позволяет Вам перемещать таблицу векторов к любой 128-байтовой границе в карте
памяти процессора Коры.

Упражнение 3.4 Загрузчик


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

Откройте установщик пакета.


Выберите вкладку Boards и “Учебные Примеры Руководства Разработчиков”.
Выберите вкладку Example и Копию “Исключая 3.4 Загрузчиками”.
Это - больше расширенной функции IDE µVision, который позволяет Вам
просматривать два или больше проекта одновременно (Рис. 3.49).

Рисунок 3.49
Загрузчик и проект Blinky в многопроектной рабочей области.

Рабочая область состоит из двух проектов, проекта загрузчика, который


разрабатывается для работы вектора сброса процессора Cortex как нормального, и
проект Blinky, который является нашим приложением. Во-первых, мы должны
разработать проект Blinky для выполнения от адреса приложения который не в том
же секторе Flash как загрузчик. В этом примере адрес приложения выбран, чтобы
быть 0x2000.

Разверните проект Blinky, щелкните правой кнопкой по папке рабочей области и


установите его как активный проект (Рис. 3.50).

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

Теперь нажмите на папку проекта Blinky и откройте опции для вкладки Target\Target
(Рис. 3.51).

Рисунок 3.51
Проекту Blinky нужно было сместить его код к 0x2000 начальному адресу.
118 Глав 3

Нормальный начальный адрес для этой микросхемы является 0x8000000, и


мы увеличили это до 0x8002000.
Откройте system_stm32F10x.c файл и найдите строку 128.
#define VECT_TAB_OFFSET 0x02000

Это содержит #define для регистра смещения Таблицы векторов. Обычно, это - нуль,
но если мы установим это на 0x2000, то таблица векторов будет ре, отображенным
для соответствия нашему коду приложения, когда это начнет работать.
Разработайте проект Blinky.
Разверните проект загрузчика и установите его как активный проект (Рис. 3.52).

Рисунок 3.52
Выберите загрузчик как активный проект.

Открытый main_boot.c

Программа начальной загрузки демонстрирует, как спрыгнуть с одной программы к


запуску другого. Мы должны определить начальный адрес нашей второй программы.
Это должно быть кратным 128 байтам (0x200). Кроме того, пустой указатель функции
также определяется:
Определение типа #define
APPLICATION_ADDRESS 0x2000, пустое
(*pFunction) (пусто); pFunction
Jump_To_Application; uint32_t JumpAddress;

Когда код загрузчика входит основной, он выполнил бы пользовательские проверки


на Flash кода приложения, такие как контрольная сумма и мог также протестировать
другие критические аспекты аппаратных средств. Загрузчик затем проверил бы,
чтобы видеть, существует ли новое приложение, готовое быть запрограммированным
в прикладную область. Это могло быть в ответ на команду от утилиты обновления
через последовательный интерфейс, например. Если бы сбой проверок прикладной
программы или новое обновление доступны, мы ввели бы в основной код загрузчика.
международное
основное (пустота)
{uint32_t флаги
начальной загрузки;
/* проверьте целостность кода приложения */
Архитектура Cortex-M 119

/* Проверьте, является ли обновление доступным */


/* если любой случай является истинным набором немного в */флагах
начальной загрузки регистра флагов начальной загрузки 5 0;

если (флаги начальной загрузки! 5 0) {


//введите код обновления Flash здесь
}

Если код приложения и аппаратные средства будут в порядке, то загрузчик передаст


коду приложения. Вектор сброса кода приложения теперь расположен в адресе
приложения 14, и это может быть загружено в указатель функции, который может
затем быть выполнен, приведя к переходу к запуску кода приложения. Прежде чем
мы перейдем к коду приложения, также необходимо загрузить указатель вершины
стека начальным адресом, ожидаемым кодом приложения.
еще {
JumpAddress 5 * (__ IO uint32_t*) (APPLICATION_ADDRESS 1 4);
Jump_To_Application 5 (pFunction) JumpAddress;
//считайте первые четыре байта кода приложения и программируйте это значение в указатель вершины
стека:

//Это устанавливает стек, готовый к коду приложения __ set_MSP


(* (__ IO uint32_t*) APPLICATION_ADDRESS);
Jump_To_Application ();

}}

Разработайте проект.

Откройте Опции загрузчика для вкладки Target\Debug и откройте файл


loadApp.ini (Рис. 3.53).

Рисунок 3.53
Сценарий отладки используется для загрузки символов проекта приложения. Это
позволяет Вам отлаживать загрузчик и код приложения
одновременно.

Загрузка ".. \\Blinky \\Flash \\Blinky. AXF", возрастающий


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

Запустите отладчик.

Одноэтапный код через загрузчик, проверяющий, что корректный адрес указателя


вершины стека загружается в MSP и что начальный адрес Blinky загружается в
указатель функции.

Используйте Окно памяти для просмотра приложения Blinky, которое запускается в


0x800200, и проверьте, что значение указателя вершины стека загружается в R13, и
адрес сброса загружается в указатель функции (Рис. 3.54).

Рисунок 3.54
Первые 8 байтов образа прикладного объекта содержат начальный адрес
указателя вершины стека и адрес обработчика
сброса.

Откройте blinky.c файл в проекте Blinky и установите точку останова на основном


(Рис. 3.55).

Рисунок 3.55
Установите точку останова на основном () в проекте Blinky.

Выполните код

Теперь, процессор Cortex оставил программу начальной загрузки и ввел


прикладную программу Blinky. Системный код запуска запрограммировал
регистр смещения Таблицы векторов поэтому теперь, аппаратная таблица
векторов соответствует программному обеспечению Blinky.
Откройте таблицу прерываний вектора Peripherals\Core Peripherals\Nested (рис. 3.56).
Рисунок 3.56
Путем программирования VTO таблица аппаратного прерывания была перемещена
для соответствия таблице векторов
программного обеспечения.
Архитектура Cortex-M 121

Теперь, таблица векторов в 0x8002000 для соответствия коду Blinky.


Откройте файл IRQ.C и установите точку останова на обработчике прерываний
SysTick (Рис. 3.57).

Рисунок 3.57
Установите точку останова в начале обработчика прерываний SysTick.

Выполните код.

Когда таймер SysTick повысит, его прерывание, адрес обработчика будет выбран от
таблицы векторов Blinky а не адреса по умолчанию в начале памяти, и корректный
обработчик SysTick будет выполняться. Теперь программа Blinky работает счастливо в
ее адресе смещения. При необходимости в коде приложения для вызова, загрузчик
затем установил шаблон в памяти и вызывает сброс в рамках кода приложения путем
записи в “Системный регистр” Управления Прерыванием и Сбросом Приложения
Блока управления.
Shared_memory 5 USER_UPDATE_COMMAND
NVIC_SystemReset ();

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

Управление питанием
В то время как Кора-M0 и Кора-M01 специально предназначены для операции
низкой мощности, Кора-M3 и Кора-M4 все еще имеют удивительно низкую
потребляемую мощность. В то время как потребление фактической мощности будет
зависеть от производственного процесса, используемого Кремниевым Поставщиком,
числа ниже дают признак ожидаемой потребляемой мощности (Таблица 3.12).

Таблица 3.12: Потребляемая мощность изображает вариантом процессора в LP на 90 нм


(Низкая мощность) процесс

Процессор Динамическая потребляемая мощность Подробнее


(µW/MHz)
Кора-M0 1 11 Исключает единицы отладки
Кора-M0 16 Исключает единицы отладки
Кора-M3 32 Исключает единицы отладки и MPU
Исключает FPU, MPU и единицы
Кора-M4 33 отладки
122 Главы 3

Процессоры Cortex-M способны к переходу к режимам низкой мощности под


названием СОН и DEEPSLEEP. Когда процессор в помещенном в Режим ожидания,
основной сигнал тактовой частоты ЦП останавливается, который останавливает
процессор Cortex-M. Остальная часть часов микроконтроллера и периферийных
устройств будет все еще работать и может использоваться для пробуждения ЦП.
Режим DEEPSLEEP является расширением режима ожидания, и его действие будет
зависеть от определенной реализации, сделанной на микроконтроллере. Как правило,
когда к режиму DEEPSLEEP переходят, периферийные часы процессора будут также
остановлены наряду с часами процессора Cortex-M. Другие области
микроконтроллера, такие как SRAM на микросхеме и питание к Флэш-памяти могут
также быть выключены в зависимости от конфигурации микроконтроллера. (Рис.
3.58).

Рисунок 3.58
wakesup контроллер является небольшой площадью логических элементов, которые не требуют
источника часов. WIC может быть расположен на другом домене питания к процессору Cortex-
M. Это позволяет всем часам процессора быть остановленными. Диапазон доступных режимов
питания определяется кремниевым производителем.

Когда процессор Cortex-M ввел режим ожидания низкой мощности, он может быть
разбужен периферийным устройством микроконтроллера повышение прерывания к
NVIC. Однако NVIC нужны часы для работы, поэтому если все часы останавливаются,
нам нужен другой аппаратный блок, чтобы сказать Блоку управления питанием (PMU)
микроконтроллера восстанавливать часы, прежде чем NVIC сможет ответить.
Процессоры Cortex-M могут быть оснащены дополнительной единицей, названной
контроллером прерываний пробуждения (WIC). Обнаружение прерывания
дескрипторов WIC, когда все часы останавливаются и позволяют всему процессору
Cortex переходить к режимам низкой мощности. Контроллер пробуждения состоит из
минимального количества логических элементов и не нуждается в системных часах.
Контроллер пробуждения может быть помещен в другой домен питания к основному
процессору Cortex-M. Это позволяет производителям микроконтроллеров
разрабатывать устройство, которое может иметь режимы низкой мощности, где
большая часть микросхемы выключена при поддержании ключевых периферийных
устройств для пробуждения процессора.
Архитектура Cortex-M 123

Переход к режимам низкой мощности

Ползунок 2 системы команд содержат две специализированных инструкции,


которые поместят процессор Cortex-M в режим SLEEP или DEEPSLEEP
(Таблица 3.13).

Таблица 3.13: инструкции по записи низкой мощности


Внутреннее CMSIS-
Инструкция Описание ядро
Ожидайте
WFI прерывания __ WFI ()
WFE Ожидайте события __ WFE

Поскольку его имя подразумевает, инструкция по Ожиданию прерывания (WFI)


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

Конфигурирование режимов низкой мощности

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


низкой мощности процессора Cortex-M (Рис. 3.59).

Рисунок 3.59
Системный регистр управления содержит биты конфигурации низкой мощности
процессора Cortex-M.

Процессор Cortex-M имеет два внешних сигнала сна, которые подключены к системе
управления питанием, разработанной производителем. По умолчанию сигнал СНА
активируется, когда WFI или инструкции WFE выполняются. Если SLEEPDEEP
укусил, установлен, второй сигнал сна, SLEEPDEEP активируется, когда процессор
Cortex-M вводит режим ожидания. Два сигнала сна используются производителем
микроконтроллеров для обеспечения более широкой схемы управления питанием
микроконтроллера. Установка SLEEPONEXIT укусила, вынудит микроконтроллер
ввести свой режим ожидания, когда это достигло конца прерывания. Это позволяет
Вам разрабатывать систему, которая просыпается в ответ на прерывание, выполняет
необходимый код и затем автоматически возвратится ко сну. В такой системе никакое
управление стеком не требуется (кроме случая вытесненных прерываний) во время
последовательности записи/выхода прерывания, и никакой фоновый код не будет
выполнен. Инструкция WFE помещает процессор Cortex-M в свой режим ожидания, и
процессор может быть
124 Главы 3

разбуженный прерыванием таким же образом как инструкция WFI. Однако


инструкция WFE имеет фиксатор внутреннего события. Если фиксатор события будет
установлен на один, то процессор очистит фиксатор, но не переходит к режиму низкой
мощности. Если фиксатор будет нулем, то он перейдет к режиму низкой мощности. На
типичном микроконтроллере события являются сигналами прерывания ввода-вывода.
Так незаконченные прерывания будут препятствовать тому, чтобы процессор спал.
SEVONPEND укусил, используется для изменения поведения инструкции WFE. Если
этот бит установлен, строки прерывания ввода-вывода могут использоваться для
пробуждения процессора, даже если прерывание отключено в NVIC. Это позволяет
Вам помещать процессор в его режим ожидания, когда прерывание ввода-вывода
произойдет, процессор разбудит и возобновит выполнение инструкции, следующей
инструкциям WFE вместо того, чтобы перейти к процедуре прерывания (Рис. 3.60).

Рисунок 3.60
Две инструкции по записи низкой мощности помещают процессор Cortex в его режим
низкой мощности. Оба режима используют прерывание ввода-вывода для пробуждения
процессора, но их поведение пробуждения отличается.

Прерывание, отключенное в NVIC, не может использоваться для выхода из режима


ожидания, вводимого инструкцией WFI. Однако инструкция WFE ответит на
действие по любой линии прерывания, даже если это будет отключено или временно
недоступно регистрами маски процессора (BASEPRI, PRIMASK и FAULTMASK).

Упражнение 3.3 Режимы низкой мощности

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


экспериментировать с режимами низкой мощности Cortex-M.
Архитектура Cortex-M 125

Выберите вкладку Boards и “Учебные Примеры Руководства Разработчиков”.


Выберите вкладку Example и Копию “Исключая 3.5 Режимами Низкой
мощности”
в то время как (1)
{
СПИТЕ 5 1; ФОН 5
0; __ wfe (); ФОН 5
1; СПИТЕ 5 0;
}

Этот проект использует SysTick и прерывания ADC, которые мы видели в последнем


примере. На этот раз мы добавили дополнительную переменную СНА для контроля
состояния работы процессора. Инструкция WFI была добавлена в основном цикле с
условием продолжения.
Разработайте проект и запустите отладчик.
Откройте окно Logic Analyzer и запустите код, выполняющий (Рис. 3.61).

Рисунок 3.61
В нашем простом проекте фоновый код только выполняется __ wfi () инструкция,
вынуждающая ЦП ввести состояние сна.

Здесь, мы видим, что фоновый код выполняется __ wfi () инструкция и затем засыпает,
пока прерывание не повышено. Когда прерывания завершились, мы возвращаемся к
фоновому коду, который сразу поместит процессор в его режим низкой мощности.
Выйдите из отладчика и измените код для соответствия строкам ниже:
SCB-.SCR 5 0x2;
СПИТЕ 5 1; ФОН 5
0; __ wfi (); в то
время как (1) {

Добавьте код для установки бита два из системного регистра управления. Это
устанавливает флаг Sleep On Exit, который вызывает процессор в режим низкой
мощности, когда он завершает прерывание. Сократите
126 Глав 3

оставление тремя строками из цикла с условием продолжения и вставляет их в раздел


инициализации основного () функция.

Создайте код, перезапустите отладчик и наблюдайте выполнение прерываний в окне


Logic Analyzer (Рис. 3.62).

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

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

Перемещение от коры-M3
В этой главе мы сконцентрировались на изучении процессора Cortex-M3. Теперь,
когда Вы знакомы с тем, как Кора-M3 работает, мы можем исследовать различия
между Корой-M3 и другими вариантами Cortex-M. Поскольку мы будем видеть, что
это главным образом архитектурные различия и если можно использовать Кору-M3,
можно легко переместиться до Коры-M4 или вниз к Коре-M0 (1) - базирующийся
микроконтроллер. Все больше кремниевые производители делают семейство
микроконтроллеров, были варианты, имеют ту же схему контактов пакета, и
периферийная покупка может быть выбрана с процессором Cortex-M0 или Cortex-M3,
разрешающим Вам беспрепятственно переключить устройства, обменивающие
производительность по сравнению со стоимостью.
Архитектура Cortex-M 127

Кора-M4
Кора-M4 наиболее легко описана как Кора-M3 с дополнительным FPU и
инструкциями по DSP. Мы посмотрим на эти функции в Главе 8 “Практический DSP
для Коры-M4 и Коры-M7”, но здесь мы возьмем тур по основным отличиям между
Корой-M3 и Корой-M4. Кора-M4 предлагает ту же вычислительную мощность 1.25
DMIPS/MHz как Кора-M3, но имеет намного большую математическую возможность.
Это поставляется тремя способами. Аппаратные средства, в которых FPU может
выполнить вычисления с плавающей точкой немного как 1 цикл по сравнению с
сотнями циклов то же вычисление, взяли бы Кору-M3. Для целочисленных
вычислений Кора-M4 имеет более высокую производительность MAC, который
изменяет к лучшему Кору-M3 MAC, чтобы позволить единственным вычислениям
цикла быть выполненными на 32-разрядных широких количествах, которые приводят
к 64-разрядному результату. Наконец, Кора-M4 добавляет группу SIMD
“Единственная Инструкция Несколько Данных” (SIMD) инструкции, которые могут
выполнить несколько целочисленных вычислений в единственном цикле. В то время
как Кора-M4 имеет большее количество логического элемента, чем Кора-M3, FPU
содержит больше логических элементов, чем весь процессор Cortex-M0 (Таблица
3.14).

Таблица 3.14: Дополнительные функции в Коре-M4

Функция Комментарии
Сопроцессор
для операций с
плавающей
точкой См., что глава 7 “Отлаживает с CoreSight”
DSP SIMD
инструкции
Поле GE в xPSR
Расширенное Кора-M4 расширяет целочисленный MAC для поддержки
целое число единственного цикла
выполнение 32-разрядных умножается который урожай 64-
Единица MAC разрядный результат

Кора-M0
Кора-M0 является уменьшенной версией Коры-M3; это предназначается для
микроконтроллеров недорогой и низкой мощности. Кора-M0 имеет вычислительную
мощность 0.84 DMIPS/MHz. В то время как Кора-M0 может работать в высоких
тактовых частотах, она часто разрабатывается в недорогие устройства с простыми
системами памяти. Следовательно, типичный микроконтроллер Коры-M0 работает с
частотой ЦП 50 DMIPS/MHz, однако, ее низкая потребляемая мощность делает его
идеальным для приложений низкой мощности. В то время как это по существу имеет
модель того же программиста как Кора-M3, существуют некоторые ограничения, и
они получены в итоге ниже (Таблицы 3.15).
128 Глав 3

Таблица 3.15: Функции, не включенные в Кору-M0

Функция Комментарии
Те же настройки канала связи как Кора-M3, но никакое
Трехэтапный конвейер спекулятивное ответвление
целевая выборка
Инструкция и данные используют тот же вход шины, который
Шинный интерфейс Von Newman может иметь более медленное
производительность по сравнению с Гарвардской
архитектурой M3/M4
Никакое условное выражение, Условные переходы всегда используются, которые вызывают
ЕСЛИ ЗАТЕМ блоки конвейерный сброс
Никакие влажные инструкции по
математике
Таймер SYSTICK является Однако до сих пор каждый микроконтроллер Коры-M0 имеет
дополнительным приспособленный
Никакая единица защиты памяти MPU охвачен в Главе 5 “Функции Передовой архитектуры”
Ограниченное количество каналов прерывания по сравнению с
32 канала NVIC Cortex-M3/
M4, однако, на практике это не реальное ограничение и Кора-M0
предназначается для небольших устройств с ограниченным
количеством периферийных устройств
Четыре программируемых Приоритетный уровень регистрируется, только реализовал 2
приоритетных уровня бита (четыре уровня), и
нет никакой приоритетной установки группы
Исключение серьезного отказа Никакой отказ использования, отказ управления памятью или
только исключение отказа шины
векторы
Та же детерминированная обработка прерываний как M3, но
16 задержек прерывания цикла с четырьмя
больше цикла наверху
Ограниченный фиксированными четырьмя уровни
Никакая приоритетная группа вытеснения
Никакой регистр BASEPRI
Никакой регистр FAULTMASK
Кора-M0 имеет меньше функций отладки по сравнению с Корой
Уменьшенные функции отладки -
M3/M4, см. Главу 8 “Практический DSP для Коры-M4 и Коры -
M7” для получения дополнительной информации
Никакие инструкции по
эксклюзивному доступу Инструкции по эксклюзивному доступу охвачены в Главе 5
“Функции передовой архитектуры”
Никакой обратный разрядный
порядок продвижения количества
нулевые инструкции
Сокращенное количество
регистров в Посмотрите ниже
системный блок управления
Таблица векторов не может быть
перемещена NVIC не включает регистр смещения таблицы векторов
Весь код выполняется на Кора-M0 не поддерживает непривилегированный рабочий
привилегированном уровне режим

Системный блок управления содержит сокращенное количество функций по


сравнению с Корой-M3\M4. Кроме того, регистры таймера SysTick были перемещены
от NVIC до системного блока управления (Таблица 3.16).
Архитектура Cortex-M 129

Таблица 3.16: Регистры в системном блоке управления Коры-M0


Размер
в
Зарегистрироваться Слова Описание
Управление SysTick и состояние 1 Включает таймер и его прерывание
Перезагрузка SysTick 1 Содержит 24-разрядное значение перезагрузки
Содержит текущее 24-разрядное значение
Текущее значение SysTick 1 таймера
Калибровка SysTick 1 Позволяет обрезать входную тактовую частоту
Зашитый идентификатор и числа пересмотра от
ИДЕНТИФИКАТОР ЦП 1 ARM и
кремниевый производитель
Управление прерыванием и Обеспечивает ожидают биты для прерываний NMI
состояние 1 и SysTick
и расширенное прерывание информация о
Pending\active
Прерывание приложения и
управление сбросом 1 Содержит те же поля как Кора-M3 минус
Поле PRIGROUP
Конфигурация и управление 1
Эти регистры содержат 8-разрядные приоритетные
Приоритет обработчика систем 2 поля для
настраиваемые исключения Процессора

Кора-M01
Кора-M01 является расширенной версией Коры-M0. Как таковой это имеет более
низкие числа потребляемой мощности, объединенные с большей вычислительной
мощностью. Кора-M01 также приносит MPU и возможность отладки в реальном
времени к очень низкопроизводительным устройствам. Кора-M01 также представляет
быстрый порт I/O, который ускоряет доступ к периферийным регистрам обычно
порты GPIO, чтобы позволить быстро переключаться контактов порта. Поскольку мы
будем видеть в Главе 7 “Отладку с CoreSight”, система отладки оснащена новой
единицей трассировки, названной микро буфером трассировки (MTB), который
позволяет Вам получать историю выполненного кода с недорогим средством
разработки (Таблица 3.17).

Таблица 3.17: кора-M0 1 функция

Функция Комментарии
Кора-M01 является кодом, совместимым с Корой-M0, и
Код, совместимый с обеспечивает
более высокая производительность с более низкой потребляемой
Кора-M0 мощностью
Это сокращает количество доступов Flash и следовательно
Двухэтапный конвейер потребляемой мощности
Порт I/O обеспечивает выборку в течение одного цикла к GPIO и
Порт I/O периферийным регистрам
Таблица векторов может Это поддерживает более сложные разработки программного
быть перемещена обеспечения. Обычно Загрузчик
и отдельное приложение
Поддерживает 16- Это позволяет устройствам, показывающим Кору-M01
разрядную Флэш-память использовать недорогую память
доступы
Код может выполниться в
привилегированном Кора-M01 имеет те же рабочие режимы как Cortex-M3/M4
и непривилегированные
уровни
Единица защиты памяти Кора-M01 имеет подобный MPU к Cortex-M3/M4
Это - единица трассировки “снимка”, к которой может получить
Микро буфер трассировки доступ недорогая отладка
единицы
130 Глав 3

Заключение
В этой главе мы покрыли основные характеристики семейства процессоров Cortex-M.
Для разработки успешно с Основанным на Cortex-M устройством необходимо будет
быть абсолютно знакомы со всеми темами, затронутыми в этой главе и Главе 2
“Разработка программного обеспечения для семейства Cortex-M”. Теперь, когда у нас
есть основное понимание процессора Cortex-M, мы посмотрим на более
усовершенствованные функции процессора плюс диапазон методов и технологий
разработки программного обеспечения.
CHPTER4

Программное обеспечение
микроконтроллера коры
Интерфейсный стандарт

Введение
Широко распространенное внедрение процессора Cortex-M в микроконтроллеры
общего назначения привело к двум возрастающим тенденциям в промышленности
электроники. В первую очередь, тот же процессор доступен из широкого спектра
поставщиков каждый с их собственным семейством микроконтроллеров. В
большинстве в корпусе каждый поставщик создает семейство микроконтроллеров,
которые охватывают диапазон требований для разработчиков встроенных систем.
Это быстрое увеличение количества устройств означает, что как разработчик можно
выбрать подходящий микроконтроллер из нескольких тысяч устройств все еще с
помощью тех же инструментов и навыков независимо от кремниевого поставщика.
Этот взрывной рост в Основанных на Cortex-M микроконтроллерах сделал
процессор Cortex-M фактическим промышленным стандартом для 32-разрядных
микроконтроллеров и в настоящее время нет никаких настоящих претендентов (Рис.
4.1).

Рисунок 4.1
CMSIS-совместимым инструментам разработки программного обеспечения и
стопкам промежуточного программного
обеспечения позволяют нести логотип CMSIS.

Оборот монеты является дифференцированием. Для поставщика микроконтроллера


было бы возможно разработать их собственный 32-разрядный процессор. Однако это
дорого, чтобы сделать и также требует, чтобы экосистема доступных инструментов и
программного обеспечения получила массовое принятие. Это более экономически
эффективно, чтобы лицензировать процессор Cortex-M от ARM и затем использовать
их собственные экспертные знания для создания микроконтроллера с
инновационными периферийными устройствами. Существуют теперь больше
чем 17 (от 10, когда я сначала записал эту книгу 3 несколько лет назад),
кремниевые поставщики, поставляющие Основанные на Cortex-M
микроконтроллеры. В то время как в каждом устройстве процессор Cortex-M
является тем же, но каждый изготовитель заключительного кремния стремится
предложить уникальную группу пользователя

Руководство разработчика по семейству процессоров Cortex-M.


DOI: http://dx.doi.org/10.1016/B978-0-08-100629-0.00004-9 131
© 2016 Elsevier Ltd. Все права защищены.
132 Главы 4

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


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

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

Эти двойные факторы привели к обширному “облаку” стандартных


микроконтроллеров со все больше сложными периферийными устройствами. А также
типичные периферийные устройства микроконтроллера, такие как USART, I2C, ADC
и DAC, современный высокопроизводительный микроконтроллер мог иметь
Хост/Устройство контроллер USB, Ethernet MAC, контроллер SDIO и интерфейс LCD.
Программное обеспечение для управления любым из этих периферийных устройств
является эффективно проектом сам по себе, так уведенный дни разработчика,
использующего микроконтроллер на 8/16 битов и пишущего весь код приложения от
вектора сброса. Для выпуска любого вида сложного продукта, почти бесспорно, что
Вы будете использовать некоторую форму стороннего кода для выполнения работы в
срок. Сторонний код может принять форму примера кода, или коммерческого стека с
открытым исходным кодом или библиотеки, обеспеченной
кремниевый поставщик. Обе из этих тенденций создали потребность заставить уровень
“C” кодировать более портативный между различными средствами разработки и
различными микроконтроллерами. Существует также потребность смочь легко
интегрировать код, взятый от множества источников в единственный проект.

Для решения этих проблем, консорциум кремниевых поставщиков и


поставщиков инструментов разработал “Стандарт Программного интерфейса
Микроконтроллера Коры” или CMSIS (Объявленный seeMsys), если коротко.
Стандарт программного интерфейса микроконтроллера коры 133

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

В этой точке стоит согласиться точно, каков CMSIS. CMSIS состоит из семи
взаимосвязанных спецификаций, которые поддерживают разработку кода через все
Основанные на Cortex-M микроконтроллеры. Эти семь спецификаций следующим
образом; CMSIS-ядро, CMSIS-RTOS, CMSIS-DSP, CMSIS-драйвер, CMSIS-пакет,
CMSIS-SVD и CMSIS-DAP (Рис. 4.3).

Рисунок 4.3
CMSIS состоит из нескольких отдельные спецификации (ЯДРО, DSP, RTOS, SVD,
ДРАЙВЕР, DAP и ПАКЕТ), которые делают исходный код более портативным
между инструментами и устройствами.

Это также стоит быть ясным, каков CMSIS не. CMSIS не является сложным уровнем
абстракции, который вынуждает Вас пользоваться сложной и большой библиотекой.
Скорее CMSIS-базовая спецификация берет очень небольшое количество ресурсов
приблизительно 1 К кода и всего 4 байта RAM и просто стандартизирует способ,
которым Вы получаете доступ к регистрам процессора и микроконтроллера Cortex-
M. Кроме того, CMSIS действительно не влияет на способ, которым Вы
разрабатываете код или вынуждаете Вас принять конкретную методологию. Это
просто служит основой, которая помогает Вам интегрировать сторонний код и код
повторного использования будущих проектов. Каждая из спецификаций CMSIS не
то, что сложный и может быть изучен легко.
134 Главы 4

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


с URL www.keil.com/cmsis. Каждая из спецификаций CMSIS интегрируется в
Набор инструментальных средств MDK-ARM и документация CMSIS доступны путем
открытия Run-Time Environment и нажимания на ссылку CMSIS в столбце описания
(Рис. 4.4).

Рисунок 4.4
К документации CMSIS получают доступ через ссылку описания в менеджере по
Среде выполнения.

CMSIS-ядро
Базовая спецификация обеспечивает минимальный набор функций и макросов
для доступа к ключевым регистрам процессора Cortex-M. Базовая
спецификация также определяет функцию к
настройте осцилляторы микроконтроллера и синхронизируйте дерево в коде запуска,
таким образом, устройство готово к употреблению, когда Вы достигаете основной ().
Базовая спецификация также стандартизирует соглашение о присвоении имен для
периферийных регистров устройства. CMSIS-базовая спецификация также включает
поддержку Трассировки Инструментария во время сеансов отладки.

CMSIS-RTOS
Спецификация CMSIS-RTOS обеспечивает стандартный API для Операционной
системы реального времени. Это - в действительности ряд функций обертки, которые
переводят API CMSIS-RTOS в API определенного RTOS, который Вы используете.
Мы посмотрим на использование RTOS в целом и API CMSIS-RTOS в Главе 9
“CMSIS-RTOS”. Keil RTX RTOS был первым RTOS, который будет поддерживать API
CMSIS-RTOS, и он был выпущен как ссылочная реализация с открытым исходным
кодом. RTX может быть скомпилирован с Keil/ARM, GCC и IAR
Стандарт программного интерфейса микроконтроллера коры 135

компиляторы. Это лицензируется с тремя лицензиями Распределения программного


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

CMSIS-DSP
Поскольку мы видели в Главе 3 “Архитектуру Cortex-M” Кора-M4, “Контроллер
Цифрового сигнала” со многими улучшениями для поддержки алгоритмов DSP.
Разработка оперативной системы DSP лучше всего описана как “нетривиальное время
передачи” и может быть довольно пугающей для всех кроме самых простых систем.
Чтобы помочь простым смертным включать алгоритмы DSP в Cortex-M4/M7 и
проекты Коры-M3, CMSIS включает библиотеку DSP, которая обеспечивает более чем
60 из обычно используемых математических функций DSP. Эти функции
оптимизированы для работы Коры-M4 и Коры-M7, но могут также быть
скомпилированы для работы Коры-M3. Мы взглянем на пользование этой
библиотекой в Главе 8 “Практический DSP для Коры-M4 и Коры-M7”.

CMSIS-драйвер
Спецификация CMSIS-драйвера определяет стандартный API для диапазона
периферийных устройств, которые характерны для большинства семейств
микроконтроллеров. Это включает периферийные устройства, такие как USART,
SPI, и I2C, а также более сложные периферийные устройства, такие как Ethernet
MAC и USB.
CMSIS-драйверы предназначаются для обеспечения стандартной цели для
библиотек промежуточного программного обеспечения. Например, это позволило
бы стороннему разработчику создавать библиотеку USB, которая использовала
драйвер CMSIS-USB. Такая библиотека могла затем быть развернута на любом
устройстве, которое имеет драйвер CMSIS-USB. Это значительно ускоряет
поддержку новых устройств и разрешает библиотеку
разработчики для концентрации на добавлении опций к их продуктам вместо того,
чтобы постоянно иметь необходимость потратить поддержку разработки времени
новых устройств.

CMSIS-SVD и DAP
Одна из ключевых проблем для поставщиков инструментов должна смочь оказать
поддержку отладки для новых устройств, как только они выпущены. Одной из
основных областей, которые должны быть настроены в отладчике, являются окна
“Peripheral View”, которые показывают разработчику текущее состояние
периферийных устройств микроконтроллера. С ростом и в числе поставщиков Cortex-
M и также в возрастающем числе и сложности периферийных устройств на
микросхеме для любого данного поставщика инструментов становится почти
невозможно поддержать поддержку всех возможных микроконтроллеров. Для
преодоления этого препятствия, спецификация CMSIS-SVD определяет “Системный
файл” Описания Средства просмотра. Этот файл обеспечивается и сохраняется
кремниевым поставщиком и содержит полное описание периферийных регистров
микроконтроллера в формате XML. Этот файл затем импортируется средством
разработки, которое использует его для автоматического построения периферийных
окон отладки для микроконтроллера. Этот подход позволяет полной поддержке для
отладочных средств быть доступной, как только новые микроконтроллеры выпущены.
136 Глав 4

Спецификация CMSIS-DAP определяет интерфейсный протокол для аппаратной


единицы отладки, которая находится между хостом ПК и Портом доступа Отладки
микроконтроллера (Рис. 4.5). Это позволяет любой отладчик программного
обеспечения, который поддерживает CMSIS-DAP для соединения с любой аппаратной
единицей отладки, которая также поддерживает CMSIS-DAP. Существует растущее
число очень недорогих оценочных плат, которые содержат интегральный отладчик,
который соединяется с ПК с помощью USB. Во многих случаях этот аппаратный
отладчик поддерживает протокол CMSIS-DAP так, чтобы он мог быть подключен к
любому совместимому набору инструментальных средств.

Рисунок 4.5
CMSIS-DAP допускает совместимость между различными поставщиками — отладчики
программного и аппаратного обеспечения.

CMSIS-пакет
Спецификации CMSIS-ядра и Драйвера могут использоваться для разработки
допускающих повторное использование компонентов программного обеспечения,
которые являются портативными через семейства устройств. Спецификация CMSIS-
пакета определяет метод связывания всех элементов компонента (программные файлы,
примеры, справочные файлы, шаблоны) в программный пакет. Такой Пакет может быть
загружен и установлен в Ваш набор инструментальных средств. Пакет также содержит
информацию о зависимостях от компонента программного обеспечения, то есть, другие
файлы, которые должны присутствовать, когда компонент используется. Это позволяет
Вам быстро интегрировать программное обеспечение из многих источников для создания
платформы, на которой можно разработать код приложения. Поскольку сложность
микроконтроллеров Cortex-M когда-либо увеличивается, это - очень важная технология
для повышения производительности и надежности кода разработчика.

В Главе 12 "Software Components" мы посмотрим на использование


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

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

Процессор Cortex-M и периферийные регистры микроконтроллера. Эта


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

Кодирование правил
В то время как CMSIS важен для обеспечения стандартизированного программного
интерфейса для всех микроконтроллеров Cortex-M, это также интересно для
встроенных разработчиков, потому что это основано на непротиворечивом множестве
“C” кодирующие правила под названием MISRA-C. При применении эти правила
кодирования генерируют четкий однозначный код “C”, и этот подход стоит изучить,
поскольку он воплощает многие лучшие практики, которые должны быть приняты
при записи исходного кода “C” для собственного прикладного программного
обеспечения.

MISRA-C
MISRA-C кодирование стандарта сохраняется и публикуется MIRA. MIRA, обозначает
“Агентство по Исследованию Автомобильной промышленности”, расположен около
Регби в Англии и ответственен за многие промышленные стандарты, используемые
британской автомобильной промышленностью. В 1998 его подразделение
программного обеспечения выпустило первую версию его правил кодирования,
официально названных “инструкции MISRA для использования C в электронике
механизма” (Рис. 4.6).

Рисунок 4.6
Исходный код CMSIS был разработан с помощью MISRA-C в качестве
стандарта кодирования.
Исходная спецификация MISRA-C содержала 127 правил, которые попытались,
предотвращают общие ошибки кодирования и разрешают серые области ANSI C
спецификация при применении к встроенным системам. Хотя первоначально
предназначено для автомобильной промышленности, MISRA-C встретил признание в
более широком сообществе встроенных систем. В 2004 исправленное издание MISRA-C
138 Глав 4

был выпущен с заголовком “Инструкции MISRA-C для использования C в критических


системах”. Это изменение в заголовке отражает растущее принятие MISRA-C как стандарт
кодирования для общих встроенных систем. Было два дальнейших обновления стандарта
MISRA-C в 2008 и 2012. Одна из других ключевых достопримечательностей MISRA-C -
то, что он был записан инженерами и не программистами. Это привело к ясному,
компактному, и легкий понять подшипник. Каждое правило ясно объяснено с примерами
хорошей практики кодирования. Это означает, что весь стандарт кодирования содержится
в книге всего 106 страниц, которые могут легко быть считаны вечером. Типичный пример
правила MISRA-C показывают ниже:

Правило 13.6 (потребовало), чтобы Числовые переменные, используемые в для


цикла для итеративного подсчета, не должны быть изменены в теле цикла
Счетчики цикла не должны быть изменены в теле цикла. Однако другие
контрольные переменные цикла, представляющие логические значения, могут быть
изменены в цикле. Например, флаг, чтобы указать, что что-то было завершено,
который затем тестируется в на оператор.
Отметьте 5 1;
Для ((я 5 0; (я, 5) && (отмечают 55 1); i11)

{
/*. . .. . ..*/

Отметьте 5 0; Совместимый/* позволяет раннее завершение цикла */i 5 я 1 3;/* Не


Совместимое изменение счетчика цикла */

Где возможный правила MISRA-C были разработаны так, чтобы они могли быть
статически проверены или вручную или специальным инструментом. Стандарт
MISRA-C не является открытым стандартом и публикуется в газете и электронной
форме на веб-сайте MIRA. Полное изложение того, как получить Стандарт MISRA,
доступно в Приложении A.

В дополнение к инструкциям MISRA-C CMSIS осуществляет некоторые


дополнительные правила кодирования. Для предотвращения любой неоднозначности
в реализации компилятора стандарта “C” типы CMSIS использует типы данных,
определенные в ANSI C заголовочный файл stdint.h (Таблица 4.1).

Таблица 4.1: типы переменных CMSIS

Стандартный ANSI C тип MISRA C тип


Символ со знаком int8_t
Со знаком короткий int16_t
Интервал со знаком int32_t
Подписанный __ int64 int64_t
Неподписанный символ unit8_t
Короткое целое без знака uint16_t
Неподписанный интервал uint32_t
Неподписанный __ int64 uint64_t
Стандарт программного интерфейса микроконтроллера коры 139

Тип определяет, гарантируют, что ожидаемый размер данных отображается на


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

CMSIS также указывает спецификаторы типа IO для доступа к периферийным


переменным. Это определения типов, которые ясно дают понять тип доступа,
который каждый периферийный регистр имеет (Таблица 4.2).

Таблица 4.2: спецификаторы CMSIS IO


Спецификатор MISRA-C
IO ANSI C тип Описание
Энергозависима Только для
#define __ Я я константа чтения
Энергозависимы Только для
#define __ O й записи
Энергозависимы Читайте и
#define __ IO й запишите

В то время как это не обеспечивает дополнительной функциональности для Вашего


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

Большая часть документации CMSIS автоматически генерируется с помощью


инструмента под названием Doxygen. Это - бесплатная загрузка, выпущенная в
соответствии с лицензией GPL. В то время как Doxygen не может на самом деле
записать документацию для Вас, это действительно делает большую часть тусклого
скучного материала для Вас (отъезд Вас, чтобы сделать увлекательную работу
документации). Doxygen работает путем анализа исходного кода и извлечения
объявлений и определенных комментариев исходного кода для создания
всестороннего “объектного словаря” для проекта. Выходным форматом по умолчанию
для Doxygen является доступный для просмотра HTML, но это может быть
преобразовано в другие форматы при желании. Комментарии исходного кода CMSIS
содержат определенные теги, снабженные префиксом символ, например, @brief. Эти
теги используются Doxygen для аннотирования описаний функций CMSIS.
/**
* @brief включают прерывание в контроллере прерываний NVIC
* @param IRQn номер прерывания, который указывает прерывание
* @return ни один.
* Включите указанное прерывание в Контроллере прерываний NVIC.
* Другие настройки прерывания, такие как приоритет не затронуты. */
Когда инструмент Doxygen выполняется, он анализирует Ваш исходный код и
генерирует отчет, содержащий словарь Вас функции и переменные на основе
объявлений исходного кода и комментариев.

CMSIS-базовая структура
CMSIS-базовые функции могут быть включены в Ваш проект посредством
добавления трех файлов. Они включают код запуска по умолчанию со стандартной
таблицей векторов CMSIS.
140 Глав 4

Второй файл является system_, устройством.. c файл, который содержит


необходимый код для инициализации системных периферийных устройств
микроконтроллера. Наконец, устройство включает файл, который импортирует
заголовочные файлы CMSIS, которые содержат CMSIS-базовые функции и
макросы (Рис. 4.7).

Рисунок 4.7
CMSIS-базовый стандарт состоит из запуска устройства, система C код и заголовок
устройства. Заголовок устройства определяет периферийные регистры устройства и
получения по запросу в заголовочных файлах CMSIS. Заголовочные файлы CMSIS
содержат все CMSIS-базовые функции.

Код запуска
Код запуска обеспечивает вектор сброса, начальное значение указателя вершины стека
и символ для каждого из векторов прерывания.
__ Векторы DCD __ initial_sp ; Вершина стека
DCD Reset_Handler ; Обработчик сброса
DCD NMI_Handler ; Обработчик NMI
; Обработчик серьезных
DCD HardFault_Handler отказов
; Обработчик ошибок
DCD MemManage_Handler MPU

Когда процессор запустится, он инициализирует основной указатель вершины


стека путем загрузки значения, сохраненного в первых 4 байтах таблицы
векторов. Затем это перейдет к обработчику сброса;
Reset_Handler PROC
ЭКСПОРТИРУЙТЕ [СЛАБЫЙ] Reset_Handler
ИМПОРТИРУЙТЕ __ основной
ИМПОРТ SystemInit
LDR R0, 5 SystemInit
BLX R0
LDR R0, 5 __ основной
BX R0
ENDP
Стандарт программного интерфейса микроконтроллера коры 141

Системный код
Обработчик сброса называет SystemInit () функцией, которая расположена в CMSIS
system_, устройство.. c файл. Этот код поставляется кремниевым производителем,
и он предоставляет весь необходимый код для конфигурирования
микроконтроллера после того, как он оставляет вектор сброса. Обычно это
включает установку внутренних цепей фазовой синхронизации, настраивая
часы микроконтроллера древовидная и внутренняя структура шины, включая
внешнюю шину при необходимости. Конфигурацией функций инициализации
управляет ряд #defines расположенный
в начале модуля. Это позволяет Вам настраивать базовую конфигурацию
системные периферийные устройства микроконтроллера. Начиная с SystemInit ()
выполняется функция, когда листы микроконтроллера сбросят системные
периферийные устройства микроконтроллера, и процессор Cortex-M будет в
полностью настроенном состоянии, когда программа достигает основной (). В
прошлом этот системный код инициализации - что-то, что необходимо было бы
записать или запереть от примера кода. На новом микроконтроллере это было бы
работой нескольких дней, таким образом, SystemInit () функция действительно
сохраняет Вас много времени и усилия. SystemInit () функция также устанавливает
глобальную переменную CMSIS SystemCoreClock на частоту ЦП. Эта переменная
может затем использоваться кодом приложения в качестве ссылочного значения при
конфигурировании периферийных устройств микроконтроллера. В дополнение к
SystemInit () функция системный файл CMSIS содержит дополнительную функцию
для обновления переменной SystemCoreClock, если частота тактовой частоты ЦП
изменяется на лету. Функциональный SystemCoreClockUpdate (); пустая функция,
которая должна быть вызвана, если частота тактовой частоты ЦП изменяется. Эта
функция адаптируется в соответствии с каждым микроконтроллером и оценит
регистры дерева часов, чтобы вычислить новую рабочую частоту ЦП и заменить
переменную SystemCoreClock соответственно.

Однажды SystemInit () функция работала, и мы достигаем кода приложения, мы


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

Заголовочный файл устройства


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

Структура определения типа определяется для каждой группы специальных


функциональных регистров на поддерживаемом микроконтроллере. В коде ниже,
общее определение типа GPIO объявляется для группы перерегистров GPIO. Это -
стандартное определение типа, но мы используем спецификаторы IO для
обозначения типа доступа предоставленным данному регистру.
структура определения типа
{
__ IO uint32_t MODER; /*!, регистр режима порта GPIO, Смещение адреса: 0x00 */
__ IO uint32_t OTYPER; /*!, регистр типа выхода порта GPIO, Смещение адреса: 0x04 */
__ IO uint32_t OSPEEDR; /*!, регистр скорости выхода порта GPIO, Смещение адреса: 0x08 */
142 Главы 4

__ IO uint32_t PUPDR; /*!, порт GPIO регистр pull-up/pull-down, Смещение адреса: 0x0C */
__ IO uint32_t IDR; /*!, регистр входных данных порта GPIO, Смещение адреса: 0x10 */
__ IO uint32_t ODR; /*!, регистр данных выхода порта GPIO, Смещение адреса: 0x14 */
__ IO uint16_t BSRRL; /*!, набор битов порта GPIO / сбросил низкий регистр, Смещение адреса: 0x18 */
__ IO uint16_t BSRRH; /*!, набор битов порта GPIO / сбросил высокий регистр, Смещение адреса: 0x1A */
__ IO uint32_t LCKR; /*!, регистр блокировки конфигурации порта GPIO, Смещение адреса: 0x1C */
__ IO uint32_t AFR[2]; /*!, GPIO чередуют функциональные регистры, Смещение адреса: 0x24-0x28 */
} GPIO_TypeDef;

Следующие #defines привыкли к расположению карта распределения памяти


микроконтроллера. Сначала базовый адрес периферийных специальных
функциональных регистров объявляется и затем сместил адреса к каждым из
периферийных шин и наконец смещения к базовому адресу каждого порта GPIO.
#define PERIPH_BASE ((uint32_t) 0x40000000)
APB1PERIPH_BASE PERIPH_BASE #define
#define GPIOA_BASE (AHB1PERIPH_BASE 1 0x0000)
#define GPIOB_BASE (AHB1PERIPH_BASE 1 0x0400)
#define GPIOC_BASE (AHB1PERIPH_BASE 1 0x0800)
#define GPIOD_BASE (AHB1PERIPH_BASE 1 0x0C00)

Затем символы регистра для каждого порта GPIO могут быть объявлены.
#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE)
#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)
#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE)

Затем в коде приложения мы можем программировать периферийные специальные


функциональные регистры путем доступа к элементам структуры.
освободите LED_Init (пусто) {
RCC-.AHB1ENR | 5 ((1UL, 3));/* Включают часы GPIOD */GPIOD-
.MODER и 5 B ((3UL, 2*12) |
(3UL, 2*13) |
(3UL, 2*14) |
(3UL, 2*15)); Фунт 12/*.. 15 производится */GPIOD-
.MODER | 5 ((1UL, 2*12) |
(1UL, 2*13) | (1UL,
2*14) | (1UL,
2*15));

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


определения для всех периферийных специальных функциональных регистров на
микросхеме. Эти определения создаются и сохраняются кремниевым производителем
и поскольку они не используют никого не, ключевые слова ANSI во включать файле
могут использоваться с любым компилятором “C”. Это означает, что любой
периферийный код драйвера, написанный к спецификации CMSIS, является
полностью портативным между CMSIS-совместимыми инструментами.
Микроконтроллер включает файл, также предоставляет определения номера канала
прерывания для каждого источника прерывания ввода-вывода.
Стандарт программного интерфейса
микроконтроллера коры 143

WWDG_IRQn 5 0, /*!, окно прерывание WatchDog */


PVD_IRQn 5 1, /*!, PVD через Прерывание обнаружения Строки EXTI */
TAMP_STAMP_IRQn 5 2, /*!, Трамбовка и TimeStamp прерывают через строку EXTI */
RTC_WKUP_IRQn 5 3, /*!, прерывание Пробуждения RTC через строку EXTI */
FLASH_IRQn 5 4, /*!, Flash глобальное Прерывание */
RCC_IRQn 5 5, /*!, RCC глобальное Прерывание */
EXTI0_IRQn 5 6, /*!, прерывание EXTI Line0 */
EXTI1_IRQn 5 7, /*!, прерывание EXTI Line1 */
EXTI2_IRQn 5 8, /*!, прерывание EXTI Line2 */
EXTI3_IRQn 5 9, /*!, прерывание EXTI Line3 */
EXTI4_IRQn 5 10, /*!, прерывание EXTI Line4 */

В дополнение к регистру и определениям прерывания, кремниевый поставщик может


также обеспечить библиотеку периферийных функций драйвера. Снова, поскольку этот
код написан к стандарту CMSIS, который он скомпилирует с любым подходящим
средством разработки. Часто эти библиотеки очень полезны для получения работы
проекта быстро и минимизируют количество времени, необходимо потратить
низкоуровневый код написания. Однако они часто - очень общие библиотеки, которые не
приводят к большей части оптимизированного кода. Таким образом, если необходимо
получить максимальную производительность или минимальный размер кода, необходимо
будет переписать функции драйвера для удовлетворения определенному приложению.
Микроконтроллер включает файл, также импортирует, до пяти далее включают файлы.
Это “stdint.h”, “CMSIS-базовый” файл для процессора Cortex-M, который Вы используете.
Заголовочный файл “system_, устройство.. h” также включен для предоставления доступа
к функциям в системном файле. Внутренняя инструкция CMSIS и функции помощника
содержится в двух дальнейших файлах “core_cminstr.h” и “core_cmfunc.h”. При
использовании Коры-M4 или Коры-M7, дополнительный файл "core_CM4_simd.h"
добавляется для оказания поддержки для инструкций Коры-M4 SIMD. Как обсуждено
ранее “stdint.h” файл обеспечивает типы MISRA-C, которые используются в определениях
CMSIS и должны использоваться через
Ваш код приложения.

CMSIS-базовые заголовочные файлы


В CMSIS-базовой спецификации существует небольшое количество, определяет,
которые являются установкой для данного микроконтроллера. Они могут быть
найдены в, устройство.. h процессор включают файл (Таблица 4.3).

Таблица 4.3: значения конфигурации CMSIS

CMSIS определяют Описание


__ CMx_REV Базовое число пересмотра
Число приоритетных битов реализовано в приоритетных регистрах
__ NVIC_PRIO_BITS NVIC
Определяет, если MPU присутствует (см. Главу: 5 Функций Передовой
__ MPU_PRESENT архитектуры)
Определяет, если FPU присутствует (см. Главу: 7 Отладок с
__ FPU_PRESENT CoreSight)
__ Определяет, если существует поставщик определенная
Vendor_SysTickConfig Конфигурация SysTick
144 Главы 4

Процессор включает файл, также импортирует заголовочные файлы CMSIS, которые


содержат CMSIS-базовые функции помощника. Функции помощника разделяются на
группы как показано в Таблице 4.4:

Таблица 4.4: группы функции CMSIS


CMSIS-базовые функциональные группы
Функции доступа NVIC
Конфигурация SysTick
Доступ регистра ЦП
Инструкция ЦП intrinsics
Cortex-M4-SIMD intrinsics
Функции отладки ITM
Функции FPU (Только Кора-M7)
Функции кэша (Только Кора-M7)

Группа NVIC обеспечивает все функции, необходимые для конфигурирования


прерываний Cortex-M и исключений. Подобная функция обеспечивается для
конфигурирования таймера SysTick и прерывания. Группа регистров ЦП позволяет Вам
легко читать и писать в регистры ЦП с помощью Регистра Перемещения для
Специального Регистра (MRS) и Перемещение Специальные Регистры для Регистрации
инструкций (MSR). Любые инструкции, которые не достижимы языком “C”,
поддерживаются специализированными встроенными функциями и содержатся в группе
инструкций ЦП. Расширенный набор intrinsics также обеспечивается для Коры-M4 и
Коры-M7 для доступа к инструкциям SIMD. Наконец некоторые стандартные функции
обеспечиваются для доступа к Трассировке Инструментария отладки.

Прерывания и исключения
Управление регистрами NVIC может быть сделано функциями, обеспеченными в
группе исключения и прерывании. Эти функции позволяют Вам устанавливать канал
прерывания NVIC и управлять его приоритетом, а также опрашивать регистры NVIC
в течение времени выполнения (Таблица 4.5).

Таблица 4.5: прерывание CMSIS и группа исключения

Функция CMSIS Описание


NVIC_SetPriorityGrouping Установите приоритетную группировку
NVIC_GetPriorityGrouping Считайте приоритетную группировку
NVIC_EnableIRQ Включите канал прерывания ввода-вывода
Отключите канал прерывания ввода-
NVIC_DisableIRQ вывода
Считайте незаконченное состояние канала
NVIC_GetPendingIRQ прерывания
Установите незаконченное состояние
NVIC_SetPendingIRQ канала прерывания
NVIC_ClearPendingIRQ Очистите незаконченное состояние канала
прерывания
Получите активное состояние канала
NVIC_GetActive прерывания
Установите активное состояние канала
NVIC_SetPriority прерывания
NVIC_GetPriority Получите приоритет канала прерывания
NVIC_EncodePriority Кодирует приоритетную группу
NVIC_DecodePriority Декодирует приоритетную группу
NVIC_SystemReset Вызывает системный сброс
Стандарт программного интерфейса микроконтроллера коры 145

Функция конфигурирования также обеспечивается для таймера SysTick (Таблица 4.6).


Таблица 4.6: функция CMSIS-SysTick

Функция CMSIS Описание


Настраивает таймер и включает
SysTick_Config прерывание

Так, например, для конфигурирования внешней линии прерывания мы сначала


должны найти название внешнего вектора прерывания используемым в таблице
векторов кода запуска.
DCD FLASH_IRQHandler ; Flash
DCD RCC_IRQHandler ; RCC
DCD EXTI0_IRQHandler ; EXTI Line0
DCD EXTI1_IRQHandler ; EXTI Line1
DCD EXTI2_IRQHandler ; EXTI Line2
DCD EXTI3_IRQHandler ; EXTI Line3
DCD EXTI4_IRQHandler ; EXTI Line4
DCD DMA1_Stream0_IRQHandler; поток DMA1 0

Таким образом для внешней линии прерывания 0 мы просто должны создать


пустую функцию, копирующую имя, используемое в таблице векторов;
освободите EXTI0_IRQHandler (пусто);

Это теперь становится нашей процедурой обработки прерывания. Кроме того, мы


должны настроить периферийное устройство микроконтроллера и NVIC для
включения канала прерывания. В случае внешней линии прерывания следующий код
установит Порт контакт 0 для генерации прерывания к NVIC на убывающем фронте.
AFIO-.EXTICR [0] И 5 BAFIO_EXTICR1_EXTI0; /* ясный используемый контакт */
AFIO-.EXTICR [0] | 5 AFIO_EXTICR1_EXTI0_PA; /* набор PA.0 для использования */
ЭКС-TI-.IMR | 5 EXTI_IMR_MR0; /* размаскируйте прерывание */
ЭКС-TI-.EMR И 5 BEXTI_EMR_MR0; /* никакое событие */
/* никакой триггер нарастающего
ЭКС-TI-.RTSR И 5 BEXTI_RTSR_TR0; фронта */
/* установите триггер убывающего
ЭКС-TI-.FTSR | 5 EXTI_FTSR_TR0; фронта */

Затем мы можем использовать функции CMSIS для включения канала прерывания.


NVIC_EnableIRQ (EXTI0_IRQn);

Здесь мы используем определенный перечислимый тип для номера канала


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

Мы можем также добавить второй источник прерывания при помощи функции


конфигурирования SysTick, которая является единственной функцией в группе
SysTick.
uint32_t SysTick_Config (uint32_t галочки)

Эта функция настраивает значение обратного отсчета таймера SysTick и включает его
прерывание, таким образом, исключение будет повышено, когда его количество
достигнет нуля. Начиная с systemInit () функция
146 Глав 4

устанавливает глобальную переменную SystemCoreClock с частотой ЦП, которая


также используется Вы таймер SysTick, мы можем легко установить таймер SysTick
для генерации желаемого периодического прерывания. Таким образом, одно
прерывание миллисекунды может быть сгенерировано следующим образом.
SysTick_Config (SystemCoreClock/1000);

Снова мы можем искать обработчик исключений от таблицы векторов:


DCD 0; Зарезервировано
Обработчик
DCD PendSV_Handler; PendSV
Обработчик
DCD SysTick_Handler; SysTick

и создайте соответствие “C” функция;


освободите SysTick_Handler (пусто);

Теперь, когда у нас есть два источника прерывания, мы можем использовать другое
прерывание CMSIS и функции исключения для управления приоритетными
уровнями. Количество приоритетных уровней будет зависеть от того, сколько
приоритетных битов было реализовано кремниевым производителем. Для всех
процессоров Cortex-M мы можем использовать простую “плоскую” систему
приоритетов, где нуль является самым высоким приоритетом. Приоритетный
уровень установлен:
NVIC_SetPriority (IRQn_Type IRQn, uint32_t приоритет);

NVIC_SetPriority () функция немного более интеллектуален, чем простой макрос.


Это использует номер канала IRQn NVIC для дифференциации между
пользовательскими периферийными устройствами и исключениями процессора
Cortex-M. Это позволяет этому программировать или приоритетные регистры
обработчика систем в системном блоке управления или приоритетные регистры
прерывания в самом NVIC. NVIC_SetPriority () функция также использует
определение NVIC_PRIO_BITS для смещения приоритетного значения в активные
приоритетные биты, которые были реализованы кремниевым поставщиком.
_STATIC_INLINE освобождают NVIC_SetPriority (IRQn_Type IRQn, uint32_t приоритет)
{
если (IRQn, 0) {
SCB-.SHP [((uint32_t) (IRQn) и 0xF)-4] 5 ((приоритет, (8 - __ NVIC_PRIO_BITS)) и 0xff);}/* Приоритет набора
для Системных прерываний Cortex-M */
еще {
NVIC-.IP [(uint32_t) (IRQn)] 5 ((приоритет, (8 - __ NVIC_PRIO_BITS)) и 0xff);}/* Приоритет набора для
устройства определенные Прерывания */
}

Однако для Cortex-M3/M4 и Кора-M7 у нас есть опция установить приоритетные


группы и подгруппы, как обсуждено в Главе 3 “Архитектура Cortex-M”. В
зависимости от числа приоритетных битов, определенных производителем, мы можем
настроить приоритетные группы и подгруппы.
NVIC_SetPriorityGrouping ();

Установить приоритет NVIC, группирующий Вас, должно записать в “Регистр”


Управления Прерыванием и Сбросом приложения. Как обсуждено в Главе 3
“Архитектура Cortex-M” этот регистр защищена
Стандарт программного интерфейса микроконтроллера коры 147

его полем VECTKEY. Для обновления этого регистра, необходимо записать “0x5FA” в
поле VECTKEY. SetPriorityGrouping () функция предоставляет весь необходимый код,
чтобы сделать это.

__ STATIC_INLINE освобождают NVIC_SetPriorityGrouping (uint32_t PriorityGroup)


{
uint32_t reg_value;
uint32_t PriorityGroupTmp5 (PriorityGroup&(uint32_t) 0x07);/* только оценивает 0.. 7 используемый */reg_value
5 SCB-.AIRCR;/* читают старую конфигурацию регистра */reg_value &5 B
(SCB_AIRCR_VECTKEY_Msk|SCB_AIRCR_PRIGROUP_Msk); ясные биты/* для изменения */reg_value 5
(reg_value | ((uint32_t) 0x5FA, SCB_AIRCR_VECTKEY_Pos) |/* Вставляют ключ записи и приоритетную группу
*/

(PriorityGroupTmp, 8)); SCB-


.AIRCR 5 reg_value;
}

“Прерывание и Исключение” группа также обеспечивают системную


функцию сброса, которая генерирует жесткую перезагрузку целого
микроконтроллера.
NVIC_SystemReset (пусто);

Эта функция пишет в бит два из “Регистра” Управления Сбросом Прерывания


Приложения. Это стробирует логическую строку из Ядра Cortex-M к схеме сброса
микроконтроллера, которая сбрасывает периферийные устройства микроконтроллера и
процессор Cortex-M. Однако необходимо быть немного осторожными здесь, как
реализация этой функции до производителя микроконтроллеров и не может быть
полностью реализована. Таким образом, если Вы собираетесь использовать эту функцию,
необходимо протестировать ее сначала. Разрядный нуль того же регистра сделает "теплый"
сброс процессора Cortex-M. Это - сила сброс процессора Cortex-M, но оставьте регистры
микроконтроллера настроенными.

Упражнение 4.1 CMSIS и пользовательское сравнение кода


В этом осуществлении мы пересмотрим несколько примеров прерываний и исследуем
переписывание кода с помощью CMSIS-базовых функций.
Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Выберите вкладку в качестве примера и Копию “EX 4.1 CMSIS Несколько
Прерывание”.
Выберите вкладку в качестве примера и Копию “EX 3.3 Несколько Прерываний”.
Откройте main.c в обоих проектах и сравните код инициализации.
Прерывания таймера и ADC SysTick могут быть инициализированы со следующими
функциями CMSIS.

SysTick_Config (SystemCoreClock / 100);


NVIC_EnableIRQ (ADC1_2_IRQn);
NVIC_SetPriorityGrouping (5);
NVIC_SetPriority (SysTick_IRQn, 4);
NVIC_SetPriority (ADC1_2_IRQn, 4);
148 Глав 4

Или можно использовать эквивалентный non-CMSIS код....


SysTick-.VAL 5 0x9000; //Запустите значение для счетчика Галочки sys
SysTick-.LOAD 5 0x9000; //Значение перезагрузки
SysTick-.CTRL 5 SYSTICK_INTERRUPT_ENABLE |SYSTICK_COUNT_ENABLE; //Запустите и
включите
прерывание
NVIC-.ISER [0] 5 (1UL, 18); /* включите Прерывание ADC */
NVIC-.IP[18] 5 (2, 6 | 2, 4);
SCB-.SHP[11] 5 (1, 6 | 3, 4);
Временный файл 5 SCB-.AIRC;
Временный файл и 5 B0x
Временный файл 5 временных файлов | (0xAF0) | (0x05);

Хотя оба блока кода достигают того же самого, версия CMSIS намного быстрее для
записи более читаемый и намного менее подверженный кодированию ошибок.
Разработайте оба проекта и сравните размер произведенного кода.

Функции CMSIS представляют маленькие издержки, но это - приемлемый


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

CMSIS-базовый доступ регистра

Следующая группа функций CMSIS предоставляет Вам прямой доступ к регистрам


процессора CPU (Таблица 4.7).
Таблица 4.7: CMSIS функции регистра ЦП

Базовая функция Описание


__ get_Control Прочитайте регистр управления
__ set_Control Запишите в регистр управления
__ get_IPSR Считайте регистр IPSR
__ get_APSR Считайте регистр APSR
__ get_xPSR Считайте регистр xPSR
__ get_PSP Считайте указатель стека процесса
__ set_PSP Запишите в указатель стека процесса
__ get_MSP Считайте основной указатель вершины стека
Запишите в основной указатель вершины
__ set_MSP стека
__ get_PRIMASK Считайте PRIMASK
__ set_PRIMASK Запишите в PRIMASK
__ get_BASEPRI Считайте регистр BASEPRI
__ set_BASEPRI Запишите в регистр BASEPRI
__ get_FAULTMASK Считайте FAULTMASK
__ set_FAULTMASK Запишите в FAULTMASK
__ get_FPSCR Считайте FPSCR
__ set_FPSCR Запишите в FPSCR
Включите прерывания и настраиваемые
__ enable_irq исключения отказа
Отключите прерывания и настраиваемые
__ disable_irq исключения отказа
Включает прерывания и все обработчики
__ enable_fault_irq ошибок
Отключает прерывания и все обработчики
__ disable_fault_irq ошибок
Стандарт программного интерфейса микроконтроллера коры 149

Эти функции предоставляют Вам способность глобально управлять прерываниями NVIC


и установить конфигурацию процессора Cortex-M в его более усовершенствованный
рабочий режим. Сначала мы можем глобально включить и отключить прерывания
микроконтроллера со следующими функциями.

__ set_PRIMASK (пусто); __
set_FAULTMASK (пусто); __
разрешать-IRQ __
enable_Fault-irq __
set_BASEPRI ()

В то время как все эти функции включают и отключают источники прерывания, они
все имеют немного отличающиеся эффекты. __ set_PRIMASK () функция и функции
enable_IRQ/Disable_IRQ имеют тот же эффект, в котором они устанавливают и
очищаются, PRIMASK укусил, который включает и отключает все источники
прерывания кроме Обработчика Серьезных отказов и Немаскируемого прерывания. __
set_FAULTMASK () функция может использоваться для отключения всех прерываний
кроме Немаскируемого прерывания. Мы будем видеть позже, как это может быть
полезно, когда мы хотим обойти единицу Защиты памяти. Наконец __ set_BASEPRI ()
функция устанавливает минимальный активный приоритетный уровень для
пользовательских прерываний ввода-вывода. Когда регистр Базового приоритета
установлен на ненулевой уровень и прерывание на том же приоритетном уровне или
ниже будет отключен.

Эти функции позволяют Вам читать регистр состояния программы и его


псевдонимы. Можно также получить доступ к регистру управления для включения
усовершенствованных рабочих режимов процессора Cortex-M, а также явно
устанавливания значений указателя вершины стека. Специализированная функция
также обеспечивается для доступа к “Плавающей точке tatus и Управлению”
регистр, если Вы используете Кору-M4 или Кору-M7. Мы более внимательно
рассмотрим в более усовершенствованном
рабочие режимы процессора Cortex-M в Главе 5 “Функции Передовой архитектуры”.

CMSIS-ядро-процессора внутренние инструкции


CMSIS-базовый заголовок также обеспечивает две группы стандартизированных
встроенных функций. Первая группа характерна для всех процессоров Cortex-M, и
второе предоставляет стандарт, внутренний для инструкций Коры-M4 SIMD
(Таблица 4.8).

Таблица 4.8: инструкция CMSIS intrinsics


CMSIS
Функция Описание Больше информации
__
ТОЛЬКО
ДЛЯ
УКАЗАНН
ЫХ
ЦЕЛЕЙ Никакая операция
__ WFI Ожидайте прерывания
__ WFE Ожидайте события
__ SEV Событие Send См. главу 3 “архитектура Cortex-M”
__ ISB Барьер синхронизации инструкции
__ DSB Барьер синхронизации данных
Барьер синхронизации памяти
__ DMD данных

(Длительн
ый)
150 Глав 4

Таблица 4.8: (Длительный)


CMSIS
Функция Описание Больше информации
__
ВЕРСИЯ Обратный порядок байтов (32 бита)
Обратный порядок байтов (16
См. главу 4 “программное обеспечение
__ REV16 битов)
микроконтроллера коры
Обратный порядок байтов,
Соедините интерфейсом со Стандартом” для
__ REVSH подписанный короткий
инструкций по вращению
Обратный разрядный порядок (не
__ RBIT для Коры-M0)
__ ROR Вращайтесь прямо n битами
__
LDREXB Загрузитесь эксклюзивный (8 битов)
__ Загрузитесь эксклюзивный (16
LDREXH битов)
__
LDREXW Загрузитесь эксклюзивный (32 бита) См. главу 5 “функции передовой архитектуры”
__
STREXB Сохраните эксклюзивный (8 битов) инструкции по эксклюзивному доступу
__
STREXH Сохраните эксклюзивный (16 битов)
__
STREXW Сохраните эксклюзивный (32 бита)
__ CLREX Удалите монопольную блокировку
__ SSAT Подписанный насыщают
См. главу 3 “архитектура Cortex-M”
__ USAT Неподписанный насыщают
См. главу 4 “программное обеспечение
__ CLZ Считайте начальные нули микроконтроллера коры
Интерфейсный стандарт”

ЦП intrinsics обеспечивает прямой доступ к инструкциям по процессору Cortex-M,


которые не непосредственно достижимы с языка “C”. Используя внутреннее позволит
специализированной единственной инструкции по циклу заменить многоадресные
команды, сгенерированные стандартом “C” код.

С ЦП, внутренним, мы можем перейти к режимам низкой мощности с помощью __


WFI () и __ WFE () инструкции. ЦП intrinsics также обеспечивает доступ к
инструкциям влажной математики, что мы встретили в Главе 3 “Архитектуру Cortex-
M”. Встроенные функции также предоставляют доступ к инструкциям по барьеру
выполнения, которые гарантируют завершение записи данных или выполнение
инструкции прежде, чем продолжить следующую инструкцию. Следующая группа
инструкции intrinsics используется для гарантии эксклюзивного доступа к региону
памяти одним регионом кода. Мы взглянем на них в Главе 5 “Функции Передовой
архитектуры”. Остаток от ЦП intrinsics поддерживает единственные функции
манипулирования данными цикла, такие как поворачивание и обратные разрядные
инструкции по порядку.

Упражнение 4.2 Внутренняя побитовая обработка


В этом осуществлении мы посмотрим на манипулирование данными, внутреннее
поддерживаемый в CMSIS.
Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Стандарт программного интерфейса микроконтроллера коры 151

Выберите вкладку в качестве примера и Копию “Внутреннее CMSIS-ядро EX 4.2”.

Осуществление объявляет входную переменную и группу выходных переменных и


затем использует каждую из внутренних функций манипулирования данными.
outputREV 5 __ ВЕРСИЯ (вводится);
outputREV16 5 __ REV16 (вводится);
outputREVSH 5 __ REVSH (вводится);
outputRBIT 5 __ RBIT (вводится);
outputROR 5 __ ROR (вход, 8);
outputCLZ 5 __ CLZ (вводится);

Разработайте проект и запустите отладчик.


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

В то время как каждая внутренняя инструкция берет единственный цикл,


некоторые окружающие инструкции требуются так, встроенные функции берут
между 9 и 18 циклами.

Исследуйте значения в выходных переменных для ознакомления с действием


каждого внутреннего (Рис. 4.8).

Рисунок 4.8
Результаты intrinsics операций.

Рассмотрите, как Вы кодировали бы каждый внутренний стандарт использования “C”


инструкции.

CMSIS-SIMD Intrinsics
Следующая группа CMSIS intrinsics обеспечивает прямой доступ к инструкциям
Коры-M4 и Коры-M7 SIMD.

Инструкции SIMD обеспечивают одновременные вычисления для двух 16-разрядных


операций или четырех 8-разрядных операций. Это значительно улучшает любую
форму повторяющегося вычисления по набору данных, как
152 Главы 4

в цифровом фильтре и мы внимательно изучим эти инструкции в Главе 8


“Практический DSP для Коры-M4 и Коры-M7”.

CMSIS-базовые функции отладки


CMSIS-базовые функции также оказывают улучшенную поддержку отладки через
Трассировку Инструментария CoreSight. Стандарт CMSIS имеет две
специализированных спецификации отладки CMSIS-SVD и CMSIS-DAP, на который
мы посмотрим в Главе 7 “Отладка с CoreSight”. Однако CMSIS-базовая
спецификация содержит некоторую полезную поддержку отладки.

Аппаратная точка останова


В первую очередь, существует специализированное внутреннее для добавления
аппаратной точки останова к коду.
__ BKPT (uint8_t значение)

Используя это внутреннее поместит аппаратную команду контрольного останова в


этом местоположении в Вашем коде. То, когда эта точка будет достигнутым
выполнением, будет остановлено, и “значение” будет передано отладчику. Во время
разработки __ BKPT () внутренний может использоваться, чтобы захватить состояния
ошибки и остановить отладчик.

Трассировка инструментария

Как часть ее аппаратной системы отладки, Кора-M3, Кора-M4 и Кора-M7


обеспечивают “единицу” Трассировки Инструментария (ITM). Это может считаться
отладкой UART, который подключен к консоли в отладчике. Путем добавления
рычагов отладки (Оснащающих) в код, возможно считать и записать данные в и от
отладчика, в то время как код работает. Мы посмотрим на использование Трассировки
Инструментария для дополнительной отладки и тестирования программного
обеспечения в Главе 7 “Отладка с CoreSight”. На данный момент существует много
функций CMSIS, которые стандартизируют связь с ITM (Таблица 4.9).

Таблица 4.9: функции отладки CMSIS

Функция отладки CMSIS Описание


энергозависимый международный ITM_RxBuffer 5 Объявите, что одно слово устройства
ITM_RXBUFFER_EMPTY; хранения данных для получает флаг
ITM_SendChar (c); Отправьте один символ в ITM
Проверьте, были ли какие-либо данные
ITM_CheckChar () получены
ITM_ReceiveChar () Считайте один символ из ITM
Стандарт программного интерфейса микроконтроллера коры 153

CMSIS-базовые функции для Corex-M7


С выпуском процессора Cortex-M7 в конце 2014 CMSIS-базовая спецификация была
расширена для обеспечения некоторых дополнительных функций, чтобы
поддерживать новые функции, представленные Corex-M7 (Таблица 4.10).

Таблица 4.10: функция Коры-M7 CMSIS

Функция CMSIS коры-M7 Описание


Одиннадцать функций для поддержки кэшей Инструкции
Функции кэша и Данных
Функция FPU Одна функция для поддержки FPU

Поскольку мы будем видеть в Главе 6 “Процессор Коры-M7”, Кора-M7 представляет


кэши Данных и Инструкции семейству процессоров Cortex-M. Функции кэша CMSIS
позволяют Вам включать и отключать кэши и управлять ими, поскольку Ваш код
выполняется. Мы посмотрим на эти функции в Главе 6 “Процессор Коры-M7”.

Заключение
Хорошее понимание каждой спецификации CMSIS является ключевым для
эффективной разработки приложений для любого Основанного на Cortex-M
микроконтроллера. В этой главе мы представили каждую спецификацию CMSIS и
бросили подробный взгляд на CMSIS-базовую спецификацию. Мы посмотрим на
остающиеся спецификации CMSIS через остальную часть этой книги.
Эта страница, намеренно
оставленная незаполненный
CHPTER5

Функции передовой архитектуры

Введение
В последних нескольких главах мы покрыли большую часть того, что необходимо
знать для разработки с Основанным на Cortex-M микроконтроллером. В этой главе мы
посмотрим на некоторые из большего количества расширенных функций процессора
Cortex-M. Все функции, обсужденные в этой главе, включены в Кору-M01,-M3,-M4,
и-M7. В этой главе мы посмотрим на различные рабочие режимы, встроенные в
каждый из процессоров Cortex-M и некоторых дополнительных инструкций, которые
разработаны для поддержки использования операционной системы реального времени
(RTOS). Мы также взглянем на дополнительную Единицу защиты памяти (MPU),
которая может быть приспособлена к Коре-M01,-M3,-M4, и-M7 и как это может
разделить карту распределения памяти. Это обеспечивает управляемый доступ к
различным регионам памяти в зависимости от рабочего режима процессора. Для
закругления главы мы взглянем на шинный интерфейс между процессором Cortex-M и
системой микроконтроллера.

Рабочие режимы процессора коры


Когда процессор Cortex-M выходит из сброса, он работает в простом “плоском”
режиме, где весь код приложения имеет доступ к полному адресному пространству
процессора и неограниченный доступ к регистрам NVIC и ЦП. В то время как это
хорошо для многих приложений, процессор Cortex-M имеет много функций, которые
позволяют Вам поместить процессор в более усовершенствованный рабочий режим,
который подходит для программного обеспечения высокой целостности и также
поддерживает RTOS.

Как первый шаг к пониманию более усовершенствованных рабочих режимов


процессора Cortex-M, мы должны понять его рабочие режимы. ЦП может выполнять
его два различных режима, режим Thread и режим Handler. Когда процессор
выполняет фоновый код (т.е., код непрерывания), он работает в режиме Thread.
Когда процессор выполняет код прерывания, он работает в режиме Handler (Рис. 5.1).
Руководство разработчика по семейству процессоров Cortex-M.
DOI: http://dx.doi.org/10.1016/B978-0-08-100629-0.00005-0 155
© 2016 Elsevier Ltd. Все права защищены.
156 Глав 5

Рисунок 5.1
Каждый процессор Cortex-M имеет два режима выполнения, Обработчик (прерывание)
и Поток (фон). Возможно настроить эти режимы для назначения полномочий и
непривилегированный доступ к регионам памяти. Также возможно настроить рабочий
режим с двумя стеками.

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


между режимом Thread и Handler. Оба режима имеют полный доступ ко всем
функциям ЦП, это известно как привилегированный режим. Путем программирования
Регистра управления процессора Cortex-M возможно поместить, режим Thread в
непривилегированном режиме путем установки уровня полномочий потока (TPL)
укусил (Рис. 5.2).

Рисунок 5.2
Регистр управления является регистром ЦП, к которому могут только получить доступ
MRS и инструкции MSR. Это содержит два бита, которые настраивают уровень
полномочий режима Thread и активацию указателя стека процесса.

В непривилегированном режиме, Регистре Перемещения к Специальному Регистру


(MRS), Перемещение Специальные Регистры для Регистрации (MSR), и инструкции
по Состоянию процессора изменения (CPS) отключены для всех специальных
регистров ЦП, за исключением APSR. Это препятствует тому, чтобы процессор
Cortex-M получил доступ к УПРАВЛЕНИЮ, FAULTMASK, и регистрам PRIMASK и
Регистру состояния ПРОГРАММЫ (кроме APSR). В непривилегированном режиме
также не возможно получить доступ к регистрам таймера SysTick, NVIC или
Системному Блоку управления. Это ограничивает возможность
непривилегированного кода, случайно нарушающего эксплуатацию процессора
Cortex-M. Если режим Thread был ограничен непривилегированным доступом, не
возможно очистить Поток
Функции передовой архитектуры 157

уровень полномочий режима укусил, даже если ЦП работает в режиме Handler с


доступом полномочия. После того как TLP укусил, был установлен, код приложения,
работающий в режиме Thread, больше не может влиять на эксплуатацию процессора
Cortex-M. Когда процессор отвечает на исключение или прерывание, он перемещается
в режим Handler, который всегда выполняет код в привилегированном режиме
независимо от содержания Регистра управления. Регистр управления также содержит
дополнительный бит, Активный Выбор Указателя вершины стека (ASPEL). Установка
этого бита включает дополнительный стек, названный Указателем стека процесса
(PSP). Регистр управления является регистром ЦП, а не регистром с отображенной
памятью и может только быть получен доступ MRS и инструкциями MSR. CMSIS-
базовая спецификация обеспечивает выделенные функции, чтобы читать и записать в
регистр CONRTOL.
освободите __ set_CONTROL (uint32_t
значение); uint32_t __ get_CONTROL (пусто);

Указатель Стека процесса является окруженным валом указателем вершины стека R13,
который используется кодом, работающим в режиме Thread. Когда процессор Cortex-M
отвечает на исключение, он переходит к режиму Handler. Это вызывает ЦП к указателям
стека коммутаторов. Это означает, что режим Handler будет использовать Основной
указатель вершины стека (MSP), в то время как режим Thread использует Указатель
Стека процесса (Рис. 5.3).

Рисунок 5.3
В сбросе R13 является основным указателем вершины стека и автоматически
загружается начальным значением стека. Регистр контроля ЦП может
использоваться для включения окруженного валом регистра R13 секунды. Это
Стек процесса, который используется в режиме Thread. Код приложения должен
загрузить начальное значение стека в этот регистр.
158 Глав 5

Поскольку мы видели в Главе 3 “Архитектуру Cortex-M” в сбросе, MSP будет


загружен значением, сохраненным в первых 4 байтах памяти. Однако Указатель
Стека процесса автоматически не инициализируется и должен быть настроен кодом
приложения, прежде чем он будет включен. К счастью, CMSIS-базовая спецификация
содержит функции для конфигурирования Стека процесса.
освободите __ set_PSP (uint32_t TopOfProcStack);
uint32_t __ get_PSP (пусто);

Так, если необходимо вручную установить начальное значение Стека процесса, каково
это должно быть? Нет простого способа ответить на это, но компилятор производит
файл отчета, который детализирует статическое дерево вызова для проекта. Этот файл
создается каждый раз, когда проект разрабатывают и называют, название проекта..
htm. Файл отчета включает значение для максимального использования стека и дерево
вызова для самой долгой цепочки вызовов.

Это дерево вызова, вероятно, будет для фоновых функций и будет


максимальным значением для Указателя Стека процесса. Это значение может
также использоваться в качестве начальной точки для MSP (Рис. 5.4).

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

Упражнение 5.1 Конфигурация стека


В этом осуществлении мы взглянем на конфигурирование рабочего режима
процессора Cortex-M, таким образом, режим Thread будет работать с
непривилегированным доступом и использует Указатель Стека процесса.
Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Функции передовой архитектуры 159

Выберите вкладку Example и Копию “конфигурация EX 5.1 Стека процесса”.


Создайте код, запустите отладчик и работайте к основному ().

Это - версия проекта Blinky, который мы использовали ранее с некоторым


кодом, добавленным для конфигурирования рабочего режима процессора.
Новый код включает ряд #defines.
#define USE_PSP_IN_THREAD_MODE (1, 1)
#define THREAD_MODE_IS_UNPRIVILIGED 1
#define PSP_STACK_SIZE 0x200

Первые два объявления определяют местоположение битов, которые должны быть


установлены в регистре управления включить Указатель Стека процесса и
переключить режим Thread в непривилегированный доступ. Затем мы определяем
размер пространства Стека процесса. В начале основного мы можем использовать
функции CMSIS, чтобы настроить и включить Указатель Стека процесса. Мы можем
также исследовать рабочие режимы процессора в окне Register (Рис. 5.5).

Рисунок 5.5
Процессор Cortex-M находится в режиме Thread/privileged с помощью основного
стека. PSP не инициализируется.

_initalPSPValue 5 __ get_MSP () 1 PSP_STACK_SIZE;


_set_PSP (initalPSPValue); __ set_CONTROL
(USE_PSP_IN_THREAD_MODE);
__ ISB ();
__ ISB ();
160 Глав 5

Рисунок 5.6
Теперь процессор находится в режиме Thread/privileged, но использует Указатель
Стека процесса, который был инициализирован со стековым
пространством 200-х байтов.

При достижении основного () функция процессор находится в режиме Thread с


полным привилегированным доступом ко всем функциям микроконтроллера (Рис. 5.6).
Кроме того, только MSP используется. Если Вы ступаете через эти три строки
конфигурации, код сначала читает содержание MSP. Это будет во главе основного
стекового пространства. Для получения начального адреса для PSP мы просто
добавляем желаемый размер стека в байтах. Это значение записано в Указатель Стека
процесса прежде, чем включить его в Регистре управления. Всегда настраивайте стек
прежде, чем включить его в случае, если существует активное прерывание, которое
могло произойти, прежде чем стек готов. Затем, мы должны выполнить любой код,
который должен настроить процессор прежде, чем переключить режим Thread на
непривилегированный доступ. ADC_Init () функциональные доступы NVIC для
конфигурирования прерывания и таймера SysTick также настроен. Доступ к этим
регистрам будет запрещен, когда мы переключимся на непривилегированный режим
(Рис. 5.7). Снова, барьер инструкции используется, чтобы гарантировать, что код
завершается, прежде чем выполнение продолжается.
Рисунок 5.7
Теперь процессор был установлен в режим Потока /
непривилегированный режим.
Функции передовой архитектуры 161

Установите точку останова в строке модуля IRQ.c 32.

Это находится в стандартной программе обработчика прерываний SysTick.


Теперь, выполните код, и он поразит точку останова, когда прерывание
обработчика SysTick будет повышено (Рис. 5.8).

Рисунок 5.8
Во время исключения процессор переходит к режиму Обработчика /
привилегированному режиму.

Теперь, когда процессор служит прерыванию, он переместился в режим


обработчика прерываний с привилегированным доступом к процессору
Cortex-M и использует основной стек.

Вызов контролера
После того, как настроенный, этот более усовершенствованный рабочий режим
обеспечивает раздел между кодом исключения/прерывания, работающим в режиме
Handler и кодом фонового приложения, работающим в режиме Thread. Каждый
рабочий режим может иметь свой собственный регион кода, регион RAM и стек. Это
предоставляет полный доступ кода обработчика прерываний к микросхеме без риска,
что это может быть повреждено кодом приложения. Однако в какой-то момент код
приложения должен будет получить доступ к функциям процессора Cortex-M,
которые только доступны в режиме Handler с его полным привилегированным
доступом. Чтобы позволить этому происходить, Ползунок, 2 системы команд имеют
инструкцию, названную вызовом контролера (SVC). Когда эта инструкция
выполняется, она повышает исключение супервизора, которое перемещает процессор
от выполнения кода приложения в режиме потока / непривилегированном режиме к
стандартной программе исключения в режиме обработчика / привилегированном
режиме. SVC имеет свое собственное расположение в таблице векторов и ведет себя
как любое другое исключение (Рис. 5.9).
162 Главы 5

Рисунок 5.9
Вызов контролера (SVC) позволяет выполнению перемещаться от
непривилегированного режима Thread до привилегированного режима Handler и
получать полный неограниченный доступ к процессору Cortex. Инструкция SVC
используется вызовами API RTOS.

Инструкция SVC может также быть закодирована 8-разрядным значением, названным


ординалом. Когда вызов SVC выполняется, этот порядковый номер может читаться и
использоваться в качестве индекса для вызова одной из 256 различных функций
супервизора (Рис. 5.10).

Рисунок 5.10
Неиспользованная часть инструкции SVC может быть закодирована порядковым числом.
На записи в обработчик SVC это число может быть считано для определения, какой
SVC функционирует для выполнения.

Набор инструментальных средств компилятора обеспечивает специализированную


функцию поддержки SVC, которая используется, чтобы извлечь порядковый номер и
затем вызвать соответствующую функцию. Во-первых, функция поддержки SVC
читает регистр ссылки для определения рабочего режима, затем это читает значение
сохраненного ПК от соответствующего стека. Мы можем затем считать ячейку памяти,
содержащую инструкцию SVC, и извлечь порядковый номер. Это число затем
используется в качестве индекса в справочную таблицу для загрузки адреса функции,
которая вызывается. Функция затем вызвана и выполняется в привилегированном
режиме, прежде чем мы возвратимся назад к коду приложения, работающему в
Функции передовой архитектуры 163

непривилегированный режим потока. Этот механизм может казаться чрезмерно


сложным способом вызвать функцию, но он обеспечивает основание разделения
супервизора/пользователя, куда операционная система (OS) работает в
привилегированном режиме и действует как супервизор к потокам приложения,
работающим в непривилегированном режиме потока. Таким образом, отдельные
потоки не имеют доступа к критическим функциям процессора кроме путем создания
вызовов API ОС.

Упражнение 5.2 Вызов контролера


В этом осуществлении мы посмотрим на вызывание некоторых функций с
инструкцией SVC вместо того, чтобы перейти к стандартной программе как в вызове
стандартной функции.
Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Выберите вкладку Example и Копию “вызов контролера EX 5.2”
Во-первых, давайте взглянем на структуру проекта (Рис. 5.11).

Рисунок 5.11
Инструкции SVC поддерживаются путем добавления дополнительного модуля
SVC.c. Этот модуль предоставляет код для “декодирования”
инструкции SVC 1 порядковое.

Проект состоит из стандартного файла запуска проекта и системного файла


инициализации. Исходный код приложения находится в файле main.c. Существует
дополнительный исходный файл SVC.c, который оказывает поддержку для обработки
исключений SVC. Файл SVC.c содержит обработчик исключений SVC, это -
стандартный файл поддержки, которому предоставляют компилятор ARM. Мы будем
164 Главы 5

более внимательно рассмотрите при его операции позже. Код приложения в


main.c вызывает две простых функции, которые в свою очередь называют
стандартные программы для выполнения основных арифметических операций.
международное
основное
(пустота) {test_a
(); test_t ();

в то время как (1);


}
освободите test_a (пусто)
{res 5 добавляет (74, 27);
res 1 5 mul4 (res);

}
освободите test_t (пусто)
{отделение res 5 (res,
10); модификация res 5
(res, 3);

Каждая из арифметических функций разработана, чтобы быть названной с


инструкцией SVC так, чтобы все эти функции, выполненные в режиме обработчика, а
не режиме потока. Для преобразования функций арифметики от стандартных функций
до функций программного прерывания мы должны изменить способ, которым
объявляется прототип функции. Путем это сделано, будет варьироваться между
компиляторами, но в компиляторе ARM существует функциональный спецификатор
__ svc. Это используется как показано ниже для преобразования функции, чтобы быть
SVC и позволяет Вам передавать до четырех параметров и получать возвращаемое
значение. Так добавление () функция объявляется следующим образом:
интервал __ svc (0) добавляет (интервал
i1, интервал i2); интервал __ SVC_0
(интервал i1, интервал i2) {
возвратитесь (i1 1 i2);
}

__ svc спецификатор определяет эту функцию как SVC и определил порядковое


число функции. Используемые ординалы должны начать с нуля и вырасти вверх
непрерывно максимум до 256. Для включения каждого ординала необходимо
создать справочную таблицу в файле SVC.c.
; Импортируйте пользователя функции
SVC сюда.
ИМПОРТИРУЙТЕ __
SVC_0
ИМПОРТИРУЙТЕ __ SVC_1
ИМПОРТИРУЙТЕ __ SVC_2
ИМПОРТИРУЙТЕ __ SVC_3
SVC_Table
; Введите пользователя функции SVC здесь
DCD __ SVC_0
DCD __ SVC_1 ;
DCD __ SVC_2 ;
DCD __ SVC_3 ;
Функции передовой архитектуры 165

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


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

В проекте создают код и запускают средство моделирования. Ступают код, пока Вы не


достигаете строки 61, вызов к добавить функции.

Следующий код отображен в окне дизассемблирования, и в окне регистра мы видим,


что процессор работает в режиме потока (Рис. 5.12).

Рисунок 5.12
До инструкции SVC процессор работает в режиме Thread.

Параметры функции загружаются в R0 регистров передачи параметров и R1, и


нормальная команда перехода заменяется инструкцией SVC. Инструкция SVC
кодируется порядковым номером 3. Если Вы сделаете окно дизассемблирования
активным окном и ступите через эти инструкции, то исключение SVC будет
повышено, и Вы введете обработчик SVC в SVC.c. В окне Registers можно также
видеть, что процессор теперь работает в режиме обработчика (Рис. 5.13).

Рисунок 5.13
После того как инструкция SVC была выполнена, provesor будет работать в режиме
Handler.

Первый раздел кода SVC_Handler удается, какой стек используется и затем читает,
значение счетчика команд экономило на стеке. Значение счетчика команд является
обратным адресом, таким образом, инструкция по загрузке вычитает 2 для получения
адреса инструкции SVC.
166 Глав 5

Это будет адресом инструкции SVC, которая повысила исключение. Инструкция


SVC затем загружается в R12, и порядковый номер извлечен. Код использует R12,
потому что двоичный файл ARM взаимодействует через интерфейс, стандарт
определяет R12 как “Регистр Царапины Вызова процедуры Intra”; это означает,
что не будет содержать данных программы и свободно для использования.
ПРОДВИНЬТЕ {R4, LR} ; Сохраните регистры
LDR LR, 5 SVC_Count
LDR LR, [LR]
CMP R12, LR
BHS SVC_Dead ; Переполнение
LDR LR, 5 SVC_Table
LDR R12, [LR, R12, LSL № 2] ; Загрузите адрес функции SVC
BLX R12 ; Вызовите функцию SVC

Следующий раздел обработчика исключений SVC готовится переходить к добавлению


() функция. Во-первых, регистр ссылки и R4 продвинуты на стек. Размер таблицы SVC
загружается в регистр ссылки. Ординал SVC сравнивается с размером таблицы, чтобы
проверить, что это - меньше, чем размер таблицы SVC и следовательно верный номер.
Если это допустимо, функциональный адрес загружается в R12 из таблицы SVC, и
функция вызвана. Если порядковое число не было добавлено к таблице, код перейдет к
прерыванию под названием SVC_DEAD. Хотя R4 не используется в этом примере, он
сохраняется на стеке, поскольку для вызванной функции возможно использовать его.

ПОП {R4, LR}


TST LR, #4
MRSNE R12, PSP
MOVEQ R12, SP
; Функциональные
STM R12, {R0-R3} возвращаемые значения
BX LR ; RETI

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

Исключение PEND_SV
Кора-M01,-M3,-M4, и-M7 имеют дополнительное исключение процессора,
названное исключением PENDSV. Исключение PENDSV было добавлено к
процессору Cortex-M, прежде всего, для поддержки RTOS. Мы более тщательно
изучим то, как RTOS использует исключение PENDSV в Главе 9 “CMSIS-RTOS”,
но на данный момент мы посмотрим на то, как это работает. Исключение PENDSV
может считаться каналом прерывания NVIC, который подключен к регистру
процессора, а не периферийному устройству микроконтроллера. Исключение
PENDSV может быть повышено прикладным программным обеспечением,
пишущим в регистр PENDSV, исключение PENDSV затем обработано таким же
образом как любое другое исключение.
Функции передовой архитектуры 167

Пример Pend_SV
В этом примере мы исследуем, как использовать прерывание вызова системной
службы PENDSV.
Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Выберите вкладку Example и Копию “исключение EX 5.3 PENDSV”
Разработайте проект и запустите отладчик.

Код инициализирует ADC и включает его “Конец Прерывания Преобразования”. Это


также изменяет PENDSV и приоритет прерывания ADC от их опций по умолчанию
(Рис. 5.14). SVC имеет приоритетный нуль (самый высокий), в то время как ADC
имеет приоритет 1, и прерывание PENDSV имеет приоритет 2 (самый низкий).
systemCode стандартная программа использует инструкцию SVC повысить
исключение и переместиться в режим Handler (Рис. 5.15).
NVIC_SetPriority (PendSV_IRQn, 2); //приоритеты прерывания набора
NVIC_SetPriority (ADC1_2_IRQn, 1);
NVIC_EnableIRQ (ADC1_2_IRQn); //включите прерывание ADC
ADC1-.CR1 | 5 (1UL, 5); //включите ADC и запустите преобразование
ADC1-.CR2 | 5 (1UL, 0);
ADC1-.CR2 | 5 (1UL, 22);
systemCode (); //назовите некоторый системный код с прерыванием SVC

Установите точку останова на systemCode () функция и выполните код.

Рисунок 5.14
Выполните код до systemCode () функция.

Откройте окно контроллера прерываний Периферийных устройств/Вложенного


вектора периферийных устройств/ядра и проверьте приоритетные уровни SVC,
PENDSV и прерываний ADC.
Рисунок 5.15
Окно Peripherals/NVIC показывает, что прерывания включены, ни один не активен или
незакончен. Мы можем также видеть их приоритетные
уровни.
168 Глав 5

Теперь шаг в systemCode стандартную программу (F11), пока Вы не достигаете


функции C.
освободите __ svc (0) systemCode (пусто);
освободите __ SVC_0 (пусто) {
неподписанный интервал i, ожидая;
для (я 50; я, 100; i11);
ожидая 5 NVIC_GetPendingIRQ (ADC1_2_IRQn);
если (ожидание 551) {
SCB-.ICSR | 5 1, 28; //устанавливает ожидание, ожидают
} еще {
Do_System_Code ();
}
}

В systemCode () стандартная программа, существует короткий цикл, который


представляет критический раздел кода, который должен быть выполнен. В то время как
этот цикл работает, ADC закончит преобразование и, поскольку это имеет более низкий
приоритет, чем прерывание SCV, это введет незаконченное состояние. Когда мы
выходим из цикла, мы тестируем состояние любых критических прерываний путем
чтения их незаконченных битов. Если критическое прерывание находится на
рассмотрении, то остаток от стандартной программы системного кода может быть
отложен. Чтобы сделать это, мы устанавливаем PENDSVSET, укусил в Регистре
управления Прерывания и Государственном реестре и вышел из обработчика SVC.
Установите точку останова на фигурной скобке выхода (}) systemCode () стандартная
программа и выполните код
(Рис. 5.16).

Рисунок 5.16
Выполните Do_System_Code () стандартная программа.

Теперь используйте окно отладки NVIC для исследования состояния прерываний


(Рис. 5.17).

Рисунок 5.17
Теперь исключение SVC работает в ADC и ожидании исключений PENDSV.
Теперь SVC работает в ADC и вызове системной службы PENDSV в незаконченном
состоянии.
Одноэтапный из Вызова Системной службы, пока Вы не вводите следующее
прерывание.

Оба из незаконченных прерываний будут хвостом, объединенным в цепочку на


конец вызова системной службы. ADC имеет самый высокий приоритет, таким
образом, он будет подаваться следующий (Рис. 5.18).
Функции передовой архитектуры 169

Рисунок 5.18
Теперь прерывание ADC активно, когда это закончится, стандартная программа
PENDSV будет подаваться, и стандартная программа
системного кода возобновится.

Шаг из обработчика ADC и Вы сразу введете прерывание системной службы


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

Межпроцессорные события
Процессоры Cortex-M разработаны так, чтобы было возможно создать
многопроцессорные устройства. Пример состоял бы в том, чтобы иметь Кору-M4 и
Кору-M0 в том же микроконтроллере. Кора-M0 будет обычно управлять
пользовательскими периферийными устройствами, в то время как Кора-M4 выполняет
интенсивные части кода приложения. С другой стороны, существуют устройства,
которые имеют Cortex-A9, который может запустить Linux и управлять сложным
пользовательским интерфейсом; на той же микросхеме существует две Коры-M4,
которые управляют кодом в реальном времени. Они более сложная система на
структурах кристалла требуют методов сигнального действия между различными
процессорами. Процессоры Cortex-M могут быть объединены в цепочку вместе
сигналом внешнего события. Сигнал события установлен при помощи инструкции по
событию набора. Эта инструкция может быть добавлена к Вашему коду C с помощью
__ SEV () внутренний обеспеченный CMSIS-базовой спецификацией. Когда __ SEV ()
инструкция будет дана, это разбудит целевой процессор, если это перешло к режиму
низкой мощности с помощью __ WFE () инструкция. Если целевой процессор будет
работать, то фиксатор события будет установлен так, чтобы, когда целевой процессор
выполняется __ WFE () инструкция, это сбросило фиксатор события и продолжало
бежать, не переходя к режиму низкой мощности.

Эксклюзивный доступ
Одной из основных характеристик RTOS является поддержка многозадачности. Как
мы будем видеть в следующей главе, это позволяет Вам разрабатывать свой код как
независимые потоки, которые концептуально работают параллельно на процессоре
Cortex-M. Поскольку Ваш код разрабатывает, потоки программы должны будут часто
получать доступ к общим ресурсам быть им SRAM или периферийные устройства.
RTOS обеспечивает механизмы, названные семафорами и взаимными исключениями,
которые используются для управления доступом к периферийным устройствам и
объектам общей памяти (Рис. 5.19).
170 Глав 5

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

В то время как возможно разработать “стандартные программы” блокировки


памяти на любом процессоре, Коре-M3,-M4, и-M7 обеспечивают ряд инструкций,
которые могут использоваться для оптимизации стандартных программ
эксклюзивного доступа (Таблица 5.1).

Таблица 5.1: инструкции по Эксклюзивному


доступу
__ Загрузитесь
LDREXB эксклюзивный (8 битов)
Загрузитесь
__ эксклюзивный (16
LDREXH битов)
__ Загрузитесь
LDREXW эксклюзивный (32 бита)
__ Сохраните
STREXB эксклюзивный (8 битов)
Сохраните
__ эксклюзивный (16
STREXH битов)
__ Сохраните
STREXW эксклюзивный (32 бита)
Удалите монопольную
__ CLREX блокировку

В более ранних процессорах ARM как ARM7 и ARM9, проблеме эксклюзивного


доступа ответила инструкция по подкачке, которая могла использоваться для обмена
содержанием двух регистров. Эта инструкция взяла 4 цикла, но это была атомарная
инструкция, означающая, который когда-то запустился, это не могло быть прервано и
гарантировалось эксклюзивный доступ к ЦП для проведения его операции. Поскольку
процессоры Cortex-M имеют несколько шин, для доступа для чтения и доступа для
записи возможно быть выполненным на различных шинах и даже различными
устройствами управления шиной, которые могут самостоятельно быть
дополнительными процессорами Cortex-M. На процессоре Cortex-M новый метод
инструкций по эксклюзивному доступу был представлен для поддержки
многозадачных и многопроцессорных сред (Рис. 5.20).
Функции передовой архитектуры 171

Рисунок 5.20
Загрузка и хранит эксклюзивные инструкции, может использоваться для управления
доступом к обращению за помощью памяти. Они разработаны для работы
с единственными и многопроцессорными устройствами.

Система эксклюзивного доступа работает путем определения переменной блокировки


для защиты совместно используемого ресурса. Прежде чем к совместно
используемому ресурсу можно получить доступ, заблокированная переменная
проверяется с помощью эксклюзивной инструкции по чтению; если это - нуль, то к
совместно используемому ресурсу в настоящее время не получают доступ. Прежде
чем мы получим доступ к совместно используемому ресурсу, переменная блокировки
должна быть установлена с помощью эксклюзивной инструкции по хранилищу. После
того как переменная блокировки была установлена, мы теперь имеем контроль над
совместно используемым ресурсом и можем записать в нее. Если наш процесс
вытесняется прерыванием или другим потоком, который также выполняет чтение
эксклюзивного доступа, то аппаратные средства привязываются, монитор
эксклюзивного доступа установлен, препятствуя исходной эксклюзивной инструкции
по хранилищу писать в переменную блокировки. Это дает эксклюзивный контроль к
процессу вытеснения.
Когда мы закончены с совместно используемым ресурсом, переменная блокировки
должна быть записана для обнуления; это очищает переменную и также удаляет
блокировку. Если Ваш код запускает процесс эксклюзивного доступа, но должен
отказаться от него, существует четкая эксклюзивная инструкция (CLREX), которая
может использоваться для удаления блокировки. Инструкции по эксклюзивному
доступу управляют доступом между различными процессами, работающими на
единственном процессоре Cortex-M, но та же техника может быть расширена
172 Главы 5

к многопроцессорной среде при условии, что кремниевый разработчик включает


дополнительные аппаратные сигналы шины монитора между процессорами Cortex.

Упражнение 5.4 Эксклюзивный доступ


В этом осуществлении мы создадим блокировку эксклюзивного доступа, которая
совместно используется процессом фонового потока и стандартной программой
обработчика SVC, чтобы продемонстрировать блокировку и разблокировать процесс.
Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Выберите вкладку Example и Копию “эксклюзивный доступ EX 5.4”
Создайте код и запустите отладчик.
международное основное (пустота) {
если (__ LDREXB (&lock_bit) 5 5 0) {
если (! __ STREXB (1, и lock_bit 5 5 0))
{семафор 1 1; lock_bit 5 0;
}
}

Первый блок кода демонстрирует простое использование инструкций по


эксклюзивному доступу. Мы сначала тестируем переменную блокировки с
эксклюзивной инструкцией по загрузке. Если ресурс не заблокирован другим
процессом, мы устанавливаем бит блокировки с эксклюзивной инструкцией по
хранилищу. Если это успешно, мы можем затем получить доступ к ресурсу общей
памяти, названному семафором. После того как эта переменная была обновлена,
переменная блокировки записана для обнуления, и четкая эксклюзивная инструкция
выпускает аппаратную блокировку.
Шаг через код для наблюдения его поведения.
если (__ LDREXB (&lock_bit) 55 0)
{thread_lock ();
если (! __ STREXB (1, &lock_bit))
{semaphore11;
}
}

Второй блок кода делает точно то же самое кроме между эксклюзивной загрузкой и
эксклюзивным хранилищем, которым называют функциональную блокировку потока.
Это - стандартная программа SVC, которая перейдет к режиму обработчика и
переходу к стандартной программе SVC0.
освободите __ svc (0) thread_lock (пусто);
освободите __ SVC_0 (пусто) {
__ LDREXB (&lock_bit);
}

Стандартная программа SVC просто делает другое эксклюзивное чтение переменной


блокировки, которая установит аппаратные средства, привязывают монитор
эксклюзивного доступа. Когда мы возвращаемся к исходной стандартной программе
и
Функции передовой архитектуры 173

попытайтесь выполнить эксклюзивную инструкцию по хранилищу, она перестанет


работать, потому что любое исключение, которое происходит между LDREX и
STREX, заставит STREX перестать работать. Локальный монитор эксклюзивного
доступа очищен автоматически при записи/выходе исключения.
Шаг через второй блок кода и наблюдает процесс блокировки.

Единица защиты памяти


Кора-M01,-M3,-M4, и-M7 процессоры имеют дополнительный MPU, который может
быть включен в ядро процессора кремниевым производителем, когда микроконтроллер
разработан. MPU позволяет Вам расширять привилегированную/непривилегированную
модель кода. Если это приспособлено, MPU позволяет Вам определять регионы в рамках
карты распределения памяти процессора Cortex-M и предоставлять привилегированный
или непривилегированный доступ к этим регионам. Если процессор будет работать в
непривилегированном режиме и попытках получить доступ к адресу в
привилегированном регионе, то исключение защиты памяти будет повышено, и
процессор векторизует к защите памяти ISR. Это позволяет Вам обнаруживать и
исправлять ошибки памяти во время выполнения. При использовании с Корой-M7 MPU
используется для конфигурирования Кэшей Инструкции и Данных, существующих в
Коре-M7. В следующем разделе мы посмотрим о том, как использованию MPU с Корой-
M01,-M3, и-M4. Мы посмотрим на функции конфигурации кэша в Главе 6 “Процессор
Коры-M7” (Рис. 5.21).
Рисунок 5.21
Единица защиты памяти доступна на Коре-M01, M3, M4 и M7. Это позволяет Вам
помещать шаблон защиты над картой памяти процессора.
174 Главы 5

На практике MPU позволяет Вам определять восемь регионов памяти в адресном


пространстве процессора Cortex-M и предоставлять привилегированный или
непривилегированный доступ к каждому региону. Эти регионы могут затем быть
далее подразделены на восемь одинаково размерных подобластей, которые в свою
очередь могут быть предоставлены привилегированный или непривилегированный
доступ. Существует также фоновая область памяти по умолчанию, которая покрывает
всех 4 ГБ адресного пространства. Когда этому региону включают, он делает доступ
ко всем ячейкам памяти привилегированным. Для дальнейшего усложнения вещей
регионы памяти могут быть перекрыты с самым высоким пронумерованным
регионом, берущим прецедент. Также любая область памяти, которая не покрыта
регионом MPU, не может иметь никакого вида доступа к памяти (Рис. 5.22).

Рисунок 5.22
MPU позволяет Вам определять восемь регионов, каждого с восемью
подобластями по карте памяти процессора. Каждый регион может предоставить
различные права доступа своему диапазону адресов. Также возможно установить
привилегированный доступ значения по умолчанию по целой карте распределения
памяти и затем создать “дыры” с различными правами доступа.
Таким образом, возможно создать сложные шаблоны защиты по пространству адреса
памяти. Это позволяет Вам разрабатывать режим защиты, который помогает создать
устойчивую операционную среду, но также и дает Вам достаточно веревки для
зависания себя.
Функции передовой архитектуры 175

Конфигурирование MPU
MPU настроен через группу регистров с отображенной памятью, расположенных в
системном блоке процессора Cortex-M. К этим регистрам можно только получить
доступ, когда процессор Cortex работает в привилегированном режиме (Рис. 5.23).

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

Регистр управления содержит три активных бита, которые влияют на полную


операцию MPU. Это бит PRIVDEFENABLE, который включает привилегированный
доступ по целой карте распределения памяти на 4 ГБ. Следующий бит является битом
HFNMIENA; когда установлено, этот бит включает операцию MPU во время
Серьезного отказа, NMI или исключения FAULTMASK. Заключительный бит является
MPU, ВКЛЮЧАЮТ бит; когда установлено, это включает операцию MPU. Как
правило, при конфигурировании MPU, последняя выполненная операция должна
установить этот бит. После того, как сброшено, все эти биты очищены для обнуления
(Рис. 5.24).

Рисунок 5.24
Регистр управления позволяет Вам включать глобальный привилегированный регион
(PRIVDEFENA). Разрешать бит используется для создания настроенных регионов
MPU активными, и HFMIENA используется для включения регионов, когда Серьезный
отказ, NMI или исключения FAULTMASK активны.
Остающиеся регистры используются для конфигурирования восьми регионов MPU.
Для конфигурирования данного региона (0 7) сначала выбирают регион путем записи
его номера региона в регистр числа региона. После того как регион был выбран, он
может затем быть настроен базовым адресом и
176 Глав 5

регистр атрибута и размера. Индексный регистр 27-разрядное поле адреса,


допустимый бит и также повторение номера региона MPU (Рис. 5.25).

Рисунок 5.25
Регион адреса Индексного регистра позволяет Вам устанавливать начальный адрес
региона MPU. Значения адреса, которые могут быть записаны, будут зависеть от
установки размера в регистре Атрибута и Размера. Если допустимый установлен на 1,
то набор номера региона в поле региона используется; иначе номер региона в
регистре региона используется.

Как Вы могли бы ожидать, базовый адрес региона MPU должен быть


запрограммирован в поле адреса. Однако доступные базовые адреса, которые могут
использоваться, зависят от размера определенного для региона. Минимальный размер
для региона - от 32 байтов до 4 ГБ. Базовый адрес региона MPU должен быть кратным
размеру региона. Программирование поля адреса устанавливает выбранный базовый
адрес регионов. Вы не должны устанавливать допустимый бит. Если Вы пишете
новый номер региона в поле региона индексного регистра, устанавливаете
допустимый бит и пишете новый адрес; можно начать настраивать новый регион без
потребности обновить регистр числа региона. Программирование атрибута и размера
регистрирует конфигурацию концов региона MPU (Рис. 5.26).

Рисунок 5.26
Регистр Атрибута и Размера позволяет Вам определять размер региона MPU от 32
байтов до 4 ГБ. Это также настраивает атрибуты памяти и опции
управления доступом.

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

Емкость памяти региона MPU 5 2 военнопленных ð РАЗМЕР 1


Это дает нам минимальный размер, запускающийся на уровне всего 32 байтов. Как
отмечено выше, выбранный размер также определяет диапазон возможных базовых
адресов. Затем, возможно установить атрибуты региона и права доступа. Как
процессор Cortex-M, MPU разработан для поддержки многопроцессорных систем.
Следовательно, возможно определить регионы, как совместно используемые
Функции передовой архитектуры 177

между процессорами Cortex-M или как являющийся эксклюзивным к данному


процессору. Также возможно определить политику кэша для области памяти,
покрытой регионом MPU. В настоящее время, подавляющее большинство
микроконтроллеров только имеют единственный процессор Cortex-M, хотя
асимметричные многопроцессорные устройства начали появляться (Кора-M4 и Кора-
M0). Кора-M7 представляет Кэши Инструкции и Данных, которые настроены через
MPU. Мы посмотрим на это более подробно в Главе 6 "Cortex-M7".

Атрибуты MPU определяются TEX, C, B, и биты S и подходящие настройки для


большинства микроконтроллеров показывают в Таблице 5.2.

Таблица 5.2: атрибуты региона Памяти

Регион памяти TEX C B S Атрибуты


Нормальная память, несовместно
Flash 000 1 0 0 используемая, пишет через
Внутренний Нормальная память, совместно используемая,
SRAM 000 1 0 1 пишет через
Нормальная память, совместно используемая,
Внешний SRAM 000 1 1 1 записывает запись обратно, выделяют
Периферия 000 0 1 1 Память устройства, совместно используемая

При работе с MPU мы больше интересуемся определением прав доступа. Они


определяются для каждого региона в поле AP (Таблица 5.3).

Таблица 5.3: права Доступа к памяти


Привилегирован Непривилегиров
AP ный анный Описание
Все доступы генерируют отказ
000 Никакой доступ Никакой доступ разрешения
Форма доступа привилегированный код
001 RW Никакой доступ только
Непривилегированные записи вызывают
010 RW RO отказ разрешения
011 RW RW Полный доступ
Непредсказуем Непредсказуем
100 ый ый Зарезервировано
101 RO Никакой доступ Чтения привилегированным кодом только
Только для чтения для привилегированного
110 RO RO и непривилегированного кода
111 RO RO

Однажды размер, атрибуты и права доступа определяются, разрешать бит может быть
установлен сделать регион активным. Когда каждый из необходимых регионов был
определен, MPU может быть активирован путем установки глобального, включают
бит в Регистре управления. Когда MPU активен, и код приложения делает доступ,
который нарушает полномочия региона, исключение MPU будет повышено. После
того как Вы вводите исключение MPU, существует несколько регистров, которые
предоставляют информацию, чтобы помочь диагностировать проблему. Первый байт
Настраиваемого регистра Состояния отказа, расположенного в системном блоке
управления, называют регистром Состояния отказа Диспетчера памяти (Рис. 5.27).
178 Глав 5

Рисунок 5.27
Регистр состояния отказа MPU является подразделом настраиваемого регистра
состояния отказа в системном блоке управления. Это содержит флаги ошибки,
которые установлены, когда исключение MPU происходит. Цель каждого флага
показывают в Таблице 5.4.

Таблица 5.4: регистр Состояния отказа отмечает описания

Флаг Описание
Флаг состояния нарушения прав доступа
IACCVIOL инструкции
DACCVIOL Флаг состояния нарушения доступа к данным
MUNSTKERR Отказ диспетчера памяти на неукладке
MSTKERR Отказ диспетчера памяти на укладке
Диспетчер памяти FPU ленивая ошибочная Кора-M4
MLSPERR укладки только
(см. главу 5: “Усовершенствованные архитектурные
функции”)
MMARVALID Допустимый адрес отказа диспетчера памяти

В зависимости от состояния состояния отказа адрес инструкции, которая вызвала


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

Упражнение 5.5 Конфигурация MPU


В этом осуществлении мы настроим MPU для работы с проектом Blinky.
Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Выберите вкладку Example и Копию “конфигурация EX 5.5 MPU”.

На этот раз используемым микроконтроллером является NXP LPC1768, которому


оснастили процессор Cortex-M3 MPU. Во-первых, мы должны настроить проект так,
чтобы были отличные регионы кода и данных, которые будут использоваться
процессором в режимах обработчика и потоке. При выполнении этого полезно
изобразить схематически карту распределения памяти кода приложения и затем
определить шаблон MPU соответствия (Рис. 5.28).
Функции передовой архитектуры 179

Рисунок 5.28
Карта распределения памяти проекта Blinky может быть разделена на
шесть регионов.

Регион 0 непривилегированных кодов приложения


Регион 1 Привилегированный системный код
Регион 2 непривилегированных SRAM
Регион 3 привилегированных SRAM
Регион 4 Привилегированных и непривилегированных стековых пространства
Регион 5 Привилегированных и непривилегированных пользовательских
периферийных устройств

Теперь откройте меню Options for Target/Target. Здесь, мы можем создать регионы
памяти для соответствия предложенному шаблону защиты MPU (Рис. 5.29).
180 Глав 5

Рисунок 5.29

Целевая карта распределения памяти определяет два региона 0-0x3FFF памяти кода и
0x4000 0x7FFF. Более низкий регион будет использоваться в качестве региона по
умолчанию для содержания кода приложения и будет получен доступ процессором в
непривилегированном режиме. Верхний регион будет использоваться для содержания
прерывания и служебных программ исключения и будет получен доступ процессором
в привилегированном режиме. Точно так же существует два региона RAM 0x10000000,
и 0x100008000 будет содержать данные, используемые непривилегированным кодом и
системными стопками, в то время как верхний регион 0x0207C000 — будет
использоваться для содержания данных, используемых привилегированным кодом. В
этом примере мы не собираемся устанавливать привилегированный регион фона,
таким образом, мы должны отобразить регионы MPU для периферийных устройств.
Все периферийные устройства кроме GPIO находятся в одном непрерывном блоке от
0x40000000, в то время как регистры GPIO находятся в 0x000002C9. К периферийным
устройствам получит доступ процессор, в то время как это находится и в
привилегированных и в непривилегированных режимах
(Рис. 5.30).

Рисунок 5.30
Используйте опции присвоения локальной памяти настроить регионы
памяти, используемые кодом прерывания.
Для подготовки кода мы должны вызвать код обработчика прерываний в регионы,
которые будут предоставлены привилегированный доступ. В этом примере весь код,
который будет работать в режиме Handler, был помещен в один модуль. В локальных
опциях для этого модуля мы можем выбрать код
Функции передовой архитектуры 181

и регионы данных, которым даст привилегированные права доступа MPU. Весь


другой код и данные будет помещен в регионы памяти по умолчанию, которые будут
работать в непривилегированном режиме. После того как расположение памяти
проекта было определено, мы можем добавить код к проекту настроить шаблон
защиты MPU.
#define SIZE_FIELD 1
#define ATTRIBUTE_FIELD 16
#define ACCESS_FIELD 24
#define
ВКЛЮЧАЮТ 1
#define ATTRIBUTE_FLASH 0x4
#define ATTRIBUTE_SRAM 0x5
#define ATTRIBUTE_PERIPHERAL 0x3
#define PRIV_RW_UPRIV_RW 3
#define PRIV_RO_UPRIV_NONE 5
#define PRIV_RO_UPRIV_RO 6
#define PRIV_RW_UPRIV_RO 2
#define USE_PSP_IN_THREAD_MODE 2
#define THREAD_MODE_IS_UNPRIVILIGED 1
#define PSP_STACK_SIZE 0x200
#define TOP_OF_THREAD_RAM 0x10007FF0
MPU-.RNR 5 0x00000000;
MPU-.RBAR 5 0x00000000;
MPU-.RASR 5 (PRIV_RO_UPRIV_RO, ACCESS_FIELD)
| (ATTRIBUTE_FLASH, ATTRIBUTE_FIELD)
| (17, SIZE_FIELD) |ENABLE;

Код, показанный выше, используется для установки региона MPU для


непривилегированного кода потока в начале памяти. Во-первых, мы должны
определить номер региона, сопровождаемый базовым адресом региона. Так как это
будет Флэш-память, мы можем использовать стандартный атрибут для этого типа
памяти. Затем, мы можем определить его тип доступа. В этом случае мы можем
предоставить Доступ только для чтения и для привилегированных и для
непривилегированных режимов. Затем, мы можем установить размер региона,
который является 256K, который должен равняться 2POW (РАЗМЕР 1 1), которые
приравниваются к 17. Разрешать бит установлен активировать этот регион, когда MPU
полностью включен. Каждый из других регионов программируется подобным
способом. Наконец, исключение управления памятью и MPU включены.
NVIC_EnableIRQ (MemoryManagement_IRQn);
MPU-.CTRL 5 ВКЛЮЧАЕТ;

Запустите отладчик, установите точку останова на строке 82 и выполните код.

Когда точка останова достигнута, мы можем просмотреть конфигурацию MPU


через периферийные устройства / ядро peripherals/MPU (Рис. 5.31).
182 Главы 5

Рисунок 5.31
Окна Peripheral отладчика обеспечивают подробное представление
настроенного MPU.

Здесь, мы можем легко видеть определенные регионы и права доступа, которые


предоставили.
Теперь выполните код в течение нескольких секунд и затем остановите процессор.

Исключение MPU было повышено, и выполнение перешло к MemManager_Handler


(Рис. 5.32).

Рисунок 5.32
Когда исключение MPU произойдет, код векторизует к MemManager_Handler по
умолчанию в коде запуска.
Функции передовой архитектуры 183

Вопрос теперь, что вызвало исключение MPU? Мы можем узнать это путем
рассмотрения отказа диспетчера памяти и регистра состояния (Рис. 5.33).
Откройте окно Peripherals/Core Peripherals/Fault Reports.

Рисунок 5.33
Отладчик также обеспечивает сжатое представление всех регистров
отказа.

Здесь, мы видим, что отказ был заставлен нарушением доступа к данным


обратиться к 0x2007C008. Если мы теперь открываем файл карты, произведенный
компоновщиком, мы можем искать этот адрес и найти, какая переменная
помещается в это местоположение.

Выделите название проекта в окне проекта и двойном щелчке. Это откроет файл
карты. Теперь используйте Редактировать/Находить диалоговое окно для поиска
файла карты адрес 0x2007C008 (Рис. 5.34).

Рисунок 5.34
Можно просмотреть компоновщика файл MAP путем двойного щелчка по корневому
узлу проекта в окне Project. Затем переройте этот файл для нахождения
символа расположенным в 0x2007C008.

Это показывает, что переменная clock_1s в 0x2007C008 и что это объявляется в irq.c.

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


основного цикла, работающего в непривилегированном режиме. Однако эта
переменная расположена в привилегированном регионе RAM, настолько
получающем доступ к этому, в то время как процессор работает в
непривилегированном режиме, вызовет отказ MPU (Рис. 5.35).
184 Главы 5

Найдите объявление clock_1s в blinky.c и удалите ключевое слово экстерна.


Теперь найдите объявление для clock_1s в irq.c и добавьте экстерна
ключевого слова. Создайте код и просмотрите обновленный файл карты.

Рисунок 5.35
Теперь clock_1s переменная расположена в SRAM, к которому можно получить
доступ и привилегированным и
непривилегированным кодом.

Теперь clock_1s объявляется в blinky.c и расположен в непривилегированном регионе


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

Подобласти MPU
Как мы видели, MPU имеет максимум восьми регионов, которые могут быть
индивидуально настроены с размером местоположения и типом доступа. Любой
регион, который настроен с размером 256 байтов или больше будет содержать
восемь одинаково подобласти пространства. Когда регион настроен, каждая из
подобластей включена и имеет атрибуты региона по умолчанию и настройки
доступа. Возможно отключить подобласть путем установки бита подобласти
соответствия в поле SRD регистра атрибута и размера MPU. Когда подобласть
отключена, “дыра” создается в регионе, эта “дыра” наследовала атрибуты и право
доступа любого перекрытого региона. Если не будет никакого перекрытого региона,
то глобальная привилегированная фоновая область памяти будет использоваться.
Если фоновая область памяти не будет включена затем, то никакие права доступа не
предоставят, и исключение MPU будет повышено, если доступ будет сделан к
адресу в подобласти “дырой” (Рис. 5.36).
Рисунок 5.36
Каждый регион имеет восемь подобластей. Если подобласть отключена, она
наследовала права доступа от перекрытого региона или
глобальной фоновой области памяти.
Функции передовой архитектуры 185

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

Ограничения MPU
При разработке прикладного программного обеспечения для использования MPU
необходимо понять, что MPU только контролирует действие процессора Cortex-M.
Многие, если вообще, Кора, основанные на M микроконтроллеры имеют другие
периферийные устройства, такие как единицы DMA, которые способны к
автономному доступу к памяти и периферийным регистрам. Этими единицами
являются дополнительные “Устройства управления шиной”, которые выносят
решение с процессором Cortex-M для получения доступа к ресурсам
микроконтроллера. Если такая единица сделает доступ к запрещенному региону
памяти, то она не инициирует исключение MPU. Это важно для запоминания,
поскольку процессор Cortex-M имеет структуру шины, которая разработана для
поддержки нескольких независимых устройств “Устройства управления шиной”.

AHB облегченный шинный интерфейс


Семейство процессоров Cortex-M имеет заключительное важное архитектурное
улучшение по более раннему поколению ARM7-и основанных на ARM9
микроконтроллеров. В них первое поколение основанных на ARM
микроконтроллеров с ЦП соединили интерфейсом к микроконтроллеру через два типа
шин. Они были усовершенствованной высокоскоростной шиной (AHB) и
усовершенствованной периферийной шиной (APB) (Рис. 5.37).

Рисунок 5.37
Первое поколение основанных на ARM микроконтроллеров имело систему
внутренней шины на основе усовершенствованной высокоскоростной шины и
усовершенствованной периферийной шины. Поскольку несколько устройств
управления шиной (ЦП, DMA) были представлены, арбитражная фаза шины должна
была быть завершена, прежде чем передача могла быть сделана через шину.
186 Глав 5

Высокоскоростная шина подключила ЦП к Flash и памяти SRAM, в то время как


периферийные устройства микроконтроллера были подключены к одним или
нескольким шинам APB. Шина AHB также поддерживала дополнительные
устройства управления шиной, такие как единицы DMA для нахождения вместе с
процессором ARM7. В то время как эта система работала, структура шины начала
становиться узким местом особенно как более сложными периферийными
устройствами, такими как Ethernet, MAC и USB были добавлены. Эти периферийные
устройства содержали свои собственные единицы DMA, которые также должны были
действовать как устройство управления шиной. Это означало, что могло быть
несколько устройств (ARM7 ЦП, DMA общего назначения и Ethernet MAC DMA)
выносящий решение для шины AHB в любом данном моменте времени. Поскольку
все более сложные периферийные устройства добавляются, полная пропускная
способность и детерминированная производительность стали трудными предсказать.

Семейство процессоров Cortex-M преодолевает эту проблему при помощи матрицы


шины AHB (Рис. 5.38). Матрица шины AHB состоит из многих параллельных шин
AHB, которые подключены к различным ресурсам устройства, таким как блок RAM
или группа периферийных устройств
на шине APB. Соединение шин AHB и расположение ресурсов устройства,
присвоенных производителем, когда микросхема разработана. Каждый регион
ресурсов устройства является ведомым устройством. Каждый из этих регионов затем
подключен назад к каждому из устройств управления шиной через дополнительные
шины AHB для формирования матрицы шины. Это позволяет производителям
разрабатывать сложные устройства с несколькими процессорами Cortex-M,
единицами DMA, и усовершенствованными периферийными устройствами, каждым с
параллельными путями к различным ресурсам устройства. Матрица шины
предрасположена в
Рисунок 5.38
Семейство процессоров Cortex-M заменяет единственную шину AHB матрицей
шины, которая обеспечивает параллельные пути для каждого
устройства управления шиной к каждому блоку ведомых устройств.
Функции передовой архитектуры 187

микроконтроллеру и не нужна никакая конфигурация Вашим кодом приложения.


Однако при разработке кода приложения необходимо обратить внимание туда, где
различные объекты памяти расположены. Например, память, используемая
контроллером Ethernet, должна быть помещена в один блок SRAM, в то время как
память USB расположена в отдельном блоке SRAM. Это позволяет Ethernet и USB
единицу DMA для работы параллельно, в то время как процессор Cortex-M получает
доступ к Flash и пользовательским периферийным устройствам. Таким образом
путем структурирования карты распределения памяти кода приложения можно
использовать эту степень параллелизма и получить дополнительное повышение
производительности.

Заключение
Если Вы намереваетесь написать код без операционной системы затем, объем
информации в этой главе может быть проигнорирован. Однако эти функции
критически важны, если Вы хотите использовать больше платформы перспективной
разработки, такой как RTOS, поскольку мы будем видеть в Главе 9 “CMSIS-RTOS”,
В то время как процессоры Cortex-M просты в использовании, они действительно
включают функции для поддержки безопасности, критических, и приложений
защиты, а также многоядерных систем.
Эта страница, намеренно
оставленная незаполненный
CHPTER6

Процессор коры-M7
В первых нескольких главах этой книги мы посмотрели на Кору-M0,-M01,-M3,
и процессоры-M4. Затем мы собираемся исследовать последний процессор Cortex-M,-
M7. Кора-M7 в настоящее время является самым высоким процессором Cortex-M
выполнения. Это сохраняет модель того же программиста как другие члены семейства
так все, что мы изучили, до сих пор может быть применен к Коре-M7. Однако его
внутренняя архитектура имеет некоторые радикальные различия к более ранним
процессорам Cortex-M, которые существенно улучшают его производительность.
Кора-M7 также имеет более сложную систему памяти, которую мы должны понять и
управлять (Рис. 6.1).

Рисунок 6.1
Кора-M7 имеет более сложную структуру шины и структуру памяти, но она сохраняет
Cortex-M
модель
программиста.
Руководство разработчика по семейству процессоров
Cortex-M.
DOI: http://dx.doi.org/10.1016/B978-0-08-100629-0.00006-2 189
© 2016 Elsevier Ltd. Все права защищены.
190 Глав 6

Разработчику модель программиста процессора Cortex-M7 выглядит одинаково как


другие процессоры Cortex-M. Однако его производительность улучшена многими
архитектурными функциями, которые очень отличны от остальной части семейства.
Они включают шестиэтапный двойной конвейер проблемы, расширенную единицу
предсказания ветвлений и единицу математики плавающей точки двойной точности. В
то время как эти функции повышают производительность Коры-M7, они в основном
очевидны для разработчика. Для разработчика Кора-M7 действительно начинает
отличаться от других процессоров Cortex-M с точки зрения своей модели памяти. Для
достижения длительной высокой производительности, обрабатывающей Кору-M7,
представляет иерархию памяти, которая состоит из “сильно связанных памятей” и
пары внутренней кэш-памяти в дополнение к основному Flash микроконтроллера и
SRAM. Кора-M7 также представляет новый тип шинного интерфейса, шины AXI-M.
Шина AXI-M позволяет 64-разрядную передачу данных и также поддерживает
несколько транзакций.

Суперскалярная архитектура
Кора-M7 имеет суперскалярную архитектуру и расширенный конвейер. Это означает,
что может к “двойной проблеме” инструкции, и при определенных условиях эти две
инструкции могут быть обработаны параллельно (Рис. 6.2).

Рисунок 6.2
Кора-M7 имеет шестиэтапный двойной конвейер проблемы. ЦП имеет несколько
обработок “каналы”, которые позволяют различным группам
инструкций быть обработанными параллельно.

Конвейер Коры-M7 был увеличен до шести этапов. Шестиэтапные конвейерные


действия как два трехэтапных конвейера каждый с выборкой декодирует и выполняет
этап. Два конвейера подключены к хранилищу памяти через 64-разрядную шину,
которая позволяет двум инструкциям быть выбранными и введенными в конвейеры
параллельно. Оба конвейера в свою очередь подключены к нескольким “каналам” в
блоке обработки. Каждый из каналов процессора способен к выполнению a
Процессор 191 коры-M7

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


для инструкций по Загрузке и Хранилищу, инструкций MAC, ALU и инструкций с
плавающей точкой. Это позволяет быть параллельным инструкциям по процессу,
если мы можем дать эти две инструкции в конвейере к различным каналам
обработки. В то время как это увеличивает сложность процессора, для разработчика
это происходит “под капотом” и является проблемой для компилятора для
упорядочивания инструкций по программе как доступов памяти с чередованием
адресов и инструкций по обработке данных.

Предсказание ветвлений
Производительность Коры-M7 далее улучшена путем добавления кэша ответвления к
единице предсказания ветвлений (Рис. 6.3). Это - специализированный блок кэш-
памяти с 64 записями каждый 64 бита шириной. Во время выполнения во время
выполнения Целевой кэш адреса ответвления (BTAC) обеспечит корректный адрес
ответвления. Если правильно предсказано BTAC позволяет ответвлениям цикла быть
обработанными в единственном цикле. Команды перехода могут также быть
обработаны параллельно с другой двойной данной инструкцией, далее
минимизирующей ответвление наверху. Это - критическая функция, поскольку она
позволяет микроконтроллеру общего назначения близко подходить к соответствию
производительности цикла выделенного устройства DSP.

Рисунок 6.3
BTAC гарантирует, что команды перехода являются единственным циклом.
Это значительно уменьшает любые издержки в
программных циклах.
Упражнение 6.1 Простой цикл
В этом осуществлении мы собираемся использовать некоторые реальные
аппаратные средства в форме платы Исследования STM32F7 и платы
Исследования STM32F4 вместо средства моделирования программного
обеспечения.
192 Главы 6

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


Исследования STM32F7.

В этом осуществлении мы измерим время выполнения простого цикла и на Corex-M4


и на Коре-M7.
Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Выберите вкладку в качестве примера и Копию “Исключая 6.1 Простыми циклами
Коры-M7”.

Это - многопроектная рабочая область. Тот же код создается в проекте Коры-M4


и проекте Коры-M7 (Рис. 6.4).

Рисунок 6.4
Эти два проекта открыты в многопроектной рабочей области.

Пакет разрабатывает проект (Рис. 6.5).

Рисунок 6.5
Разработайте оба проекта с командой Batch Build.

Выберите проект M7 (Рис. 6.6).

Рисунок 6.6
Выберите M7 как активный проект.
Процессор 193 коры-M7

Запустите отладчик и установите точку останова.


Выполните отладчик, пока он не поразит команду контрольного останова.
Возьмите количество цикла в окне регистра (Рис. 6.7).

Рисунок 6.7
Читайте цикл значат M7.

Повторитесь для-M4 и сравните (Рис. 6.8).

Рисунок 6.8
Читайте цикл значат-M4.

С этим простым примером мы видим, что код, скомпилированный для Коры-M7,


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

Структура шины
Кора-M7 также имеет более сложную структуру шины, чем более ранние процессоры
Cortex-M, все еще поддерживая линейную карту распределения памяти. Кора-M7
имеет шинный интерфейс AXI-M,
194 Главы 6

шина периферийного интерфейса AHB, ведомая шина AHB и также выделенные


локальные шины для Инструкции-TCM и Данных-TCM (Рис. 6.9).

Рисунок 6.9
Кора-M7 представляет много новых шинных интерфейсов.

Интерфейс главной шины между Корой-M7 и микроконтроллером является шиной


AXI-M ARM. Это - 64-разрядная широкая шина, способная к поддержке нескольких
транзакций. Шина AXI обеспечивает много ведомых портов, которые соединяются
мостом на облегченной шине AHB. Облегченная шина AHB совпадает с, найден на
других членах семейства Cortex-M; это помогает кремниевому повторному
использованию поставщиков существующие проекты микроконтроллера с
процессором Cortex-M7. Кора-M7 также имеет порт (AHBP) периферийной шины
AHB, который используется для доступа к периферийным устройствам
микроконтроллера через матрицу шины AHB.
Шина AHBP оптимизирована для периферийного доступа, таким образом,
периферийный доступ регистра будет иметь более низкую задержку по сравнению
с другими процессорами Cortex-M. Кора-M7 также имеет второй порт AHB; это -
ведомый порт (AHBS) AHB. Этот порт позволяет другие устройства управления
шиной, обычно единицы DMA, доступ к Инструкции-TCM и Данным-TCM.
Типичную реализацию этих шин в микроконтроллере показывают на (Рис. 6.10).
Процессор 195 коры-M7

Рисунок 6.10
Типичная конфигурация шинного интерфейса для микроконтроллера
Коры-M7.

В этом примере шина AXI-M подключена к матрице шины AHB через мост. Однако
AHB соединяют шиной, только подключает входы шины AXI-M к системной памяти
микроконтроллера. Периферийные шины шины AHB подключены назад к Коре-M7
через порты AHBP. Каждая из единиц DMA может действовать как устройства
управления шиной и иметь доступ ко всей системной памяти и периферийным
устройствам и может использовать Ведомую шину ADB для доступа к Инструкции и
Данным TCM. Хотя шина AHBS показывается как направляемый через Кору-M7, эта
шина будет бодрствовать, если процессор Cortex-M7 будет помещен в режим низкой
мощности. Это позволяет другим устройствам управления шиной получить доступ к
TCM, даже когда Кора-M7 полностью затекает.

Иерархия памяти
Более сложная структура шины Коры-M7 поддерживает карту распределения памяти,
которая содержит иерархию регионов памяти, которую должен понять и управлять
разработчик (Рис. 6.11).
196 Глав 6

Рисунок 6.11
Кора-M7 имеет иерархию памяти различных уровней производительности.

Во-первых Кора-M7 имеет два блока TCM — один для данных и один для
инструкций. Инструкция-TCM и Данные-TCM подключены к процессору через 64-
разрядную шину и являются памятью состояния с нулевым временем ожидания.
Инструкция-TCM и Данные-TCM могут быть до 16 K (Рис. 6.12).

Рисунок 6.12
TCMs являются памятями состояния с нулевым временем ожидания, с
которыми соединяют интерфейсом
непосредственно к ЦП через
специализированные 64-разрядные шины.

Код, расположенный в Инструкции-TCM, будет работать в состояниях с нулевым


временем ожидания и будет очень детерминирован. Таким образом, этот регион
памяти должен являться родиной любых критических стандартных программ и
процедур обработки прерывания. Данные-TCM являются самой быстрой RAM
данных, доступной процессору, и должны быть дома любых часто используемых
данных и являются также хорошим местоположением для памяти "кучи" и стека.
Процессор 197 коры-M7

Упражнение 6.2 Определение местоположения кода и данных


в TCM
Это осуществление демонстрирует, как загрузить код в Инструкцию-TCM и
данные в Данные-TCM и сравнить его выполнение для кодирования
расположенный в системной Флэш-памяти.
Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Выберите вкладку в качестве примера и Копию “Исключая 6,2 6.4 Коры-M7 TCM и I-
кэш” (Рис. 6.13).

Рисунок 6.13
Проект имеет два модуля цикла, которым определили местоположение их кода
в ITCM и Флэш-памяти AXI.

Откройте опции для целевого меню.

В этом проекте у нас есть два набора функций цикла, которые накапливают
значения, сохраненные в тысяче массивов элемента. По умолчанию проект
поместит код во флэш-память, которая расположена на шине AXI-M в 0x8000000
(Рис. 6.14).
Рисунок 6.14
Расположение памяти с дополнительным регионом (RAM1), созданный для
покрытия ITCM.
198 Глав 6

Однако мы также определили RAM (RAM1) регион в 0x0000000 для 32 K, который


является местоположением Инструкции-TCM относительно этого устройства.
Флажок галочки по умолчанию снимается так, компоновщик не поместит объектов в
этот регион, если мы конкретно не скажем его.
Откройте “Options for file loop_TCM.c” (Fig. 6.15).

Рисунок 6.15
Модуль локальные опции используется для отображения данных кода/константы в
регион RAM1. Код, расположенный в регион RAM I-TCM, будет автоматически
загружен из Flash в I-TCM кодом запуска.

В опциях присвоения памяти мы можем выбрать регион RAM1 для сегментов


Code/Const в этом файле. Это означает, что код в loop_TCM.c файле будет сохранен
во флэш-памяти, но будет скопирован в регион RAM1 (Инструкция TCM SRAM) при
запуске. В качестве награды отладочные символы будут также соответствовать
адресу загрузки, это позволяет нам отлаживать код, загруженный в Инструкцию-
TCM, не имея необходимость делать специальную сборку.
Открытый main.c.
Массивы, которые содержат данные, которые будут накоплены, определяются в
начале основного ().
uint32_t array_DTCM[NUM_SAMPLES] __ приписывает __ ((в (0x20000000)));//Располагаются в самой быстрой
памяти данных DTCM

uint32_t array_SDRAM[NUM_SAMPLES] __ приписывает __ ((в (0xC0000000)));//Определяют местоположение в


SDRAM самой
медленной памяти
данных

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


местоположение массива в абсолютном адресе. В этом случае мы вызываем первый
массив в регион D-TCM и второе в SRAM, расположенный на шине AXI. В основном ()
приложение мы настраиваем таймер SysTick для действия как таймер секундомера.
Основной () затем вызывает идентичные функции цикла, которые выполняются или из
Инструкции-TCM или из Flash AXI. Функции цикла также получают доступ к экземпляру
массива, который расположен или в Данных-TCM или в AXI-M SRAM.
Процессор 199 коры-M7

Создайте код и запустите отладчик.


Откройте окна/отладку представления / последовательные окна/отладку printf окно.
Выполните код и наблюдайте различное время выполнения, отображенное в
последовательном окне.
Синхронизация Цикла меры в Flash AXI и ITCM использование DTCM для данных
Синхронизация цикла Flash AXI с помощью DTCM RAM 5 79156
Синхронизация цикла ITCM с помощью DTCM RAM 5 24432
Синхронизация цикла Flash AXI с помощью SDRAM 5 89827
Синхронизация цикла ITCM с помощью SDRAM 5 37306

Блоки кэш-памяти
За пределами TCMs весь код программы и данные будут сохранены в системной памяти.
Это будет микроконтроллером внутренний Flash и SRAM. Микроконтроллер может
также иметь интерфейс внешней шины для доступа к дополнительной RAM и памяти
ROM. Как мы видели с Корой-M3 и-M4, необходимо обеспечить некоторую форму
“Акселератора Флэш-памяти” для освобождения инструкций от флэш-памяти до ЦП для
поддержания обработки в полной тактовой частоте ЦП. Кора-M7 является оба более
высоким процессором производительности и разработана для выполнения в более
высоких тактовых частотах, и эта форма ускорения памяти больше не является
полностью эффективной. Для соблюдения и его кода и требований пропускной
способности Кора-M7
может быть реализован и с Кэшами Данных и с Инструкции (Рис. 6.16).
Рисунок 6.16
I-кэш и D-кэш привыкли к кэш-памяти, расположенной на шине AXI-M.
200 Глав 6

Оба из кэшей используются для содержания копий инструкций, и данные,


выбранные из памяти, получили доступ по шине AXI-M. Однажды инструкция или
значение данных был загружен в кэш, к этому можно получить доступ больше
быстрее, чем системный Flash и SRAM.

Операция кэша
Как TCMs, Кэши Инструкции и Данных являются блоками памяти, внутренней к
процессору Cortex-M7, которые способны к тому, чтобы быть полученным
доступ с состояниями с нулевым временем ожидания. Кэш Инструкции может
составить до 64 Кбит в размере, и Кэш Данных может составить до 16 Кбит
(Рис. 6.17).

Рисунок 6.17
Кэш состоит из строки данных, которая отображается на физической памяти через Тег. Биты
C определяют политику кэша, в то время как V и биты D используются для отслеживания
состояние данных.

Кэш-память Инструкции и Данных расположена в серию строк кэша, которые 32


байта длиной. Каждая строка кэша имеет кэш-тег. Кэш-тег содержит информацию,
которая отображает строку кэша на системную память. Тег также имеет группу битов,
которые детализируют текущий статус строки кэша. И Кэш Инструкции и Данных
имеет V или допустимый бит, который указывает, что строка кэша содержит в
настоящее время допустимую информацию. Кэш данных имеет дополнительный D и
биты C. Кэш данных D бит указывает, что данные, в настоящее время сохраненные в
кэше, грязны. Это означает, что значение, сохраненное в кэше, было обновлено, но
местоположение соответствия в системной памяти не имеет. Два бита C содержат
атрибуты кэша для этой строки кэша, и мы обсудим их через мгновение (Рис. 6.18).
Процессор 201 коры-M7

Рисунок 6.18
Строка кэша зеркально отражается к ячейкам памяти через пространство
физической памяти.

Кэш отображается как страница памяти, которая отражается через адресное


пространство процессора Cortex-M7. Это означает, что каждая строка кэша имеет
много ячеек памяти соответствия, равномерно расположенных с интервалами через
системную память.

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


памяти, загружается в ЦП и также в местоположение кэша соответствия. Кэш-тег
будет установлен декодировать адрес данных в системной памяти, и допустимый бит
будет установлен. После того, как загруженный в кэш дальнейшие доступы к этому
местоположению считают значение из кэша, а не системной памяти. В зависимости от
политики кэша, которая установлена кодом приложения, записи к ячейке памяти
вызовут запись к строке кэша соответствия.
Снова кэш-тег будет обновлен с адресом декодирования местоположения системной
памяти. Допустимый бит будет установлен указать, что кэш содержит корректное
текущее значение данных. Точка, в которой обновляется системная память, будет
зависеть от политики кэша, которая установлена битами C в кэш-теге. Мы посмотрим
на настройки политики кэша позже. Если кэш-память будет содержать значение,
которое еще не было записано в системную память, которую укусил D, то будет
установлен. Поскольку код приложения выполняется, данные и инструкции будут
перемещены в кэши. Если данные были загружены в строку кэша, и доступ сделан к
другому местоположению в системной памяти, которая отображается на той же строке
кэша затем, старые данные будут “выселены”. Новые данные будут скопированы в
строку кэша, и кэш-тег будет обновлен (Рис. 6.19).
202 Главы 6

Рисунок 6.19
Во время выполнения данные будут загружены в кэш. Это может также быть
выселено, если к зеркальному местоположению
кэша получают доступ.

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


будут часто получать доступ, то они будут постоянно выселять друг друга. Это
известно как перегрузка кэша, и большая перегрузка уменьшит эффективность кэша
(Рис. 6.20).

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

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


названных “путями”, а не одним непрерывным блоком памяти. Кэш Инструкции
расположен как два пути, и кэш данных расположен как четыре пути. Теперь кэш-
память отображается через систему при гранулярности каждого кэша путь. Это
создает много параллельных местоположений в кэше, в который может быть
отображена данная ячейка памяти. Это уменьшает вероятность перегрузки кэша и
приводит к более эффективному использованию кэш-памяти.
Процессор 203 коры-M7

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

Таблица 6.1: CMSIS-базовые функции I-управления-кэшем


Функции CMSIS-I-Cache
освободите SCB_EnableICache
(пусто) освобождают
SCB_DisableICache (пусто)
освобождают
SCB_InvalidateICache (пусто)

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

Упражнение 6.3 Кэш инструкции


Это осуществление измеряет увеличение производительности, достигнутое при
помощи кэша Инструкции.
Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Вновь откройте последнее осуществление “Исключая 6,2 6.4 Коры-M7 TCM и I-кэш”.
Открытый main.c.
Удалите комментарии в строках 75 и 91.

Это добавляет новый блок кода к последнему примеру. Здесь мы включаем Кэш
Инструкции и повторно выполняем функции цикла AXI для наблюдения изменения
в синхронизации.
Откройте окна/окно отладки представления / последовательные окна/окно отладки.
Выполните код и наблюдайте различие во время выполнения по сравнению с
исходным примером.
Синхронизация Цикла меры в Flash AXI с I-кэшем Включила
синхронизацию цикла AXI с I-кэшем и DTCM RAM 5 62395
Синхронизация цикла AXI с I-кэшем и SDRAM 5 76300
204 Главы 6

Кэш Инструкции является большим улучшением по выполнению от Flash, но не


столь хороший как Инструкция-TCM.

Кэш данных
Кэш Данных также расположен на шине AXI-M для кэширования любых системных
доступов RAM. В то время как это ускоряет доступ к данным программы, это может
представить неожиданные побочные эффекты из-за проблем когерентности данных
между системной памятью и Кэшем Данных. Кэш Данных является в
действительности затенением системная память так, чтобы переменная программы
могла жить в двух местах в кэше и в памяти SRAM. Это было бы прекрасно, если бы
ЦП был единственным устройством управления шиной в системе. В типичном
микроконтроллере Коры-M7 может быть несколько других устройств управления
шиной в форме периферийных единиц DMA или даже другие процессоры Cortex-M. В
такой много основной системе кэш может теперь представить проблему
когерентности данных (Рис. 6.21).

Рисунок 6.21
D-кэш может представить проблемы когерентности данных. Системная память может
быть обновлена другими устройствами управления шиной. D-кэш может
“скрыть” эти изменения от ЦП.

Так как наши данные могут теперь быть сохранены, несколько местоположений в
иерархии памяти (регистр ЦП, Кэш Данных, микроконтроллер SRAM), чем более
медленная системная память может содержать историческую ценность, которая
отличается от текущих данных, расположенных в Кэше Данных, единица DMA будет
только иметь доступ к системной памяти, так будет использовать, тем более старая
историческая ценность, а не текущее значение, сохраненное в кэше, Кроме того,
обновление DMA микроконтроллера SRAM, может быть замаскирована от ЦП
устаревшим значением, сохраненным в кэше данных. Это означает, что Кэш Данных,
действительно требует большего количества управления, чем Кэш Инструкции. В
CMSIS-базовой спецификации существует восемь функций Управления кэшем
Данных
(Таблица 6.2).
Процессор 205 коры-M7

Таблица 6.2: CMSIS-базовые функции кэша данных

CMSIS-базовые функции кэша данных


SCB_EnableDCache (пусто)
SCB_DisableDCache (пусто)
SCB_InvalidateDCache (пусто)
SCB_CleanDCache (пусто)
SCB_CleanInvalidateDCache (пусто)
SCB_InvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize)
SCB_CleanDCache_by_Addr (uint32_t *addr, int32_t dsize)
SCB_CleanInvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize)

Как Кэш Инструкции существуют функции, чтобы включить, отключить, и делать


недействительным кэш данных. Кроме того, мы можем убрать кэш. Это вызывает все
данные, которые, как сохранили в кэше, были записаны в системную память,
делающую целое когерентное хранилище памяти. Также возможно убрать и делать
недействительным регионы системной памяти, которая может быть сохранена в
кэше.
Кэш данных Делает недействительным Сброс, что находится в кэш-памяти и
вызывает перезагрузку
от системной памяти
Чистый Кэш данных Запишите данные, сохраненные в кэш-памяти к
системе
память
Чистый Кэш данных и Память кэша записи к системной памяти и сбросу
Делайте недействительным кэш-память

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

Барьеры памяти
В Главе 5 “Функции Передовой архитектуры” мы видели, что ползунок Cortex-M 2
системы команд содержит группу инструкций по барьеру памяти. Инструкции по
барьеру памяти используются для поддержания данных и когерентности инструкции в
микроконтроллере Cortex-M. Эти инструкции редко используются в большинстве
проектов Cortex-M и когда они - это, главным образом для безопасного
программирования. Однако при работе с Кэшами Инструкции и Данных Коры-M7 они
используются, чтобы гарантировать, что операции кэша закончились прежде, чем
позволить ЦП продолжать обрабатывать. CMSIS-базовые функции кэша включают
необходимые инструкции по барьеру памяти гарантировать, что все операции кэша
завершились, когда функция возвращается.
__ STATIC_INLINE освобождают SCB_EnableICache (пусто)
{
#if (__ ICACHE_PRESENT 55 1U)
__ DSB ();
206 Глав 6

__ ISB ();
SCB-.ICIALLU 5 0UL;/* делают недействительным I-кэш */SCB-.CCR | 5
(uint32_t) SCB_CCR_IC_Msk;/* включают I-кэш */__ DSB ();

__ ISB ();
#endif
}

Упражнение 6.4 Кэш данных в качестве примера


Это осуществление измеряет увеличение производительности, достигнутое путем
включения Кэша Данных.
Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Вновь откройте последнее осуществление “Исключая 6,2 6.4 Коры-M7 TCM и I-
КЭШ”.
Открытый main.c.
Удалите комментарии в строках 92 и 106.

Это добавляет новый блок кода к последнему примеру. Здесь мы включаем Кэш
Инструкции и повторно выполняем функции цикла AXI для наблюдения изменения
в синхронизации.
Откройте окна/окно отладки представления / последовательные окна/окно отладки.

Выполните код и наблюдайте различие во время выполнения по сравнению с


исходным примером.
Синхронизация цикла меры в Flash AXI с I-кэшем и D-кэшем включена
Синхронизация цикла Flash AXI с I-кэшем и D-кэшем 5 33305

Так включение Кэша Данных дает другое повышение производительности, когда


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

Единица защиты памяти и конфигурация кэша


Единица защиты памяти (MPU) распространена через всех членов семейства
процессоров Cortex-M за исключением Коры-M0. Поскольку мы видели в Главе 5
“Функции Передовой архитектуры” MPU, может использоваться для управления
доступом к различным регионам карты распределения памяти в Cortex-M01\-M3
и-M4. На Коре-M7 MPU предлагает ту же функциональность, но кроме того это
используется для конфигурирования регионов кэша и политики кэша.
Процессор 207 коры-M7

Политика кэша
Политика кэша для различных регионов памяти в микроконтроллере может быть
определена через регионы MPU с битами конфигурации кэша в MPU “Атрибут и
Размер” регистр (Рис. 6.22; Таблица 6.3).

Рисунок 6.22
MPU “Атрибут и Размер” регистр.

Таблица 6.3: опции D-конфигурации-кэша MPU

Поле конфигурации кэша Описание


Введите
TEX расширение
C Кэшируемый
B Bufferable
С обеспечением
совместного
S доступа

Опция с обеспечением совместного доступа в MPU “Атрибут и Размер” регистр


определяет, если регион памяти может быть совместно использован двумя
устройствами управления шиной. Если регион будет объявлен как совместно
используемый, то его данные будут сохранены когерентными между кэшем и
физической памятью. Это означает, что любое устройство управления шиной,
получающее доступ к данным, будет всегда получать корректное текущее значение.
Однако, чтобы сделать это, ЦП должен будет записать через Кэш Данных, когда он
обновляет значение RAM, если RAM обновляется другим устройством управления
шиной, он должен быть загружен в кэш. Так создание совместно используемого
SRAM удаляет проблемы когерентности, но уменьшает полную производительность
Кэша Данных.

Политика кэша также определяет, как данные записаны между кэш-памятью и


системной памятью. Сначала мы можем определить, когда данные выделяются в
кэш. Существует две опции для выделить политики, мы можем вынудить данные
быть загруженными в кэш, когда местоположение RAM читается, или мы можем
выбрать для загрузки местоположения RAM в кэш, когда это считано или записано в.
Эта политика установлена путем конфигурирования битов Расширения Типа (TEX)
(Таблица 6.4).

Таблица 6.4: Кэш выделяет настройки политики

TEX Кэш выделяет политику


000 Читайте выделяют, загружают ячейку памяти в кэш, когда это читается из
Читайте и запись выделяют, загружают ячейку памяти в кэш, когда это считано из
001 или записано в
208 Глав 6

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

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

“Запись через” политику вынудит записи ЦП обновить кэш-память и системную


память одновременно. Это понижает производительность кэша, но поддерживает
когерентность для записей кэша (Рис. 6.23).

Рисунок 6.23
Запишите через политику кэша.

Запись назад политика вызовет записи к кэш-памяти только, и данные будут только
записаны в системную память, когда данные кэша будут выселены или кэш, чистая
инструкция дается. Это максимизирует производительность кэша для записей данных
за счет когерентности кэш-памяти (Рис. 6.24).

Рисунок 6.24
Политика кэша с обратной записью.

Политика обновления кэша настроена через C и биты B в регистре MPU


(Таблица 6.5).

Таблица 6.5: политика обновления Кэша

C B Политика обновления кэша


Запишите обратно — кэшируемый и
1 1 bufferable
Запишите Через — кэшируемый, но
1 0 никакая буферизация
Процессор 209 коры-M7

Управление кэшем данных


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

Выключите кэш

Самая простая вещь сделать, выключают Кэш Данных. В то время как это удалит
любую проблему когерентности, она уменьшит производительность Коры-M7.
Однако это может быть полезная опция в начале проекта для упрощения системы.

Отключите кэширование по региону системной памяти

Это подобно первой опции кроме, мы можем программировать регион MPU для
предотвращения данных, кэширующихся на регионе системной памяти. Мы можем
затем определить местоположение данных, которые характерны для Коры-M7 и
других устройств управления шиной в этот регион. Так как весь доступ будет к
системной памяти не будет никаких проблем когерентности, но доступы к этому
региону памяти с Corex-M7 будут в их самом низком.

Измените политику кэша для региона системной памяти

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

Используйте функции управления кэшем для гарантии когерентности

Функции управления кэшем могут использоваться, чтобы убрать или делать


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

Упражнение 6.5 Конфигурация кэша данных


Это осуществление демонстрирует поведение различных конфигураций кэша. Если
Вы планируете использовать Кору-M7, необходимо экспериментировать с этим
примером для получения полного понимания Кэша Данных.
Initilise_Device ();
MPU_Config ();
//SCB_EnableDCache ();//кэш отключен в начале проекта
210 Глав 6

Initilise_Arrays ();//загружают данные в array_sdram1 и нуль array_sdram2


//Cache_Clean ();
Update_Source_Array ();//Запись новые значения к array_sdram1
//Cache_Clean ();
DMA_Transfer (); //копируют sdram1 в array_sdram2 с помощью устройства управления шиной DMA
//Cache_Invalidate ();
Test_Coherence (); //Тест когерентность между array_sdram1 и array_sdram2
Test_Coherence (); //Тест когерентность между array_sdram1 и array_sdram2

В этом осуществлении MPU настраивает Кэш Данных для покрытия первых 128 Кбит
внешнего SDRAM, который заполняется с двумя массивами данных. Код приложения
заполняет массив некоторыми заказанными данными и пишет нуль в секунду. Затем
единица DMA (устройство управления шиной) используется для копирования данных
из первого массива во второе. Наконец мы тестируем на когерентность данных между
содержанием двух массивов. Мы можем использовать эту простую программу для
наблюдения эффекта различных параметров кэширования. Код MPU содержится в
единственном исходном файле и заголовочном файле, таким образом, он может быть
снова использован в других проектах.
Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Вновь откройте последнее осуществление “Исключая 6.5 Кэшами Данных”.
Прокомментируйте строку 90, таким образом, Кэш Данных не включен.
Разработайте проект.
Запустите отладчик.
Откройте окна/отладку представления / последовательные окна/отладку printf окно.
Выполните код.

Во время этого первого показа Кэш Данных отключен, чтобы дать нам базовую
линию для различных конфигураций кэша. Циклы, взятые для каждой операции,
следующие:
-. Циклы ЦП потратили для инициализации массивов: 5 217-.CPU
циклов потратили ре, инициализирующее исходный массив 1065-
.CPU циклы, потраченные на Передачу DMA: 11985
-. Циклы ЦП потратили для сравнения: 13912 было
0 различных чисел

Откройте main.c и строку некомментария 90 для включения кэша данных.


Открытый mpu.h.

Это - шаблонный конфигурационный файл для кода в mpu.c. Первоначальная


конфигурация отображает регион Кэша Данных в начале внешнего SRAM в
0xC0000000 для 128 Кбит. В опциях Конфигурации кэша Данных мы включаем
регион как с обеспечением совместного доступа с другими устройствами управления
шиной в микроконтроллере (Рис. 6.25).
Процессор 211 коры-M7

Рисунок 6.25
Параметры конфигурации MPU.

Восстановите код.
Запустите отладчик и выполните код.
-. Циклы ЦП потратили для инициализации массивов: 5 184-.CPU
цикла потратили ре, инициализирующее исходный массив 1064-
.CPU циклы, потраченные на Передачу DMA: 11985
-. Циклы ЦП потратили для сравнения: 13910 было
0 различных чисел

В то время как Кэш Данных теперь работает, он не имеет значительного эффекта,


потому что он имеет запись и чтение от системной памяти для поддержания
когерентности.
В mpu.h изменяют опцию с обеспечением совместного доступа от Да ни до КАКОГО
(Рис. 6.26).

Рисунок 6.26
Установите регион D-кэша, чтобы быть нес обеспечением
совместного доступа.
212 Глав 6

Создайте и повторно выполните пример.

Теперь регион не совместно используем, но политика загрузки кэша установлена


записать через так данные массива, записанные в кэш, будет также записан в
память SDRAM.
-. Циклы ЦП потратили для инициализации массивов: 3 388-.CPU
циклов потратили ре, инициализирующее исходный массив 1057-
.CPU циклы, потраченные на Передачу DMA: 11981
-. Циклы ЦП потратили для сравнения: 4418 было
0 различных чисел

Большое повышение производительности найдено в стандартной программе


сравнения. Это вызвано тем, что текущие данные для первого массива загружаются в
кэш. После того как сравнение было выполнено, данные для второго массива будут
теперь также загружены (Чтение Выделяют), поэтому, если мы выполняем
стандартную программу сравнения снова, время еще быстрее, потому что теперь все
доступы данных к Кэшу Данных.
-. Циклы ЦП потратили для сравнения: 2083 Там
был 0 различными числами

Открытый mpu.h.
Изменитесь Bufferable к Да Записывают обратно.
Расширение Типа изменения Чтения Уровня 1 и Записи Выделяет (Рис. 6.27).

Рисунок 6.27
Установите политику D-кэша быть, “Записывают обратно” и “Чтение, и
Запись Выделяют”.

Создайте и выполните код.

На этот раз код перестал работать, потому что значения данных массива сохранены
в Кэше Данных. Правильные значения не копируются DMA. Также, так как мы
выбрали чтение, и Запись Выделяют, array_sdram2 [] загружается в Кэш Данных,
когда это инициализируется. Это означает, что DMA обновляет SDRAM, но Кора-
M7 будет только видеть старые значения, сохраненные в кэше.
Процессор 213 коры-M7

Строка некомментария 98 Invalidate_Cache ();


Строка некомментария 94 Clean_Cache ();
Создайте и выполните код.

Снова код перестал работать, но более интересным способом. На этот раз


Invalidate_Cache () функция загрузила значения в SDRAM в кэш, но они -
неправильные значения. Мы инициализировали оба массива и затем назвали
Clean_Cache () функцией. Это помещает начальные значения в SDRAM. Однако мы
затем обновляем array_sdram1 [] значения, которые будут только изменены в кэше.
Строка некомментария 96 Clean_Cache ();
Создайте и выполните код.
-. Циклы ЦП потратили для инициализации массивов: 3 051-
.CPU цикл, потраченный на чистый кэш: 1067
-. Циклы ЦП потратили ре, инициализирующее исходный массив
1062-.CPU циклы, потраченные на чистый кэш: 1095
-. Циклы ЦП потратили на Передачу DMA: 11 999-
.CPU циклов, потраченных на кэш, делают
недействительным: 371-.CPU цикл потратил для
сравнения: 2696 было 0 различных чисел

-. Циклы ЦП потратили для сравнения: 2081 Там


был 0 различными числами

На этот раз код работает правильно, потому что мы поддержали когерентность между
Кэшем Данных и SDRAM.

Сопроцессор для операций с плавающей точкой двойной


точности
Как Кора-M4, Кора-M7 имеет Аппаратный Сопроцессор для операций с плавающей
точкой (FPU).
Эта единица тесно интегрируется в конвейер процессора, чтобы позволить очень
быстро обрабатывать и значений с плавающей точкой одинарной и двойной точности.
Кора-M7, которую FPU включен через регистр CPARC в Системном Блоке
управления процессора Cortex-M7, это обычно делается системным кодом запуска.
Вычисления с плавающей точкой теперь используют аппаратный блок, а не
библиотеки программного обеспечения, если параметры компилятора были
установлены правильно. Поскольку Кора-M7 может быть оснащена синглом
или двойная точность FPU CMSIS-базовая спецификация обеспечивает функцию,
чтобы запросить процессор и возвратить тип FPU, приспособленного (Рис. 6.28).
214 Глав 6

Рисунок 6.28
CMSIS-Core получает функцию типа FPU.

После того как FPU включили, он может использоваться таким же образом, мы


видели в Главе 3 “Архитектуру Cortex-M”.

Функциональная безопасность
Много секторов дизайна требуют соответствия некоторой форме стандарта
безопасности. Некоторые очевидные секторы являются Медицинскими,
Автомобильными, и Космос. Все больше другие секторы, такие как Управление
производственным процессом, Робототехника и Бытовая электроника все требуют
соответствия к стандартам безопасности. Как показывает опыт, процессы
проектирования, требуемые для функциональной безопасности сегодня, приняты
основными разработчиками завтра. Разработка проекта функциональной безопасности
намного больше, чем пишет и тестирует код полностью. Базовое кремниевое
устройство должно быть продуктом одинаково строгого процесса разработки с
доступной документацией для резервного копирования этого. Микроконтроллер
должен также включить функции (коды с коррекцией ошибок на шинных
интерфейсах, созданных в самопроверке), которые позволяют программному
обеспечению проверять это, процессор работает правильно и смочь обнаружить и
исправить отказы. IEC 61508-3 системы уровня (SIL3) будет часто состоять из
сдвоенных процессоров, работающих или на шаге блокировки или с расположением
супервизора и приложением. Это позволяет системе обнаруживать и справляться с
отказами процессора.

Кора-M7 была разработана и с аппаратными средствами и с документацией


процесса/безопасности, которая позволяет этому использоваться в высоких
системах целостности. Во время записи никаких микроконтроллеров,
использующих эти функции, были все же выпущены.
Процессор 215 коры-M7

Функции безопасности коры-M7


Кора-M7 представляет диапазон функций безопасности, которые позволяют
кремниевому поставщику разрабатывать устройство, подходящее для высокой
системы надежности. Функции безопасности, совместно использованные с другими
процессорами Cortex-M, следующим образом (Таблица 6.6):

Таблица 6.6: Общие функции безопасности Cortex-M

Единица защиты памяти


Инструкция и трассировка данных
Исключения отказа

Кора-M7 расширяет доступные функции безопасности с помощью дополнительных


функций (Таблица 6.7).

Таблица 6.7: функции безопасности Corex-M7


Функция
безопасности Описание
Коррекция Кора-M7 может быть настроена, чтобы обнаружить и
ошибок исправить трудно и
Коды исправимые ошибки в ПОРШНЯХ Кэша с помощью ECC
TCM соединяет интерфейсом с поддержкой,
взаимодействующей через интерфейс к памяти с ECC
оборудование
Двухъядерная Кора-M7 может быть реализована, как двухъядерный дизайн
блокировка был
Шаг оба процессора работают на Шаге Блокировки
Кора-M7 может быть синтезирована с Памятью, Созданной в
MBIST самопроверке
интерфейс, который поддерживает проверку памяти во время
производства и
время выполнения

Документация безопасности
Чтобы позволить кремниевым поставщикам разработать новый микроконтроллер,
который подходит для использования безопасности, ARM также предоставляет
обширную документацию в форме пакета безопасности (Таблица 6.8).

Таблица 6.8: документация безопасности коры-M7

Документ Описание
Руководство Руководство по безопасности, описывающее подробно
по отказ процессора
безопасности
обнаружение и функции управления и информация о
аспекты интеграции в реализациях устройства Silicon
Partner
Руководство
FMEA Виды отказа и Анализ Эффектов с качественным анализом
из видов отказа в логике процессора, последствиях отказа
на
поведение процессора и пример количественных
аппаратных средств
метрики
Отчет, ясно дающий понять, как инженеры Silicon Partner
Разработка должны
интерфейсный
отчет управляйте результатами ARM и что ожидать от них
216 Глав 6

Эти отчеты только представляют интерес для Кремниевых Разработчиков и


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

Средства разработки
Существует много наборов инструментальных средств, которые были
сертифицированы для использования безопасности. Это главным образом относится
к компилятору и компоновщику. Компилятор ARM, используемый в MDK-ARM,
сертифицирован следующим образом (Таблица 6.9):

Таблица 6.9: документация безопасности Компилятора

Функция безопасности Описание


Сертификация ¨
безопасности Сертификация TUV SUD
ISO 26262 (ASILD)
IEC 61508-3 (SIL3)
Пять лет расширили
Обслуживание обслуживание
Критические дефекты фиксируют
Сохраняемое ответвление
компилятора
Документация Руководство по безопасности
Документация процесса
разработки
Отчет о тестировании
Дефектный отчет

Заключение
В этой главе мы видели, что Кора-M7 сохраняет модель программиста Cortex-M
разрешение нас для легкого перехода к этому новому процессору. Однако это
действительно требует времени для понимания большого увеличения
производительности по Коре-M4. Это станет более отмеченным, Кремниевые
Поставщики перемещают меньшие технологии процесса и достигают еще более
высоких тактовых частот. Кора-M7 является также первым процессором Cortex-M с
полным комплектом документации безопасности, которая позволяет кремниевым
поставщикам разрабатывать устройства, подходящие для важных приложений
безопасности.
CHPTER7

Отладка с CoreSight

Многие разработчики, которые запускают работу с микроконтроллера Cortex-M,


предполагают, что его система отладки является формой интерфейса “JTAG (Joint Test
Action Group)”. На самом деле процессор Cortex-M имеет архитектуру отладки под
названием “CoreSight”, который значительно более мощен. В дополнение к
управлению выполнением и функциям доступа к памяти, обеспеченным “JTAG”,
система отладки “CoreSight” включает много единиц трассировки в реальном времени,
которые предоставляют Вам подробное представление отладки процессора, когда это
работает. В этой главе мы будем видеть, какие функции доступны и как настроить их.

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

Рисунок 7.1
Электрически стираемая программируемая постоянная память была
предшественником сегодняшней Флэш-
памяти.

Для помощи отладке код был “оснащен” путем добавления дополнительных строк
кода, чтобы записать отладочную информацию из UART или переключить контакт
ввода-вывода. Программы отладчика монитора были разработаны для работы
целевого микроконтроллера и выполнения управления кода приложения. В то время
как отладчики монитора были большим шагом вперед, они использовали ресурсы на
микроконтроллере и любой ошибке, которая, вероятно, откажет, код приложения
также разрушит программу мониторинга только в точке, Вам был нужен он (Рис. 7.2).

Руководство разработчика по семейству процессоров Cortex-M.


DOI: http://dx.doi.org/10.1016/B978-0-08-100629-0.00007-4 217
© 2016 Elsevier Ltd. Все права защищены.
218 Глав 7

Рисунок 7.2
Внутрисхемный эмулятор обеспечивает ненавязчивую отладку в реальном времени для
более старых встроенных микроконтроллеров.

Если бы у Вас были деньги, то альтернатива должна была использовать


внутрисхемный эмулятор. Это было сложной частью аппаратных средств, которые
заменили целевой микроконтроллер и позволили полный контроль над выполнением
программы без любого проникновения на времени выполнения ЦП или ресурсах. В
конце 1990-х более усовершенствованные микроконтроллеры начали показывать
различные формы единицы отладки на микросхеме. Одна из самых популярных
единиц отладки на микросхеме была указана “Joint Test Action Group” и известна
инициалами JTAG. Интерфейс отладки JTAG обеспечивает основное соединение
отладки между микроконтроллером ЦП и отладчиком ПК через недорогой адаптер
отладки (Рис. 7.3).

Рисунок 7.3
Сегодня аппаратные средства отладки низкой стоимости доступны для
программирования всех устройств Cortex-M.

JTAG позволяет Вам запускать и останавливать выполнение ЦП. Это также позволяет
Вам читать и писать в ячейки памяти и вставлять инструкции в ЦП. Это позволяет
разработчику отладчика останавливать ЦП, сохранять состояние процессора,
выполнять серию команд отладки и затем восстанавливать состояние ЦП и
выполнение перезапуска прикладной программы. В то время как этот процесс
очевиден для пользователя, это означает, что программа отладчика ПК выполнила
управление ЦП (сброс, работала, останов, и установила точку останова) и доступ к
памяти (чтение-запись пользователю
Отладка с CoreSight 219

память и периферийные устройства). Главное преимущество JTAG - то, что он


предоставляет базовому набору функций отладки с надежностью эмулятора по
намного более низкой цене. Недостаток JTAG - то, что необходимо добавить
аппаратный сокет к макетной плате, и интерфейс JTAG использует некоторые
контакты микроконтроллера. Как правило, интерфейс JTAG требует пяти контактов
GPIO, которые могут также быть мультиплексированы с другими периферийными
устройствами. Что еще более важно, интерфейс JTAG должен остановить ЦП,
прежде чем любая отладочная информация сможет быть предоставлена отладчику
ПК. Этот стиль выполнения/остановки отладки становится очень ограниченным,
когда Вы имеете дело с системой реального времени, такой как протокол связи или
блок управления приводом. В то время как интерфейс JTAG использовался на
ARM7/9-based микроконтроллерах, новая архитектура отладки под названием
CoreSight была представлена ARM для всего Cortex-M/R и Пониженных
процессоров.

Аппаратные средства CoreSight


При первом рассмотрении таблицы данных Основанного на Cortex-M
микроконтроллера легко пропустить доступные функции отладки или предположить,
что это имеет форму интерфейса JTAG. Однако архитектура отладки CoreSight
обеспечивает очень мощный набор функций отладки, которые идут путем вне того,
что может быть предложено JTAG. В первую очередь, на практической стороне
основное соединение отладки CoreSight только требует двух контактов,
Последовательных В и Последовательный (Рис. 7.4).
Рисунок 7.4
Архитектура отладки CoreSight заменяет коннектор айсберга JTAG двумя
стилями сверхминиатюрного коннектора.
220 Глав 7

Аппаратный сокет JTAG является 20-контактным коннектором айсберга, который


часто имеет большее место на PCB, чем микроконтроллер, который отлаживается.
CoreSight указывает два коннектора: 10-контактный коннектор для стандартных
функций отладки и 20-контактный коннектор для стандартных функций отладки и
трассировки инструкции. Мы будем говорить об опциях трассировки позже, но если
Ваш микроконтроллер поддерживает трассировку инструкции затем, рекомендуется
установить более крупный 20-контактный сокет, таким образом, у Вас есть доступ к
единице трассировки, даже если Вы первоначально не намереваетесь использовать
его. В сложной ошибке можно разобраться в течение многих часов с инструментом
трассировки, где с основным выполнением/остановкой, отлаживающим его, мог
занять недели (Рис. 7.5) (Таблица 7.1).

Рисунок 7.5
Эти два отладочных соединителя требуют минимального количества контактов
процессора для аппаратной отладки.

Таблица 7.1: сокеты отладки CoreSight

Сокет Samtec Коннекс Дона


10-контактная стандартная
отладка FTSH-105-01-L-DV-K C42-10-B-G-1
20-контактная стандартная 1
трассировка ETM FTSH-110-01-L-DV-K C42-20-B-G-1

Эта стандартная система отладки использует 10-контактный сокет. Это требует


минимума двух из контактов микроконтроллера, последовательный провод IO (SWIO)
и последовательные проводные часы (SWCLK) плюс целевой Vcc, земля и сброс. Как
мы будем видеть ниже, Кора-M3 и Кора-M4 оснащены двумя единицами трассировки,
которые требуют и дополнительный контакт, названный последовательным проводом
(SWO). Некоторые устройства Коры-M3 и Коры-M4 оснащены дополнительной
единицей трассировки инструкции. Это поддерживается 20-контактным коннектором
и использует еще четыре контакта процессора для канала трассировки инструкции.

Аппаратные средства отладчика


После того как Вам оснастили Вашу плату подходящим сокетом CoreSight, Вам будет
нужна единица адаптера отладки, которая включает сокет и обычно подключается к
ПК через USB или соединение Ethernet. Растущее число недорогих макетных плат
также включает интерфейс отладки USB на основе CMSIS-DAP (Порт доступа
Стандартной Отладки Программного интерфейса Микроконтроллера Коры)
спецификация.
Отладка с CoreSight 221

Архитектура отладки CoreSight


Существует несколько уровней поддержки отладки, оказанной по семейству Cortex-
M. Во всех случаях система отладки независима от ЦП и не использует ресурсы
процессора или время выполнения (Рис. 7.6).

Рисунок 7.6
Кроме того, для выполнения управления Коры-M3 и Коры-M4 основная система
отладки включает две единицы трассировки. Трассировка
данных и трассировка инструментария.

Минимальная система отладки, доступная на Коре-M3 и Коре-M4, состоит из интерфейса


последовательного провода (SW), подключенного к системе управления отладкой,
которая состоит из блока управления выполнения, единицы точки останова и единицы
доступа к памяти. Единица точки останова поддерживает до восьми аппаратных точек
останова, на самом деле доступное общее количество будет зависеть от числа, указанного
Кремниевым Поставщиком, когда микросхема будет разработана. В дополнение к
единицам управления отладкой стандартная поддержка отладки CoreSight Коры-M3 и
Коры-M4 включает две единицы трассировки, трассировку часов данных и трассировку
инструментария (ITM). Трассировка часов данных позволяет Вам просматривать
внутреннюю RAM и периферийные местоположения “на лету”, не используя циклов ЦП.
Единица часов данных позволяет Вам визуализировать поведение своих данных
приложений.

Упражнение 7.1 Отладка CoreSight


Для большинства примеров в этой книге я использовал отладчик средства
моделирования, который является частью IDE µVision. В этом осуществлении,
однако, я пробегу установку отладчика для работы с платой Исследования STM32F7.
Эта оценочная плата имеет свой собственный адаптер отладки, включенный как часть
платы. В то время как существует множество оценочных плат, доступных для
222 Главы 7

различные устройства Cortex-M конфигурация аппаратного интерфейса отладки


являются по существу тем же для всех плат.

Аппаратная конфигурация
При разработке собственного аппаратного и программного обеспечения внешний
адаптер отладки подключен к макетной плате через 10-контактный сокет отладки
CoreSight. Адаптер отладки в свою очередь подключен к ПК через USB-кабель (Рис.
7.7).

Рисунок 7.7
Типичная оценочная плата обеспечивает коннектор JTAG/CoreSight. Оценочная плата
должна также иметь свой собственный источник питания. Часто это
обеспечивается через гнездо USB.

Важно отметить здесь, что макетная плата также имеет свой собственный источник
питания. Адаптер отладки снизит некоторый ток в макетную плату, достаточно
чтобы включить светодиоды на плате и дать появление, что аппаратные средства
работают. Однако недостаточно тока обеспечивается, чтобы позволить плате
работать надежно; всегда удостоверяйтесь, что макетная плата приводится в
действие ее обычным источником питания (Рис. 7.8).
Рисунок 7.8
Плата Исследования STM32F7xx.
Отладка с CoreSight 223

В этом примере мы настроим аппаратный отладчик, встроенный в плату


Исследования STM32F7. Эта плата подключена к разработке ПК с помощью USB-
кабеля. На этой плате USB-кабель предоставляет питание плате Исследования и
также соединяется со встроенным интерфейсом отладки.

Конфигурация программного обеспечения


Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Выберите вкладку Example и Копию “аппаратная EX 7.1 Отладка”.
Это - версия примера Blinky для платы Исследования ST.
Теперь откройте вкладку Options for Target\Debug

Рисунок 7.9
Вкладка Debug позволяет, Вы для конфигурирования отладчика для аппаратных
средств отлаживаете и выбираете адаптер
отладки.

Возможно переключиться от использования средства моделирования к отладчику


CoreSight путем нажатия на переключатель “Use” на правой стороне меню (Рис. 7.9).
В выпадающем поле удостоверяются, что Отладчик Ссылки ST выбран. Как средство
моделирования возможно запустить скрипт, когда отладчик микровидения
запускается. В то время как отладчик запустится успешно без этого сценария,
сценарий используется для программирования регистра в системе отладки
микроконтроллера, которая позволяет нам настраивать любые уникальные опции для
используемого микроконтроллера
(Рис. 7.10).
224 Главы 7

Рисунок 7.10
Файл сценария отладчика позволяет Вам настраивать отладочные регистры CoreSight.
Здесь, мы можем заморозить таймеры и управлять поведением
отладчика во время выключения питания.

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


позволяют некоторым пользовательским периферийным устройствам быть
остановленными, когда ЦП Cortex-M останавливается системой отладки. В этом
случае пользовательские таймеры, сторожевые таймеры и модуль CAN могут быть
заморожены, когда ЦП останавливается. Сценарий также позволяет нам включать
поддержку отладки, когда кора ЦП помещается в режимы низкой мощности. В этом
случае режимы ожидания, разработанные производителем микроконтроллеров, могут
быть настроены, чтобы позволить источнику часов системе отладки CoreSight
продолжаться управлять, в то время как остальная часть микроконтроллера переходит
к требуемому режиму низкой мощности. Наконец, мы можем настроить
последовательный контакт трассировки. Это должно быть включено путем выбора
TRACE_IOEN с набором TRACE_MODE к Асинхронному. Когда отладчик
запустится, сценарий запишет, что пользовательская конфигурация оценивает
отладочному регистру MCU (Рис. 7.11).
_WDWORD (0xE0042004, 0x00000027);

Теперь нажмите кнопку настроек.


Отладка с CoreSight 225

Рисунок 7.11
Установочное меню драйвера первоначально покажет Вам, что адаптер отладки
подключен и работа. Успешно чтение coreID доказывает, что
микроконтроллер работает.

Это откроет окно конфигурации адаптера отладки. Две основных области в этом
диалоговом окне показывают состояние соединения адаптера отладки к ПК и к
микроконтроллеру. Область USB адаптера отладки показывает что порядковый номер
адаптера отладки и версия микропрограммного обеспечения. Это также позволяет
Вам выбирать, с каким стилем отладки соединяют интерфейсом для использования
при соединении с микроконтроллером. Для микроконтроллеров Cortex-M необходимо
обычно всегда использовать SW, но JTAG также доступен, должен Вы нуждаться в
нем. Поле галочки SWJ позволяет отладчику выбирать стиль интерфейса отладки
динамично.

Когда Вы будете подключены к микроконтроллеру, диалоговое окно устройства SW


отобразит все доступные интерфейсы отладки (на некоторых микроконтроллерах может
быть больше чем один). Хотя Вы обычно не должны реализовывать конфигурацию для
выбора порта отладки, эта информация полезна в этом, это говорит Вам, что
микроконтроллер работает. При переводе в рабочее состояние новой платы впервые
может быть полезно проверить этот экран, когда плата сначала соединена для получения
некоторой уверенности, что микроконтроллер работает (Рис. 7.12).
Рисунок 7.12
Раздел отладки позволяет Вам определять соединение и сбрасывать метод,
используемый отладчиком.
226 Глав 7

Диалоговое окно отладки в установке позволяет Вам управлять, как отладчик


соединяется с аппаратными средствами. Опция подключения определяет, если сброс
применяется к микроконтроллеру, когда отладчик соединяется, у Вас также есть опция
содержать микроконтроллер в сбросе. Помните, что, когда Вы программируете код во
флэш-память и сбрасываете процессор, код будет работать за многими циклами перед
соединением отладчика. Если код приложения делает что-то для нарушения
соединения отладки, то отладчик может не соединиться. Способность сбросить и
остановиться, код может быть окольным путем такие проблемы. Методом сброса
можно также управлять, это может быть аппаратным сбросом, относился к целому
микроконтроллеру или программному сбросу, вызванному путем записи в регистры
“SYSRESET” или “VECTRESET” в NVIC. В случае опции “SYSRESET” возможно
сделать “теплый” сброс, который сбрасывает ЦП Cortex-M, не сбрасывая
периферийные устройства микроконтроллера. Влияние опций кэша, когда физическая
память считана и отображена. Если код будет кэшироваться затем, то отладчик не
будет читать физическую память, но содержать кэшированную версию изображения
программы в памяти ПК. При написании кода самоизменения необходимо снять
флажок с этой опцией. Кэш памяти данных также сохранен, если используется, кэш
данных отладчика только обновляется однажды, когда код останавливается. Если Вы
хотите видеть периферийное обновление регистров, в то время как код
останавливается, необходимо снять флажок с этой опцией (Рис. 7.13).
Теперь нажмите на вкладку Trace.

Рисунок 7.13
Вкладка Trace используется, чтобы настроить Инструкцию, данные и единицы
трассировки инструментария и также включить счетчики
производительности.

Это диалоговое окно позволяет нам настраивать внутренние единицы трассировки


устройства Cortex-M. Для обеспечения точной синхронизации базовая тактовая
частота должна быть установлена на частоту тактовой частоты ЦП процессора
Cortex. Опции порта трассировки настроены для интерфейса SW с помощью
протокола связи UART. В этом меню мы можем также включить и настроить данные
Отладка с CoreSight 227

наблюдайте трассировку и включите различные счетчики события трассировки.


Это диалоговое окно также настраивает ITM, и мы взглянем на это далее в этой
главе (Рис. 7.14).
Теперь нажмите вкладку Flash Download.

Рисунок 7.14
Алгоритм программирования для внутренней Флэш-памяти
микроконтроллера.

Это диалоговое окно позволяет Вам устанавливать алгоритм Загрузки Flash для Флэш-
памяти микроконтроллера. Это будет обычно настраиваться автоматически, когда
проект будет определен. Это меню позволяет Вам обновлять или добавлять алгоритмы
для поддержки дополнительной внешней параллельной или последовательной Флэш-
памяти.

После того, как настроенный, можно запустить отладчик как нормальный, и он будет
подключен к аппаратным средствам вместо имитационной модели. Это позволяет Вам
осуществлять код реальных аппаратных средств через тот же интерфейс отладчика,
который мы использовали для средства моделирования. С данными трассировка часов
включила, Вы видите текущее состояние своих переменных в часах и окнах памяти, не
имея необходимость останавливать код приложения. Также возможно добавить
глобальные переменные к Анализатору логики для трассировки значений переменной
со временем. Это может быть невероятно полезно при работе с данными реального
времени (Рис. 7.15).
228 Глав 7

Рисунок 7.15
Трассировка Исключения и Счетчики события обеспечивают полезные
метрики выполнения кода.

Окна трассировки часов данных дают некоторую высокоуровневую информацию о


производительность во время выполнения кода приложения. Окна трассировки часов
данных обеспечивают необработанное высокоуровневое исключение трассировки и
доступ к данным. Трассировка исключения также доступна, который предоставляет
подробную информацию исключения и поведения прерывания (Рис. 7.16).
Отладка с CoreSight 229

Рисунок 7.16
Счетчики события являются руководством по тому, как эффективно процессор
Cortex-M работает в микроконтроллере.

Архитектура отладки CoreSight также содержит много счетчиков, которые


показывают производительность процессора Cortex-M. Дополнительные циклы
на количество инструкции являются количеством состояний ожидания,
процессор встретился с ожиданием инструкций, которые будут освобождены от
Флэш-памяти. Это - хороший признак в том, как эффективно процессор
работает.

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

Трассировка инструментария
В дополнение к трассировке часов данных основная структура отладки на Коре-M3 и
Коре-M4 включает вторую единицу трассировки, названную ITM. Можно думать о
ITM как о последовательном порте, который подключен к отладчику. Можно затем
добавить код к приложению, которое пишет пользовательские сообщения отладки в
ITM, которые затем отображены в отладчике. Путем оснащения кода этот путь можно
отправить сложную отладочную информацию в отладчик. Это может использоваться,
чтобы помочь определить местоположение неясных ошибок, но это также особенно
полезно для тестирования программного обеспечения.

ITM немного отличается от других двух единиц трассировки, в которых это


навязчиво на ЦП, то есть, это действительно использует несколько циклов ЦП. ITM
лучше всего считается отладкой UART
230 Глав 7

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


оснастить код путем добавления простой, отправляют и получают рычаги. Эти
рычаги являются частью стандарта CMSIS и автоматически определяются в
стандартном заголовочном файле микроконтроллера. Рычаги состоят из трех
функций и одной переменной.
статичный __ ВСТРАИВАЮТ uint32_t ITM_SendChar (uint32_t ch); //Отправляют символ в ITM
энергозависимый международный ITM_RxBuffer 5 ITM_RXBUFFER_EMPTY; //Получают буфер для ITM
статичный __ ВСТРАИВАЮТ международный ITM_CheckChar (пусто); //Проверка, чтобы видеть, имеет ли
символ
отправленный
//от отладчика
статичный __ ВСТРАИВАЮТ международный ITM_ReceiveChar (пусто); //Read символ от ITM

ITM на самом деле немного более сложен в этом, он имеет 32 отдельных канала. В
настоящее время канал 31 используется RTOS (Операционная система реального
времени) ядро для отправки сообщений в отладчик для ядра осведомленные окна
отладки. Канал 0 является каналом пользователя, который может использоваться
Вашим кодом приложения для отправки printf () сообщения стиля к консоли в
отладчике.

Упражнение 7.2 Установка ITM


В этом осуществлении мы посмотрим на конфигурирование ITM, чтобы отправить и
получить сообщения между микроконтроллером и отладчиком ПК.
Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Выберите вкладку Example и Копию “аппаратная EX 7.1 Отладка”.

Мы настроим проект Blinky так, чтобы было возможно отправить сообщения


через ITM из кода приложения. Во-первых, мы должны настроить отладчик,
чтобы включить приложению канал ITM.
Откройте диалоговое окно “Options for Target\debug”.
Нажмите кнопку настроек ST-Link и выберите вкладку Trace (Рис. 7.17).
Рисунок 7.17
Базовая Тактовая частота должна быть установлена правильно, чтобы ITM
работал успешно.
Отладка с CoreSight 231

Для включения ITM Базовые Часы должны быть установлены на корректную частоту,
как обсуждено в последнем осуществлении, и Трассировке нужно включить (Рис.
7.18).

Рисунок 7.18
ITM имеет 32 канала. В настоящее время канал 31 и 0 используется для
представления события RTOS и пользовательского
канала отладки ITM.

В меню портов стимула ITM порт 31 будет включен по умолчанию. Для включения
порта приложения, мы должны включить порт 0. Мы хотим смочь использовать
Приложение форма ITM привилегированный и непривилегированный режим так
Привилегированный Порт 7.. 0 должен быть неконтролируем.

После того как настройки Trace и ITM настроены, нажимают "OK" и


возвращаются назад к редактору.

Откройте редактора во время выполнения.


Выберите Компилятор:: раздел IO.

Здесь, мы можем настроить канал, используемый в качестве стандарта IO (STDIO).


Опция File оказывает поддержку для вызовов низкого уровня, выполненных
функциями stdio.h. Уезжайте это сняло флажок, если Вы не добавили файловую
систему (Рис. 7.19).
Рисунок 7.19
Компилятор:: опции ввода-вывода позволяют Вам выбирать канал STDIO
низкого уровня.
232 Главы 7

Включите STDERR, STDIN, STDOUT и TTY, и выберите ITM из выпадающего


меню.

Рисунок 7.20
Обновленный проект с ITM поддерживает для STDIO в retarget_IO.c.

Это добавляет “retarget_io.c” файл к проекту. Этот файл содержит функции драйвера
STDIO низкого уровня, которые читают и пишут отдельный символ в ITM (Рис. 7.20).
Откройте Blinky.c.
Добавьте, что stdio.h к списку включают файлы.
#include "RTE_Components.h"
#include, stdio.h.

Добавьте printf оператор после kernelStart () вызов API.


osKernelStart (); printf ("RTX
Started\n"); в то время как (1) {

Запустите отладчик.
Откройте view\serial windows\Debug (printf) средство просмотра.
Выполните код.

Рисунок 7.21
Сообщение отладки, отправленное от кода приложения до окна консоли
отладки.
Отладка с CoreSight 233

printf () сообщение отправляется на канал STDIO, который является ITM. Это


сообщение прочитано и отображено в окне консоли отладки (Рис. 7.21).

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


во время выполнения в Главе 10 “Методы RTOS” и также как использовать его
в качестве части схемы тестирования программного обеспечения в Главе 11
"Test-Driven Development".

Системная поддержка отладки блока управления


Интерфейс отладчика CoreSight позволяет Вам управлять выполнением своего кода
приложения и исследовать значения в памяти и периферийных регистрах.
Объединенный с различными единицами трассировки, это предоставляет Вам
мощную систему отладки для нормальной разработки программы. Однако, поскольку
мы видели в Главе 3 “Архитектуру Cortex-M”, процессоры Cortex-M имеют до
четырех исключений отказа, которые будут инициированы, если код приложения
сделает неправильное использование процессора Cortex-M или аппаратных средств
микроконтроллера (Таблица 7.2).

Таблица 7.2: исключения Отказа

Исключение отказа Приоритет Процессор коры


Серьезный отказ 21 Кора-M0, кора-M01, кора-M3, кора-M4
Программируе
Отказ шины мый Кора-M3, кора-M4
Программируе
Отказ использования мый Кора-M3, кора-M4
Отказ диспетчера Программируе
памяти мый Кора-M3, кора-M4 (дополнительно)

Когда это произойдет, Ваша программа будет захвачена на обработчике ошибок по


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

Поведение исключений отказа может быть настроено регистрами в системном блоке


управления. Ключевые регистры перечислены в Таблице 7.3.

Таблица 7.3: регистры конфигурации исключения Отказа

Зарегистрироваться Процессо Описание


р
Активируйте дополнительные опции исключения
Конфигурация и управление M3, M4 отказа
Управление обработчиком Включите и незаконченные биты для исключений
систем и состояние M3, M4 отказа
Настраиваемый регистр
состояния отказа M3, M4 Подробные биты состояния отказа
Состояние серьезного отказа M3, M4 Сообщает эскалация серьезного отказа или отказа
Адрес отказа диспетчера Адрес местоположения, которое вызвало отказ
памяти M3, M4 диспетчера памяти
Адрес отказа шины M3, M4 Адрес местоположения, которое вызвало отказ шины
234 Главы 7

Когда процессор Cortex-M выходит из сброса, только обработчик серьезных отказов


включен. Если использование, шина или отказ диспетчера памяти будут повышены, и
обработчик исключений для этих отказов не включен, то отказ “возрастет” к
серьезному отказу. Регистр состояния серьезного отказа обеспечивает два бита
состояния, которые указывают на источник серьезного отказа (Таблица 7.4).

Таблица 7.4: регистр состояния Серьезного отказа

Имя: Бит Использовать


ПРИНУДИТЕЛ Достигнутый серьезный отказ, должный
ЬНЫЙ 30 давать сбой эскалация
Достигнутый серьезный отказ из-за
VECTTBL 1 дефектного чтения
из таблицы векторов

“Управление Обработчиком систем и” регистр состояния содержат, включают,


ожидание и активные биты для шины, использования и обработчиков исключений
диспетчера памяти. Мы можем также настроить поведение исключений отказа с
“Конфигурацией и Управления” регистр (Таблица 7.5).

Таблица 7.5: Регистр конфигурации и регистр управления

Имя: Бит Использовать


STKALIGN 9 Настраивает 4-или 8-байтовое выравнивание стека
Отключает отказы шины данных, вызванные инструкциями
BFHFMIGN 8 по хранилищу и загрузкой
DIV_0_TRP 4 Включает отказ использования для деления нулем
Включает отказ использования для невыровненного
UNALIGNTRP 3 доступа к памяти

“Делятся на нулевое” исключение, может быть полезное прерывание для включения,


особенно во время разработки. Остающиеся исключения нужно оставить
отключенными, если у Вас нет серьезного основания включить их. То, когда
исключение отказа диспетчера памяти произойдет, адрес инструкции, которая
попыталась получить доступ к запрещенному региону памяти, будет сохранен в
“Адресном регистре Отказа памяти”, так же когда отказ шины повышен адрес
инструкции, которая вызвала отказ, будет сохранено в “регистре” Адреса Отказа
Шины. Однако при некоторых условиях, не всегда возможно записать, что отказ
адресует к этим регистрам. Настраиваемый регистр “Состояния отказа” содержит
обширный набор флагов, которые сообщают о состояниях ошибки процессора Cortex-
M, которые помогают Вам разыскать причину исключения отказа.

Отслеживание отказов
Если Вы прибыли в обработчик серьезных отказов, сначала проверьте “регистр”
Состояния Серьезного отказа. Это скажет Вам при достижении серьезного отказа,
должного давать сбой эскалация или ошибка чтения таблицы векторов. Если
существует эскалация отказа, затем проверьте “Управление Обработчиком систем и”
регистр состояния для наблюдения, который другое исключение отказа активно.
Следующая остановка
Отладка с CoreSight 235

“Настраиваемое Состояние отказа” регистр. Это имеет широкий спектр флагов,


которые сообщают о состояниях ошибки процессора (Таблица 7.6).

Таблица 7.6: Настраиваемый регистр состояния отказа


Настраиваемый регистр состояния отказа
Имя: Бит Использовать
DIVBYZERO 25 Разделитесь на нулевую ошибку
НЕВЫРОВНЕН
НЫЙ 24 Невыровненный доступ к памяти
NOCP 19 Никакие CoProcessor не представляют
INVPC 18 Недопустимая загрузка ПК
Несанкционированный доступ регистр состояния
INVSTATE 17 программы выполнения EPSR
UNDEFINSTRA Предпринятое выполнение неопределенной
SSE 16 инструкции
BFARVALID 15 Адрес в адресном регистре отказа шины допустим
STKERR 12 Отказ шины на укладке записи исключения.
UNSTKERR 11 Отказ шины на неукладке выхода исключения
Ошибка шины данных. Ошибочный адрес, не
IMPRECISERR 10 сложенный
PRECISERR 9 Ошибка шины данных. Ошибочный адрес сложен
IBUSERR 8 Ошибка шины инструкции
Адрес в адресном регистре отказа диспетчера памяти
MMARVALID 7 допустим
Укладка на записи исключения вызвала отказ
MSTKERR 4 диспетчера памяти
Укладка на выходе исключения вызвала отказ
MUNSTKERR 3 диспетчера памяти
DACCVIOL 1 Флаг нарушения доступа к данным
IACCVIOL 0 Флаг нарушения прав доступа инструкции

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

Упражнение 7.3 Исключения отказа процессора


Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Выберите вкладку Example и Копию “Отслеживание Отказа EX 7.3”.

В этом проекте мы генерируем исключение отказа и посмотрим на то, как он


обрабатывается NVIC. После того как исключение отказа произошло, мы можем
опросить стек для нахождения инструкции, которая вызвала исключение
ошибки.
236 Глав 7

энергозависимый uint32_t
op1; международное
основное (пустота)
{
международный op2 5 0x1234, op3 5 0;
SCB-.CCR 5 0x0000010;//Включают, делятся на нулевой отказ использования
op1 5 op2/op3;//выполняют деление нулем для генерации исключения использования

в то время как (1);


}

Код сначала включает, “делятся на нулевой отказ использования”, и затем


выполняет деление нулем для порождения исключения.
Создайте код и запустите отладчик.
Установите точку останова на строке кода, которая содержит инструкцию по делению
(Рис. 7.22).

Рисунок 7.22
Установите точку останова на операторе деления.

Выполните код, пока он не поразит эту точку останова.

Откройте окно Peripherals\Core Peripherals\System Control и Configuration и проверьте,


что Делению Нулевым прерыванием включили (Рис. 7.23).

Рисунок 7.23
Проверьте, что Деление Нулевым прерыванием включено при помощи
“Конфигурации системы и Управления”
периферийное представление.
Отладка с CoreSight 237

Одноэтапный инструкция по делению (Рис. 7.24).

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

Исключение отказа использования будет повышено. Мы не включили вектор


исключения отказа использования, таким образом, отказ поднимет до серьезного
отказа.
Откройте окно Peripherals\Core Peripherals\Fault Reports (Рис. 7.25).

Рисунок 7.25
Если отказ происходит, можно просмотреть обзор регистров диагностики отказа
в периферийном окне сообщений о
неисправностях.
238 Глав 7

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

В окне Register считайте содержание R13, Основного Указателя вершины стека, и


откройте Окно памяти в этом местоположении (Рис. 7.26).

Рисунок 7.26
Используйте окно Register, считайте текущий адрес, сохраненный в указателе
вершины стека. Затем используйте Окно памяти для чтения
значения ПК, сохраненного в стековом фрейме.

Рисунок 7.27
Значение ПК, сохраненное в стековом фрейме, приводит нас к инструкции SDIV, которая вызвала
исключение ошибки.

Считайте значение ПК, сохраненное в Стековом фрейме, и откройте окно Disassembly


в этом местоположении (Рис. 7.27).
Это забирает нас к инструкции SDIV, которая вызвала отказ.
Выйдите из отладчика и добавьте строку кода ниже к началу программы.
SCB-.SHCSR 5 0x00060000;

Это включает Исключение отказа использования в NVIC.


Теперь добавьте обработчик исключений отказа использования уровня “C”.
освободите UsageFault_Handler (пусто)
{
error_address 5 (uint32_t *) (__ get_MSP ());//загружают текущий базовый адрес
указатель вершины стека
error_address 5 error_address 1 6; //Определяют местоположение значения ПК в
последнем стеке
кадр
в то время как (1);
}
Разработайте проект и запустите отладчик.
Установите точку останова на цикле с условием продолжения в функции исключения
(Рис. 7.28).
Отладка с CoreSight 239

Рисунок 7.28
Стандартная программа исключения отказа использования может
использоваться для чтения значения ПК из стека.

Выполните код, пока исключение не повышено, и точка останова достигнута.

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


инициирована. Это читает значение, сохраненное в указателе вершины стека, и
извлекает значение ПК, сохраненного в стековом фрейме.

Трассировка инструкции со встроенной макроячейкой


трассировки
Кора-M3, Кора-M4 и Кора-M7 могут иметь дополнительный модуль отладки,
приспособленный Кремниевым Поставщиком, когда микроконтроллер разработан.
Встроенная макроячейка трассировки (ETM) является третьей единицей
трассировки, которая обеспечивает трассировку инструкции, поскольку код
приложения выполняется на процессоре Cortex-M. Поскольку ETM является
дополнительной стоимостью для Кремниевого Поставщика, он обычно только
приспосабливается к Коре-M3 более высокого уровня, Коре-M4 и основанным на
коре-M7 микроконтроллерам. При выборе устройства это будет перечислено как
функция микроконтроллера в таблице данных (Рис. 7.29).
Рисунок 7.29
Кора-M3, Кора-M4 и Кора-M7 могут дополнительно быть оснащены третьей
единицей трассировки. Встроенная макроячейка трассировки (ETM) поддерживает
трассировку инструкции. Это позволяет Вам быстро находить сложные ошибки. ETM
также включает покрытие кода и аналитические инструменты производительности,
которые важны для проверки программного обеспечения.
240 Глав 7

Канал трассировки ETM требует четырех дополнительных контактов, которые


производятся к более крупному 20-контактному сокету, который включает контакты
отладки SW и контакты трассировки ETM. Стандартные отладчики JTAG/CoreSight не
поддерживают канал трассировки ETM, таким образом, Вы будете более сложная
единица отладки (Рис. 7.30).

Рисунок 7.30
Единица трассировки ETM обеспечивает все функции отладчика стандартного
оборудования плюс трассировка
инструкции.

В начале этой главы мы посмотрели на различные методы отладки, которые


использовались исторически с маленькими микроконтроллерами. В течение долгого
времени единственным решением, которое обеспечило бы любой вид трассировки
инструкции, был внутрисхемный эмулятор. Аппаратные средства эмулятора
получили бы каждую инструкцию, выполняемую микроконтроллером, и сохранили
бы его во внутреннем буфере трассировки. При необходимости трассировка могла
быть отображена в отладчике ПК как ассемблер или высокоуровневый язык обычно
“C.”. Однако буфер трассировки имел конечный размер, и было только возможно
получить часть выполненного кода, прежде чем буфер трассировки был полон. Так, в
то время как буфер трассировки был очень полезен, он имел некоторые серьезные
ограничения и взял некоторый опыт использовать правильно. Напротив, ETM
является трассировкой потоковой передачи, какие выводы сжали трассировочную
информацию. Эта информация может быть получена инструментом трассировки
CoreSight, более сложные единицы передадут данные трассировки потоком
непосредственно к жесткому диску ПК без потребности буферизовать ее в
аппаратных средствах отладчика (Рис. 7.31).
Отладка с CoreSight 241

Рисунок 7.31
Единица трассировки “Потоковой передачи” способна к записи каждой инструкции
непосредственно на жесткий диск ПК. Размер буфера трассировки только
ограничен размером Вашего жесткого диска.

Эта трассировка потоковой передачи позволяет программному обеспечению


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

Упражнение 7.4 Использование трассировки ETM


В этом осуществлении мы посмотрим на то, как настроить Ulink, Pro отлаживают
адаптер для потоковой передачи трассировки и затем рассматривают
дополнительные функции отладки, доступные через ETM (Рис. 7.32).
Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Выберите вкладку Example и Копию “Трассировка инструкции EX 7.4”.
Откройте файл инициализации STM32_TP.ini.
242 Главы 7

Рисунок 7.32
Файл сценария отладки используется для включения дополнительных четырех
контактов трассировки инструкции, когда
отладчик запускается.

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


отладки. На этот раз TRACE_MODE был установлен для 4-разрядных синхронных
данных трассировки. Это включит обоим, которые трассировка ETM передает по
каналу и переключает внешние контакты микроконтроллера с GPIO для отладки
контактов (Фиги. 7.33 и 7.34).

Рисунок 7.33
Выберите адаптер отладки, который способен к собиранию данных от
ETM.
Рисунок 7.34
Порт Trace может теперь быть настроен для доступа к
ETM.
Отладка с CoreSight 243

Теперь нажмите кнопку настроек ULINK Pro.


Выберите вкладку Trace.

Когда инструмент ULINK Pro Trace подключен, у Вас есть опция включить
трассировку ETM. Неограниченная опция трассировки позволяет Вам передавать
потоком каждую инструкцию, выполняемую в файл на Вашем жестком диске ПК.
Буфер трассировки затем только ограничен размером жесткого диска ПК. Это
позволяет проследить выполняемые инструкции в течение многих дней при
необходимости, да дни.
Нажмите "OK" для выхода назад редактору µVision.
Запустите отладчик.
Теперь отладчик имеет дополнительное окно трассировки инструкции (Рис. 7.35).

Рисунок 7.35
Окно трассировки отладчика может теперь отобразить все инструкции,
выполняемые процессором Cortex-M (передающий
трассировку потоком).

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


информацию о покрытии кода, которая была ранее только доступна в
средстве моделирования (Рис. 7.36).
Рисунок 7.36
Трассировка потоковой передачи позволяет Вам отображать точную
информацию о покрытии кода.
244 Главы 7

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


с кодом “C” или как аналитический отчет о производительности (Рис. 7.37).

Рисунок 7.37
Анализатор производительности показывает кумулятивное время выполнения
для каждой функции.

CMSIS-DAP

Рисунок 7.38
Спецификация CMSIS-DAP разработана для поддержки совместимости между
другими аппаратными средствами отладчика и
программным обеспечением отладчика.

Спецификация CMSIS-DAP определяет интерфейсный протокол между аппаратными


средствами отладчика CoreSight и программным обеспечением отладчика ПК (Рис. 7.38).
Это создает новый уровень совместимости между отладчиками программного и
аппаратного обеспечения различных поставщиков. Встроенное микропрограммное
обеспечение CMSIS-DAP разработано для превращения недорогого микроконтроллера
Cortex-M с периферийным устройством USB в отладчик Coresight. Это позволяет даже
самой основной оценочной плате размещать общий интерфейс отладки, который может
использоваться с любым совместимым набором инструментальных средств CMSIS (Рис.
7.39).
Отладка с CoreSight 245

Рисунок 7.39
Модуль MBED является первым для поддержки спецификации CMSIS-
DAP.

Спецификация CMSIS-DAP разработана для поддержки интерфейса USB между


целевыми аппаратными средствами и ПК. Это позволяет многим простым модулям
приводиться в действие непосредственно от USB-порта ПК (Рис. 7.40).

Рисунок 7.40
Драйвер CMSIS-DAP должен быть выбран в меню отладчика.

Интерфейс CMSIS-DAP может быть выбран в меню отладки вместо собственного


Ulink2. Параметрами конфигурации является по существу то же как ulink2, но
доступные опции будут зависеть на уровне встроенного микропрограммного
обеспечения, реализованного производителем устройств. Спецификация CMSIS-
DAP поддерживает все функции отладки, найденные в архитектуре отладки
CoreSight включая Микро буфер трассировки (MTB) Коры-M01.

Кора-M01 MTB
В то время как ETM доступен для Коры-M3 и Коры-M4, никакая форма трассировки
инструкции не в настоящее время доступна для Коры-M0. Однако Кора-M01 имеет
простую форму буфера трассировки инструкции, названного MTB. MTB использует
регион внутреннего SRAM, который является
246 Глав 7

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


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

Упражнение 7.5 Микро буфер трассировки


Это осуществление основано на управлении Свободы NXP по микроконтроллеру
MKL25Z. Это было первым микроконтроллером, доступным для использования
Коры-M01.
Соедините плату свободы через ее USB-кабель к ПК.
Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Выберите вкладку Example и Копию “EX 7.5 Микро Буфер трассировки”.
Откройте меню Options for Target/debug (Рис. 7.41).

Рисунок 7.41
Выберите адаптер отладки CMSIS-DAP и Микро файл сценария Буфера
трассировки.

Здесь интерфейс CMSIS-DAP выбран наряду с файлом инициализации для MTB.


Файл сценария инициализации имеет мастер, который позволяет Вам
настраивать размер и конфигурацию MTB (Рис. 7.42).
Отладка с CoreSight 247

Рисунок 7.42
Файл сценария раньше настраивал Микро Буфер трассировки.

Здесь мы можем выбрать сумму внутреннего SRAM, который должен


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

По умолчанию MTB расположен в начале внутреннего SRAM (0x20000000). Таким


образом, необходимо сместить запуск пользователя SRAM размером памяти,
выделенной MTB. Это сделано в Опциях Для диалогового окна Target\Target (Рис.
7.43).

Рисунок 7.43
Необходимо сместить пользовательскую RAM от региона, используемого
Микро Буфером трассировки.

Теперь запустите отладчик и выполните код.


Остановите отладчик и откройте окно Trace (Рис. 7.44).
248 Глав 7

Рисунок 7.44
Содержание Микро Буфера трассировки загружено на ПК и отображено в окне Trace
отладчика.

В то время как это - ограниченный буфер трассировки, он может использоваться


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

Системное описание средства просмотра CMSIS


Формат системного описания средства просмотра (SVD) CMSIS разработан для
предоставления кремниевым производителям метод создания описания
периферийных регистров в их микроконтроллере. Это описание может быть передано
сторонним производствам инструментов так, чтобы компилятор включал файлы, и
периферийные окна представления отладчика могут быть созданы автоматически. Это
означает, что не будет никакой задержки в поддержке разработки программного
обеспечения, когда следующее новое семейство устройств будет выпущено. Как
разработчик Вы не должны будете обычно работать с этими файлами, но полезно
понять, как процесс работает так, чтобы можно было зафиксировать любые ошибки,
которые могут неизбежно произойти. Также возможно создать Ваши собственные
дополнительные периферийные окна отладки. Это позволило бы, Вы для создания
представления внешней памяти отобразили периферийное устройство, или обеспечьте
представление отладки сложного объекта памяти.
Когда Кремниевый Поставщик разрабатывает новый микроконтроллер, они также
создают XML-описание регистров микроконтроллера. Утилита преобразования затем
используется для создания версии двоичных файлов файла, который используется
отладчиком для автоматического создания периферийных окон отладки (Рис. 7.45).
Отладка с CoreSight 249

Рисунок 7.45
ARM создал репозиторий “системных файлов” описания средства просмотра. Это
позволяет поставщикам инструментов иметь поддержку новых
устройств, поскольку они выпущены.

Вместе с определением XML-описания ARM представил систему представления и


публикации для новых файлов SVD. Когда Кремниевый Поставщик разрабатывает
новый микроконтроллер, его системный файл описания отправлен через веб-сайт
CMSIS. После того как это было рассмотрено и проверено, это затем публикуется для
общедоступной загрузки на основном веб-сайте ARM.

Упражнение 7.6 CMSIS-SVD


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

Для этого осуществления Вам будет нужен XML-редактор. Если Вы не имеете


один, то загрузите испытательный или бесплатный инструмент с Интернета.
Откройте свой веб-браузер и перейдите к www.arm.com/cmsis.

Если у Вас не будет учетной записи пользователя на веб-сайте ARM, то необходимо


будет создать один и вход в систему.
На странице CMSIS выберите вкладку CMSIS-SVD (Рис. 7.46).
250 Глав 7

Рисунок 7.46
Веб-сайт CMSIS имеет каналы общего доступа к текущим спецификациям CMSIS
и репозиторию CMSIS-SVD.

Выберите ссылку STMicroelectronics.


В окне ST выберите загрузку SVD, которая поддерживает STM32F103RB
(Рис. 7.47).

Рисунок 7.47
Выберите файлы STM32F103 SVD.

Затем нажмите кнопку загрузки внизу страницы.


Разархивируйте сжатый файл в каталог.
Откройте файл STM32F103xx.svd с XML-редактором (Рис. 7.48).
Отладка с CoreSight 251

Рисунок 7.48
Файлы SVD состоят из XML-описания периферийных регистров
микроконтроллера.

Каждое из периферийных окон структурировано как серия XML-тэгов, которые


могут быть отредактированы, или может быть добавлена новая периферийная
область. Это позволило бы Вам отображать регистры внешнего периферийного
устройства, с которым соединяют интерфейсом на внешнюю шину. Каждое
периферийное окно запускается с имени, описания и названия группы,
сопровождаемого базовым адресом периферийного устройства
(Рис. 7.49).
Рисунок 7.49
Описание SVD для регистра порта GPIO.
252 Главы 7

После того как периферийные детали были определены, описание каждого регистра в
периферийном устройстве добавляется. Это состоит из имени регистра и описания
его смещения от периферийного базового адреса наряду с его размером в битах, типе
доступа и значении сброса (Рис. 7.50).

Рисунок 7.50
Описание SVD периферийного битового поля регистра.

Также возможно определить битовые поля в регистре. Это позволяет окну отладки
разворачивать представление регистра и отображать содержание битового поля (Рис.
7.51).

Рисунок 7.51
Получающееся периферийное представление.

Сделайте небольшое изменение XML-файла и сохраните результаты (Рис. 7.52).

Рисунок 7.52
Сделайте редактирование к описанию SVD.

Генерируйте файл швейцарского франка при помощи утилиты SVDConv.exe.


Эта утилита расположена в c:\keil\arm\cmsis\svd.
Преобразователь должен быть вызван со следующей командной строкой.
SVDConv STM32F103xx.svd - генерируйте 5 sfr
Это создаст STM32F103xx. Швейцарский франк.
Отладка с CoreSight 253

Теперь запустите µVision и откройте предыдущее осуществление.

Откройте меню “Options for Target” и выберите STM32F103xx.sfr как системный


файл средства просмотра (Рис. 7.53).

Рисунок 7.53
Загрузите файл швейцарского франка в меню Target проекта.

Разработайте проект и запустите отладчик.


Откройте выбор Средства просмотра View\System и просмотрите обновленное
периферийное окно
(Рис. 7.54).

Рисунок 7.54
Модификации теперь видимы в отладчике.

Уважение к Симпсонам в стороне, полезно знать, как добавить и изменить


периферийные окна, таким образом, можно исправить ошибки или добавить в
собственной определенной поддержке отладки.
254 Главы 7

Сводка функций отладки заключения


В этой главе мы взглянули через усовершенствованные функции отладки, доступные в
архитектуре отладки CoreSight для Cortex-M. Таблица 7.7 суммирует функции,
доступные на различных процессорах Cortex-M.

Таблица 7.7: сводка функции Отладки

Функция Cortex-M0/Cortex-M01 Cortex-M3/M4/M7


JTAG прежней версии JTAG прежней версии
или последовательный или последовательный
Интерфейс Debug провод провод
“Непрерывный” доступ к
памяти Да Да
6 инструкций 1 2
Аппаратная точка останова 4 литерала
Контрольная точка данных 2 4
Точка останова
программного обеспечения Да Да
Трассировка инструкции
ETM Нет Да (дополнительно)
Трассировка данных Нет Да (дополнительно)
Трассировка
инструментария Нет Да
Последовательное
проводное средство
просмотра Нет Да
Микро буфер трассировки Да (Только Кора-M01) Нет
CHPTER8

Практический DSP для


коры-M4 и коры-M7

Введение
С точки зрения разработчика Кора-M4 и Кора-M7 являются версиями процессора
Cortex-M, которые имеют дополнительные функции для поддержки Обработки
цифровых сигналов (DSP). Ключевые улучшения по Коре-M3 являются добавлением
“Единственной Инструкции Несколько Данных” или инструкций SIMD, улучшенный
Умножается, Накапливают (MAC) единицу для целочисленной математики и
дополнительное добавление аппаратных средств “Сопроцессор для операций с
плавающей точкой” (FPU). В случае Коры-M4 это - одинарная точность FPU, в то
время как Кора-M7 имеет опцию или одинарной или двойной точности FPU. Эти
улучшения дают Коре-M4 способность выполнить алгоритмы DSP на достаточно
высоко уровнях производительности для конкуренции с выделенными 16-разрядными
процессорами DSP. Как мы видели в Главе 6 "Cortex-M7", процессор Cortex-M7 имеет
более усовершенствованный конвейер и блок кэш-памяти ответвления. Обе из этих
функций существенно улучшают его возможность DSP. В этой главе мы посмотрим
на использование Cortex-M4/M7 для обработки сигналов реального мира (Рис. 8.1).

Рисунок 8.1
Кора-M4 и Кора-M7 расширяют Кору-M3 с помощью добавления инструкций по DSP и
быстрых возможностей математики. Это создает микроконтроллер, способный к
поддержке алгоритмов DSP в реальном времени, контроллера цифрового сигнала.

Аппаратные средства FPU


Одной из основных функций процессоров Cortex-M4 и Cortex-M7 является добавление
аппаратных средств FPU. FPU поддерживает арифметические операции с плавающей
точкой к стандарту IEEE 754.
Руководство разработчика по семейству процессоров Cortex-M.
DOI: http://dx.doi.org/10.1016/B978-0-08-100629-0.00018-9 255
© 2016 Elsevier Ltd. Все права защищены.
256 Глав 8

Первоначально, FPU может считаться сопроцессором, к которому получают доступ


специализированные инструкции выполнить большинство арифметических операций с
плавающей точкой в нескольких циклах (Таблица 8.1).

Таблица 8.1: производительность Сопроцессора для


операций с плавающей точкой

Операция Количество цикла


Добавить/Вычесть 1
Разделиться 14
Умножиться 1
Умножьтесь накапливаются (MAC) 3
Сплавленный MAC 3
Квадратный корень 14

FPU состоит из группы регистров управления и состояния и 31 регистра скаляра


одинарной точности. Скалярные регистры могут также быть просмотрены как 16
регистров двойного слова (Рис. 8.2).

Рисунок 8.2
FPU 32-разрядные скалярные регистры может также быть просмотрен как 64-
разрядные регистры двойного слова. Это поддерживает
очень эффективный кастинг между типами C.

В то время как FPU разработан для операций с плавающей точкой, возможно


загрузить и сохранить фиксированную точку и целочисленные значения. Также
возможно преобразовать между плавающей точкой в фиксированную точку и
целочисленными значениями. Это означает, что “C”, бросающий между значениями с
плавающей точкой и целочисленными значениями, может быть сделан в
единственном цикле.
Интеграция FPU
В то время как возможно считать FPU как сопроцессор смежным с процессорами
Cortex-M4 и Cortex-M7, это не действительно верно. FPU является неотъемлемой
частью Cortex-M
Практический DSP для коры-M4 и коры-M7 257

процессор, инструкции с плавающей точкой выполняются в FPU в параллельном


конвейере к инструкциям по процессору Cortex-M. Пока это увеличивает
производительность FPU, это “невидимо” для кода приложения и не представляет
странных побочных эффектов (Рис. 8.3).

Рисунок 8.3
FPU описан как сопроцессор в документации регистра. В действительности это
очень сильно связано с основным конвейером инструкции.

Регистры FPU
В дополнение к скалярным регистрам FPU имеет блок регистров управления и
состояния (Таблица 8.2).

Таблица 8.2: регистры управления FPU

Зарегистрироваться Описание
Управление доступом
сопроцессора Управляет уровнем доступа полномочия к FPU
Управление контекстом с
плавающей точкой Настраивает укладку и ленивые опции укладки
Адрес контекста с плавающей Содержит адрес безлюдного стекового пространства
точкой FPU
Управление состоянием по Содержит коды условий FPU и параметры конфигурации
умолчанию с плавающей точкой FPU
Управление состоянием с Содержит значения управления состоянием по
плавающей точкой умолчанию

Все регистры FPU с отображенной памятью кроме Регистра Управления состоянием с


плавающей точкой (FPSC), который является регистром ЦП, к которому получает
доступ Регистр Перемещения к Специальному Регистру (MRS) и Перемещение
Специальные Регистры для Регистрации инструкций (MSR). Доступ к этой функции
поддерживается CMSIS-базовой функцией.
uint32_t __ get_FPSCR (пусто);
пусто __ set_FPSCR (uint32_t (fpscr)

Регистр FPSCR содержит три группы битов. Лучшие четыре бита содержат флаги кода
условия N, Z, C, и V, которые соответствуют флагам кода условия в xPSR. Эти флаги
установлены и очищены подобным образом результатами операций с плавающей
точкой. Следующие группы битов содержат параметры конфигурации для FPU. Эти
биты позволяют Вам изменять операцию FPU из стандарта IEEE 754. Если у Вас нет
веской причины сделать это, рекомендуется оставить их в покое. Заключительная
группа битов является флагами состояния для исключений FPU. Если FPU встретится
с ошибкой во время выполнения, то исключение будет повышено и
258 Глав 8

флаг состояния соответствия будет установлен. Строка исключения постоянно


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

Кора-M7 FPU
Микроконтроллеры с помощью Коры-M7 могут быть разработаны без FPU или
могут быть оснащены единицей одинарной или двойной точности. CMSIS-базовая
спецификация была расширена с помощью функции для создания отчетов о
конфигурации процессора Cortex-M7.
uint32_t SBC_GetFPUType (пусто)

0 5 никаких FPU
1 5 одинарных точностей
2 5 двойной точности

Эта функция читает регистр конфигурации в Системном Блоке управления,


“Регистр функции Media и VFP” затем возвращает конфигурацию процессора
Cortex-M7. Эта функция может только использоваться с Корой-M7.

Включение FPU
Когда Кора-M4 или Кора-M7 оставляют вектор сброса, FPU отключен. FPU включен
путем установки сопроцессора 10 и 11 битов в регистре CPARC. Необходимо
использовать инструкцию по барьеру данных гарантировать, что запись сделана,
прежде чем код продолжается. Команда барьера инструкции также используется,
чтобы гарантировать, что конвейер сбрасывается, прежде чем код продолжается.
SCB-.CPACR | 5 ((3UL, 10*2) | (3UL, 11*2));//Набор CP10 и Полный доступ CP11
__ DSB (); //барьер Данных
__ ISB (); //барьер Инструкции

Для записи в регистр CPARC процессор должен быть в привилегированном


режиме. После того, как включенный, FPU может использоваться в
привилегированных и непривилегированных режимах.

Исключения и FPU
Когда FPU будет включен, расширенный стековый фрейм будет продвинут, когда
исключение повышено. В дополнение к стандартному стековому фрейму процессор
Cortex-M также продвигает первые 16 регистров скаляра FPU и FPSCR. Это
расширяет стековый фрейм с 32 до 100 байтов. Очевидно продвигая этот объем
данных на стек, каждое прерывание значительно увеличило бы задержку прерывания.
Сохранять 12 задержек прерывания цикла, Cortex-M
Практический DSP для коры-M4 и коры-M7 259

процессор использует технику, названную “ленивая укладка”. Когда прерывание


повышено, нормальный стековый фрейм продвинут на стек, и указатель вершины
стека увеличен для оставления пространства для регистров FPU, но их значения не
продвинуты на стек. Это оставляет вакуум в стеке. Начальный адрес этого вакуума
автоматически хранится в “Адресном регистре Контекста С плавающей точкой”
(FPCAR). Если процедура прерывания будет использовать вычисления с плавающей
точкой, то регистры FPU будут продвинуты в это пространство с помощью адреса,
сохраненного в FPCAR как базовый адрес. “Регистр управления Контекста С
плавающей точкой” используется для выбора используемого метода укладки. Ленивая
укладка включена по умолчанию, когда FPU сначала включен. Методом укладки
управляют на старшие значащие 2 бита в “Регистре управления Контекста С
плавающей точкой”; это Автоматическое Сохранение состояния, Включают (АСПЕН),
и Ленивое Сохранение состояния Включают (LSPEN) (Таблица 8.3).

Таблица 8.3: Ленивые опции укладки


LSPEN Конфигурация АСПЕНА
0 0 Никакое автоматическое сохранение состояния. Только используйте, когда
прерывания не будут использовать плавающую точку
0 1 Ленивая укладка отключена
1 0 Ленивых укладок включены
1 1 Недопустимая конфигурация

Использование FPU
После того как Вы включили FPU, компилятор начнет использовать аппаратные
вычисления плавающей точки вместо библиотек программного обеспечения.
Исключением является инструкция по квадратному корню sqrt (), который является
частью math.h библиотеки. При включении FPU компилятор ARM предоставляет
внутреннюю инструкцию использовать инструкцию по квадратному корню FPU.
плавайте __ sqrtf (пустите в ход x);

Примечание: Внутренняя функция квадратного корня отличается от ANSI sqrt ()


библиотечная функция, в которой это берет и возвращает плавание, а не двойное.

Упражнение 8.1 Сопроцессор для операций с плавающей


точкой
Это осуществление выполняет несколько простых вычислений с плавающей точкой
с помощью процессора Cortex-M4 так, чтобы мы могли сравнить
производительность времени выполнения плавающей точки программного и
аппаратного обеспечения.
Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Выберите вкладку Example и Копию “сопроцессор для операций с плавающей точкой
EX 8.1”.
260 Глав 8

Код в основном цикле является смесью операций математики для осуществления FPU.
#include, math.h.
пускают в ход a, b, c,
d, e; интервал f, g 5
100;

в то время как (1) {


5 10.1234; b 5
100.2222; c 5
a*b;
d 5 c-a; e
5 d 1 b;
f 5 (интервал)
a; f 5 f*g;
a1 5 (неподписанный
интервал) a; 5 __ sqrtf (e);
//5 sqrt (e); 5 c/f;
e 5 a/0;
}
}

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


компилятор создаст код для использования FPU.
Откройте Options for Target и выберите меню Target (Рис. 8.4).

Рисунок 8.4
Аппаратная поддержка плавающей точки включена в опциях Project Target.

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


FPU” в поле аппаратных средств вычислений с плавающей точкой. Это включит
необходимые параметры компилятора и загрузит корректную модель средства
моделирования.
Закройте меню Options for Target и возвратитесь к редактору (Рис. 8.5).
Практический DSP для коры-M4 и коры-M7 261

Рисунок 8.5
Этот проект в качестве примера использует моделирование процессора
Corex-M4.

В дополнение к нашему исходному коду проект включает запуск CMSIS и


системные файлы для Коры-M4.
Теперь разработайте проект и запишите размер сборки (Рис. 8.6).

Рисунок 8.6
Отметьте размер кода проектом с помощью аппаратных средств
FPU.

Запустите отладчик.

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


останова, которая была задана в system_ARMCM4.c файле (Рис. 8.7).

Рисунок 8.7
CMSIS-ядро SystemInit () функция включит FPU на запуске.
262 Главы 8

Стандартный микроконтроллер включает файлы, которые определят набор функций


процессора Cortex-M включая доступность FPU. В нашем случае мы используем
имитационную модель Коры-M4 только и используем минимальный ARMCM4_FP.h,
включают файл, обеспеченный как часть базовой спецификации CMSIS. Если FPU
будет присутствовать на микроконтроллере, SystemInit (), то функция удостоверится,
что это включается перед достижением основных приложений () функция.
Определения процессора находятся в ARMCM4_FP.H
/* 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 процессоров *//* 5 5 5 5 5 5 5 5
5 и базовое периферийное устройство разделяют 5 5 5 5 5 5 5 5 5 5 *//* 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 */
/* — — — — — — Конфигурация процессора коры-M4 и базовой периферии — — — — — */
#define __ CM4_REV 0x0001 /*!, Базовый пересмотр r0p1 */
#define __ MPU_PRESENT 1 /*!, подарок MPU или нет */
#define __ NVIC_PRIO_BITS 3 /*!, Число Битов используется для Приоритетных Уровней */
#define __ Vendor_SysTickConfig 0 /*!, Набор к 1, если другая Конфигурация SysTick используется */
#define __ FPU_PRESENT 1 /*!, существующий FPU или нет */

Затем __ FPU_USED определяется в core_cm4.h

#if (__ FPU_PRESENT 5 5 1U)


#define __ FPU_USED 1U

Откройте main.c модуль и выполните код к основному в то время как () цикл (Рис.
8.8).

Рисунок 8.8
Используйте локальные параметры отладчика для выполнения к
основному () в то время как (1) цикл.

Теперь откройте окно Disassembly (Рис. 8.9).


Практический DSP для коры-M4 и коры-M7 263

Рисунок 8.9
Окно Disassembler покажет Вам вызовы аппаратным средствам FPU.

Это покажет исходный код “C”, чередованный с инструкциями по сборке Коры-M4.


В Project окно выбирают окно Register (Рис. 8.10).

Рисунок 8.10
Окно Register позволяет Вам просматривать регистры FPU.

Окно Register теперь показывает 31 скалярный регистр в их формате .raw и формате


IEE754 (Рис. 8.11).
264 Главы 8

Рисунок 8.11
Выполните вычисления с плавающей точкой. Отметьте количество циклов, взятых для
каждой операции.

Содержание регистра FPSC также показывают. В этом осуществлении мы будем также


использовать состояния (количество цикла) значение, также показанное в окне
Register.

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


цикла каждым вычислением.
Теперь выйдите из отладчика и измените код для использования библиотек операций с
плавающей точкой программного обеспечения.
a1 5 (неподписанный
интервал) a;//5 __ sqrtf (e);
5 sqrt (e);

Прокомментируйте __ sqrtf () внутренний и замените его ANSI C sqrt () функция.

В настройках Options for Target\target мы также должны удалить поддержку FPU


(Рис. 8.12).
Рисунок 8.12
Отключите поддержку FPU в целевом меню проекта.
Практический DSP для коры-M4 и коры-M7 265

Также измените заголовочный файл процессора для Коры-M4 без FPU.


#include, ARMCM4.h.

Восстановите код и сравните размер сборки с исходной версией (Рис. 8.13).

Рисунок 8.13
Восстановите проект и сравните размер кода в исходном проекте.

Теперь перезапустите выполненный отладчик и выполните код к основному.

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


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

К концу этого осуществления можно ясно видеть не только значительное повышение


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

Cortex-M4/M7 DSP и Инструкции SIMD


Ползунок 2 системы команд имеют много дополнительных инструкций, которые
полезны в алгоритмах DSP (Таблица 8.4).

Таблица 8.4: инструкции ползунка по 2 дес. ложкам

Инструкция Описание
Считайте
CLZ начальные нули
Обратные
ВЕРСИЯ, REV16, REVSH и RBIT инструкции
Пригодное поле
BFI вставляет
Ясное битовое
BFC поле
Аппаратные
UDIV и SDIV средства делятся
Знак и нуль
SXT и UXT расширяются
Кора-M4 и система команд M7 включают новую группу инструкций, которые могут
выполнить несколько арифметических вычислений в единственном цикле.
Инструкции SIMD позволяют данным на 8 битов или на 16 битов, упакованным в два
32-разрядных слова управляться на параллельно. Так, например,
266 Глав 8

можно выполнить, два 16-разрядных умножается и 32-разрядное, или 64-разрядные


накапливаются или квадратическое 8-разрядное дополнение в одном цикле
процессора. Начиная со многой работы алгоритмов DSP над конвейером данных
инструкции SIMD могут использоваться для существенного повышения
производительности (Рис. 8.14).

Рисунок 8.14
Инструкции SIMD поддерживают несколько арифметических операций в
единственном цикле. Данные операнда должны быть
упакованы в 32-разрядные слова.

Инструкции SIMD имеют дополнительное поле в регистре xPSR. “Больше, чем или
Равное” поле (GE) содержит 4 бита, которые соответствуют 4 байтам в операнде
результата инструкции SIMD. Если байтом операнда результата будет GE для
обнуления затем флага GE соответствия, то будет установлен (Рис. 8.15).

Рисунок 8.15
Кора-M4 xPSR регистр имеет дополнительное большее, чем или равное поле.
Каждый из четырех битов GE обновляется, когда инструкция
SIMD выполняется.

Инструкции SIMD можно рассмотреть как три отличных группы: Добавьте и вычтите
операции, умножьте операции и инструкции по поддержке. Добавление и вычитает
операции, может быть выполнен на 8-или 16-разрядные и неподписанные количества
со знаком. И неподписанная инструкция по сокращению вдвое со знаком также
предоставлена; эта инструкция добавляет или вычитает 8 или 16-разрядные
количества и затем половины результат как показано в Таблице 8.5.

Таблица 8.5: SIMD добавляют сокращение вдвое и вычитают


сокращающиеся наполовину инструкции

Инструкция Описание Операция


Неподписанное 16-разрядное
UHSUB16 сокращение вдвое вычитает Res [15:0] 5 (Op1[15:0] 2 Op2[15:0])/2
Res [31:16] 5 (Op1[31:16] 2Op2[31:16])/2
Неподписанное 16-разрядное
UHADD16 сокращение вдвое добавляет Res [15:0] 5 (Op1[15:0]1Op2[15:0])/2
Res [31:16] 5 (Op1[31:16]1Op2[31:16])/2

Инструкции SIMD также включают Добавление и Вычитают с Exchange (ASX) и


Вычитанием и Добавляют с Exchange (SAX). Эти инструкции выполняют и
добавляют и вычитают
Практический DSP для коры-M4 и коры-M7 267

на этих двух полусловах и хранилище результаты в верхних и более низких


полусловах целевого регистра (Таблица 8.6).

Таблица 8.6: SIMD добавляют обмен и вычитают обменные инструкции


Инструкци
я Описание Операция
Неподписанный 16-разрядный вычитают и
USAX добавляют с обменом Res [15:0] 5Op1 [15:0] 1Op2 [31:16]
Res [31:16] 5 Op1[31:16] 2 Op2[15:0]
Неподписанный 16-разрядный добавляют и
UASX вычитают с обменом Res [15:0] 5 Op1[15:0]1Op2[31:16]
Res [31:16] 5 Op1[31:16] 2 Op2[15:0]

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


добавляет (или добавляет и вычитает) с обменной инструкцией по сокращению вдвое.
Это дает совсем немного возможных перестановок. Сводка добавления и вычитает
инструкции SIMD, показан в Таблице 8.7.

Таблица 8.7: Перестановки SIMD добавляют, вычитают, сокращение вдвое и


насыщение инструкций
Неподписанн Неподписанны
Со знаком Со знаком ый й
Инструкци Со Сокращен Неподпис Сокращение
я знаком Насыщение ие вдвое анный Насыщение вдвое
ADD8 SADD8 QADD8 SHADD8 UADD8 UQADD8 UHADD8
SUB8 SSUB8 QSUB8 SHSUB8 USUB8 UQSUB8 UHSUB8
ADD16 SADD16 QADD16 SHADD16 UADD16 UQADD16 UHADD16
SUB16 SSUB16 QSUB16 SHSUB16 USUB16 UQSUB16 UHSUB16
ASX SASX QASX SHASX UASX UQASX UHASX
SAX SSAX QSAX SHSAX USAX UQSAX UHSAX

Инструкции SIMD также включают группу, умножают инструкции, которые


воздействуют на упакованные 16-разрядные значения со знаком. Как добавление и
вычитают инструкции, умножить инструкции также поддерживают насыщаемые
значения. А также умножьтесь и умножьтесь, накапливаются, SIMD умножаются,
поддержки инструкций умножаются, вычитают и умножаются, добавляют как
показано в Таблице 8.8.

Таблица 8.8: SIMD умножают инструкции

Инструкция Описание Операция


Установка Q, двойная 16-разрядный подписанный,
SMLAD умножается с 32-разрядным единственным X 5 X 1 (3 B) 1 (C 3 D)
аккумулятор
Двойной 16-разрядный подписанный умножаются с
SMLALD единственным 64-разрядным аккумулятором X 5 X 1 (3 B) 1 (C 3D)
Установка Q, двойная 16-разрядный подписанный,
SMLSD умножается, вычитают с 32-разрядным X 5 X 1 (3 B) 2 (B 3 C)
накопиться
Установка Q, двойная 16-разрядный подписанный,
SMLSLD умножается, вычитают с 64-разрядным X 5 X 1 (3B) 2 (B 3C)
накопиться
Сумма установки Q двойных, 16-разрядных
SMUAD подписанный, умножается X 5 (3B) 1 (C 3 D)
Двойной 16-разрядный подписанный умножают
SMUSD различие в возврате. X 5 (3B) 2 (C 3 D)
268 Глав 8

Чтобы сделать инструкции SIMD более эффективными, группа поддержки пакета и


распаковать инструкции была также добавлена к системе команд.
Упаковать/распаковать инструкции могут использоваться, чтобы извлечь 8-и 16-
разрядные значения от регистра и переместить их в целевой регистр.
Неиспользованные биты в 32-разрядном слове могут быть обнулены
(неподписанные) или один (подписанный). Инструкции по пакету могут также взять
два 16-разрядных количества и загрузить их в верхние и более низкие полуслова
целевого регистра (Рис. 8.16) (Таблица 8.9).

Рисунок 8.16
Группа инструкции SIMD включает инструкции по поддержке упаковать 32-разрядные
слова 8-и 16-разрядные количества.

Таблица 8.9: SIMD поддержка инструкций


Мнемосхе
ма Описание
PKH Упакуйте полуслово
Расширьте 8-разрядное значение со знаком
SXTAB до 32 битов и добавьте
Двойной расширяют 8-разрядное значение со
SXTAB16 знаком до 16 битов и добавляют
Расширьте 16-разрядное значение со знаком
SXTAH до 32 битов и добавьте
SXTB Знак расширяет байт
Двойной расширяют 8-разрядные значения со
SXTB16 знаком до 16 битов и добавляют
SXTH Знак расширяет полуслово
Расширьте 8-разрядное значение со знаком
UXTAB до 32 битов и добавьте
Двойной расширяются на 8 - 16 битов и
UXTAB16 добавляют
Расширьте 16-разрядное значение и
UXTAH добавьте
UXTB Нуль расширяет байт
Двойной нуль расширяется на 8 - 16 битов и
UXTB16 добавляет
UXTH Нуль расширяет полуслово

Когда инструкция SIMD будет выполняться, она установит или очистит биты xPSR
GE в зависимости от значений в получающихся байтах или полусловах.
Дополнительный выбор (SEL) инструкция обеспечивается для доступа к этим
битам. Инструкция SEL используется для выбора байтов, или полуслова от двух
входных операндов в зависимости от условия GE отмечает (Таблица 8.10).
Практический DSP для коры-M4 и коры-M7 269

Таблица 8.10: xPSR, “Больше, чем или равные” результаты битового


поля
GE укусил GE укусил
GE укусил [3:0] 51 50
0 Res [7:0] 5 OP1[7:0] Res [7:0] 5 OP2[7:0]
1 Res [15:8] 5 OP1[15:8] Res [15:8] 5 OP2[15:8]
2 Res [23:16] 5 OP1[23:16] Res [23:16] 5 OP2[23:16]
3 Res [31:24] 5 OP1[31:24] Res [31:24] 5 OP2[31:24]

Упражнение 8.2 Инструкции SIMD


В этом осуществлении у нас будет первый взгляд на использование инструкций
Cortex-M4/M7 SIMD. Мы просто умножим и накопим два 16-разрядных массива
сначала с помощью инструкции SIMD и затем с помощью операторов “C”
стандарта.

Сначала откройте CMSIS-базовую документацию, и SIMD подписал MAC,


внутренний __ SMLAD (Рис. 8.17).

Рисунок 8.17
Документация CMSIS-DSP для __ SMLAD () внутренний.

Откройте установщик пакета.


Выберите Советы:: разработчики ведут учебное руководство.
Выберите вкладку Example и Копию “EX 8.2 SIMD”..
Код приложения определяет два набора массивов как объединение 16-разрядных и 32-
разрядных количеств.
объединение _test {
int16_t Arry_halfword[100]; int32_t
Arry_word[50];
};
270 Глав 8

Код сначала инициализирует массивы со значениями 0 100.


для (n 5 0; n, 100; n11) {
op1. Arry_halfword[n] 5 op2. Arry_halfword[n] 5 n;}

Мы затем делаем умножение накапливает сначала использование инструкции SIMD,


затем стандартной Инструкции MAC.
для (n 5 0; n, 50; n11) {
Результат 5 __ SMLAD (op1. Arry_word[n], op2. Arry_word[n], Результат);}

Результат затем сбрасывается, и вычисление повторяется, не используя инструкцию


SIMD.
Результат 5 0;
для (n 5 0; n, 100; n11) {
Результат 5 Результатов 1 (op1. Arry_halfword[n] * op2. Arry_halfword[n]);}

Создайте код и запустите отладчик.


Установите точку останова в строке 23 и 28 (Рис. 8.18).

Рисунок 8.18
Набор устанавливает контрольные точки по обе стороны от кода
SIMD.

Выполненный к первой точке останова и обращают внимание на количество цикла


(Рис. 8.19).

Рисунок 8.19
Отметьте количество цикла запуска.
Выполните код, пока он не поразит вторую точку останова. Посмотрите, сколько
циклов использовалось для выполнения инструкции SIMD (Рис. 8.20).
Практический DSP для коры-M4 и коры-M7 271

Рисунок 8.20
Отметьте заключительное количество цикла.

Циклы использовали 5 5172 2 4066 5 1106


Установите точку останова в заключительном цикле с условием продолжения (Рис.
8.21).

Рисунок 8.21
Теперь установите точку останова после стандартной программы
копии массива.

Выполните код и посмотрите, сколько циклов используется для выполнения


вычисления, не используя инструкцию SIMD (Рис. 8.22).

Рисунок 8.22
Отметьте заключительное количество цикла.

Циклы использовали 5 7483 2 5172 5 2311

Сравните количество циклов раньше выполняло то же вычисление, не используя


инструкции SIMD.

Как ожидалось инструкции SIMD намного более эффективны при выполнении


вычислений на больших наборах данных.

Основное использование для инструкций SIMD должно оптимизировать


производительность алгоритмов DSP. В следующем осуществлении мы посмотрим на
различные методы в дополнение к инструкциям SIMD, которые могут использоваться
для повышения, увеличивают эффективность данного алгоритма.
272 Главы 8

Упражнение 8.3 Оптимизация алгоритмов DSP


В этом осуществлении мы посмотрим на оптимизацию Конечного фильтра
Импульсной характеристики (FIR). Это - классический алгоритм, который широко
используется в приложениях DSP (Рис. 8.23).

Рисунок 8.23
Фильтр FIR является фильтром усреднения со своими характеристиками,
определенными серией коэффициентов, относился к
каждому образцу в серии “касаний”.

Фильтр FIR является фильтром усреднения, который состоит из многих “касаний”.


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

Рисунок 8.24
Математическое выражение для фильтра FIR.

В этом осуществлении мы будем использовать имитационную модель Коры-M4 для


рассмотрения нескольких методов, которые могут использоваться для оптимизации
алгоритма DSP, работающего на процессоре Cortex-M.
Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Выберите вкладку Example и Копию “EX 8. Оптимизация FIR”.
Разработайте проект и запустите отладчик.

Основная функция состоит из четырех функций FIR, которые представляют


различную оптимизацию стандартному алгоритму FIR.
Практический DSP для коры-M4 и коры-M7 273

международное основное
(пустота) {
ель (data_in, data_out, коэффициент, &index, FILTERLEN, BLOCKSIZE);
fir_block (data_in, data_out, коэффициент, &index, FILTERLEN, BLOCKSIZE);
fir_unrolling (data_in, data_out, коэффициент, &index, FILTERLEN, BLOCKSIZE);
fir_SIMD (data_in, data_out, коэффициент, &index, FILTERLEN, BLOCKSIZE);
fir_SuperUnrolling (data_in, data_out, коэффициент, &index, FILTERLEN, BLOCKSIZE);

в то время как (1);


}

Шаг в первую функцию и исследует код.

Функция фильтра реализована в “C” как показано ниже. Это -


стандартная реализация фильтра FIR, записанного просто в “C”.
пустая ель (q31_t *в, q31_t *, q31_t *coeffs, интервал *stateIndexPtr, интервал filtLen,
интервал blockSize)

{
международн
ый образец;
интервал k;
сумма q31_t;

международный stateIndex 5 *stateIndexPtr;


для (демонстрационные 50; образец, blockSize; sample11)
{
[stateIndex11] 5 состояния в [образце];
суммируйте 5 0;

для (k 5 0; k, filtLen; k11)


{
суммируйте 1 5 coeffs [k] * состояние [stateIndex];
stateIndex-;

если (stateIndex, 0)
{
stateIndex 5 filtLen-1;
}
}
[демонстрационные] 5 сумм;
}
*stateIndexPtr 5 stateIndex;
}

В то время как это компилирует и хорошо работает, это не в полной мере


пользуется улучшениями DSP Коры-M4. Для вытаскивания лучшего из Коры-M4
мы должны оптимизировать этот алгоритм, особенно внутренний цикл.
Внутренний цикл работает, FIR умножаются и накапливаются для каждого касания.
для (k 50; k, filtLen; k11)
{
суммируйте 1 5 coeffs [k] * состояние [stateIndex];
stateIndex-;

если (stateIndex, 0)
274 Главы 8

{
stateIndex 5 filtLen-1;
}
}

Внутренний цикл обрабатывает образцы путем реализации кольцевого буфера в


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

Рисунок 8.25
Обработка данных в кольцевом буфере требует, чтобы Кора-M4 проверила на конец
буфера на каждом повторении. Это увеличивает время
выполнения.

Выполненный к запуску внутреннего цикла и набора точка останова (Рис. 8.26).

Рисунок 8.26
Установите точку останова в начале внутреннего цикла.

Выполните код, таким образом, он делает одно повторение внутреннего


цикла и отмечает количество используемых циклов.

Круговое обращение требует, чтобы мы выполнили конец буферного теста на


каждом повторении. Выделенное устройство DSP может поддерживать кольцевые
буферы в аппаратных средствах без любых таких издержек, таким образом, это -
одна область, мы должны улучшиться. Путем передачи нашей функции фильтра FIR
блок данных, а не отдельные образцы позволяет нам использовать блок,
обрабатывающий в качестве альтернативы круговому обращению. Это повышает
эффективность на критическом внутреннем цикле (Рис. 8.27).
Практический DSP для коры-M4 и коры-M7 275

Рисунок 8.27
Обработка блока увеличивает размер буфера, но увеличивает
эффективность внутреннего цикла обработки.

Путем увеличения размера буфера состояния к количеству фильтра касается 1


размера блока обработки, мы можем избавить от необходимости круговое обращение.
Во внешнем цикле блок образцов загружается в вершину буфера состояния (Рис.
8.28).

Рисунок 8.28
С обработкой блока буфер фиксированного размера обрабатывается без
потребности проверить на конец буфера.

Внутренний цикл затем выполняет вычисления фильтра для каждого образца блока
путем скольжения окна фильтра, один элемент направо для каждого проходит через
цикл. Таким образом, внутренний цикл теперь становится
для (k 5 0; k, filtLen; k11)

{
суммируйте 1 5 coeffs [k] * состояние [stateIndex];
stateIndex11;

После того как внутренний цикл закончил обрабатывать, текущий блок


демонстрационных данных, сохраненных в буфере состояния, должен быть смещен
направо и новый блок данных, загруженный (Рис. 8.29).
276 Глав 8

Рисунок 8.29
После того как блок данных был обработан, внешний цикл смещает образцы один блок
налево и добавляет новый блок данных.

Теперь шаг во вторую функцию FIR.


Исследуйте, как код был изменен для обработки блоков данных.

Во внешнем цикле существует некоторый дополнительный код, но это только


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

Установите точку останова на том же внутреннем цикле и запишите количество


циклов, которые это берет для выполнения.

Затем, мы можем далее повысить эффективность внутреннего цикла при помощи


приема компилятора, названного “развертыванием цикла”. Вместо того, чтобы
выполнять итерации вокруг цикла для каждого касания, мы можем обработать
несколько касаний в каждом повторении путем встраивания нескольких
вычислений касания на цикл.
Я 5 filtLen.. 2
для (k 5 0; k, filtLen; k11)
{
суммируйте 1 5 coeffs [k] * состояние [stateIndex];
stateIndex11;

суммируйте 1 5 coeffs [k] * состояние [stateIndex];


stateIndex11;

суммируйте 1 5 coeffs [k] * состояние [stateIndex];


stateIndex11;

суммируйте 1 5 coeffs [k] * состояние [stateIndex];


stateIndex11;

}
Теперь шаг в третью функцию феркина.

Установите точку останова на том же внутреннем цикле и запишите количество


циклов, которые это берет для выполнения. Разделите это на четыре и сравните его
с предыдущими реализациями.

Следующий шаг должен использовать инструкции SIMD. Путем упаковки


коэффициента и демонстрационных данных в 32-разрядные слова, единственные
MAC могут быть заменены двойным MAC со знаком
Практический DSP для коры-M4 и коры-M7 277

который позволяет нам расширять развертывание цикла с четырех суммирования


до восемь для того же количества циклов.
для (k 50; k, filtLen; k11)
{
суммируйте 1 5 coeffs [k] * состояние [stateIndex];
stateIndex11;

суммируйте 1 5 coeffs [k] * состояние [stateIndex];


stateIndex11;

суммируйте 1 5 coeffs [k] * состояние [stateIndex];


stateIndex11;

суммируйте 1 5 coeffs [k] * состояние [stateIndex];


stateIndex11;

Шаг в четвертый феркин функционирует и снова вычисляет количество циклов,


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

Помните, что мы теперь вычисляем восемь суммирования, поэтому разделите


необработанное количество цикла цикла на восемь.

Для сокращения количества цикла внутреннего цикла еще больше мы можем


расширить развертывание цикла для вычисления нескольких результатов
одновременно (Рис. 8.30).
Рисунок 8.30
Супер развертывание цикла расширяет развертывание цикла для обработки нескольких
выходных образцов одновременно.
278 Глав 8

Это - своего рода “супер развертывание цикла”, где мы выполняем каждое


из вычислений внутреннего цикла для блока данных в одной передаче.
демонстрационные 5
blockSize/4;
сделать

{
sum0 5 sum1 5 sum2 5 sum3 5 0;
statePtr 5 stateBasePtr; coeffPtr 5 (q31_t
*) (S-.coeffs); x0 5 * (q31_t *)
(statePtr11);

x1 5 * (q31_t *) (statePtr11); я 5
numTaps.. 2;
сделать
{
c0 5 * (coeffPtr11);
x2 5 * (q31_t *) (statePtr11);
x3 5 * (q31_t *) (statePtr11); sum0 5
__ SMLALD (x0, c0, sum0); sum1 5 __
SMLALD (x1, c0, sum1); sum2 5 __
SMLALD (x2, c0, sum2); sum3 5 __
SMLALD (x3, c0, sum3); c0 5 *
(coeffPtr11);
x0 5 * (q31_t *) (statePtr11);
x1 5 * (q31_t *) (statePtr11); sum0 5 __
SMLALD (x0, c0, sum0); sum1 5 __
SMLALD (x1, c0, sum1); sum2 5 __
SMLALD (x2, c0, sum2); sum3 5 __
SMLALD (x3, c0, sum3);
}, в то время как (-i);
*pDst11 5 (q15_t) (sum0.. 15); *pDst11
5 (q15_t) (sum1.. 15); *pDst11 5 (q15_t)
(sum2.. 15); *pDst11 5 (q15_t) (sum3..
15);

stateBasePtr 5 stateBasePtr 1 4;}, в то


время как (-образец);

Теперь шаг в заключительный FIR функционирует и снова вычисляет количество


циклов, используемых внутренним циклом на касание.

На этот раз мы вычисляем восемь суммирования для четырех касаний


одновременно; это приносит нам близко к одному циклу на касание, которое
сопоставимо с выделенным устройством DSP.

В то время как можно кодировать алгоритмы DSP в “C” и получить разумную


производительность, эти виды оптимизации необходимы для получения уровней
производительности, сопоставимых с выделенным устройством DSP. Этому виду
разработки кода нужен опыт Cortex-M4/M7 и алгоритмы DSP, которые Вы хотите
реализовать. К счастью, ARM обеспечивает свободную библиотеку DSP, уже
оптимизированную для процессоров Cortex-M.
Практический DSP для коры-M4 и коры-M7 279

Библиотека CMSIS-DSP
В то время как возможно кодировать все Ваши собственные функции DSP, это может
быть трудоемким и требует большого зависящего от домена знания. Чтобы помочь
добавить общие функции DSP к Вашему приложению, ARM опубликовал библиотеку
61 общей функции DSP, которые составляют CMSIS-DSP (Стандартная Обработка
цифровых сигналов Программного интерфейса Микроконтроллера Коры)
спецификация. Каждая из этих функций оптимизирована для Cortex-M4/M7, но может
также быть скомпилирована для работы Коры-M3 и даже на Коре-M0. Библиотека
CMSIS-DSP является бесплатной загрузкой и лицензируется для использования в
любом коммерческом или некоммерческом проекте. Библиотека CMSIS-DSP также
включена как часть установки MDK-ARM и просто должна быть добавлена к Вашему
проекту путем выбора CMSIS:: опция DSP в менеджере по Среде выполнения (RTE).
Установка включает предварительно созданную библиотеку для каждого из
процессоров Cortex-M и всего исходного кода.

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


может открытый из окна “Manage Run-Time Environment” (рисунок 8.31).

Рисунок 8.31
Документация CMSIS-DSP, к которой получают доступ путем нажимания на
ссылку описания, доступную в окне Manage Run-Time
Environment.

Библиотечные функции CMSIS-DSP


Библиотека CMSIS-DSP обеспечивает простые в использовании функции для обычно
используемых алгоритмов обработки сигналов. Функции, включенные в библиотеку,
показывают в Таблице 8.11.
280 Глав 8

Таблица 8.11: библиотечные функции CMSIS-DSP

Основные функции математики Матричные функции


Векторное умножение Матричная инициализация
Векторное вычитание Сложное умножение матриц
Векторное дополнение Матричное дополнение
Векторный масштаб Матричное вычитание
Векторный сдвиг Умножение матриц
Векторное смещение Матричная инверсия
Вектор инвертирует Матрица транспонирует
Векторный абсолют Матричный масштаб
Векторное скалярное произведение Преобразовывает
Быстрые функции математики Сложные функции FFT
Косинус Реальные функции FFT
Синус Тип DCT функции IV
Квадратный корень Функции контроллера
Сложные функции математики Косинус синуса
Блок управления приводом
Сопряженное комплексное число PID
Векторный парк
Сложное скалярное произведение преобразовывает
Векторный обратный парк
Сложная величина преобразовывает
Вектор Clarke
Сложная величина придала квадратную форму преобразовывает
Векторная инверсия Clarke
Комплекс сложным умножением преобразовывает
Комплекс реальным умножением Статистические функции
Фильтры Питание
Среднеквадратичное
Свертка значение
Частичная свертка Стандартное отклонение
Корреляция Различие
Конечный фильтр импульсной характеристики Максимум
Конечная импульсная характеристика decemator Минимум
Конечный фильтр решетки импульсной
характеристики Средний
Импульсная характеристика Бога образовывает
решетку фильтр Функции поддержки
Конечная импульсная характеристика редкий
фильтр Векторная копия
Конечная интерполяция фильтра импульсной
характеристики Векторная заливка
Преобразуйте 8-разрядное
Каскадный фильтр высокой точности Q31 Biquad целочисленное значение
Biquad располагают каскадом БИХ-фильтр с Преобразуйте 16-разрядное
помощью прямой формы, которую я структурирую целочисленное значение
Biquad располагают каскадом БИХ-фильтр с Преобразуйте 32-разрядное
помощью прямой формы II целочисленное значение
транспонированная структура
Наименьшее количество средних квадратичных Преобразуйте 32-разрядное
фильтр FIR плавание
значение точки
Наименьшее количество средних квадратичных
нормализовало фильтр FIR Функции интерполяции
Линейный интерполируют
функцию
Билинейный интерполируют
функцию

Упражнение 8.3 Пользование библиотекой CMSIS-DSP


В этом проекте у нас будет первый взгляд на пользование библиотекой CMSIS-
DSP путем установки проекта экспериментировать с алгоритмом управления
Пропорциональной интегральной производной (PID) (Рис. 8.32).
Практический DSP для коры-M4 и коры-M7 281

Рисунок 8.32
Контур управления PID состоит из пропорциональных, интеграла и производных
блоков управления.

Откройте установщик пакета.


Выберите Советы:: разработчики ведут учебное руководство.
Выберите вкладку Example и Копию “EX 8.3 CMSIS-DSP PID” (Рис. 8.33).

Рисунок 8.33
Проект PID в качестве примера настроен с DSP, добавленным как компонент
программного обеспечения CMSIS.

Проект предназначен для Коры-M4 с FPU. Это включает запуск CMSIS и системные
файлы для Коры-M4 и функций CMSIS-DSP как предварительно скомпилированная
библиотека. Библиотека CMSIS-DSP расположена в c:\CMSIS\lib with subdirectories for
the ARM compiler and GCC versions of the library (Fig. 8.34).

Рисунок 8.34
Библиотека CMSIS-DSP добавляется к проекту как компонент программного
обеспечения в RTE.
282 Главы 8

Существуют предварительно скомпилированные версии библиотеки DSP для


каждого процессора Cortex. Существует также версия библиотеки для Коры-M4 с и
без FPU. Для нашего проекта была добавлена библиотека операций с плавающей
точкой Коры-M4.
Откройте project\Options для Целевого диалогового окна (Рис. 8.35).

Рисунок 8.35
FPU включен в настройках Project Target.

В этом примере мы используем имитационную модель для процессора Cortex-M4


только. 512K регион памяти был определен для кода и данных. FPU включен, и
тактовая частота ЦП была установлена на 100 МГц (Рис. 8.36).

Рисунок 8.36
FPU должен быть включен кодом запуска.

На вкладке параметров компилятора _FPU_PRESENT определяют, установлен на


одного. Обычно Вы не должны будете настраивать эту опцию, поскольку это будет
сделано в микроконтроллере, включают файл.
Практический DSP для коры-M4 и коры-M7 283

Мы также должны добавить #define для конфигурирования заголовочного файла


DSP для процессора, который мы используем. Библиотека определяет:
ARM_MATH_CM4
ARM_MATH_CM3
ARM_MATH_CM0

Исходный код для библиотеки расположен в C:\keil\arm\CMSIS\DSP_Lib\Source.


Откройте файл pid_example_f32.c, который содержит код приложения.
Для доступа к библиотеке мы должны добавить ее заголовочный файл к нашему коду.
#include “arm_math.h”

Этот заголовочный файл расположен в c:\keil\arm\cmsis\include.

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


библиотеке DSP имеют два вызова функции: функция инициализации и функция
процесса.
освободите arm_pid_init_f32 (arm_pid_instance_f32 *S, int32_t resetStateFlag) __,
STATIC_INLINE освобождают arm_pid_f32 (arm_pid_instance_f32 *s, float32_t в)

Функция инициализации передается конфигурационная структура, которая уникальна


для алгоритма. Конфигурационная структура содержит константы для алгоритма,
полученных значений, и выстраивает для памяти состояния. Это позволяет нескольким
экземплярам каждой функции быть созданными.
структура определения
типа
{
float32_t A0; / **, полученное усиление, A0 5 Kp 1 Ki 1 Kd. */
float32_t A1; / **, полученное усиление, A1 5 - Kp - 2Kd. */
float32_t A2; / **, полученное усиление, A2 5 Kd. */
состояние float32_t [3]; / **, массив состояния длины 3. */
float32_t Kp; / **, пропорциональное усиление. */
float32_t Ki; / **, интегральное усиление. */
float32_t Kd; / **, производное усиление. */
} arm_pid_instance_f32;

Конфигурационная структура PID позволяет Вам определять значения для


пропорционального, интеграла и производных усилений. Структура также включает
переменные для полученных усилений A0, A1, и A2, а также небольшой массив для
содержания локальных переменных состояния.
int32_t, основной (пустота) {
интервал i; S.Kp 5 1; S.Ki 5 1; S.Kd 5 1;
заданное значение 5 10;
arm_pid_init_f32 (&S, 0);
в то время как (1) {
ошибка 5 заданных-значений-motorOut;
motorIn 5 arm_pid_f32 (&S, ошибка);
motorOut 5 transferFunction (езда на автомобиле, время);
284 Главы 8

время 1 5 1;
для (я 5 0; я, 100000; i11);
}}

Код приложения устанавливает значения усиления PID и инициализирует функцию


PID. Основной цикл вычисляет ошибочное значение прежде, чем вызвать функцию
процесса PID. Вывод PID питается в моделируемую аппаратную функцию
передачи. Вывод функции передачи возвращен в ошибочное вычисление для
закрытия обратной связи. Переменная времени обеспечивает псевдопривязку по
времени.
Разработайте проект и запустите отладчик.
Добавьте ключевые переменные к Анализатору логики и запустите код,
выполняющий (Рис. 8.37).

Рисунок 8.37
Анализатор логики неоценим для визуализации сигналов в реальном
времени.

Анализатор логики неоценим для визуализации данных в алгоритме в реальном


времени и может использоваться в средстве моделирования или может собрать
данные от единицы трассировки часов данных CoreSight, поскольку мы видели в
Главе 7 “Отладку с CoreSight”.
Эксперимент со значениями усиления для настройки функции PID.

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


корректировки значений усиления. Как грубое руководство, каждое из значений
усиления имеет следующий эффект:
Kp Производит время нарастания сигнала управления.
Ki Effects установившаяся ошибка сигнала управления.
Kd Производит проскакивание сигнала управления.
Практический DSP для коры-M4 и коры-M7 285

Методы обработки данных DSP


Одна из основных проблем приложения DSP управляет потоком данных из датчиков
и Аналого-цифрового преобразователя (ADC) через алгоритм DSP, и отступите к
реальному миру через Цифро-аналоговый преобразователь (DAC) (Рис. 8.38).

Рисунок 8.38
Типичная система DSP состоит из аналогового демонстрационного этапа,
микроконтроллера с алгоритмом DSP и вывода DAC. В этой главе, мы программное
обеспечение микроконтроллера в изоляции от аппаратного дизайна.

В типичной системе каждое выбранное значение является дискретным значением в


моменте времени. Частота дискретизации должна быть по крайней мере дважды
пропускной способностью сигнала или до четырех раз пропускной способностью для
высококачественной сверхдискретизированной аудиосистемы. Очевидно объем
данных собирается расти очень быстро, и это становится основной проблемой
обработать данные в режиме реального времени. С точки зрения обработки
выборочных данных существует два основных подхода, потоковая обработка или
обработка блока (Рис. 8.39).

Рисунок 8.39
Аналоговые данные могут быть обработаны как единственные образцы с
минимальной задержкой или как блок образцов для
максимальной эффективности обработки.

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


Это дает самую низкую задержку сигнала и также минимальные требования к
памяти. Однако это имеет недостаток создания более сложного алгоритма DSP.
Алгоритм DSP должен быть
286 Глав 8

работайте каждый раз, когда преобразование ADC сделано, который может вызвать
проблемы с другими первоочередными процедурами прерывания. Альтернатива
потоковой обработке является обработкой блока. Здесь, много результатов ADC
хранятся в буфере, обычно приблизительно 32 образца, и затем этот буфер
обрабатывается алгоритмом DSP как блок данных. Это понижает количество раз,
которое должен выполнить алгоритм DSP. Как мы видели в осуществлении
оптимизации, существует много методов, которые могут повысить эффективность
алгоритма при обработке блока данных. Блок, обрабатывающий также, интегрирует
хорошо с микроконтроллером единицу DMA и RTOS. На оборотной стороне
обработка блока представляет больше задержки сигнала и требует большего
количества Флэш-памяти, чем потоковая обработка. Для большинства приложений
обработка блока должна быть предпочтительным маршрутом.

Упражнение 8.4 Фильтр FIR с обработкой блока


В этом осуществлении мы реализуем фильтр FIR, на этот раз при помощи функций
CMSIS-DSP. Это осуществление использует тот же шаблон проекта в качестве
программы PID. Характеристики фильтра определяются коэффициентами фильтра.
Возможно вычислить содействующие значения вручную или при помощи средства
проектирования. Вычисление коэффициентов выходит за рамки этой книги, но
приложения перечисляют некоторые превосходные средства проектирования и книги
DSP для дополнительных материалов для чтения.
Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Выберите вкладку Example и Копию “EX 8.4 CMSIS-DSP FIR” (Рис. 8.40).
Рисунок 8.40
Проект FIR имеет сборки для Коры-M7, M4 и M3.
Практический DSP для коры-M4 и коры-M7 287

Существует дополнительный файл данных, который содержит набор выборочных


данных и дополнительный math_helper. “C” файл, который содержит некоторые
вспомогательные функции.
int32_t, основной (пустота)
{
uint32_t i; arm_fir_instance_f32
S; состояние arm_status;

float32_t *inputF32, *outputF32;


/* Инициализируйте входные и выходные буферные
указатели */inputF32 5 &testInput_f32_1kHz_15kHz [0];
outputF32 5 &testOutput[0];

/* Назовите FIR init функцией для инициализации структуры экземпляра. */arm_fir_init_f32 (&S,
NUM_TAPS, (float32_t *) &firCoeffs32[0], &firStateF32[0],
blockSize);
для (я 50; я, numBlocks; i11)
{
arm_fir_f32 (&S, inputF32 1 (я * blockSize), outputF32 1 (я * blockSize), blockSize);
}
snr 5 arm_snr_f32 (&refOutput[0], &testOutput[0], TEST_LENGTH_SAMPLES); если (SNR,
SNR_THRESHOLD_F32)
{
состояние 5
ARM_MATH_TEST_FAILURE;} еще {
состояние 5 ARM_MATH_SUCCESS;
}

Код сначала создает экземпляр фильтра FIR с 29 касаниями. Размер блока обработки
составляет 32 байта. Массив состояния FIR также создается для содержания значений
рабочего состояния для каждого касания. Размер этого массива вычисляется как
“размер блока 1 количество касаний 2 1”. После того как фильтр был
инициализирован, мы можем передать его демонстрационным данным в 32-байтовых
блоках и хранить получающиеся обработанные данные в выходном массиве.
Фильтрованный результат финала затем по сравнению с предрасчетным результатом.
Разработайте проект и запустите отладчик.
Шаг через проект исследовать код.
Поиск функции CMSIS-DSP используется в документации справки.
Установите точку останова в конце проекта (Рис. 8.41).
288 Глав 8

Рисунок 8.41
Установите точку останова на финале в то время как () цикл.

Сбросьте проект и выполните код, пока он не поразит точку останова.


Теперь посмотрите на количество цикла в окне Registers (Рис. 8.42).

Рисунок 8.42
Используйте состояния окон регистра в противоречии с монитором количество
выполняемых циклов.

Откройте проект в c:\exercises\CMSIS _FIR\CM3.


Это - тот же проект, разработанный для Коры-M3.
Разработайте проект и запустите отладчик.

Установите точку останова в том же месте как предыдущий пример


Коры-M4. Сбросьте проект и выполните код, пока он не поразит точку
останова.
Теперь сравните количество цикла, привыкшее Корой-M3 к версии Коры-M4 (Рис.
8.43).
Рисунок 8.43
Сравните количество цикла Коры-M3 с Корой-M4.
Практический DSP для коры-M4 и коры-M7 289

При использовании чисел с плавающей точкой Кора-M4 почти и порядок


быстрее, чем библиотеки операций с плавающей точкой программного
обеспечения использования Коры-M3. При использовании математики
фиксированной точки Кора-M4 все еще имеет значительное преимущество
перед Корой-M3 (Рис. 8.44).

Рисунок 8.44
Гистограммы показывают сравнение между Корой-M3 и Корой-M4 для общих
алгоритмов DSP.

DSP фиксированной точки с числами Q


Функции в библиотеке DSP поддерживают данные и фиксированной точки с
плавающей точкой. Данные фиксированной точки сохранены в числовом формате Q.
Q числа фиксированная точка дробные числа, сохраненные в целочисленных
переменных. Числу Q следовало за знаковым битом постоянное число битов для
представления целочисленного значения. Остающиеся биты представляют дробную
часть числа.
Подписанный 5 S IIIIIIIIII.FFFFF

Число Q определяется как число битов в целочисленной части переменной и число


битов в дробной части переменной. Подписанные числа Q хранятся как значения
комплимента пар. Число Q обычно упоминается числом дробных битов, оно
использует так Q10, имеет 10 дробных мест. Библиотечные функции CMSIS-DSP
разработаны для взятия входных значений между 11 и 21. Поддерживаемые
целочисленные значения показывают в Таблице 8.12.

Таблица 8.12: производительность Сопроцессора для


операций с плавающей точкой

Определение типа CMSIS-DSP Q число


Q31_t Q31
Q15_t Q15
Q7_t Q7
290 Глав 8

Библиотека включает группу функций преобразования для изменения между числами


с плавающей точкой и целым числом Q чисел. Функции поддержки также
обеспечиваются для преобразования между различными разрешениями числа Q
(Таблица 8.13).

Таблица 8.13: функции преобразования типов CMSIS-DSP


arm_float_to_q31 arm_q31_to_float arm_q15_to_float arm_q7_to_float
arm_float_to_q15 arm_q31_to_q15 arm_q15_to_q31 arm_q7_to_q31
arm_float_to_q7 arm_q31_to_q7 arm_q15_to_q7 arm_q7_to_q15

Как пример реального мира можно выбирать данные с помощью 12-разрядного ADC,
который дает вывод от 1 0xFFF. В этом случае мы должны были бы масштабировать
результат ADC, чтобы быть между 11 и 21 и затем преобразовать в число Q.
Q31_t ADC_FixedPoint;
временный файл
плавающий;

Считайте регистр ADC в переменную плавающую. Масштаб между 11 и 21


работайте временно 5 ((float32_t) ((ADC_DATA_REGISTER) и 0xFFF) / (0xFFF / 2)) - 1;

Преобразуйте значение плавающее в фиксированную точку значение Q31.


arm_float_to_q31 (&ADC_FixedPoint, &temp, 1);

Точно так же после того, как функция DSP работала, необходимо преобразовать
назад в значение с плавающей точкой перед использованием результата. Здесь, мы
преобразовываем от результата Q31 до 10-разрядного целочисленного значения до
вывода значения к периферийному устройству DAC.
arm_q31_to_float (&temp, &DAC_Float, 1); DAC_DATA_REGISTER 5
(((uint32_t) ((DAC_Float))) и 0x03FF);

Упражнение 8.5 Фиксированная точка FFT преобразовывает


В этом проекте мы будем использовать Быстрое преобразование Фурье для анализа
сигнала.
Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Выберите вкладку Example и Копию “EX 8.5 CMSIS-DSP FFT” (Рис. 8.45).
Практический DSP для коры-M4 и коры-M7 291

Рисунок 8.45
Проект настроен для Коры-M4. Данные сигнала включены в arm_fft_bin_data.c файл.

Проект FFT использует тот же шаблон в качестве примера PID с добавлением файла
данных, который содержит массив демонстрационных данных. Эти данные являются
сигналом на 10 кГц плюс случайный “белый шум”.
int32_t, основной (пустота) {arm_status
состояние;

arm_cfft_radix4_instance_q31 S; q31_t
maxValue;
состояние 5 ARM_MATH_SUCCESS;
/* Преобразуйте значения с плавающей точкой формат */arm_float_to_q31
фиксированной точки Q31 (testInput_f32_10khz, testInput_q31_10khz, 2048);/*
Инициализируют модуль CFFT/CIFFT */

состояние 5 arm_cfft_radix4_init_q31 (&S, fftSize, ifftFlag, doBitReverse);/* Обрабатывают


данные через модуль */arm_cfft_radix4_q31 CFFT/CIFFT (&S, testInput_q31_10khz);

/* Обработайте данные через Сложный Модуль Величины для вычисления


величины в каждом мусорном ведре */arm_cmplx_mag_q31 (testInput_q31_10khz,
testOutput, fftSize);/* Вычисляет maxValue и возвращает соответствующий
*/arm_max_q31 значения МУСОРНОГО ВЕДРА (testOutput, fftSize, &maxValue,
&testIndex); если (testIndex! 5 refIndex)

{
состояние 5 ARM_MATH_TEST_FAILURE;
}

Код инициализирует сложный FFT, преобразовывают с размером блока 1 024


выходных мусорных ведер. Когда функция FFT вызвана, демонстрационный набор
данных сначала преобразовывается в фиксированную точку формат Q31 и затем
передается преобразованию как один блок. Затем комплексный выход
преобразовывается в скалярную величину и затем сканируется для нахождения
максимального значения. Наконец, мы сравниваем это значение с ожидаемым
результатом.
Работа через код проекта и ищет используемые функции CMSIS-DSP.

Примечание: В FFT преобразовывают, количество выходных мусорных ведер


будет половиной размера демонстрационного размера данных.
Разработайте проект и запустите отладчик.
292 Главы 8

Выполните функцию кода функцией и запишите время выполнения, требуемое


выполнить функции DSP.

Заключение
В этой главе мы посмотрели на расширения DSP, включенные в Cortex-M4/M7 и как
лучше всего использовать эти функции в реальном приложении. Библиотека CMSIS-
DSP обеспечивает много общих функций DSP, которые были оптимизированы для
Cortex-M4/M7. В Главе 10 “Методы RTOS”, мы посмотрим на то, как интегрировать
непрерывную обработку DSP в реальном времени и управляемый событиями код
микроконтроллера в тот же проект.
CHPTER9

Программный интерфейс
микроконтроллера коры
Стандартная операционная система
реального времени

Введение
Эта глава является введением в использование маленькой операционной системы
реального времени (RTOS) места на микроконтроллере Cortex-M. Поскольку мы видели в
Главе 4 “Стандарт программного интерфейса микроконтроллера коры (CMSIS)”,
определяет стандартный API для Cortex-M RTOS. Если Вы привыкли писать процедурный
код “C” маленького 8-/16-bit микроконтроллеры, можно сомневаться о потребности в
такой операционной системе. Если Вы не знакомы с использованием RTOS в режиме
реального времени встроенные системы, необходимо прочитать эту главу прежде, чем
отвергнуть идею. Использование RTOS представляет более сложный подход дизайна, по
сути способствуя структурированной разработке кода, которая осуществляется
интерфейсом прикладного программирования (API) RTOS.

Структура RTOS позволяет Вам проявлять более ориентируемый на объект подход


дизайна при тихом программировании в “C”. RTOS также предоставляет Вам
многопоточную поддержку на маленьком микроконтроллере. Эти две функции на
самом деле создают настоящий сдвиг в принципах проектирования, отодвигая нас от
размышления о процедурных кодовых таблицах “C” и блок-схемах. Вместо этого мы
рассматриваем фундаментальные потоки программы и поток данных между ними.
Использование RTOS также обладает несколькими дополнительными
преимуществами, которые не могут быть сразу очевидными. Так как основанный на
RTOS проект состоит из четко определенных потоков, он помогает улучшить
управление проектами, повторное использование кода и тестирование программного
обеспечения.

Компромисс для этого - то, что RTOS имеет дополнительные требования к памяти и
увеличенную задержку прерывания. Как правило, Keil RTX RTOS будет требовать
500 байтов RAM и 5k байтов кода, но помнить, что часть кода RTOS копировалась
бы в Вашей программе так или иначе. У нас теперь есть поколение маленьких
недорогих микроконтроллеров, которые имеют достаточно памяти на микросхеме и
вычислительной мощности для поддержки использования RTOS. Разработка
использующий этот подход поэтому намного более доступна.
В этой главе мы сначала посмотрим на установку вводного проекта RTOS для
основанного на Cortex-M микроконтроллера. Затем, мы пройдем каждый из
примитивов RTOS и как они влияют на дизайн нашего кода приложения. Наконец,
когда у нас есть ясное понимание функций RTOS, мы более тщательно изучим
параметры конфигурации RTOS. Если Вы привыкли программировать
микроконтроллер, не используя RTOS, который является чистым металлом, там

Руководство разработчика по семейству процессоров Cortex-M.


DOI: http://dx.doi.org/10.1016/B978-0-08-100629-0.00009-8 293
© 2016 Elsevier Ltd. Все права защищены.
294 Главы 9

две ключевых вещи состоят в том, чтобы понять, поскольку Вы работаете через этот
учебный Параллелизм и синхронизацию. В следующих разделах мы сфокусируемся
на создании и управлении потоками. Ключевое понятие здесь состоит в том, чтобы
рассмотреть их работающий как параллельные параллельные объекты. В разделе
“Inter-Thread Communication” мы посмотрим на то, как связаться между потоками. В
этом разделе ключевое понятие является синхронизацией параллельных потоков.

Первые шаги с CMSIS-RTOS


Сам RTOS состоит из планировщика (Рис. 9.1), который поддерживает циклический
алгоритм, приоритетную, и кооперативную многозадачность потоков программы, а
также услуги по управлению памятью и тайм-менеджмент. Коммуникация межпотока
поддерживается дополнительными объектами RTOS, включая инициирование
сигнала, семафоры, взаимное исключение и систему почтового ящика. Поскольку мы
будем видеть в Главе 10 “Методы RTOS”, обработка прерываний может также быть
выполнена расположенными по приоритетам потоками, которые планируются ядром
RTOS.

Рисунок 9.1
Ядро RTOS содержит планировщик, который выполняет код программы как задачи.
Коммуникация между задачами выполняется объектами RTOS, такими как события,
семафоры, взаимные исключения и почтовые ящики.
Дополнительные сервисы RTOS включают тайм-менеджмент и управление
памятью и прерывают поддержку.

Доступ к API CMSIS-RTOS


Для доступа к любой из функций CMSIS-RTOS в нашем коде приложения,
необходимо включать следующий заголовочный файл:
#include, cmsis_os.h.
Этот заголовочный файл сохраняется ARM как часть стандарта CMSIS-RTOS. Для
Keil RTX RTOS это - API по умолчанию. Другой RTOS будет иметь их собственный
API, но может обеспечить слой обертки для реализации API CMSIS-RTOS, таким
образом, они смогут использоваться, где совместимость со стандартом CMSIS
требуется.
Стандартная Операционная система реального времени программного
интерфейса микроконтроллера коры 295

Потоки
Стандартные блоки типичной программы “C” являются функциями, которые мы
вызываем для выполнения конкретной процедуры и которые затем возвращаются к
функции вызова. В CMSIS-RTOS основная единица выполнения является “потоком”.
Поток очень похож на процедуру “C”, но имеет некоторые очень принципиальные
различия.
неподписанная международная процедура (пусто) освобождает поток (пусто)
{ {
в то время как (1)
. . .. . . {
. . .. . .
возвратитесь (ch); }
} }

В то время как мы всегда возвращаемся из нашей функции “C”, когда-то запустился,


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

Программа RTOS составлена из многих потоков, которыми управляет планировщик


RTOS. Этот планировщик использует таймер SysTick для генерации периодического
прерывания как основы времени. Планировщик выделит определенное количество
времени выполнения к каждому потоку. Таким образом, thread1 будет работать за 5
миллисекундами затем быть de-scheduled, чтобы позволить thread2 работать в течение
подобного периода; thread2 будет уступать thread3 и наконец управлять, пасует назад
к thread1. Путем выделения этих частей времени выполнения к каждому потоку
циклическим способом мы получаем появление всех трех потоков, работающих
параллельно друг другу.

Концептуально, мы можем думать о каждом потоке как о выполнении определенного


функционального блока нашей программы со всеми потоками, работающими
одновременно. Это приводит нас к более ориентируемому на объект дизайну, где
каждый функциональный блок может быть кодирован и протестирован в изоляции и
затем интегрирован в полностью запускающую программу. Это не только налагает
структуру на дизайн нашего заключительного приложения, но также и отладку
средств, поскольку конкретная ошибка может быть легко изолирована к
определенному потоку. Это также помогает повторному использованию кода в более
поздних проектах. Когда поток создается, он также выделяется его собственный
идентификатор потока. Это - переменная, которая действует как дескриптор для
каждого потока и используется, когда мы хотим справиться с действием потока.
osThreadId id1, id2, id3;
Чтобы заставить процесс коммутации потока произойти, у нас есть код наверху RTOS, и
мы должны выделить аппаратный таймер ЦП для обеспечения привязки по времени
RTOS. Кроме того, каждый раз, когда мы переключаем рабочие потоки, мы должны
сохранить состояние всех переменных потока к стопке потока. Кроме того, вся
информация о выполнении о потоке хранится в блоке управления потока, которым
управляет ядро RTOS. Таким образом “время контекстного переключения”, то есть, время,
чтобы накопить состояние текущего потока и загрузиться и запустить следующий поток,
является решающим числом и будет зависеть и от ядра RTOS и от дизайна используемого
оборудования.
296 Глав 9

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

Блок управления Потока (Рис. 9.2) содержит информацию о состоянии потока. Часть
этой информации является своим состоянием выполнения. В данной системе только
один поток может работать и все, что другие будут временно отстранены, но готовы
выполнить. RTOS имеет различные методы коммуникации межпотока (сигналы,
семафоры, сообщения). Здесь, поток может быть приостановлен для ожидания, чтобы
быть сообщенным другим потоком или прерыванием, прежде чем это возобновит свое
состояние готовности, после чего это может быть помещено в состояние выполнения
планировщиком RTOS (Таблица 9.1).

Таблица 9.1: Потоки могут быть в одном из трех состояний


Выполнени
е В настоящее время рабочий поток
Готовый Потоки, готовые работать
Ожидать Заблокированные потоки, ожидающие события OS
Остающиеся потоки будут готовы работать и будут запланированы ядром. Потоки могут также
ожидать, ожидая событие OS. Когда это произойдет, они возвратятся к состоянию готовности и будут
запланированы ядром.

Запуск RTOS
Для создания простой программы RTOS, мы объявляем каждый поток, как
стандарт “C” функционирует и также объявляет идентификационную переменную
потока для каждой функции.
освободите thread1
(пусто); освободите
thread2 (пусто);
osThreadId thrdID1, thrdID2;

По умолчанию планировщик CMSIS-RTOS будет работать, когда основной () будет


введен и основное (), функция становится первым активным потоком. Однажды в
основном (), мы можем остановить планировщик
Стандартная Операционная система реального времени программного
интерфейса микроконтроллера коры 297

поток, переключающийся путем вызова osKernelInitialize (). В то время как RTOS


останавливается, мы можем создать дальнейшие потоки и другие объекты RTOS.
После того как система находится в определенном состоянии, мы можем
перезапустить планировщик RTOS с osKernelStart ().
Можно выполнить любой код инициализации, который Вы хотите прежде, чем
запустить RTOS.
освободите основной (пустота)
{
osKernelInitialize ();
IODIR1 5 0x00FF0000; //Делают любой код C, который Вы хотите
Init_Thread (); //Создают Поток
osKernelStart (); //Запускают RTOS
}

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


потоков, готовых работать, и у них всех есть тот же приоритет, то они будут
выделены время выполнения циклическим способом. Однако, если поток с более
высоким приоритетом станет готовым работать, то планировщик RTOS будет de-
расписание в настоящее время рабочий поток и запускать высокоприоритетное
выполнение потока. Это называют упреждающим основанным на приоритете
планированием. При присвоении приоритетов необходимо быть осторожными,
потому что высокоприоритетный поток продолжит работать, пока он не введет
состояние ожидания или пока поток равного или более высокого приоритета не готов
работать (Рис. 9.3).

Рисунок 9.3
Потоки равного приоритета будут запланированы циклическим способом.
Высокоприоритетные задачи вытеснят низкоприоритетные задачи и
введут состояние выполнения “по требованию”.
Упражнение 9.1 первый проект CMSIS-RTOS
Этот проект возьмет Вас через шаги, необходимые, чтобы создать и отладить CMSIS-
RTOS-based проект. Мы создадим этот проект с нуля — справочный пример включен
как пример 9.1 в пакете в качестве примера.
Запустите µVision и избранный Проект - Новый Проект µVision (Рис. 9.4).
298 Глав 9

Рисунок 9.4
Создайте новый проект.

В новом диалоговом окне проекта вводят подходящее название проекта и каталог и


нажимают Save.

Затем база данных устройства откроется. Перейдите до STMicroelectronics::


STM32F103:STM32F103RB (Рис. 9.5).

Рисунок 9.5
Выберите микроконтроллер.

После того как Вы выбрали это устройство, нажимают "OK".

После того как вариант микроконтроллера был выбран, менеджер по Среде


выполнения откроется (Рис. 9.6).
Стандартная Операционная система реального времени программного
интерфейса микроконтроллера коры 299

Рисунок 9.6
Добавьте RTOS.

Это позволяет Вам настраивать платформу компонентов программного обеспечения,


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

Для конфигурирования проекта для использования с CMSIS-RTOS Keil RTX


просто отметьте CMSIS:: RTOS (API): поле Keil RTX (Рис. 9.7).

Рисунок 9.7
Элементы столбца Sel. становятся оранжевыми (светло-серый в печатной
версии). RTOS требует, чтобы другие компоненты
были добавлены.

Это заставит рамку выделения поворачивать оранжевое подразумевать, что


требуются дополнительные компоненты. Необходимый компонент будет
отображен в Окне вывода Проверки (Рис. 9.8).
300 Глав 9

Рисунок 9.8
Поле проверки перечисляет недостающие компоненты.

Для добавления недостающих компонентов, можно нажать кнопку Resolve в левом


нижнем угле RTE.

Это добавит код запуска устройства и CMSIS-базовую поддержку. Когда все


необходимые компоненты будут присутствовать, столбец выделения станет зеленым
(Рис. 9.9).

Рисунок 9.9
Нажатие кнопки твердости добавляет недостающие компоненты, и столбец Sel.
становится зеленым (светло-серый в печатной
версии).

Также возможно получить доступ к справочным файлам компонента путем


нажатия на синюю гиперссылку в Столбце описания.

Теперь нажмите кнопку OK, и все выбранные компоненты будут добавлены к


новому проекту (Рис. 9.10).
Стандартная Операционная система реального времени программного
интерфейса микроконтроллера коры 301

Рисунок 9.10
Настроенная платформа проекта.

Компоненты CMSIS добавляются к папкам, отображенным как зеленый ромб.


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

Для наблюдения это открыть файл RTX_Conf_CM.c и у основания окна


редактора выбирает вкладку “Configuration Wizard” (Рис. 9.11).

Рисунок 9.11
Выбор мастера конфигурации.

Нажмите на “Expand All” для наблюдения всех параметров конфигурации как


графический список выбора
(Рис. 9.12).
302 Главы 9

Рисунок 9.12
Параметры конфигурации RTX.

На данный момент не необходимо внести любые изменения здесь, и эти опции


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

Таблица 9.2: конфигурационные файлы Проекта

Имя файла Описание


Startup_STM32F10x_md.s Ассемблерная таблица векторов
C кодируют для инициализации ключевых
System_STM32F10x.c системных периферийных устройств, такой как
синхронизируйте дерево, интерфейс внешней
памяти PLL.
RTE_Device.h Настраивает мультиплексирование контакта
RTX_Conf_CM.c Настраивает Keil RTX

Теперь, когда у нас есть базовая платформа для нашего проекта на месте, мы можем
добавить некоторый пользовательский исходный код, который запустит RTOS и
создаст рабочий поток (Рис. 9.13).
Рисунок 9.13
Добавление исходного модуля.
Стандартная Операционная система реального времени программного
интерфейса микроконтроллера коры 303

Сделать этот щелчок правой кнопкой папка “Source Group 1” и выбор, “Добавляют
новый объект к Source Group 1”.

В Добавлении нового диалогового окна Объекта выбирают “Пользовательский


шаблонный Значок” кода, и в CMSIS раздел выбирает “CMSIS-RTOS 'основная'
функция” и нажимает Add (Fig. 9.14).

Рисунок 9.14
Выбор шаблона CMSIS-RTOS.

Повторите это, но на этот раз выберите “Поток CMSIS-RTOS”.


Это теперь добавит два исходных файла к нашему проекту main.c и thread.c (Рис. 9.15).

Рисунок 9.15
Проект с основным и код потока.
304 Главы 9

Откройте thread.c в редакторе.

Мы посмотрим на определения RTOS в этом проекте в следующем разделе. На


данный момент этот файл содержит две функции Init_Thread (), который используется
для запуска выполнения потока и фактической функции потока.
Скопируйте прототипа функции Init_Thread и затем откройте main.c.

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


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

В main.c добавляют прототип Init_Thread как внешнее объявление и затем


называют его после функции osKernelInitialize как показано ниже.
#define osObjectsPublic
#include "osObjects.h"
интервал экстерна Init_Thread (пусто);//Добавляют эту строку
международное основное (пустота) {
osKernelInitialize ();
Init_Thread (); //Добавляют эту строку
osKernelStart ();
}

Создайте проект (F7).

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


отладчика для выполнения кода без потребности в любом внешнем оборудовании.
Выделите Цель 1 корневая папка, щелкните правой кнопкой, и избранные “Опции для
цели 1”.
Выберите вкладку отладчика.

Это меню находится в двух половинах: левая сторона настраивает средство


моделирования, и правильная половина настраивает аппаратный отладчик.

Установите переключатель Simulator и проверьте, что “Диалоговое окно DLL”


установлен на DARMSTM. DLL с параметром-pSTM32F103RB (Рис. 9.16).
Стандартная Операционная система реального времени программного
интерфейса микроконтроллера коры 305

Рисунок 9.16
Конфигурирование средства моделирования.
Нажмите ОК для закрытия опций для
целевого меню. Запустите отладчик (Ctrl 1
F5).
Это выполнит код до основного.
Откройте Debug - поддержку ОС - система и распараллельте средство просмотра (рис.
9.17).
Рисунок 9.17
Средство просмотра Системы и Потока RTOS.
306 Глав 9

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


В данный момент у нас есть три потока, которые являются основными,
os_idle_demon, и osTimerThread.
Запустите код, выполняющий (F5) (Рис. 9.18).

Рисунок 9.18
Рабочие потоки.

Теперь пользовательский поток создается и основной, завершается.


Выйдите из отладчика.

В то время как этот проект на самом деле не делает ничего, что он


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

Создание потоков
После того как RTOS работает, существует много системных вызовов, которые
используются, чтобы управлять активными потоками. По умолчанию основное ()
функция автоматически создается как первое выполнение потока. В первом примере
мы использовали его для создания дополнительного потока, затем позволяют ему
завершиться путем пробежки закрывающей фигурной скобки. Однако, если мы хотим,
мы можем продолжить использовать основной в качестве потока самостоятельно.
Если мы хотим управлять основной как поток, мы должны получить его
идентификатор потока. Первая функция RTOS, которую мы должны поэтому вызвать,
является osThreadGetId (), который возвращает Идентификационный номер потока в
настоящее время рабочего потока. Это затем хранится в его идентификационном
дескрипторе. Когда мы хотим обратиться к этому потоку в будущих вызовах ОС, мы
используем этот дескриптор, а не имя функции потока.
osThreadId main_id;//создают дескриптор потока, пустой
основной (пустота)

{
/* Прочитайте идентификатор потока основного
*/main_id 5 osThreadGetId потока ();
в то время как (1)
{
. . .. . .. . .
}
}

Теперь, когда у нас есть идентификационный дескриптор для основного, мы могли


создать потоки приложения и затем назвать osTerminate (main_id) для окончания
основного потока. Это - лучший способ закончить поток
Стандартная Операционная система реального времени программного
интерфейса микроконтроллера коры 307

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

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


средства запуска для создания потоков приложения. Это сделано на двух этапах.
Сначала структура потока определяется; это позволяет нам определять рабочие
параметры потока.
osThreadId thread1_id; //распараллеливают дескриптор
освободите thread1 (пустая константа *аргумент); //прототип функции для thread1
osThreadDef (thread1, osPriorityNormal, 1, 0);//распараллеливают структуру определения

Структура потока требует, чтобы мы определили название функции потока, ее


приоритета потока, количества экземпляров потока, который будет создан, и его
размер стека. Мы посмотрим на эти параметры более подробно позже. После того
как структура потока была определена, поток может быть создан с помощью
osThreadCreate () вызов API. Затем поток создается из кода приложения; это часто
делается в основном потоке, но может быть в любой точке в коде.
thread1_id 5 osThreadCreate (osThread (thread1), ПУСТОЙ УКАЗАТЕЛЬ);

Это создает поток и запускает его выполнение. Также возможно передать параметр
потоку, когда это запускается.
uint32_t startupParameter 5 0x23;
thread1_id 5 osThreadCreate (osThread (thread1), startupParameter);

Когда каждый поток создается, ему также присваивают его собственный стек для того,
чтобы хранить данные во время контекстного переключения. Это не должно быть
перепутано с собственной стопкой процессора Cortex; это - действительно блок памяти,
которая выделяется потоку. Размер стека по умолчанию определяется в
конфигурационном файле RTOS (мы будем видеть это позже), и этот объем памяти будет
выделен каждому потоку, если мы не переопределим его для выделения
пользовательского размера. Размер стека по умолчанию будет присвоен потоку, если
значение размера стека в структуре определения потока будет обнулено. При
необходимости потоку можно дать дополнительные ресурсы памяти путем определения
большего размера стека в структуре потока.

osThreadDef (thread1, osPriorityNormal, 1, 0);//присваивают размер стека по умолчанию этому потоку

osThreadDef (thread2, osPriorityNormal, 1, 1024);//присваивают 1 КБ стека к этому потоку

Однако при выделении большего размера стека потоку затем, дополнительная память
должна быть выделена в конфигурационном файле RTOS; снова мы будем видеть это
позже.
Упражнение 9.2 Создание и управление потоками
В этом проекте мы будем создавать и управлять некоторыми дополнительными
потоками. Каждый из созданных потоков переключит контакт GPIO на порте GPIO
B для моделирования высвечивания светодиода. Мы можем затем просмотреть это
действие в средстве моделирования.
308 Глав 9

Откройте установщик пакета.


Выберите Советы:: разработчики ведут учебное руководство.
Выберите вкладку в качестве примера и Копию “EX 9.2 и 9.3 Потоков CMSIS-RTOS”.
Ссылочная копия первого осуществления включена как Упражнение 9.1.
Это установит проект на каталоге по Вашему выбору и откроет проект в µVision.

Откройте менеджер среды выполнения.

В разделе поддержки платы отмечается поле MCBSTM32E:LED. Это добавляет функции


поддержки для управления состоянием банка светодиода на порте Microcontroller's GPIO B
(Рис. 9.19).

Рисунок 9.19
Выбор платы поддерживает компоненты.

Когда RTOS запустится основной () выполнения как поток, и мы создадим два


дополнительных потока. Сначала мы создаем дескрипторы для каждого из потоков
и затем определяем параметры каждого потока. Они включают приоритет, который
поток выполнит в, количество экземпляров каждого потока, который мы создадим
и его размер стека (объем памяти, выделенный ему), нуль указывает, что это будет
иметь размер стека по умолчанию.
osThreadId main_ID, led_ID1, led_ID2; osThreadDef (led_thread2,
osPriorityNormal, 1, 0); osThreadDef (led_thread1,
osPriorityNormal, 1, 0);

Затем в основном () функция два потока создаются.


led_ID2 5 osThreadCreate (osThread (led_thread2), ПУСТОЙ
УКАЗАТЕЛЬ); led_ID1 5 osThreadCreate (osThread (led_thread1),
ПУСТОЙ УКАЗАТЕЛЬ);

Когда поток создается, мы можем передать его в качестве параметра вместо


ПУСТОГО УКАЗАТЕЛЯ, определяют.
Разработайте проект и запустите отладчик.

Запустите выполнение кода и откройте Debug - Поддержку ОС - Система и


Средство просмотра Потока (Рис. 9.20).
Стандартная Операционная система реального времени программного
интерфейса микроконтроллера коры 309

Рисунок 9.20
Рабочие Потоки.

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


подготавливают.
Откройте Debug - поддержку ОС - Event Viewer (рис. 9.21).

Рисунок 9.21
Средство просмотра события показывает историю переключения
потока.

Средство просмотра события показывает выполнение каждого потока как


трассировка против времени. Это позволяет Вам визуализировать действие каждого
потока и получать ощущение суммы процессорного времени, использованного
каждым потоком.
Теперь откройте окно Peripherals - General Purpose IO - GPIOB (Рис. 9.22).
Рисунок 9.22
Периферийное окно показывает светодиодное действие контакта.
310 Глав 9

Наши два светодиодных потока каждый переключают контакт порта GPIO. Оставьте
выполнение кода и наблюдайте, что контакты переключаются в течение нескольких
секунд.

Если Вы не видите, что окна отладки обновляют, проверьте опцию обновления


окна представления / периодическая опция обновления окна отмечается.
освободите led_thread2 (пустая константа *аргумент)
{для (;;) {

LED_On (1);
задержка
(500);
LED_Off (1);
задержка
(500);
}}

Каждый поток вызывает функции для переключения Вовлеченного и прочь и


использует функцию задержки между каждым на и прочь. Несколько важных вещей
происходят здесь. Сначала функция задержки может быть безопасно вызвана каждым
потоком. Каждый поток сохраняет локальные переменные в своем стеке, таким
образом, они не могут быть повреждены никаким другим потоком. Во-вторых, ни один
из потоков не вводит descheduled, ожидающий состояние, это означает, что каждый
работает за его полным выделенным интервалом прежде, чем переключиться на
следующий поток. Поскольку это - простой поток, на который большая часть его
времени выполнения будет проведена в цикле задержки, эффективно тратя впустую
циклы. Наконец между потоками нет никакой синхронизации. Они работают как
отдельные “программы” на ЦП и как мы видим от окна отладки GPIO, переключенные
контакты кажутся случайными.

Управление потоком и приоритет


Когда поток создается, ему присваивают приоритетный уровень. Планировщик RTOS
использует приоритет потока решить, какой поток, как должны планировать, будет
работать. Если много потоков будут готовы работать, то поток с самым высоким
приоритетом будет помещен в состояние выполнения. Если высокоприоритетный
поток станет готовым работать, то он вытеснит рабочий поток более низкого
приоритета. Значительно, высокоприоритетный поток, работающий на ЦП, не
прекратит работать, если он не заблокируется на вызове API RTOS или вытесняется
более высоким приоритетным потоком. Приоритет потока определяется в структуре
потока, и следующие приоритетные определения доступны. Приоритет по умолчанию
является osPriorityNormal (Таблица 9.3).
Таблица 9.3: приоритетные уровни CMSIS-RTOS
Приоритетные уровни CMSIS-RTOS
osPriorityIdle
osPriorityLow
osPriorityBelowNormal
osPriorityNormal
osPriorityAboveNormal
osPriorityHigh
osPriorityRealTime os
PriorityError
Стандартная Операционная система реального времени программного
интерфейса микроконтроллера коры 311

После того как потоки работают, существует небольшое количество системных


вызовов ОС, которые используются для управления рабочими потоками. Также затем
возможно поднять или понизить приоритет потока или от другой функции или из ее
собственного кода.
osStatus osThreadSetPriority (threadID, приоритет); osPriority
osThreadGetPriority (threadID);

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

osStatus 5 osThreadTerminate (threadID1);

Наконец, существует особый случай переключения потока, где рабочий поток


передает управление к следующему готовому потоку того же приоритета. Это
используется для реализации третьей формы планирования названного совместного
переключения потока.
osStatus osThreadYield ();//переключаются на следующий, готовый выполнять поток

Упражнение 9.3 Создание и управление потоками II


В этом осуществлении мы посмотрим на присвоение различных приоритетов к
потокам и также как создать и завершить потоки динамично.
Вернитесь к проекту “Исключая 9.2 и 9.3 Потоками”.
Измените приоритет светодиода Thread2 к Нормальному Вышеупомянутому.
osThreadDef (led_thread2, osPriorityAboveNormal, 1, 0); osThreadDef
(led_thread1, osPriorityNormal, 1, 0);

Разработайте проект и запустите отладчик.


Запустите выполнение кода.
Откройте окно Debug - OS Support - Event Viewer (Рис. 9.23).
Рисунок 9.23
Только led_thread2 работает.
312 Глав 9

Здесь мы видим, что thread2 работает, но никакой знак thread1. Рассмотрение


монитора покрытия для двух потоков показывает нам, что led_thread1 не работал
(Рис. 9.24).

Рисунок 9.24
Монитор покрытия показывает то, что код выполнил путем окраски граничного
зеленого (темно-серым в печатной версии).

Led_thread1 работает в нормальном приоритете, и led_thread2 работает в более


высоком приоритете, так вытеснил led_thread1. Делать это еще худшим led_thread2
никогда блоки, таким образом, это выполнит навсегда предотвращение более низкого
приоритетного потока от когда-либо выполнения.

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

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

UART и затем создает два рабочих экземпляра того же кода потока. Здесь каждый
экземпляр кода UART мог управлять различным UART.
Сначала мы создаем структуру потока и определяем номер экземпляров потока к два:
osThreadDef (thread1, osPriorityNormal, 2, 0);

Затем мы можем создать два экземпляра потока, присвоенного различным


дескрипторам потока. Параметр также передается, чтобы позволить каждому
экземпляру определять, за который UART это ответственно.
ThreadID_1_0 5 osThreadCreate (osThread (thread1), UART1);
ThreadID_1_1 5 osThreadCreate (osThread (thread1), UART2);

Упражнение 9.4 Несколько экземпляров потока


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

В Пакете Установщик выбирают “Исключая 9,4 Несколько Экземпляров” и копии


это к Вашему учебному каталогу.

Этот проект выполняет ту же функцию как предыдущая светодиодная программа


проблескового сигнала. Однако у нас теперь есть ведомая функция переключателя
того, которая использует аргумент, переданный в качестве параметра для решения
который светодиод высветиться.
освободите ledSwitcher (пустая константа
*аргумент) {для (;;) {

LED_On ((uint32_t) аргумент);


задержка (500); LED_Off ((uint32_t)
аргумент); задержка (500);
}
}

Когда мы определяем поток, мы корректируем параметр экземпляров к два.


osThreadDef (ledSwitcher, osPriorityNormal, 2, 0);

Затем в основном потоке мы создаем два потока, которые являются различными


экземплярами того же основного кода. Мы передаем другой параметр, который
соответствует ведомому, который будет переключен экземпляром потока.
led_ID1 5 osThreadCreate (osThread (ledSwitcher), (освобождают *) 1UL);
led_ID2 5 osThreadCreate (osThread (ledSwitcher), (освобождают *) 2UL);
Создайте код и запустите отладчик.
314 Глав 9

Запустите выполнение кода и откройте задачи RTX и системное окно (Рис. 9.25).

Рисунок 9.25
Несколько экземпляров выполнения потока

Здесь мы видим оба экземпляра ledSwitcher задачи каждый с различным


идентификатором.
Исследуйте Стек вызовов 1 окно местных жителей (Рис. 9.26).

Рисунок 9.26
Окно часов ориентировано на многопотоковое
исполнение.

Здесь мы видим оба экземпляра потоков ledSwitcher и состояние их переменных.


Другой аргумент был передан каждому экземпляру потока.

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

Задержка
Самой основной из этих услуг по синхронизации является простая функция задержки
таймера. Это - простой способ обеспечить задержки синхронизации в рамках Вашего
приложения. Хотя размер ядра RTOS заключается в кавычки как 5k байты, функции,
такие как циклы задержки и простые циклы планирования часто являются частью
non-RTOS приложения и использовали бы байты кода так или иначе, таким образом,
издержки RTOS могут быть меньше, чем это сразу появляется.
освободите osDelay (uint32_t
миллисекунда)
Стандартная Операционная система реального времени программного
интерфейса микроконтроллера коры 315

Этот вызов поместит вызывающий поток в состояние WAIT_DELAY для


конкретного количества миллисекунд. Планировщик передаст выполнение
следующему потоку в Состоянии готовности (Рис. 9.27).

Рисунок 9.27
В течение их времени жизни распараллеливает перемещение через многие
состояния. Здесь рабочий поток заблокирован вызовом osDelay, таким образом, он
вводит состояние ожидания. Когда задержка истекает, она перемещается в готовый.
Планировщик поместит его в состояние выполнения. Если его интервал истечет, то он
попятится к готовому.

Когда таймер истечет, поток оставит состояние wait_delay и переместится в


Состояние готовности. Поток продолжит работать, когда планировщик переместит
его в СОСТОЯНИЕ ВЫПОЛНЕНИЯ. Если поток затем продолжит выполнять без
дальнейшего блокирования вызовы ОС, то это будет descheduled в конце своего
интервала и помещается в состояние готовности, предполагая, что другой поток того
же приоритета готов работать.

Ожидание события
В дополнение к чистой задержке возможно заставить поток остановить и ввести
состояние ожидания, пока поток не инициирован другим событием RTOS. События
RTOS могут быть сигналом, сообщением или почтовым событием. osWait () вызову
API также определили период тайм-аута в миллисекундах, который позволяет
потоку просыпаться и продолжать выполнение, если никакое событие не имеет
место.
osStatus osWait (uint32_t миллисекунда)

Когда интервал истекает, перемещения потока от ожидания до Состояния готовности и


будет помещен в состояние выполнения планировщиком. osWait является
дополнительным вызовом API в спецификации CMSIS-RTOS. Если Вы намереваетесь
использовать эту функцию, необходимо сначала проверить, что она поддерживается
RTOS, который Вы используете. osWait вызов API не поддерживается Keil RTX RTOS.

Упражнение 9.5 Тайм-менеджмент


В этом осуществлении мы посмотрим на использование
основной функции с временной задержкой.
316 Глав 9

В Пакете Установщик выбирают “Исключая 9.5 Тайм-менеджментом” и копией


это к Вашему учебному каталогу.

Это - наша исходная светодиодная программа проблескового сигнала, но простая


функция задержки была заменена osDelay вызовом API. LED2 переключается,
каждые 100 миллисекунд и LED1 переключаются каждые 500 миллисекунд.
освободите ledOn (пустая константа
*аргумент) {для (;;) {

LED_On (1);
osDelay (500);
LED_Off (1);
osDelay (500);
}}

Разработайте проект и запустите отладчик.


Запустите выполнение кода и откройте окно средства просмотра события (Рис. 9.28).

Рисунок 9.28
Используя osDelay () позволяет потоку блокироваться, когда это
неактивно.

Теперь мы видим, что действие кода очень отличается. Когда каждая из


светодиодных задач достигает osDelay вызова API, он “блокируется” и перемещается
в состояние ожидания. Основная задача будет в состоянии готовности, таким
образом, планировщик запустит ее выполнение. Когда время задержки испытает
таймаут, светодиодные задачи переместятся в состояние готовности и будут
помещены в состояние выполнения планировщиком. Это дает нам многопоточную
программу, где время выполнения ЦП эффективно совместно используется задачами.
Это совместное использование времени выполнения ЦП позволяет нам думать о
наших потоках, работающих одновременно, когда мы разрабатываем систему.

Виртуальные таймеры
API CMSIS-RTOS может использоваться для определения любого количества
виртуальных таймеров, которые действуют, как считают в обратном порядке
таймеры. Когда они истекут, они выполнят пользовательскую функцию обратного
вызова для выполнения a
Стандартная Операционная система реального времени программного
интерфейса микроконтроллера коры 317

определенное действие. Каждый таймер может быть настроен как выстрел того или
повторный таймер. Виртуальный таймер создается первым определением структуры
таймера.
osTimerDef (timer0, led_function);

Это определяет название таймера, и название вызова назад функционируют. Таймер


нужно затем инстанцировать в потоке RTOS.
osTimerId timer0_handle 5 osTimerCreate (таймер (timer0), osTimerPeriodic, (освобождают *) 0);

Это создает таймер и определяет его как периодический таймер или единственный
таймер выстрела (osTimerOnce). Заключительный параметр передает аргумент
вызову, назад функционируют, когда таймер истекает.
osTimerStart (timer0_handle, 0x100);

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

Упражнение 9.6 Виртуальный таймер


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

В Пакете Установщик выбирают “Исключая 9.6 Виртуальными Таймерами” и


копией это к Вашему учебному каталогу.

Это - наша исходная светодиодная программа проблескового сигнала, и код был


добавлен для создания четырех виртуальных таймеров для инициирования функции
обратного вызова. В зависимости от которого истек таймер, эта функция
переключит дополнительный светодиод.
Таймеры определяются в начале кода:
osTimerDef (timer0_handle, обратный вызов);
osTimerDef (timer1_handle, обратный вызов);
osTimerDef (timer2_handle, обратный вызов);
osTimerDef (timer3_handle, обратный вызов);

Они затем инициализируются в основной функции.


osTimerId timer0 5 osTimerCreate (osTimer (timer0_handle), osTimerPeriodic, (освобождают *) 0); osTimerId
timer1 5 osTimerCreate (osTimer (timer1_handle), osTimerPeriodic, (освобождают *) 1); osTimerId timer2 5
osTimerCreate (osTimer (timer2_handle), osTimerPeriodic, (освобождают *) 2); osTimerId timer3 5
osTimerCreate (osTimer (timer3_handle), osTimerPeriodic, (освобождают *) 3);
Каждый таймер имеет различный дескриптор и идентификатор и передал как
различный параметр общей функции обратного вызова.
318 Глав 9

пустой обратный вызов (освобождают


константу *параметрический усилитель)
{переключатель ((uint32_t)
параметрический усилитель) {
случай 0:
GPIOB-.ODR ^ 5 0x8;
поврежд
ение;
случай
1:
GPIOB-.ODR ^ 5 0x4;
поврежд
ение;
случай
2:
GPIOB-.ODR ^ 5 0x2;
повреждение;
}}

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


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

В дополнение к конфигурированию виртуальных таймеров в исходном коде поток


таймера должен быть включен в конфигурационном файле RTX.
Откройте файл RTX_Conf_CM.c и нажмите вкладку мастера конфигурации (Рис.
9.29).

Рисунок 9.29
Конфигурирование виртуальных таймеров.
В конфигурации системы раздел удостоверяется, что поле User Timers отмечается.
Если этот поток не будет создан, то таймеры не будут работать.
Разработайте проект и запустите отладчик.
Выполните код и наблюдайте действие контактов GPIOB в периферийном окне
(Рис. 9.30).
Рисунок 9.30
Пользовательские таймеры переключают дополнительные
светодиодные контакты.
Стандартная Операционная система реального времени программного
интерфейса микроконтроллера коры 319

Также будет дополнительный поток, работающий в окне System и Thread Viewer


(Рис. 9.31).

Рисунок 9.31
Пользовательские таймеры создают дополнительный
osTimerThread.

osDelay () функция обеспечивает относительную задержку от точки, в которой


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

Задержки подмиллисекунды
В то время как различные функции времени CMSIS-RTOS имеют разрешение 1
миллисекунды, возможно создать задержки с разрешением в микросекундах с
помощью необработанного количества SysTick. Эта форма задержки не делает
deschedule задача, но это просто останавливает свое выполнение в течение
желаемого периода. Для создания задержки, мы можем сначала получить
количество SysTick.
галочка int32_t, delayPeriod;
отметьте 5 osKernelSysTick (); //добираются, запускают значение системной галочки Ядра

Затем мы можем масштабировать период в микросекундах к значению количества


SysTick.
delayPeriod 5 osKernelTickMicroSec (100));

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

сделайте {\ //Задержка в течение 100 микросекунд


}, в то время как ((osKernelSysTick () - галочка), delayPeriod);

Неактивный демон
Заключительная услуга таймера, предоставленная RTOS, не является действительно
таймером, но это - вероятно, лучшее место для обсуждения этого. Если во время
нашей программы RTOS у нас не будет выполнения потока и никакого потока,
готового работать (например, они все ожидают на функциях задержки), затем, то
RTOS будет использовать запасное время выполнения для вызова “Неактивного
Демона”, который снова расположен в файле RTX_Conf_CM.c. Этот неактивный код
является в действительности низкоприоритетным потоком в RTOS, который только
работает, когда ничто иное не готово.
320 Глав 9

освободите os_idle_demon (пусто)


{
для (;;) {
/* ЗДЕСЬ: включайте здесь дополнительный пользовательский код, который будет выполняться, когда
никакой поток не будет работать. */
}
}

Можно добавить любой код к этому потоку, но он должен соблюсти те же правила


как пользовательские потоки. Самое простое использование неактивного демона
должно поместить микроконтроллер в режим низкой мощности, когда это ничего не
делает.
освободите os_idle_demon (пусто)
{для (;;) {
__ wfe ();
}}

Что происходит, затем зависит от режима питания, выбранного в


микроконтроллере. Как минимум ЦП остановится, пока прерывание не
сгенерировано таймером SysTick, и выполнение планировщика возобновится. Если
будет поток, готовый работать затем, то выполнение кода приложения
возобновится. Иначе неактивный демон будет повторно введен, и система вернется
ко сну.

Упражнение 9.7 Неактивный поток


В Пакете Установщик выбирают “Исключая 9,7 Idle” и копией это к Вашему
учебному каталогу.
Это - копия виртуального проекта таймера.
Откройте файл RTX_Conf_CM.c и нажмите вкладку текстового редактора.
Найдите поток os_idle_demon.
освободите os_idle_demon (пусто)
{int32_t i;
для (; ;)
{//wfe ();
}}

Создайте код и запустите отладчик.


Выполните код и наблюдайте действие потоков в конечном счете Средство
просмотра.
Это - простая программа, которая проводит большую часть ее времени в
неактивном демоне, таким образом, этот код будет работать почти непрерывно
(Рис. 9.32).
Стандартная Операционная система реального времени программного
интерфейса микроконтроллера коры 321

Рисунок 9.32
Неактивный поток является хорошим руководством по загрузке
ЦП.

Можно также видеть действие неактивного демона в конечном счете средство


просмотра. В реальном проекте количество времени, проведенное в неактивном
демоне, является признаком запасных циклов ЦП.
Откройте представление - аналитический Windows - анализатор производительности
(рис. 9.33).

Рисунок 9.33
Анализатор производительности показывает, что большая часть времени
выполнения тратится в неактивном цикле.

Это окно показывает кумулятивное время выполнения для каждой функции в


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

Удалите цикл задержки и инструкцию по переключателю и добавьте __ wfe ()


инструкция в для цикла, таким образом, код теперь похож на это.
322 Главы 9

освободите os_idle_demon (пусто)


{для (;;) {
__ wfe ();
}}

Восстановите код, перезапустите отладчик.

Теперь, когда мы входим, неактивный поток __ wfe () (ожидайте прерывания),


инструкция остановит ЦП, пока не будет прерывание периферийного устройства или
SysTick (Рис. 9.34).

Рисунок 9.34
__ wfe () внутренние остановы ЦП, когда это вводит неактивный цикл.
Сохранение циклов и энергии во время
выполнения.

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

Покрытие кода и аналитические инструменты производительности доступны, когда


Вы отлаживаете на реальных аппаратных средствах, а не моделировании. Однако для
использования этих функций Вам нужны две вещи: Во-первых, Вам нужен
микроконтроллер, который был оснащен дополнительной Встроенной макроячейкой
трассировки (ETM). Во-вторых, необходимо использовать адаптер отладки Keil
ULINKpro, который поддерживает трассировку инструкции через ETM.
Стандартная Операционная система реального времени программного
интерфейса микроконтроллера коры 323

Коммуникация межпотока
До сих пор мы видели, как код приложения может быть определен как независимые
потоки и как мы можем получить доступ к услугам синхронизации, предоставленным
RTOS. В реальном приложении мы должны смочь связаться между потоками для
подавания полезной заявки. С этой целью типичный RTOS поддерживает несколько
различных коммуникационных объектов, которые могут использоваться для
соединения потоков для формирования значимой программы. API CMSIS-RTOS
поддерживает связь межпотока с сигналами, семафорами, взаимными исключениями,
почтовыми ящиками и очередями сообщений. В первом разделе ключевое понятие
было параллелизмом. В этом разделе ключевое понятие синхронизирует действие
нескольких потоков.

Сигналы
CMSIS-RTOS Keil RTX поддерживает до 16 сигнальных флагов для каждого потока. Эти
сигналы хранятся в блоке управления потока. Возможно остановить выполнение потока,
пока конкретный сигнальный флаг или группа сигнальных флагов не установлены другим
потоком в системе (Рис. 9.35).

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

Сигнал ожидает, системные вызовы приостановят выполнение потока и поместят его в


состояние wait_evnt. Выполнение потока не запустится до всего набора флагов в
сигнале ожидают, вызов API был установлен. Также возможно определить
периодический тайм-аут, после которого поток ожидания попятится к состоянию
готовности, так, чтобы это могло возобновить выполнение при выборе
планировщиком. Значение 0xFFFF определяет бесконечный период тайм-аута.
324 Главы 9

osEvent osSignalWait (int32_t сигналы, uint32_t миллисекунда);

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


устанавливая любой флаг, заставит поток возобновлять выполнение. Вы видите,
какой флаг был установлен путем чтения osEvent.value.signals возвращаемого
значения.
Любой поток может установить или очистить сигнал на любом другом потоке.
int32_t osSignalSet (osThreadId thread_id, int32_t сигналы); int32_t osSignalClear
(osThreadId thread_id, int32_t сигналы);

Сигналы упражнения 9.8


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

Это - измененная версия светодиодной программы проблескового сигнала,


которую один из потоков называет той же Функцией светодиодного индикатора и
использует osDelay () для приостановки потока. Кроме того, это устанавливает
сигнальный флаг для пробуждения второго светодиодного потока.
освободите led_Thread2 (пустая константа
*аргумент) {для (;;) {

LED_On (2);
osSignalSet (T_led_ID1,0x01); osDelay
(500);
LED_Off (2);
osSignalSet (T_led_ID1,0x01); osDelay
(500); }}

Второй светодиодный поток ожидает сигнальных флагов, которые будут установлены


прежде, чем назвать Функции светодиодного индикатора.
освободите led_Thread1 (пустая константа
*аргумент) {для (;;) {

osSignalWait (0x01, osWaitForever); LED_On


(1);
osSignalWait (0x01, osWaitForever); LED_Off
(1);
}}
Разработайте проект и запустите отладчик.
Откройте периферийное окно GPIOB и запустите выполнение кода.

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


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

Это - простое осуществление, но оно иллюстрирует ключевое понятие


синхронизирующегося действия между потоками в основанном на RTOS приложении.

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

Рисунок 9.36
Семафоры помогают управлять доступом к ресурсам программы. Прежде чем поток
может получить доступ к ресурсу, он должен получить маркер. Если ни один не
доступен, это ожидает. Когда это закончено с ресурсом, это должно возвратить
маркер.
Схема выше иллюстрирует использование семафора для синхронизации двух потоков.
Во-первых, семафор должен быть создан и инициализирован с начальным маркерным
количеством. В этом случае семафор инициализируется с единственным маркером.
Оба потока выполнят и достигнут точки в их
326 Глав 9

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


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

Между тем выполняющийся поток может выпустить маркер назад к семафору. Когда это
произойдет, поток ожидания получит маркер и оставит состояние ожидания для состояния
готовности. Однажды в состоянии готовности планировщик поместит поток в состояние
выполнения так, чтобы выполнение потока могло продолжиться. В то время как семафоры
имеют простой набор вызовов ОС, они могут быть одним из более трудных объектов ОС
полностью понять. В этом разделе мы сначала посмотрим на то, как добавить семафоры к
программе RTOS и затем продолжить смотреть на самые полезные семафорные
приложения.
Для использования семафора в CMSIS-RTOS, необходимо сначала объявить
семафорный контейнер:
osSemaphoreId sem1;
osSemaphoreDef (sem1);

Затем в потоке семафорный контейнер может быть инициализирован со многими


маркерами.
sem1 5 osSemaphoreCreate (osSemaphore (sem1), SIX_TOKENS);

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

После того как семафор инициализируется, маркеры могут быть получены и


отправлены в семафор подобным способом к флагам события. Вызов os_sem_wait
используется для блокирования потока, пока семафорный маркер не доступен, как
вызов os_evnt_wait. Период тайм-аута может также быть указан с 0xFFFF,
являющимся бесконечным ожиданием.
osStatus osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t миллисекунда);

После того как поток закончил использовать семафорный ресурс, он может


отправить маркер в семафорный контейнер.
osStatus osSemaphoreRelease (osSemaphoreId semaphore_id);
Упражнение 9.9 Семафорная передача сигналов
В этом осуществлении мы будем смотреть на конфигурацию семафора и
использовать его для передачи сигналов между двумя задачами.

В Пакете Установщик выбирают “Исключая 9.9 Сигналами прерывания” и


копией это к Вашему учебному каталогу.
Стандартная Операционная система реального времени программного
интерфейса микроконтроллера коры 327

Во-первых, код создает семафор, названный sem1, и инициализирует его с нулевыми


маркерами.
osSemaphoreId sem1;
osSemaphoreDef (sem1);
международное основное
(пустота) {
sem1 5 osSemaphoreCreate (osSemaphore (sem1), 0);

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


освободите led_Thread1 (пустая константа
*аргумент) {для (;;) {

osSemaphoreWait (sem1, osWaitForever); LED_On


(1);
osDelay (500);
LED_Off (1);
}
}

В то время как вторая задача периодически отправляет маркер в семафор.


освободите led_Thread2 (пустая константа
*аргумент) {для (;;) {

LED_On (2); osSemaphoreRelease


(sem1); osDelay (500);
LED_Off (2);
osDelay (500);
}}

Разработайте проект и запустите отладчик.


Установите точку останова в led_Thread2 задаче (Рис. 9.37).

Рисунок 9.37
Точка останова на семафорном выпуске звонит в led_Thread2.

Выполните код и наблюдайте состояние потоков, когда точка останова будет


достигнута
(Рис. 9.38).
Рисунок 9.38
Led_Thread1 ожидает для получения семафора.
328 Глав 9

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


led_Thread1 был создан с более высоким приоритетом, чем led_thread2 поэтому, как
только маркер помещается в семафор, он переместится в состояние готовности и
вытеснит более низкий приоритетный поток и начнет работать. Когда это достигнет
osSemaphoreWait () вызов, это снова заблокируется.

Теперь блок ступает код (F10) и наблюдает действие потоков и семафора.

Использование семафоров
Хотя семафоры имеют простой набор вызовов ОС, у них есть широкий спектр
синхронизирующихся приложений. Это делает их, возможно, самым сложным
объектом RTOS понять. В этом разделе мы посмотрим на наиболее общее
использование семафоров. Они взяты из “Небольшой Книги Семафоров” Allen B.
Downey. Эта книга может быть свободно загружена с URL, данного в библиографии в
конце этой книги.

Передача сигналов
Синхронизация выполнения двух потоков является самым простым использованием
семафора:
osSemaphoreId sem1;
osSemaphoreDef (sem1);
освободите thread1 (пусто)
{
sem1 5 osSemaphoreCreate (osSemaphore (sem1), 0); в то
время как (1)

{
FuncA ();
osSemaphoreRelease (sem1)
}
}
освободите task2 (пусто)
{
в то время как (1)
{
osSemaphoreWait (sem1, osWaitForever)
FuncB ();
}
}
В этом случае семафор используется, чтобы гарантировать, что код в FuncA ()
выполнен перед кодом в FuncB ().
Стандартная Операционная система реального времени программного
интерфейса микроконтроллера коры 329

Мультиплексирование
Мультиплексирование используется для ограничения количества потоков, которые
могут получить доступ к критическому разделу кода. Например, это могло быть
стандартной программой, что ресурсы памяти доступов и могут только поддерживать
ограниченное количество вызовов.
мультиплексирование
osSemaphoreId; osSemaphoreDef
(мультиплексирование);
освободите thread1 (пусто)
{
мультиплексируйте 5osSemaphoreCreate (osSemaphore (мультиплексирование),
FIVE_TOKENS); в то время как (1) {

osSemaphoreWait (мультиплексирование, osWaitForever)


ProcessBuffer ();
osSemaphoreRelease (мультиплексирование);
}}

В этом примере мы инициализируем мультиплексный семафор с пятью маркерами.


Прежде чем поток может назвать ProcessBuffer () функцией, это должно получить
семафорный маркер. После того как функция завершилась, маркер передают обратно
семафору. Если больше чем пять потоков пытаются назвать ProcessBuffer (), шестое
должно ожидать, пока поток не закончился с ProcessBuffer () и возвращает свой
маркер. Таким образом мультиплексный семафор гарантирует, что максимум пяти
потоков может назвать ProcessBuffer () функцией “одновременно”.

Упражнение 9.10 Мультиплексирование


В этом осуществлении мы посмотрим на использование семафора для
управления доступом к функции путем создания мультиплексирования.
В Пакете Установщик выбирают “Исключая 9.10 Мультиплексированием” и копией
это к Вашему учебному каталогу.

Проект создает семафор, названный semMultiplex, который содержит один маркер.


Затем, шесть экземпляров потока, содержащего семафорное мультиплексирование,
создаются.
Создайте код и запустите отладчик.
Откройте окно Peripherals - General Purpose IO - GPIOB.
Выполните код и наблюдайте, как задачи устанавливают контакты порта.
Когда код работает, только один поток за один раз может получить доступ к
Функциям светодиодного индикатора, таким образом, только один контакт порта
установлен.

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


будет создано.
semMultiplex 5 osSemaphoreCreate (osSemaphore (semMultiplex), 3);
330 Глав 9

Создайте код и запустите отладчик.


Выполните код и наблюдайте контакты GPIOB.
Теперь три потока могут получить доступ к Функциям светодиодного индикатора
“одновременно”.

Рандеву
Более обобщенная форма семафорной передачи сигналов является рандеву.
Рандеву гарантирует, чтобы два потока достигли определенного момента
выполнения. Ни один не может продолжить, пока оба не достигли точки рандеву.
osSemaphoreId arrived1, arrived2;
osSemaphoreDef (arrived1);
osSemaphoreDef (arrived2);
освободите thread1 (пусто) {
Arrived1 5osSemaphoreCreate (osSemaphore (arrived1), ZERO_TOKENS); Arrived2
5osSemaphoreCreate (osSemaphore (arrived2), ZERO_TOKENS); в то время как (1) {

FuncA1 ();
osSemaphoreRelease (Arrived1);
osSemaphoreWait (Arrived2, osWaitForever);
FuncA2 ();
}}
освободите thread2 (пусто)
{в то время как (1) {
FuncB1 (); os_sem_send
(Arrived2);
os_sem_wait (Arrived1, osWaitForever); FuncB2 ();

}}

В вышеупомянутом случае эти два семафора гарантируют, что оба потока будут
рандеву и затем продолжать выполнять FuncA2 () и FuncB2 ().

Упражнение 9.11 Рандеву


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

В Пакете Установщик выбирают “Исключая 9.11 Рандеву” и копией это к


Вашему учебному каталогу.
Разработайте проект и запустите отладчик.
Откройте окно Peripherals\General Purpose IO\GPIOB.
Выполните код.
Стандартная Операционная система реального времени программного
интерфейса микроконтроллера коры 331

Первоначально семафорный код в каждом из светодиодных потоков


комментируется. Так как потоки не синхронизируются, контакты GPIO
переключатся случайным образом.
Выйдите из отладчика.
Не прокомментируйте семафорный код в светодиодных задачах.
Разработанный проект и запускают отладчик.
Выполните код и наблюдайте действие контактов в окне GPIOB.

Теперь потоки синхронизируются семафором и выполняют Функции


светодиодного индикатора “одновременно”.

Турникет барьера
Хотя рандеву очень полезно для синхронизации выполнения кода, это только работает
на два потока. Барьер является более обобщенной формой рандеву, которое работает
для синхронизации нескольких потоков.
количество osSemaphoreId, барьер;
osSemaphoreDef (счетчик);
osSemaphoreDef (барьер);
неподписанное международное
количество;
освободите thread1 (пусто)
{
количество 5 osSemaphoreCreate (osSemaphore (количество), ONE_TOKEN);
барьер 5 osSemaphoreCreate (osSemaphore (барьер), ZERO_TOKENS); в то время как
(1) {

//Позвольте только одной задаче за один раз выполнять


этот код osSemaphoreWait (счетчик);
количество 5 count11;
если количество 55 5 os_sem_send (барьер, osWaitForever);
osSemaphoreRelease (счетчик);
//когда все пять задач прибыли, барьер открыт os_sem_wait (барьер,
osWaitForever); os_sem_send (барьер);

critical_Function ();
}}

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


потоков, которые прибыли в барьер. Когда каждая функция прибывает в барьер, это
будет ожидать, пока это не сможет получить маркер от встречного семафора. После
того, как полученный, переменная количества будет увеличена одной. После того как
мы увеличили переменную количества, маркер отправляется во встречный семафор
так, чтобы другие потоки ожидания могли продолжиться. Затем, барьерный код читает
переменную количества. Если это равно количеству потоков, которые ожидают для
прибытия в барьер, мы отправляем маркер в семафор барьера.
332 Главы 9

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


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

Упражнение 9.12 Семафорный барьер


В этом осуществлении мы будем использовать семафоры для создания барьера для
синхронизации нескольких задач.
В Пакете Установщик выбирают “Исключая 9.12 Барьерами” и копией это к Вашему
учебному каталогу.
Разработайте проект и запустите отладчик.
Откройте Peripherals\General Purpose IO\GPIOB window.k.
Выполните код.

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


потоки не синхронизируются, контакты GPIO переключатся случайным образом как в
примере рандеву.
Выйдите из отладчика.
Удалите комментарии к строкам 34, 45, 53, и 64 для включения барьерного кода.
Разработайте проект и запустите отладчик.
Выполните код и наблюдайте действие контактов в окне GPIOB.

Теперь потоки синхронизируются семафором и выполняют Функции


светодиодного индикатора “одновременно”.

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

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


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

Взаимное исключение
Взаимное исключение обозначает “Взаимное исключение”. В действительности
взаимное исключение является специализированной версией семафора. Как семафор,
взаимное исключение является контейнером для маркеров. Различие - то, что
взаимное исключение может только содержать один маркер, который не может быть
создан или уничтожен. Принципиальное использование взаимного исключения
должно управлять доступом к ресурсу микросхемы, такому как периферийное
устройство. Поэтому взаимоисключающий маркер является двоичным и ограничен.
Кроме этого это действительно работает таким же образом семафором. В первую
очередь, мы должны объявить взаимоисключающий контейнер и инициализировать
взаимное исключение:
osMutexId uart_mutex;
osMutexDef (uart_mutex);

После того, как объявленный взаимным исключением должен быть создан в потоке.
uart_mutex 5 osMutexCreate (osMutex (uart_mutex));

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


должен сначала получить взаимоисключающий маркер:
osMutexWait (osMutexId mutex_id, uint32_t миллисекунда;

Наконец, когда мы закончены с периферийным устройством, взаимное исключение


должно быть выпущено:
osMutexRelease (osMutexId mutex_id);

Взаимоисключающее использование намного более твердо, чем семафорное


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

Упражнение 9.13 Взаимное исключение


В этом осуществлении наша программа пишет потоки символов к микроконтроллеру
UART от различных потоков. Мы будем объявлять и использовать взаимное
исключение, чтобы гарантировать, что каждый поток имеет эксклюзивный доступ к
UART, пока это не закончило писать свой блок символов.
В Пакете Установщик выбирают “Исключая 9.13 Взаимными исключениями” и
копией это к Вашему учебному каталогу.

Этот проект объявляет два потока который оба блока записи символов к UART.
Первоначально, взаимное исключение комментируется.
освободите uart_Thread1 (пустая константа
*аргумент) {uint32_t i;

для (;;) {
//osMutexWait (uart_mutex, osWaitForever); для (я 5 0; я,
10; i11) SendChar ('1'); SendChar ('\n');
334 Главы 9

SendChar ('\r');//osMutexRelease
(uart_mutex);
}}

В каждом потоке код распечатывает число потока. В конце каждого блока символов
это затем печатает символы возврата каретки и символы новой строки.
Создайте код и запустите отладчик.
Откройте окно консоли UART1 с View\Serial Windows\UART # 1 (Рис. 9.39).

Рисунок 9.39
Откройте окно консоли UART.

Запустите выполнение кода и наблюдайте вывод в консоли (Рис. 9.40).

Рисунок 9.40
Мисс заказала последовательный вывод.

Здесь мы видим, что поток выходных данных повреждается каждым потоком,


пишущим в UART без любого управления доступом.
Выйдите из отладчика.
Не прокомментируйте взаимоисключающие вызовы в каждом потоке.
Стандартная Операционная система реального времени программного
интерфейса микроконтроллера коры 335

Создайте код и запустите отладчик.


Наблюдайте вывод каждой задачи в консоли (Рис. 9.41).

Рисунок 9.41
Порядок восстановлен при помощи взаимного
исключения.

Теперь взаимное исключение гарантирует каждый эксклюзивный доступ задачи к


UART, в то время как это пишет каждый блок символов.

Взаимоисключающие протесты
Очевидно необходимо заботиться для возврата взаимоисключающего маркера, когда
Вы будете закончены с ресурсом микросхемы, или Вы будете эффективно
препятствовать тому, чтобы любой другой поток получил доступ к нему. Необходимо
также быть чрезвычайно осторожны относительно использования osThreadTerminate
() запрос к функциям, которые управляют взаимоисключающим маркером. Keil RTX
разработан, чтобы быть маленьким местом RTOS так, чтобы он мог работать даже на
очень маленьких микроконтроллерах Cortex-M. Следовательно, нет никакой
безопасности удаления потока. Это означает, что при удалении потока, который
управляет взаимоисключающим маркером, Вы уничтожите взаимоисключающий
маркер и предотвратите дальнейший доступ к защищенному периферийному
устройству.

Обмен данными
До сих пор все способы связи межпотока только использовались для инициирования
выполнения потоков; они не поддерживают обмен данными программы между потоками.
Очевидно, в реальной программе мы должны будем переместить данные между потоками.
Это могло быть сделано путем чтения и записи в глобально заявленные переменные. В
чем-либо кроме очень простой программы, пытаясь гарантировать данные
336 Глав 9

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


ошибкам. Для обмена данными между потоками нужен более формальный
асинхронный метод коммуникации.

CMSIS-RTOS предоставляет два метода передачи данных между потоками. Первый


метод является очередью сообщений, которая создает буферизированные данные
“канал” между двумя потоками. Очередь сообщений разработана для передачи
целочисленных значений (Рис. 9.42).

Рисунок 9.42
Очередь сообщений действует как буфер FIFO между потоками.

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

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

Очереди сообщений и почтовые очереди оба предоставляют метод для передачи


данных между потоками. Это позволяет Вам просматривать свой дизайн как набор
объектов (потоки), взаимосвязанные потоками данных. Поток данных реализован
очередями сообщений и почтовыми очередями. Это обеспечивает и
буферизированную передачу данных и четко определенный интерфейс связи между
потоками. Запуск с системного дизайна уровня на основе потоков, соединенных
почтовыми очередями и очередями сообщений, позволяет Вам кодировать различные
подсистемы своего проекта, особенно полезного, если Вы работаете в команде. Также,
поскольку каждый поток имеет четко определенные вводы и выводы, которые легко
изолировать для тестирования и повторного использования кода (Рис. 9.44).
Стандартная Операционная система реального времени программного
интерфейса микроконтроллера коры 337

Рисунок 9.44
Системное представление уровня основанного на RTOS проекта состоит из
объектов потока, соединенных потоками данных в форме
очередей сообщений и почтовых очередей.

Очередь сообщений
Для установки очереди сообщений, мы сначала должны выделить ресурсы памяти.
osMessageQId Q_LED;
osMessageQDef (Q_LED, 16_Message_Slots, неподписанный интервал);

Это определяет очередь сообщений с шестнадцатью запоминающими элементами. В


этой конкретной очереди каждый элемент определяется как неподписанный
интервал. В то время как мы можем отправить данные непосредственно в очередь
сообщений, также возможно отправить указатель на объект данных.
результат osEvent;

Мы также должны определить osEvent переменную, которая будет использоваться


для получения данных очереди. osEvent переменная является объединением, которое
позволяет Вам получать данные из очереди сообщений во многих форматах.
объединение
{uint32_t v
освобождает
*p

сигналы int32_t}
значение

osEvent объединение позволяет Вам считывать данные, отправленные на очередь


сообщений как неподписанный интервал или пустой указатель. После того как
ресурсы памяти создаются, мы можем объявить очередь сообщений в потоке.
Q_LED 5 osMessageCreate (osMessageQ (Q_LED), ПУСТОЙ УКАЗАТЕЛЬ);

После того как очередь сообщений была создана, мы можем поместить данные в
очередь от одного потока.
osMessagePut (Q_LED, 0x0, osWaitForever);
338 Глав 9

и затем считайте его из очереди в другом.


закончитесь 5 osMessageGet (Q_LED, osWaitForever);
LED_data 5 result.value.v;

Упражнение 9.14 Очередь сообщений


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

В Пакете Установщик выбирают “Исключая 9.14 Очередями сообщений” и


копией это к Вашему учебному каталогу.
Откройте Main.c и просмотрите код инициализации очереди сообщений.
osMessageQId Q_LED;
osMessageQDef (Q_LED, 0x16, неподписанный
символ); результат osEvent;
международное
основное
(пустота)
{LED_Init ();
Q_LED 5 osMessageCreate (osMessageQ (Q_LED), ПУСТОЙ УКАЗАТЕЛЬ);

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


структурой события.
osMessagePut (Q_LED, 0x1, osWaitForever); osDelay
(100);

Затем в одном из потоков мы можем отправить данные и получить его во втором.


закончитесь 5 osMessageGet (Q_LED, osWaitForever);
LED_On (result.value.v);

Разработайте проект и запустите отладчик.


Установите точку останова в led_thread1 (Рис. 9.45).

Рисунок 9.45
Установите точку останова на потоке получения.

Теперь выполните код и наблюдайте данные,


когда это прибывает.
Стандартная Операционная система реального времени программного
интерфейса микроконтроллера коры 339

Пул памяти
В то время как возможно отправить простые значения данных в очередь сообщений,
также возможно отправить указатель на более сложный объект. CMSIS-RTOS
поддерживает динамическое выделение памяти в форме пула памяти. Здесь мы
можем объявить структуру, которая комбинирует много элементов данных.
структура
определения типа
{uint8_t LED0;
uint8_t LED1;
uint8_t LED2;
uint8_t LED3;
} memory_block_t;

Затем мы можем создать пул этих объектов как блоки памяти.


osPoolDef (led_pool, ten_blocks, memory_block_t); osPoolId
(led_pool);

Затем мы можем создать пул памяти путем объявления этого в потоке.


led_pool 5 osPoolCreate (osPool (led_pool));

Теперь мы можем выделить пул памяти в потоке.


memory_block_t *led_data;
*led_data 5 (memory_block_t *) osPoolAlloc (led_pool);

и затем заполните его с данными;


led_data-.LED0 5 0;
led_data-.LED1 5 1;
led_data-.LED2 5 2;
led_data-.LED3 5 3;

Затем возможно поместить указатель на блок памяти в очереди сообщений.


osMessagePut (Q_LED, (uint32_t) led_data, osWaitForever);

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


событие osEvent; memory_block_t * полученный;
событие 5 osMessageGet (Q_LED, osWatiForever);
*получил 5 (memory_block *) event.value.p; led_on
(получен-.LED0);

После того как данные в блоке памяти использовались, блок должен быть выпущен
назад к пулу памяти для повторного использования.
osPoolFree (led_pool, полученный);
340 Глав 9

Упражнение 9.15 Пул памяти


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

В Пакете Установщик выбирают “Исключая 9.15 Пулами памяти” и копией это


к Вашему учебному каталогу.

Это осуществление создает пул памяти и очередь сообщений. Поток производителя


получает буфер от пула памяти и заполняет его данными. Указатель на буфер пула
памяти затем помещается в очередь сообщений. Второй поток читает указатель из
очереди сообщений и затем получает доступ к данным, хранившим в буфере пула
памяти прежде, чем освободить буфер назад к пулу памяти. Это позволяет большим
объемам данных быть перемещенными от одного потока до другого безопасным
синхронизируемым способом. Это называют “нулевой копией” очередью памяти как,
только указатель перемещен через очередь сообщений, но фактические данные не
перемещают ячейки памяти.

В начале main.c определяются пул памяти и очередь сообщений.


структура определения
типа {uint8_t canData[8];
} message_t;
osPoolDef (mpool, 16, message_t); osPoolId
mpool;
osMessageQDef (очередь, 16, message_t);
очередь osMessageQId;

В производителе поток получает буфер сообщений и заполняет его переменной


данных тестирования.;
сообщение 5 (message_t*) osPoolAlloc (mpool); для
(индекс 50; индекс, 8; index11) {
сообщение-.canData [индекс] 5 данные тестирования 1 индекс;}
osMessagePut (очередь, (uint32_t) сообщение, osWaitForever);

Затем в потребительском потоке мы можем считать очередь сообщений с помощью


event.value.p объекта указателя и затем данных доступа, хранивших в буфере пула
памяти. После того как мы использовали данные в буфере, это должно быть выпущено
назад к пулу памяти.
для (индекс 5 0; индекс, 8; index11) {
message_t *сообщение 5 (message_t*) evt.value.p; LED_On
((uint32_t) сообщение-.canData [индекс]);} osPoolFree
(mpool, сообщение);

Создайте код и запустите отладчик.


Место устанавливает контрольные точки на osMessagePut и функциях osmessageGet
(Рис. 9.46).
Стандартная Операционная система реального времени программного
интерфейса микроконтроллера коры 341

Рисунок 9.46
Набор устанавливает контрольные точки на отправке и получении
потоков.

Выполните код и наблюдайте данные, передаваемые между потоками.

Почтовая очередь
В то время как пулы памяти могут использоваться в качестве буферов данных в
потоке, CMSIS-RTOS также реализует почтовую очередь, которая является
комбинацией пула памяти и очереди сообщений. Почтовая очередь использует пул
памяти для создания отформатированных блоков памяти и передает указатели на эти
блоки в очереди сообщений. Это позволяет данным оставаться в выделенном блоке
памяти, в то время как мы только перемещаем указатель между различными
потоками. Простая почтовая очередь API делает это легким установить и
использовать. Сначала мы должны объявить структуру для почтового слота,
подобного тому, который мы использовали для пула памяти.
структура
определения типа
{uint8_t LED0;
uint8_t LED1;
uint8_t LED2;
uint8_t LED3;
} mail_format;

Эта структура сообщения является форматом блока памяти, который выделяется в


почтовой очереди. Теперь мы можем создать почтовую очередь и определить
количество блока памяти “слоты” в почтовой очереди.
osMailQDef (mail_box, sixteen_mail_slots, mail_format); osMailQId
mail_box;

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


почтовую очередь в потоке.
mail_box 5 osMailCreate (osMailQ (mail_box), ПУСТОЙ УКАЗАТЕЛЬ);
После того как почтовая очередь инстанцировали, мы можем добавить сообщение.
Это отличается от очереди сообщений, в которой мы должны сначала выделить
почтовый слот и заполнить его с данными.
mail_format *LEDtx;
LEDtx 5 (mail_format*) osMailAlloc (mail_box, osWaitForever);
342 Главы 9

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


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

После того как почтовый слот был выделен, он может быть заполнен с данными и
затем отправлен на почтовую очередь.
LEDtx-.LED0 5 led0 [индекс];
LEDtx-.LED1 5 led1 [индекс];
LEDtx-.LED2 5 led2 [индекс];
LEDtx-.LED3 5 led3 [индекс];
osMailPut (mail_box, LEDtx);

Поток получения должен объявить указатель в формате почтового слота и


osEvent структуре.
osEvent evt; mail_format
*LEDrx;

Затем в цикле потока мы можем ожидать сообщения электронной почты для


прибытия.
evt 5 osMailGet (mail_box, osWaitForever);

Мы можем затем проверить структуру события, чтобы видеть, является ли это


действительно сообщение электронной почты, и извлеките данные.
если (evt.status 55 osEventMail) {LEDrx 5
(mail_format*) evt.value.p;

После того как данные в сообщении электронной почты использовались, почтовый


слот должен быть выпущен так, это может быть снова использовано.
osMailFree (mail_box, LEDrx);

Упражнение 9.16 Почтовый ящик


Это осуществление демонстрирует конфигурацию почтового ящика и
использования его для добавления сообщений между задачами.
В Пакете Установщик выбирают “Исключая 9.16 Почтовыми ящиками” и копией это к
Вашему учебному каталогу.
Проект создает шестнадцать почтовых ящиков слота для отправки светодиодных
данных между потоками.
структура
определения типа
{uint8_t LED0;
uint8_t LED1;
Стандартная Операционная система реального времени программного
интерфейса микроконтроллера коры 343

uint8_t LED2;
uint8_t LED3;}
mail_format;
osMailQDef (mail_box, 16, mail_format); osMailQId
mail_box;
международное
основное
(пустота)
{LED_Init ();
mail_box 5 osMailCreate (osMailQ (mail_box), ПУСТОЙ УКАЗАТЕЛЬ);

Задача производителя выделяет почтовый слот, затем заполняет его данными и


отправляет его на почтовую очередь.
LEDtx 5 (mail_format*) osMailAlloc (mail_box, osWaitForever); LEDtx-.LED0 5
led0 [индекс];
LEDtx-.LED1 5 led1 [индекс];
LEDtx-.LED2 5 led2 [индекс];
LEDtx-.LED3 5 led3 [индекс];
osMailPut (mail_box, LEDtx);

Задача получения ожидает сообщения электронной почты для прибытия, затем


считывает данные. После того как данные использовались, почтовый слот выпущен.
evt 5 osMailGet (mail_box, osWaitForever); если
(evt.status 55 osEventMail) {
LEDrx 5 (mail_format*) evt.value.p; LED_Out ((LEDrx-.LED0|LEDrx-
.LED1|LEDrx-.LED2|LEDrx); osMailFree (mail_box, LEDrx);
}

Создайте код и запустите отладчик.


Установите точку останова в потоках потребителя и производителя и выполните код
(Рис. 9.47).

Рисунок 9.47
Набор устанавливает контрольные точки на отправке и получении
потоков.

Наблюдайте сообщения почтового ящика, достигающие потребительского потока.

Конфигурация
До сих пор мы посмотрели на API CMSIS-RTOS. Это включает функции управления
потоком, тайм-менеджмент и коммуникацию межпотока. Теперь, когда у нас есть
четкое представление о точно, к чему ядро RTOS способно, мы можем бросить более
подробный взгляд на
344 Главы 9

конфигурационный файл. Существует один конфигурационный файл для


всех Основанных на Cortex-M микроконтроллеров под названием
RTX_Conf_CM.c (Рис. 9.48).

Рисунок 9.48
RTX настроен с помощью одного центрального конфигурационного
файла.

Как другие конфигурационные файлы, файл RTX_Conf_CM.c является


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

Определение потока
В этом разделе мы определяем основные ресурсы, которые будут требоваться
потоками CMSIS-RTOS. Для каждого потока мы выделяем определенное стековое
пространство (в вышеупомянутом примере, это - 200 байтов.) Мы также определяем
максимальное количество параллельного выполнения потоков. Таким образом сумма
RAM, требуемой для вышеупомянутого примера, может легко быть вычислена как 200
3 6 или 1 200 байтов. Если некоторым нашим потокам нужно большее стековое
пространство, то больший стек может быть выделен, когда задача создается. Кроме
того, общий пользовательский размер стека должен быть выделен в
конфигурационном файле наряду с общим количеством потоков с пользовательским
размером стека. Снова, требование RAM легко вычисляется.
Поддержка отладки ядра
Во время разработки CMSIS-RTOS может захватить переполнения стека. Когда эта
опция будет включена, переполнение стекового пространства потока заставит ядро
RTOS вызывать os_error функцию
Стандартная Операционная система реального времени программного
интерфейса микроконтроллера коры 345

который расположен в файле RTX_Conf_CM.c. Эта функция передается код ошибки и


затем находится в бесконечном цикле. Опция проверки стека предназначается для
использования во время отладки и должна быть отключена на заключительном
приложении для уменьшения ядра наверху. Однако возможно изменить os_error ()
функция, если расширенная защита от ошибок требуется в финальной версии.
#define OS_ERROR_STACK_OVF 1
#define OS_ERROR_FIFO_OVF 2
#define OS_ERROR_MBX_OVF 3
экстерн osThreadId svcThreadGetId (пусто);
освободите os_error (uint32_t error_code) {
переключатель (error_code) {
случай OS_ERROR_STACK_OVF:
/* Переполнение стека обнаруживается для в настоящее время
выполняющейся задачи. *//* Поток может быть определен путем вызова
svcThreadGetId (). повреждение */;

случай OS_ERROR_FIFO_OVF:
/* Переполнение буфера Очереди FIFO ISR
обнаруживается. повреждение */;

случай OS_ERROR_MBX_OVF:
/* Переполнение почтового ящика
обнаруживается. повреждение */;

}
для (;;);
}

Также возможно контролировать максимальное использование стековой памяти во


время времени выполнения. При проверке опции “Stack Usage Watermark” шаблон
(0xCC) записан в каждое стековое пространство. Во время времени выполнения
этот водяной знак используется для вычисления максимального использования
памяти. Об этом числе сообщают в разделе потоков окна “System and Event
Viewer” (Рис. 9.49).

Рисунок 9.49
Создание водяных знаков стопки потока позволяет отладчику вычислять
максимальное использование памяти для
каждого потока.
Раздел определения потока также позволяет нам выбирать, работают ли потоки в
привилегированном или непривилегированном режиме. Это принимает значение
по умолчанию к привилегированному для большинства приложений, это в порядке.
Если Вы запишете безопасность, то приложение критической или высокой
безопасности, затем выбирающее непривилегированный, защитит регистры
процессора Cortex-M от случайного или злонамеренного доступа.
346 Глав 9

Системная конфигурация таймера


Таймер по умолчанию для использования с CMSIS-RTOS является таймером Cortex-
M SysTick, который присутствует почти на всех процессорах Cortex-M. Вход к
таймеру SysTick обычно будет тактовой частотой ЦП. Возможно использовать другой
таймер путем снятия выделения с опцией “Use SysTick”. Если Вы делаете это, там два
функциональных тупика в файле RTX_Conf_CM.c, которые позволяют Вам
инициализировать альтернативный таймер и подтверждать его прерывание.
интервал os_tick_init (пусто) {
возвратитесь (-1); Возврат/* количество IRQ таймера (0.. 239) */
}
освободите os_tick_irqack (пусто)
{/*... */

Какой бы ни таймер, Вы используете Вас, должен затем установить свое входное


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

Конфигурация интервала
Заключительный параметр конфигурации позволяет Вам включать круговое
планирование и определять период интервала. Это является кратным уровню галочки
таймера так в вышеупомянутом примере, который каждый поток выполнит для пяти
галочек или 5 миллисекунд, прежде чем он передаст выполнение другому потоку того
же приоритета, который готов работать. Если никакой поток того же приоритета не
будет готов работать, то он продолжит выполнение. Опции конфигурации системы
также позволяют Вам включать и настраивать виртуальный поток таймера. Если Вы
собираетесь использовать виртуальные таймеры, эта опция должна быть настроена,
или таймеры не будут работать. Затем наконец, если Вы собираетесь инициировать
поток от флагов события использования процедуры прерывания затем, возможно
определить очередь FIFO для инициированных сигналов. Это буферизует триггеры
сигнала в случае пакетов действия прерывания.
Планирование опций
CMSIS-RTOS позволяет Вам создавать приложение с тремя различными опциями
планирования ядра. Это циклическое планирование, упреждающее планирование
и кооперативная многозадачность. Сводка этих опций следующие:
Стандартная Операционная система реального времени программного
интерфейса микроконтроллера коры 347

Упреждающее планирование

Если циклическая опция отключена в файле RTX_Config_CM.c, каждый поток должен


быть объявлен с различным приоритетом. Когда RTOS запускается, и потоки
создаются, поток с самым высоким приоритетом будет работать (Рис. 9.50).

Рисунок 9.50
В приоритетном RTOS каждый поток имеет различный приоритетный уровень и
будет работать, пока он не вытесняется или достиг
блокирующегося вызова ОС.

Этот поток будет работать, пока он не заблокируется, то есть, он вынужден ожидать


флага события, семафора или другого объекта. Когда это заблокируется, следующий
готовый поток с самым высоким приоритетом будет запланирован и будет работать,
пока это не блокируется, или более высокий приоритетный поток становится готовым
работать. Таким образом с упреждающим планированием мы создаем иерархию из
выполнения потока с каждым потоком, использующим переменные суммы времени
выполнения.

Циклическое планирование

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


путем включения циклической опции в файле RTX_Conf_CM.c и объявления
каждого потока с тем же приоритетом (Рис. 9.51).
Рисунок 9.51
В круговом RTOS потоки будут работать за установленным сроком или
интервалом или пока они не достигнут
блокирующегося вызова ОС.
348 Глав 9

В этой схеме каждый поток будет выделен установленная сумма времени


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

Циклическое упреждающее планирование

Как обсуждено в начале этого учебного руководства, опция планирования


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

Кооперативная многозадачность

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


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

Рисунок 9.52
В совместном RTOS будет работать каждый поток, пока он не будет достигать
блокирующегося вызова ОС или будет
использовать osThreadYield () вызов.

Потоки могут заблокироваться на любом из стандартных объектов ОС, но


существует также дополнительный вызов ОС, osThreadYeild (), который планирует
поток к состоянию готовности и передает выполнение следующему готовому потоку.

Исходный код RTX


CMSIS-RTOS Keil RTX включен со всеми версиями набора инструментальных
средств MDK-ARM. Исходный код может быть найден в следующем каталоге
набора инструментальных средств:
C:\Keil\ARM\Pack\ARM\CMSIS\, версия. \CMSIS\RTOS\RTX
Стандартная Операционная система реального времени программного
интерфейса микроконтроллера коры 349

Если Вы хотите выполнить, отладка на уровне исходного кода кода RTOS


создают текстовый файл, содержащий следующую командную строку, где
путь является исходным каталогом RTX.
SRC 5 НАБОРА, путь.
Теперь добавьте этот файл к полю инициализации в меню отладчика (Рис. 9.53).

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

Теперь при запуске сеанса отладки, источник RTX будет загружен.

Лицензия RTX
CMSIS-RTOS Keil RTX предоставляют в соответствии с тремя пунктами лицензию
BSD и можно использовать свободно бесплатно для коммерческих и
некоммерческих проектов. RTX также скомпилирует использование инструментов
IAR и GCC. Для получения дополнительной информации используйте URL ниже:
https://www.keil.com/demo/eval/rtx.htm
350 Глав 9

Заключение
В этой главе мы проложили себе путь через API CMSIS-RTOS и представили
некоторые ключевые понятия, связанные с использованием RTOS. Единственный
реальный способ изучить, как разработать с RTOS, состоит в том, чтобы на самом деле
использовать один в реальном проекте. В следующей главе мы посмотрим на
некоторые доказанные методы, которые могут использоваться при разработке
использования работы RTOS микроконтроллера Cortex-M.
CHPTER10

Методы RTOS

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

RTOS и прерывания
В последней главе мы видели, что наш код приложения может выполниться в потоках
RTOS. Однако в реальной системе, у нас также будет много Процедур обработки
прерывания (ISRs), который будет инициирован событиями в периферийных
устройствах микроконтроллера. RTOS не влияет на необработанную задержку
прерывания, и можно обслужить прерывание точно таким же образом, Вы были бы в
non-RTOS-based системе. Однако, поскольку мы видели планировщик, и любые
вызовы API RTOS также генерируют исключения процессора Cortex-M (Рис. 10.1).

Рисунок 10.1
RTOS генерирует SysTick и исключения SVC. Они должны быть интегрированы с
пользовательскими прерываниями ввода-вывода для создания
успешной системы.

Планировщик RTOS использует исключение таймера SysTick, и вызовы API


RTOS используют вызов контролера (SVC) инструкция. Эти исключения также
борются с прерываниями ввода-вывода через систему приоритетов NVIC. Если
SysTick и исключения SVC

Руководство разработчика по семейству процессоров Cortex-M.


DOI: http://dx.doi.org/10.1016/B978-0-08-100629-0.00010-4 351
© 2016 Elsevier Ltd. Все права защищены.
352 Главы 10

настроенный с высоким приоритетом, они вытеснят пользовательские периферийные


устройства и вызовут задержку с обслуживанием периферийного ISR. Если мы
увеличим приоритет пользовательских прерываний ввода-вывода затем, то
периферийный ISR будет подаваться, но исключения RTOS будут задержаны, и это
уничтожит функции в реальном времени RTOS (Рис. 10.2).

Рисунок 10.2
Исключение SysTick выполняет минимальный объем кода RTOS для поддержания его функций
в реальном времени. Это затем устанавливает ОЖИДАТЬ исключение и выходы. Это
позволяет любым прерываниям ввода-вывода выполняться сопровождаемый ОЖИДАТЬ
исключением. ОЖИДАТЬ исключение выполнит остаток от кода RTOS.

К счастью, процессоры Cortex-M имеют дополнительное исключение, названное


ОЖИДАТЬ исключением, которое используется для смягчения против этой проблемы.
ОЖИДАТЬ прерывание является просто каналом прерывания, который подключен к
регистру программного обеспечения. В системном блоке управления Cortex-M
(USERSETMPEND укусил в регистре CFG_CTRL), а не периферийное устройство
устройства. То, когда регистр программного обеспечения записан в a, ОЖИДАЙТЕ
исключение, повышено, и NVIC включит выполнение ОЖИДАТЬ исключение тем же
способом как любой другой источник прерывания. ОЖИДАТЬ исключение также
настроено для имения самого низкого приоритета прерывания в наличии. Таким
образом в RTOS, таймер SysTick генерирует периодические исключения в самом
высоком приоритете. В исключении SysTick мы выполняем абсолютный
минимальный объем кода RTOS, чтобы поддержать его функции в реальном времени,
затем установить ОЖИДАТЬ исключение и затем выйти из исключения SysTick.
После того как мы выходим из исключения SysTick, любая незаконченная
периферийная IRS теперь могут работать. Когда все прерывания ввода-вывода будут
обслужены, ОЖИДАТЬ исключение будет обслуживаться. В ОЖИДАТЬ ISR мы
можем теперь выполнить объем кода RTOS. При помощи этого механизма мы можем
гарантировать, что поддержали функцию в реальном времени RTOS, не оказывая
негативное влияние на ответ прерывания ввода-вывода. Таким образом, возможно
разработать систему, которая использует потоки RTOS, объединенные с ISR,
работающим в собственной задержке прерывания процессора. В следующем разделе
мы будем видеть, как более полно интегрировать обработку прерывания ввода-вывода
с потоками RTOS.

Обработка прерываний RTOS


При работе с RTOS желательно сохранить функции ISR максимально короткими.
Идеально ISR просто будет несколькими строками кода, берущего минимальную
сумму времени выполнения. Один
Методы RTOS 353

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

На Рис. 10.3 мы посмотрим на интеграцию ISR и обслуживание выполнения потока с


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

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

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


освободите servicing_Thread3 (пусто)
{
в то время как (1)
{
osSignalWait (isrSignal, waitForever);//Ожидают ISR для инициирования события
//Обработайте прерывание
}\ //цикл вокруг и возвращаются сон
}
354 Главы 10

Фактический обработчик прерываний будет содержать минимальный объем кода.


освободите IRQ_Handler (пусто)
{
osSignalSet (tsk3, isrSignal); //Поток Сигнала 3 с событием
}

Упражнение 10.1 Обработка осуществления прерывания


RTOS
CMSIS-RTOS не представляет задержки в обслуживании прерываний,
сгенерированных пользовательскими периферийными устройствами. Однако
операция RTOS может быть нарушена при блокировке прерывания SysTick в течение
длительного промежутка времени. Это осуществление демонстрирует метод передачи
сигналов, потока от прерывания и обслуживания прерывания ввода-вывода с
потоком, а не стандартным ISR.
Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Выберите вкладку Example и Копию “обработка прерываний EX 10.1 RTOS”.

В основной функции мы инициализируем ADC и создаем поток ADC, который


имеет более высокий приоритет, чем все другие потоки.
osThreadDef (adc_Thread, osPriorityAboveNormal, 1, 0); международное
основное (пустота) {

LED_Init ();
init_ADC ();
T_led_ID1 5 osThreadCreate (osThread (led_Thread1), ПУСТОЙ
УКАЗАТЕЛЬ); T_led_ID2 5 osThreadCreate (osThread (led_Thread2),
ПУСТОЙ УКАЗАТЕЛЬ); T_adc_ID 5 osThreadCreate (osThread
(adc_Thread), ПУСТОЙ УКАЗАТЕЛЬ);

Однако существует проблема, когда мы входим основной (): код работает в


непривилегированном режиме, таким образом, мы не можем получить доступ к
регистрам NVIC, не вызывая исключение отказа. Существует несколько окольных
путей это; самое простое должно предоставить привилегированный доступ потоков
путем изменения настроек в RTX_Conf_CM.c (Рис. 10.4).
Рисунок 10.4
Настройте потоки RTOS для назначения полномочий доступу к регистрам процессора
Cortex-M.
Методы RTOS 355

Здесь, мы переключили “Режим процессора для Выполнения Потока” к


привилегированному, который предоставляет полный доступ потоков к процессору
Cortex-M. Поскольку мы добавили поток, мы также должны увеличить число
параллельных рабочих потоков.
Создайте код и запустите отладчик.
Набор устанавливает контрольные точки в led_Thread2, ADC_Thread и
ADC1_2_IRQHandler (Рис. 10.5).

Рисунок 10.5
Точка останова на “запускается преобразования ADC”.
И в adc_Thread () (Рис. 10.6)

Рисунок 10.6
Точка останова в потоке ADC.

И в обработчике ADC1_2_IRQ (рис. 10.7)

Рисунок 10.7
Точка останова в прерывании ADC.

Выполните код.

Вы поразите первую точку останова, которая запускает преобразование ADC, затем


выполняет код снова, и Вы введете обработчика прерываний ADC. Обработчик
устанавливает сигнал adc_thread и выходы. Установка сигнала заставит поток ADC
вытеснять любую другую выполняющуюся задачу, выполнять служебный код ADC и
затем блок, ожидающий следующего сигнала.

Пользовательские функции супервизора


В последнем примере мы смогли настроить потоки и структуру прерывания без любого
дополнительного соображения, потому что RTOS был настроен для выполнения кода
потока как привилегированного кода. В некоторых проектах может быть необходимо
настроить RTOS так, чтобы потоки работали в непривилегированном режиме. Это
означает, что код потока больше не будет мочь записать в NVIC, так как RTOS работает,
когда мы входим основной (). Мы застреваем в режиме Thread и больше не не смочь
включить любой источник прерывания. Для кода потока для доступа к NVIC мы должны
смочь изменить наш режим выполнения для выполнения в режиме Handler. В режиме
Handler мы
356 Глав 10

будет иметь полный привилегированный доступ ко всем регистрам процессора Cortex-M.


Поскольку мы видели в Главе 5 “Усовершенствованные Архитектурные Функции”, это
может быть сделано путем выполнения инструкции SVC.

Упражнение 10.2 RTOS и пользователь исключения SVC


В этом осуществлении мы посмотрим на использование исключения системного
вызова для перехода к привилегированному режиму для выполнения “системного
кода” уровня.
Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Выберите вкладку Example и копию “Исключая 10.2 ПОЛЬЗОВАТЕЛЯМИ RTOS
SVC” к Вашему учебному каталогу.
Исследуйте файл RTX_Conf_CM.c (Рис. 10.8).

Рисунок 10.8
Выполнение потока установлено на непривилегированный
режим.

В разделе Thread Configuration рабочий режим для выполнения потока


установлен на “Непривилегированный режим”.

В проекте мы добавили новый файл под названием SVC_Table.s (Рис. 10.9). Этот файл
доступен как “Пользовательский Шаблон Кода” (Пользователь CMSIS-RTOS SVC) от,
“Добавьте Новый Объект” диалоговое окно:
Рисунок 10.9
Добавьте пользовательский файл шаблона SVC.

Откройте файл
SVC_Tables.c.
Методы RTOS 357

Это - справочная таблица для прерываний SVC.


; Импортируйте пользователя функции
SVC сюда.
ИМПОРТИРУЙТЕ __
SVC_1
SVC_Table
SVC_Table ЭКСПОРТА
; Введите пользователя функции SVC здесь. SVC 0 используемых Ядром
RTX. DCD __ SVC_1; пользователь функция SVC

В этом файле мы должны добавить имя импорта и запись в таблице для каждого __
функция SVC, которую мы собираемся использовать. Добавьте __ прорезывания
зубов SVC_1 как показано выше.
Преобразуйте init_ADC () функция к исключению служебного вызова как показано
ниже.
освободите __ svc (1) init_ADC
(пусто); освободите __ SVC_1 (пусто)
{

Разработайте проект и запустите отладчик.

Шаг код (F11) к вызову к init_ADC функционирует и исследует рабочий режим в


окне Register.
Здесь мы находимся в режиме Thread, непривилегированном, и использование стека
процесса (Рис. 10.10).

Рисунок 10.10
Процессор находится в непривилегированном состоянии с помощью
стека процесса.

Теперь шаг в функцию (F11) и шаг через ассемблер, пока Вы не достигаете


init_ADC () функция.

Теперь, мы работаем в режиме Handler с привилегированным доступом и используем


основной указатель вершины стека (Рис. 10.11).
Рисунок 10.11
Процессор переключился на привилегированное состояние с помощью
основного стека.

Это позволяет нам настраивать ADC и также получать


доступ к NVIC.
358 Глав 10

Управление питанием
Одно из преимуществ разработки с RTOS - то, что мы можем полагать, что каждый из
потоков приложения работает параллельно. Это позволяет нам разрабатывать
независимые потоки кода, который каждый может выполнить специализированную
задачу и передать вместе для создания требуемого приложения. Этот уровень
абстракции предоставляет много преимуществ, поскольку проекты становятся более
сложными. Однако добавление кода управления питанием к этой многопоточной
среде может казаться пугающим сначала, потому что должны гарантировать, что
каждый поток готов ввести состояние низкой мощности.

Типичный Основанный на Cortex-M микроконтроллер будет иметь несколько


режимов низкой мощности. В то время как они будут варьироваться между
различными кремниевыми производителями, Таблица 10.1 суммирует типы режима
низкой мощности, с которым Вы, вероятно, встретитесь.

Таблица 10.1: Типичные режимы низкой мощности


микроконтроллера
Низкая
мощность
Состояние Состояние электропитания Источник пробуждения
Прерывание ввода-вывода,
Сон ЦП ЦП в состоянии низкой мощности таймер SysTick
ЦП и периферийные устройства в Сброс, контакт пробуждения или
ЦП и состоянии низкой мощности внешний
периферийное
устройство контакт прерывания
Полная мощность вниз ЦП, периферийных
Глубокий сон устройств, Сброс или контакт пробуждения
SRAM и Flash

Состояния низкой мощности вводятся путем выполнения __ wfi () инструкция. По


умолчанию это будет только влиять на процессор Cortex-M путем размещения ЦП в
его режим ожидания. Процессор Cortex-M также имеет сигнал SLEEPDEEP, который
подключен к аппаратным средствам управления питанием микроконтроллера. Если
это будет включено в Cortex-M “Системный регистр” Управления Процессором, то
сигнал SLEEPDEEP будет утверждаться, когда __ wfi () инструкция будет выполнена.
Для ввода данного состояния низкой мощности код приложения должен настроить
регистры управления питанием микроконтроллера для выбора желаемого состояния
низкой мощности. Обычно, чем глубже режим низкой мощности, тем более строгий
условия выхода.

Первые шаги управления питанием


Мы должны поместить микроконтроллер в самый низкий режим питания,
возможный, не нарушая производительность кода приложения. К счастью, первый
шаг в управлении питанием очень прост. Когда все потоки приложения будут в
заблокированном состоянии, например, ожидая прерывания для появления или
задержка для истечения, планировщик RTOS поместит os_Idle_demon () в состояние
выполнения. По умолчанию os_Idle_demon () просто содержит пустое для (; ;) цикл,
который выполняется до потока приложения, становится готовым работать. Другими
словами, мы просто сидим в os_Idle_demon () горящая энергия.
Методы RTOS 359

освободите os_idle_demon (пусто)


{для (;;) {
/* ЗДЕСЬ: включайте дополнительный пользовательский код, который будет выполняться, когда никакой
поток не будет работать. */
}}

Так, когда мы находимся в os_idle_demon (), там не имеет отношения, мы можем


просто ввести режим ожидания ЦП, который отключит часы к процессору Cortex-M,
но оставит остальную часть микроконтроллера активной. Как правило, операция
низкой мощности микроконтроллера примет значение по умолчанию к этому
режиму, таким образом, все, что мы должны сделать, будет, выполняются __ wfi ()
инструкция, когда код находится в os_idle_demon ().
освободите os_idle_demon (пусто)
{для (;;) {
__ wfi ();
}}

Теперь, как только процессор Cortex-M не выполняет значимого кода, тактовая


частота ЦП будет остановлена, пока периферийное устройство не генерирует
прерывание, или следующее прерывание SysTick происходит для выполнения
планировщика RTOS.

Эта строка кода остановит опустошительную энергию ЦП, не влияя на


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

Использование более усовершенствованных режимов питания действительно требует


немного более мысли. Когда мы переходим к более глубокому режиму низкой
мощности, методы пробуждения более ограничиваются. Это означает, что мы должны
быть уверены, что код приложения готов ввести состояние низкой мощности.
Считайте код показанным ниже:
Application_thread (пусто)
{
в то время как (1)
{
os_message ожидают ();
function_1 (); osDelay
(10); function_2 ();
}}

Поток запускается путем ввода заблокированного состояния, ожидающего сообщения


для прибытия. Когда данные сообщения прибудут, поток проснется и назовет
function_1 (), и затем это снова введет заблокированное состояние, когда osDelay ()
функция назовут. После того как задержка истекла, поток возобновит и назовет
function_2 () прежде еще раз ввести заблокированное состояние, пока следующее
сообщение не прибудет. Этот поток имеет две точки, в которых он введет
заблокированное состояние и если все другие потоки будут также заблокированы, то
заставит os_idle_demon работать. Для планировщика RTOS нет никакой реальной
разницы между двумя вызовами ОС, но для управления питанием
360 Глав 10

существует важное различие. Когда поток заблокирован os_message_wait (); звоните


это действительно неактивно и не может продолжиться, пока другая часть системы не
дает ему некоторые данные для обработки. Когда поток заблокирован osDelay ()
функция в целях управления питанием, это все еще бодрствует в том смысле, что это
продолжит обрабатывать без входа от любой другой части системы. Так, мы должны
создать наши потоки приложения так, чтобы они ожидали на “событии”,
инициированном некоторой другой частью системы, выполнили свою функцию и
затем ожидали следующего события для появления. Это означает, что каждый поток
теперь имеет ключевую точку блокирования (Рис. 10.12).

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

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

Стратегия управления питанием


Для создания нашей стратегии управления питанием мы сначала должны объявить
глобальную переменную, которая будет содержать два флага для каждого потока,
работающего на системе (Рис. 10.13).
Рисунок 10.13
Флаги управления питанием сохранены в глобальной переменной и
контролируются в неактивном потоке.
Методы RTOS 361

Каждый поток имеет один “поток, выполняющий” бит и один “поток, ожидающий”
бит. Затем, мы должны записать некоторые простые функции, которые будут
управлять этими битами. Когда поток просыпается для запуска выполнения его кода,
мы должны установить выполняющий поток бит. Поскольку несколько потоков
будут получать доступ к powerFlags переменной, она должна быть защищена
взаимным исключением.
освободите taskIsRunning (uint16_t задача)
{osMutexWait (PowerMutex, osWaitForever);
powertFlags | 5 задач; osMutexRelease (PowerMutex);

Когда это выполнило свою задачу и собирается возвратиться в состояние


ожидания, мы должны очиститься, выполнение потока укусило.
освободите taskIsSuspended (uint16_t задача)
{osMutexWait (PowerMutex, osWaitForever);
powerFlags и 5 Btask; osMutexRelease
(PowerMutex);

Таким образом, теперь поток приложения смотрит следующим образом:


#define APPLICATION_THREAD 1
Application_thread (пусто)
{
в то время как (1)
{
taskIsSuspended (APPLICATION_THREAD)
osMessageGet (почтовый ящик, osWaitForever);
taskIsRunning (APPLICATION_THREAD);
function_1 ();
osDelay (10);
function_2 ();
}}

Когда другая часть системы собирается инициировать поток, в этом случае путем
отправки сообщения мы можем установить потоки, ожидающие бит. Это
гарантирует, чтобы мы избежали любых проблем с планировщиком.
освободите taskIsPending (uint16_t задача) {osMutexWait
(PowerMutex, osWaitForever);
powerFlags | 5 (задача, NUM_THREADS);//Поставившая Задача, Ожидающая
бит osMutexRelease (PowerMutex);
}

Теперь отправка сообщения к нашему потоку приложения похожа на это:


taskIsPending (APPLICATION_THREAD); osMessagePut
(почтовый ящик, appData, osWaitForever);
362 Главы 10

Мы должны изменить taskIsRunning стандартную программу для очистки


этого бита, когда выполнение потока приложения возобновляется.
освободите taskIsRunning (uint16_t задача) {osMutexWait
(PowerMutex, osWaitForever); powertFlags | 5 задач;
powerFlags и 5 B (задача, NUM_THREADS);
osMutexRelease (PowerMutex);
}

Когда приложение вводит os_Idle _demon () поток, мы можем протестировать


powerFlags. Если какой-либо из битов задачи (активный или незаконченный)
установлен, то система не действительно неактивна. Если все флаги питания являются
нулем, то система действительно неактивна, и мы можем безопасно перейти к режиму
низкой мощности. Следующий код может быть помещен в os_idle_demon ():
если (powerFlags 55 0) {
configureAndEnterDeepPowerDown ();//Все задачи неактивны, так войдите, глубоко выключают режим
} еще {
configureAndEnterSleepMode (); //Задача активна, но мы можем ввести режим ожидания
для экономии электроэнергии времени выполнения
}

Таким образом, теперь os_idle_Demon () будет использовать доступные режимы


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

Сторожевое управление
Мы можем также использовать флаги управления питанием для решения другой
проблемы. В этом случае мы хотим включить аппаратный сторожевой таймер на
микроконтроллере. Было бы возможно снова наполнить сторожевой таймер в
каждом потоке. Однако, поскольку мы постоянно переключаемся
между потоками вероятно, что сторожевой счетчик был бы снова наполнен
несколькими различными потоками, и мы будем не мочь обнаружить, если данный
поток перестал работать. Для лучше использования сторожевой таймер мы должны
добавить отдельный системный поток, который используется для контроля потока
незаконченные биты. Системный монитор периодически работает как
пользовательский таймер. Каждый раз, когда это работает, это проверит поток
незаконченные биты. Если незаконченный бит установлен затем, переменная счетчика
соответствия увеличена. Если порог превышен затем, система по ошибке, сторожевой
таймер не будет снова наполнен, и аппаратный сброс будет вызван.
освободите taskMonitor (пусто)
{uint8_t stalledTaskError 5 0;
для (цикл 5 PEND_START_BIT, индекс 5 0; цикл, PEND_END_BIT; цикл, 51, index11) {если
(powerFlags &loop)) {
watchdogCounters [индекс] 11; если (WatchdogCounters
[индекс].MAX_TASK_STALL_COUNT) {
taskIsStalled 5 TRUE;
Методы RTOS 363

}}}
если (stalledTaskError 55 0)
{patWatchdog ();
}}

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


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

освободите taskIsRunning (uint16_t задача)


{osMutexWait (PowerMutex, osWaitForever);
powertFlags | 5 задач;
powerFlags и 5 B (задача, NUM_THREADS);
taskNumber 5 32-__ clz ((uint32_t) taskQuery);//внутренние начальные нули количества инструкции clz 5

taskWatchdogCounters[taskNumber-1] 5 0;
osMutexRelease (PowerMutex);
}

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


преобразования от небольшого положения до целочисленного значения. Это
очень эффективно и берет минимальное количество циклов ЦП.

Интеграция ISRs
В случае прерывания, которое будет будить процессор и сигнализировать, чтобы
поток продолжил обрабатывать, мы можем использовать флаги питания в качестве
средства обеспечения тайм-аута, который позволяет микроконтроллеру возвращаться
ко сну. Например, если микроконтроллер будет в режиме низкой мощности,
ожидающем данных, которые будут отправлены в UART. Затем некоторые случайные
помехи могут разбудить процессор, который будет затем ожидать полного пакета
сообщений, который будет отправлен. В этой ситуации мы можем представить флаг
питания для ISR UART, который установлен в ISR и очищен только, когда полное
сообщение было получено. В сторожевой стандартной программе мы можем
увеличить счетчик, если пороговое значение достигнуто затем вместо того, чтобы
сбросить микроконтроллер, мы просто должны очистить флаг выполнения ISR, чтобы
позволить процессору отступать ко сну. В то время как функции питания ISR по
существу выполняют ту же задачу, как питание потока функционирует, мы должны
обеспечить выделенные функции, которые не получают доступ к взаимному
исключению, поскольку взаимное исключение не может быть получено стандартной
программой ISR того же или более низкого приоритета.
освободите IsrTaskIsPending (uint16_t задача)
{powerFlags | 5 (задача, 8);
}
освободите IsrIsInactive (uint16_t задача) {powerFlags
и 5 B (задача); resetCurrentTaskWatchdogCounter
(задача);

Затем в сторожевой задаче, мы можем протестировать флаг ISR и увеличить счетчик


UART, если это установлено.
364 Главы 10

если (taskManagementFlags и WIRED_COMMS)


{
taskWatchdogCounters[WIRED_COMMS_COUNTER]11;
}

Если мы превышаем пороговый уровень, мы можем использовать защищенный


taskIsSuspended взаимного исключения () стандартная программа, чтобы очистить
флаг ISR и также сбросить сторожевой счетчик.
если (taskWatchdogCounters[UART_ISR].UART_TIMEOUT)
{
taskIsSuspended (UART_ISR);
taskWatchdogCounters[UART_ISR] 5 0;
}

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

Упражнение 10.3 Питание и сторожевое управление


Мы видим эти примеры на практике путем запущения простой программы в средстве
моделирования MDK-ARM. Это - простая программа RTX, которая использует
несколько задач высветить группу светодиодов в последовательности. Запуск каждой
последовательности инициирован аппаратным прерыванием по таймеру. В этом
примере мы запустим с рабочей программы и представим сторожевой код и
управление питанием.
Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Выберите вкладку Example и Копию “управление питанием EX 10.3 RTOS”.
Запустите средство моделирования путем выбора debug\start:: остановите сеанс
отладки.
Откройте peripherals\General Цель окно отладки IO\GPOIOB.
Запустите код, работающий с debug\run.

После начального небольшого количества секунды необходимо видеть старший


байт GPIO B контакты, переключаемые задачами приложения.
Откройте View\Analysis window\Performance анализатор.
Здесь, мы видим, что в этой простой программе большую часть времени
выполнения тратится в RTX_Idle_demon () (Рис. 10.14).
Методы RTOS 365

Рисунок 10.14
Шоу анализатора производительности, что эта простая программа проводит
большую часть своего времени в неактивной
опустошительной энергии потока.

Выйдите из отладчика путем выбора debug\start остановки.

Откройте файл RTX_Conf_CM.c и найдите os_Idle_demon на строке 141.


Не прокомментируйте __ wfi (); назовите и восстановите код с
project\build. Перезапустите средство моделирования с debug\start,
наклоняют и запускают выполнение кода.

Если мы теперь вновь исследуем проект в анализаторе производительности, мы


видим поразительное сокращение количества циклов, использованных os_Idle
задачей (Рис. 10.15).

Рисунок 10.15
Теперь процессор вводит сон в неактивный поток, который минимизирует
использование энергии во время выполнения.

__ wfi () инструкция помещает процессор в режим ожидания, который экономит


электроэнергию в процессоре Cortex-M. Однако периферийные устройства
микроконтроллера все еще расходуют энергию. Для использования в своих интересах
более глубоких режимов низкой мощности, обеспеченных производителем
микросхемы, мы должны обнаружить, когда приложение неактивно, и затем поместите
устройство в более глубокий режим низкой мощности, пока это не готово
перезапустить обработку.
366 Глав 10

Теперь исследуйте задачи приложения.


__ задача пустой phaseA (пусто) {
для (;;) {
taskIsSuspended (p_phaseA); //Задача закончилась, готовятся ко сну
osSignalWait (0x0010, osWaitForever); //точка блокирования Задачи
taskIsRunning (p_phaseA); //Задача проснулась, выполнение набора укусило
LED_On (LED_A);
signal_func ();
taskIsPending (p_phaseB); //устанавливает ожидание, обдумал Задачу B
osSignalSet (0x0001, t_phaseB);
osDelay (5);
LED_Off (LED_A);
}}

В каждом потоке мы определяем, что ключевое блокирование указывает и окружает


его taskIsSuspended () и taskIsRunning () функции. Если задача общается с другим
потоком, мы должны сначала назвать taskIsPending () функцией.

Теперь вернитесь к os_Idle_Task () и прокомментируйте __ wfi () инструкция и


не прокомментируйте enterLowPowerState () функция.

enterLowPowerState () функция проверяет, что питание отмечает и решает который


режим питания войти.
освободите enterLowPowerState (пусто) {
если (powerFlags 55 ALL_TASKS_INACTIVE)
{
configureAndEnterDeepSleepMode ();
} еще {
configureAndEnterSleepMode ();
}}

В каждой из функций конфигурирования низкой мощности мы обычно настраивали


бы режим питания микроконтроллера и работали бы __ wfi () инструкция. Однако в
демонстрационных целях мы будем сидеть в функции и просто переключать
переменную отладки.
освободите configureAndEnterDeepSleepMode (пусто)
{
задержка uint32_t;
// SCB-.SCR | 5 (1, SCB_SCR_SLEEPDEEP_Pos); //включите режим глубокого сна
// __ wfi (); //Поместите микро в глубокий сон
для (задерживаются 5 0; задержка, 0x100; delay11); //Простая задержка
debugDeepSleep ^ 5 0x01; //Переключите переменную отладки
}

Восстановите код и перезапустите отладчик.


Откройте окно Анализатора логики с view\analysis window\Logic анализатор.
Методы RTOS 367

Запустите выполнение кода.

После того, как код работал в течение нескольких секунд, нажимают кнопку Min/Max
Auto и нажимают уменьшение кнопки, пока Вы не получаете представление, подобное
Рис. 10.16.

Рисунок 10.16
Анализатор логики может использоваться для показа записи в режимы
ожидания.

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


Твердые блоки указывают, где мы находимся в режиме низкой мощности. Более
низкая трассировка показывает, что сон отлаживает переменную снова, твердые
блоки показывают, где мы находимся в режиме низкой мощности. Здесь, мы видим,
как код сохраняет энергию и в ее дежурном режиме и в также во время выполнения
во время выполнения кода приложения.
В blinky.c не комментируют os_tsk_create (Монитор, 10); запрос к строке 171.

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


задач приложения работает правильно.

Для создания ошибки не прокомментируйте код в blinky.c 131 to 136, это


позволит выполнению приложения несколько раз и затем удалит задачу A.
Создайте код и запустите средство моделирования.
Откройте watchdog.c и добавьте массив taskWatchdogCounters к окну часов.
Добавьте точку останова на taskIsStalled 5 TRUE; строка 86.
Откройте debug\os support\RTX системное окно и Задача.
Запустите выполнение кода.
После того, как код работал, светодиодная последовательность высвечивания пять
раз удалит задачу phase_A () от системы (Рис. 10.17).
368 Глав 10

Рисунок 10.17
Потоки приложения и сторожевой таймер контролируют поток.

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


и увеличьте taskWatchdogCounters, связанный с задачей phaseA.
Наблюдайте taskWatchdogCounters в окне часов (Рис. 10.18).

Рисунок 10.18
Сторожевой таймер противостоит для каждого потока.

Счетчик 0 начнет увеличивать. Когда это поразит MAX_TASK_STALL_COUNT


(пять), мы поразим точку останова.

Запустите код, работающий снова, taskIsStalled переменная будет установлена. Это


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

Этот подход к питанию и сторожевому управлению в и RTOS нужно рассмотреть при


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

Барьер запуска
Если Вы запускаете работу с нового микроконтроллера или собираетесь начать
добавлять код низкой мощности, это - хорошая практика для добавления “барьера
запуска” для кода. На ранних стадиях развития при конфигурировании системных
периферийных устройств возможно случайно поместить микроконтроллер в
возмущенное состояние, где это становится трудным или невозможным соединиться
через отладку CoreSight. Кроме того, возможно добавить код, который помещает
микросхему в неработоспособное состояние питания, которое снова лишает
возможности соединять отладчик. Если это происходит, Вы больше не можете
стирать Flash и программировать память. Если у Вас только есть ограниченное
предоставление макетных плат, это может быть смущающей проблемой! “Барьер
запуска” является просто небольшой функцией, которая только позволит коду
продолжаться, если определенный шаблон будет в определенном месте Оперативной
памяти.
энергозависимый uint32_t debuggerAttached __ приписывает __ ((в (0x2000FFFC)));
освободите startupBarrier (пусто)

{
если (debuggerAttached! 5 0x55555555) {__
BKPT (0);
}
}

Эта функция вызвана на самой первой строке system_init () перед любым кодом,
который может нарушить процессор Cortex-M, был назван. Если мы создадим
программу с таким “барьером запуска” и загрузим его во Флэш-память, то он запустит
выполнение и затем станет захваченным в барьерной функции. Это гарантирует, что
мы можем стереть и повторно программировать Флэш-память. Для заканчивания
“барьера запуска” мы можем добавить файл сценария к отладчику, который
программирует шаблон барьера в RAM (Рис. 10.19).
Рисунок 10.19
Добавьте сценарий барьера запуска как файл инициализации
отладчика.
370 Глав 10

Теперь, когда мы запускаем отладчик, шаблон барьера будет присутствовать в месте


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

Разработка в течение реального времени


До сих пор мы посмотрели на функции DSP Коры-M4 и библиотеки DSP
поддержки. В следующем разделе мы посмотрим на разработку программы DSP в
реальном времени, которая может также поддерживать не управляемый событиями
код в реальном времени как пользовательский интерфейс или коммуникационная
стопка, не нарушая производительность алгоритма DSP.

Буферизация методов — двойной или кольцевой буфер

При разработке первого приложения DSP в реальном времени первое решение,


которое необходимо принять, состоит в том, как буферизовать входящие блоки
данных от ADC и исходящие блоки данных к DAC. Стандартное решение состоит в
том, чтобы использовать форму двойного буфера как показано на Рис. 10.20.

Рисунок 10.20
Простая система DSP может использовать двойной буфер для получения
потока данных.

В то время как буфер Ping заполнен данными из ADC, алгоритм DSP обрабатывает
данные, хранившие в буфере Вони. После того как ADC достигает конца буфера
Ping, он начнет хранить данные в буфер Вони, и новые данные в буфере Ping могут
быть обработаны. Подобная структура Пинг-понга может использоваться для
буферизации выходных данных к DAC (Рис. 10.21).
Методы RTOS 371

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

Этот метод работает хорошо на простые приложения; это требует минимального


объема памяти и представляет минимальную задержку. Код приложения должен
сделать всю необходимую организацию буферизации данных. Однако когда
сложность приложения повышается, этот подход начинает сталкиваться с
проблемами. Основной вопрос - то, что у Вас есть критический крайний срок для
встречи в этом, алгоритм DSP, должно быть, закончил обрабатывать буфер Вони,
прежде чем ADC заполнит буфер Ping. Если, например, ЦП должен выполнить
некоторый другой критический код, такой как пользовательский интерфейс или
коммуникационная стопка затем не может быть достаточной вычислительной
мощности, доступной для выполнения всего необходимого кода и алгоритма DSP
вовремя для встречи конца буферного крайнего срока. Если алгоритм DSP пропустит
свой крайний срок, то ADC начнет перезаписывать активный буфер. Затем
необходимо написать более сложный код организации буферизации данных для
“нагоняния”, но действительно Вы на проигрывающую игру, и данные будут в какой-
то момент потеряны.

Буферизация очереди сообщений FIFO методов

Альтернатива основному подходу двойного буфера должна использовать RTOS для


обеспечения более сложной структуры буферизации с помощью системы почтового ящика
для создания очереди FIFO (Рис. 10.22).
372 Главы 10

Рисунок 10.22
Обработка блока с помощью почтовых очередей RTOS увеличивает задержку
сигнала, но обеспечивает надежную интеграцию потока DSP в
сложное приложение.

Используя RTX RTOS, мы можем создать задачу, которая используется для


выполнения алгоритма DSP. Вводы и выводы этой задачи являются парой почтовых
ящиков. Прерывание ADC используется, чтобы заполнить сообщение почтового
ящика блоком данных ADC и затем добавить то сообщение к задаче DSP. Эти блоки
сообщений затем помещаются в очередь FIFO, готовую быть обработанной. Теперь,
если другой критический код должен работать, задача DSP будет вытеснена и а не
проигрышные данные риска, поскольку в двойном буфере случаются, блоки данных
будут находиться в очереди сообщений. После того как критический код работал,
задача DSP продолжит работать и может использовать всю вычислительную
мощность ЦП для “нагоняния” с отставанием данных. Подобная очередь сообщений
используется для отправки блоков данных в DAC. Использование очередей
сообщений RTOS обеспечивает простую и изящную систему буферизации без
потребности написать любой низкоуровневый код.

В первом примере программы ADC выбирает на уровне 40 кГц, и выборочные


данные помещается в 32-байтовый буфер сообщений.

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


сообщения. Этот регион отформатирован в группу почтовых слотов. Каждый
почтовый слот является структурой в форме данных, которые Вы хотите отправить.
Форма почтового слота может быть любым набором данных, объявленных как
структура. В нашем случае мы хотим, чтобы массив значений с плавающей точкой
был нашим блоком данных.
Методы RTOS 373

структура определения типа {


буфер данных float32_t [BLOCK_SIZE];//объявляют структуру для почтового слота очереди сообщений}
ADC_RESULT;

Затем, блок памяти резервируется для почтовой очереди. Здесь память


зарезервирована для очереди 16 почтовых слотов. Данные могут быть записаны в
каждый почтовый слот, почтовый слот затем заблокирован, пока сообщение не
получено, и буфер выпущен.
osMailQDef (mpool_ADC, 16, ADC_RESULT);

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


указатель. Указатель помещается в очередь, которая читается как FIFO. Важно
отметить, что указатель перемещен, в то время как фактические данные остаются
статичными.
os_mbx_declare (MsgBox_ADC, 16);//объявляют указатели сообщения

Затем почтовый ящик можно инстанцировать путем форматирования окна сообщения.


osMailQId MsgBox;

И затем инициализируя очередь указателя сообщения.


MsgBox 5 osMailCreate (osMailQ (MsgBox), ПУСТОЙ УКАЗАТЕЛЬ);

После того как это сделано, почтовый ящик готов отправить данные между
потоками или ISR и потоками. Код ниже показывает обработчик ADC,
регистрирующий 32 преобразования в почтовый слот и затем отправляющий его на
стандартную программу DSP.
освободите ADC_IRQHandler (пусто) {
статический ADC_RESULT *mptr; //объявляют почтовый
слот
указатель
статический неподписанный символьный индекс 5 0;
если (индекс 55 0) {
mptr 5 _alloc_box (mpool_ADC);
mptr 5 (ADC_RESULT*) osMailAlloc (MsgBox, osWaitForever); //выделяют новое
почтовый слот
}
mptr-.dataBuffer [индекс] 5 (плавание) ((LPC_ADC-.ADGDR.. 4) и 0xFFF);//помещают данные ADC в
почтовый слот
index11;
если (индекс 55 BLOCK_SIZE) {
индекс 5 0;
osMailPut (MsgBox, mptr); //, когда почтовый слот
полный отправляют
}}
В основном потоке DSP код приложения ожидает блоков данных для прибытия в
очередь сообщений от ADC. Когда они прибывают, каждый обрабатывается и
результаты, помещенные в подобную очередь сообщений, которая будет питаться в
DAC.
374 Главы 10

освободите DSP_thread (пусто) {


ADC_RESULT *ADCptr; //объявляют указатели почтового
слота
для почтовых ящиков ADC и
DAC
ADC_RESULT *DACptr;
в то время как (1) {
evt 5 osMailGet (MsgBox_ADC, osWaitForever); //ожидают сообщения от
ADC
если (evt.status 55 osEventMail) ADCptr 5 (ADC_RESULT*) evt.value.p;
DACptr 5 (ADC_RESULT*) osMailAlloc (MsgBox, osWaitForever);//Выделяют почтовый слот для
очередь сообщений DAC
DSP_Alogrithm (ADCptr-.dataBuffer, DACptr-.dataBuffer);//Выполнение алгоритм DSP
osMailPut (MsgBox, DACptr); //Сообщение результаты к DAC
очередь сообщений
osMailFree (MsgBox, ADCptr); //Выпуск почтовый слот ADC
}}

В примере кода второй поток используется для чтения, DAC передают и пишут
обработанные данные в выходной регистр DAC.
освободите DAC_task (пусто) {
неподписанный интервал i;
ADC_RESULT *DACrptr;
в то время как (1) {
evt 5 osMailGet (MsgBox, osWaitForever); //Ожидают почтового слота
обработанные данные
если (evt.status 55 osEventMail) DACrptr 5 (ADC_RESULT*) evt.value.p;
для (я 5 0; я, (BLOCK_SIZE); i11) {
osSignalWait (0x01, osWaitForever); //синхронизируются с
Частота дискретизации ADC
LPC_DAC-.DACR 5 (неподписанный интервал) DACrptr-.dataBuffer [я], 4;//пишут обработанные данные
оцените регистру DAC
}
osMailFree (MsgBox, DACrptr); //освобождают почтовый слот
}}

osSignalWait () вызов RTX вызывает задачу DAC остановиться до другого потока, или
ISR устанавливает свои флаги события на шаблон 0x0001. Это - простой метод
инициирования между потоком, который может использоваться для синхронизации
вывода DAC с частотой дискретизации ADC. Теперь, если мы добавляем строку
osSignalSet (tsk_DAC, 0x01);//устанавливает флаг события в задаче DAC.

к ISR ADC это инициирует поток DAC каждый раз, когда ADC делает
преобразование. Задача DAC проснется каждый раз, когда ее флаг события
инициирован, и запишите выходное значение в DAC. Этот простой метод
синхронизирует входные и выходные потоки данных.
Методы RTOS 375

Балансировка загрузки

Приложение имеет две очереди сообщений, один от ISR ADC до потока DSP и другого
от потока DSP до потока DAC. Если мы хотим создать сложную систему, говорят с
GUI и стеком TCP/IP, то мы должны признать, что во время критических периодов
поток DSP будет вытеснен другими потоками, работающими на системе. При условии,
что поток DSP может работать, прежде чем очередь сообщений DAC высыхает, затем
мы не поставим под угрозу данные реального времени. Для преодоления этого мы
можем использовать очереди сообщений для обеспечения необходимой буферизации
для поддерживания системы в рабочем состоянии в течение этих пользующихся
высоким спросом периодов. Все, что мы должны сделать, чтобы гарантировать, что
это происходит, добавляют много сообщений к очереди сообщений DAC, прежде чем
мы запустим выполнение потока DAC. Это представит дополнительную задержку, но
всегда будут доступные данные для DAC. Также возможно использовать значение
тайм-аута в osMessageGet () функция. Здесь, мы можем установить значение тайм-аута
для действия как сторожевой таймер.

evt 5 osMailGet (MsgBox, WatchdogTimeout); если


(evt.status 55 osEventTimeout)
osThreadSetPriority (t_DSP, osPriorityHigh);

Теперь, мы будем знать максимальный период, в который поток DAC должен считать
данные с очереди сообщений. Мы можем установить период тайм-аута, чтобы быть
тремя четвертями этого периода. Если сообщение не прибыло затем, мы можем
повысить приоритет потока DSP. Это заставит поток DSP вытеснять рабочий поток и
процесс и отложенные пакеты данных. Они будут затем отправлены на потоке DAC.
После того как DAC имеет данные для обработки, это может понизить приоритет
потока DSP продолжить обрабатывать как нормальное. Таким образом, мы можем
гарантировать поток данных реального времени в системе с пакетами действия в
других потоках.

Очевидная оборотная сторона наличия большей глубины буферизации сообщения


является увеличенной задержкой сигнала. Однако для большинства приложений это
не должно быть проблемой. Особенно, когда Вы считаете простоту использования
почтового ящика объединенной со сложным управлением памятью RTX RTOS.

Упражнение 10.4 Реальное время RTX


Это осуществление реализует фильтр Импульсной характеристики Бога (IIR) как
задачу RTX. Периодическое прерывание по таймеру берет данные из 12-разрядного
ADC и создает блок данных, который затем отправляется на задачу DSP, которая
будет обработана. Получающиеся данные отправляются назад на таймер ISR. Как
таймер ISR получает обработанные пакеты данных, он пишет выходное значение на
прерывание к 10-разрядному DAC. Частота дискретизации составляет 32 кГц, и
демонстрационный размер блока является 256 образцами (Рис. 10.23).
376 Глав 10

Рисунок 10.23
БИХ-фильтр является фильтром обратной связи, который намного быстрее, чем
фильтр Конечной импульсной характеристики (FIR), но может
быть нестабильным, если неправильно разработано.

Откройте установщик пакета.


Выберите Советы:: разработчики ведут учебное руководство.
Выберите вкладку Example и Копию “Реальное время EX 10.4 RTOS” (Рис. 10.24).

Рисунок 10.24
Проект DSP в реальном времени.

Сначала исследуйте код, особенно модуль DSP_App.c.

Проект на самом деле разработан для основанного на коре-M3


микроконтроллера, который как имитационная модель, которая включает ADC и
DAC. Модули ADC.C, Timer.c, и
Методы RTOS 377

DAC.c содержат функции для инициализации периферийных устройств. DSP_APP.c


модуля содержит задачу инициализации, которая настраивает почтовые очереди и
создает поток DSP, названный “sigmod ()”. Дополнительные “часы ()” поток также
создаются; этот поток периодически высвечивает контакты GPIO для моделирования
другого действия по системе. DSP_App.c также содержит таймер ISR. Таймер ISR
может быть разделен на две половины, первый раздел, читает ADC и отправляет
демонстрационные данные во входящую почтовую очередь потока DSP. Вторая
половина получает сообщения от исходящей почтовой очереди потока DSP и пишет
выборочные данные в DAC. Функции фильтра CMSIS находятся в DSP_IIR.c.
Разработайте проект и запустите средство моделирования.

Когда проект запускается, он также загружает файл сценария, который создает ряд
функций моделирования. Во время моделирования к этим функциям можно
получить доступ через кнопки, созданные в диалоговом окне панели инструментов
(Рис. 10.25).
Выберите view\toolbox

Рисунок 10.25
Кнопки панели инструментов создаются файлом сценария.

Сценарий моделирования генерирует моделируемые аналоговые сигналы, связанные


с основой времени средства моделирования, и применяет их моделируемый входной
контакт ADC (Рис. 10.26).
Откройте окно Logic Analyzer.
378 Глав 10

Рисунок 10.26
Окно анализатора логики.

Анализатор логики должен иметь определенный AIN2 и AOUT двух сигналов каждый
с диапазоном 0 3.3 В. Это не переменные программы, но виртуальные регистры
моделирования, которые представляют контакт аналогового входа и выходной контакт
DAC (Рис. 10.27).

Запустите выполнение средства моделирования и нажмите кнопку “Mixed Signal


Sine” в диалоговом окне панели инструментов.

Рисунок 10.27
Вход смешал синусоидальную волну, и вывод фильтровал форму
сигнала.

Это генерирует входной сигнал, который состоит из смешанной высокочастотной


и низкочастотной синусоидальной волны. Фильтр удаляет высокочастотный
компонент и производит обработанную волну к DAC.
Теперь откройте debug\os support\event окно средства просмотра.
Методы RTOS 379

В конечном счете окно средства просмотра, мы видим действие каждого потока в


системе. Отметьте поле курсора на панели инструментов средства просмотра
события. Теперь, мы можем использовать красные и синие курсоры, чтобы сделать
измерения синхронизации потока. Это позволяет нам видеть, как система работает
на уровне потока и сколько времени обработки свободно (т.е., время, проведенное в
неактивном потоке) (Рис. 10.28).

Рисунок 10.28
Функция SigMod содержит функцию обработки DSP.

Остановите моделирование, и ветер поддерживают окно Logic Analyzer к


запуску смешанной синусоидальной волны (Рис. 10.29).

Рисунок 10.29
Обработка первого пакета образцов представляет задержку между входной и
выходной формой сигнала.

Это показывает задержку приблизительно 8,6 мс между выбираемыми данными


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

Выйдите из средства моделирования и измените размер блока DSP от 1 до 256.


DSP blocksize определяется в IIR.h.
Восстановите и повторно выполните моделирование (Рис. 10.30).
380 Глав 10

Рисунок 10.30
Сокращение пакетного размера пакета данных уменьшает задержку, но увеличивает время
выполнения алгоритма DSP.

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


приблизительно до 90 мкс. Однако, если мы смотрим на средство просмотра
события, мы видим, что поток SigMod работает за каждым образцом и использует
большинство ресурсов процессора и на самом деле блокирует задачу часов.

Взваливание на себя загрузки, контроллера прямого доступа


к памяти
Микроконтроллеры Коры-M3 и Коры-M4 разработаны со многими параллельными
внутренними шинами, это называют “облегченной матрицей шины AHB”. Матрица
шины позволяет Основанному на Cortex-M микроконтроллеру быть разработанным с
несколькими устройствами управления шиной (т.е., единица, способная к
инициированию доступ к шине), который может работать параллельно. Как правило,
микроконтроллер Cortex-M будет иметь процессор Cortex-M как устройство
управления шиной и один возможно несколько единиц Прямого доступа к памяти
(DMA). Единицы DMA могут быть запрограммированы процессором Cortex-M для
передачи данных от одного местоположения в памяти другому, в то время как
процессор Cortex-M выполняет другую задачу. При условии, что единица DMA и
процессор Cortex-M не получают доступ к ресурсам на той же руке матрицы шины
затем, они могут работать параллельно без потребности в арбитраже шины. В случае
периферийных устройств типичная единица DMA может, например, передать данные
от регистра результатов ADC до возрастающих местоположений в памяти. При работе
с периферийным устройством единица DMA может быть назначена ведомым
устройством к периферийному устройству так, чтобы периферийное устройство стало
“контроллером потока” для передач DMA. Так каждый раз существует результат ADC,
единица DMA передает новые данные следующему местоположению в памяти.
Возвращаясь к нашему исходному примеру при помощи единицы DMA, мы можем
заменить ISR ADC передачей DMA, которая помещает, ADC заканчивается
непосредственно в текущий почтовый слот. Когда единица DMA завершит свои 32
передачи, она повысит прерывание. Это позволит коду приложения добавлять
сообщение и настраивать единицу DMA для ее следующей передачи.
Методы RTOS 381

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


вокруг приложения, оставляя процессор Cortex-M свободным выполнить код
обработки DSP.

Разработка для отладки


Когда мы используем RTOS в проекте, API-функции RTOS начинают становиться
лесами, на которые опирается приложение. Многие из этих вызовов API имеют код
возврата, который скажет нам, если функция, завершенная успешно или, укажет на
причину своего отказа. Поскольку код выполняется, мы можем сообщить о любых
ошибках и также предоставить информационные сообщения для помощи процессу
отладки. Простой способ сделать это должно добавить printf () операторы, которые
сообщают о сбоях в рамках проекта.
состояние 5 osMessagePut (Q_LED, ledData, 0); если
(состояние! 5 osOK)
{
printf (“ошибка Q_LED %d\n”, состояние);
}

Теперь когда код выполняет любые проблемы с добавлением сообщений в Q_LED,


очередь сообщений будет отображена на канале STDIO (Рис. 10.31).

Рисунок 10.31
Создание низкоприоритетного диагностического потока позволяет потокам
приложения отправлять ошибку и информационные сообщения. Диагностический
поток может записать их в отладчик через ITM и / или зарегистрировать их к
энергонезависимой памяти.

Поскольку мы видели в Главе 7 “Отладку с CoreSight”, трассировка Инструментария


(ITM) обеспечивает канал последовательной передачи данных между процессором
Cortex-M и отладчиком. Это позволяет нам брать диагностику, сообщая о шаге вперед
путем разработки специализированного диагностического потока, который
отправляет сообщения в отладчик с помощью ITM. Если мы выполняем это
382 Главы 10

поток в низком приоритете, сообщения могут быть отправлены в ЦП с помощью


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

Упражнение 10.5 Диагностика во время выполнения


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

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


См., что Глава 2 “Разрабатывает программное обеспечение для Семейства
Cortex-M” для инструкций по установке.
Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Выберите вкладку Example и Копию “диагностика во время выполнения EX 10.4
RTOS”.
В проекте выберите Среду выполнения.
Выберите утилиты:: разработчик Test:Diagnostic (рис. 10.32).

Рисунок 10.32
Добавьте диагностическую платформу.
Методы RTOS 383

Это добавляет диагностический поток к проекту. Этот поток реализует почтовую


очередь, которой определили почтовые слоты как показано ниже:
структура определения
типа {символьное
сообщение [30];
уровень uint8_t;
строка uint32_t;
символьный файл
[20];

параметр uint32_t;}
mail_format;

Здесь, мы можем отправить текстовое сообщение вместе с уровнем диагностики (1 5


Ошибок,
2 5 Информационных). Мы можем также передать в исходной строке “C”, файле и
определяемом пользователем параметре.

Диагностический поток получает эти сообщения и может распечатать их к ITM и


зарегистрировать их в файл.
Откройте diagnostic.h файл (Рис. 10.33).

Рисунок 10.33
Диагностические параметры конфигурации платформы.

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


параметры потока, размер очереди сообщения диагностики, распараллелить
выделение памяти и приоритетный уровень потока. Мы можем также решить, какой
уровень сообщения диагностики обработать и наконец как отобразить его. Кроме
того, в этом файле два макросов, которые определяют ИНФОРМАЦИОННЫЕ
макросы и ОШИБКА.
ИНФОРМАЦИЯ о #define (сообщение, информационное) diagnosticMessage (сообщение,
информационное, INFO_MSSG, __ СТРОКА __, __ ФАЙЛ __)
ОШИБКА #define (сообщение, информационное) diagnosticMessage (сообщение, информационное,
ERROR_MSSG, __ СТРОКА __, __ ФАЙЛ __)

В main_app.c мы можем запустить


диагностический поток.
384 Главы 10

#include “diagnostic.h”
международное основное
(пустота)
{
tid_mainThread 5 osThreadGetId ();
LED_Initialize (); Init_diagnosticThread ();

Теперь в нашем коде, мы можем добавить сообщения диагностики в любых ключевых


пунктах.
txResult 5 osMessagePut (Q_LED, ledData, 0); если
(txResult! 5 0)
{
ОШИБКА ("Помещенная почтовая очередь перестал работать", txResult);
}

Здесь мы отправляем сообщение об ошибке, если регистрация данных к


почтовой очереди перестала работать. Функция ошибок отправляет текстовое
сообщение и передает txResult код возврата как определяемый пользователем
параметр.
Создайте код.
Запустите отладчик.
Откройте view\Serial средство просмотра Windows\Debug (printf).
Выполните код (Рис. 10.34).

Рисунок 10.34
Сообщения диагностики показывают переполнение почтовой
очереди.

После того, как код работал приблизительно за 40 мс, почтовая очередь приложения
перестанет работать, и сообщение об ошибке будет отображено.
Выйдите из отладчика.
Строка некомментария 27 в main_app.c.
Восстановите код.
Выполните код и наблюдайте вывод в Средстве просмотра Отладки (Рис. 10.35).
Методы RTOS 385

Рисунок 10.35
Информационные сообщения из исправленного кода.

Заключение
Одна из главных причин, сделанных разработчиками для того, чтобы не принимать
использование RTOS, - то, что оно представляет слишком много служебное с точки
зрения времени обработки для маленького микроконтроллера. Это больше не
складывает, примерно каждое Основанное на Cortex-M устройство способно к
поддержке RTOS и должно использоваться для всех кроме самых простых проектов.
Используемый правильно преимущества использования RTOS явно перевешивают
отрицательные стороны. После того как Вы инвестировали время в изучение, как
использовать RTOS, Вы не захотите возвращаться к проектам без операционной
системы.
Эта страница, намеренно
оставленная незаполненный
CHPTER11

Разработка через тестирование

Введение
В этом разделе мы собираемся посмотреть на новую технику под названием
“Разработка через тестирование” (TDD) для разработки кода. Когда я говорю новый, я
действительно имею в виду в новинку для разработчиков встроенной системы. TDD
был установлен в других областях вычислений приблизительно с 2003. Традиционно
большинство разработчиков встроенных систем будет склонно писать относительно
небольшой объем кода, компилировать его и затем тестировать его на аппаратных
средствах с помощью отладчика. Любое формальное тестирование затем сделано
отдельной командой, после того как вся кодовая база была записана.
Поблочное тестирование затем было бы длинной фазой тестирования, отладило бы и
зафиксировало бы, пока заключительный производственный код не считают
пригодным быть выпущенным. TDD не является заменой для формальной фазы
поблочного тестирования, но представляет тестирование как инструмент, который
является частью процесса разработки кода. Помещенный просто, TDD требует,
чтобы Вы добавили тесты для каждой функции, которую Вы пишете, но
кардинально Вы пишете, что тесты сначала затем пишут код приложения, чтобы
пройти тесты. Сначала это кажется излишне трудоемким и сложным, однако, TDD
действительно обладает многими очень положительными преимуществами.

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


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

Путем записи тестов для каждого возрастающего дополнения к нашему производству


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

Если мы разрабатываем дисциплину тестирования кода, когда мы идем, это


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

Руководство разработчика по семейству процессоров Cortex-M.


DOI: http://dx.doi.org/10.1016/B978-0-08-100629-0.00011-6 387
© 2016 Elsevier Ltd. Все права защищены.
388 Глав 11

функции из главного приложения. Это поощряет запись хорошо


структурированного производственного кода.

Поскольку наша кодовая база приложения выращивает традиционную компиляцию,


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

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

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


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

Много основанных на микроконтроллере встроенных систем разработаны


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

Цикл разработки TDD

Философии TDD можно подвести итог в трех правилах, сформулированных Robert C.


Martin (никакое отношение):
1. Нельзя написать производственный код, если он не должен делать провальную
передачу модульного теста.
2. Нельзя больше писать модульного теста, чем достаточно для сбоя; и отказы
компиляции являются отказами.
3. Нельзя больше писать производственный код, чем достаточно для передачи
одного провального модульного теста.
В то время как это чувствует себя очень неловким сначала с небольшой практикой,
это становится второй натурой. После того как Вы инвестировали время и
дисциплину для работы с TDD в проекте, Вы начнете получать выгоду.
Для использования TDD в реальном проекте, мы можем пройти следующий цикл:
1. Напишите код для добавления теста.
2. Создайте код и запустите тест, чтобы видеть, что он перестал работать.
3. Добавьте минимальную сумму кода приложения, чтобы пройти тест.
4. Выполните весь тестовый код и проверьте, что все тесты проходятся.
5. Линзовый телескоп код для улучшения его выразительности.
6. Повториться.

Среда тестирования

Чтобы заставить TDD приблизиться к работе на практике, мы должны смочь создать


тесты и выполнить их как можно быстрее. К счастью, существует много сред
тестирования, доступных, который может быть добавлен к нашему проекту создать
подходящую тестовую среду. Двумя из самых популярных платформ является
Единица и CppUtest:
Единица unity.sourceforge.net
CppUtest www.cpputest.org

В примере ниже мы будем использовать платформу Единицы. Единица разработана


для тестирования “C” - базирующиеся приложения. Это имеет маленькое место и
также доступно, поскольку программный пакет так очень легко добавить к проекту.
CppUtest является подобной платформой, разработанной и для “C” и для языков
“C11”.

Автоматизация тестирования

А также способность быстро добавить тесты к нашей платформе мы должны смочь


автоматизировать сборку и цикл испытаний. Так идеально в IDE мы сможем создать
тестовый проект, загрузить на цель, запустить тесты и видеть результаты с одним
нажатием кнопки. Это должно
390 Глав 11

затем дайте нам цикл разработки менее чем 30 секунд. В следующих двух
примерах мы посмотрим на установку и автоматизацию платформы TDD с
простым проектом.

Этот проект настроен для использования средства моделирования, таким


образом, мы можем экспериментировать с подходом TDD без потребности в
определенных аппаратных средствах.

Установка платформы единицы


Для этого примера необходимо будет установить Служебный пакет. См., что
Глава 2 “Разрабатывает программное обеспечение для Семейства Cortex-M”
для инструкций по установке.
Необходимо будет также установить следующие пакеты с помощью установщика
пакета (Таблица 11.1).

Таблица 11.1: Необходимые программные пакеты


Число минимальной
Пакет версии
Keil:: LPC1700_DFP 2.1.0
Keil:: ARM_Compiler 1.0.0
РУКА:: CMSIS 4.5.0

Как тестовый прогон результаты отправляются на канал STDIO. Компонент


платформы Единицы требует, чтобы опции Compiler IO были настроены. В
большинстве проектов результаты испытаний лучше всего отправляются через ITM в
консоль в отладчике. Кора-M0 не имеет трассировки ITM, таким образом,
необходимо было бы использовать другой канал IO для отображения результатов,
обычно это будет USART.

Упражнение 11.1 Разработка через тестирование


Откройте установщик пакета µVision (Рис. 11.1).

Рисунок 11.1
Платы установщика пакета и вкладки в качестве примера.

Выберите вкладку Boards и вкладки Examples (Рис. 11.2).


Рисунок 11.2
Выберите MCB1700 и затем среду тестирования
Единицы.
Разработка через тестирование 391

Выберите MCB1700.
Выберите вкладку в качестве примера и Копию “Среда тестирования Разработчика
Единицы”.
Это скопирует проект в Ваш выбранный каталог разработки.

Проект содержит подкаталог, названный “Установка TDD PreBuilt”, который


имеет полностью настроенную версию проекта для ссылки.

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


для включения банка светодиодов по одному. После того как все светодиоды были
включены, они будут одновременно выключены, и цикл повторится. Мы
собираемся разработать его далее путем добавления функции, которая представит
различные задержки периода в выбранных точках в светодиодном цикле. В то
время как это достаточно легко сделать, мы будем использовать этот пример, чтобы
видеть, как добавить подход TDD к нашему проекту.
В нашем проекте у нас есть наш новый код, будет помещен в файл, названный lookup.c
(Рис. 11.3).

Рисунок 11.3
Первоначальный проект с кодом под тестом в lookup.c.

Добавление среды тестирования единицы

Lookup.c содержит скелет функции, вызванной checkTick (). Эта функция передается
целочисленное значение, она должна затем просканировать массив, чтобы видеть,
находится ли это значение в массиве. Если существует совпадающее значение, оно
возвращает местоположение того значения в массиве. Если нет никакого
совпадающего значения в нуле массива, возвращается.
392 Главы 11

В TDD проект открывают Run-Time Environment (RTE). (Рис. 11.4)

Рисунок 11.4
sel столбец будет окрашен в оранжевый (светло-серый в печатной версии), если
субкомпонент будет требоваться.

Выберите утилиты:: разработчик среда тестирования Test:Unity.

Среда тестирования использовала STDIO в качестве вывода для его результатов,


таким образом, мы должны включить это и выбрать низкоуровневый канал вывода.
Используя ITM позволит нам работать на любом ядре Cortex-M, которое имеет
приспособленный ITM. ITM даст нам канал IO, который не использует ресурсов
микроконтроллера, которые конфликтовали бы с кодом приложения и не
нуждаются ни в каких ресурсах внешнего оборудования (Рис. 11.5).

Рисунок 11.5
Выберите ITM, чтобы быть каналом STDIO.

Наконец мы просто должны удостовериться, что поддержка ITM в отладчике


правильно настроена. Этот пример использует средство моделирования и не нужен в
дальнейшей конфигурации, но для проекта с помощью аппаратного отладчика, ITM
настроен следующим образом.
Только измените следующие настройки отладчика при использовании аппаратного
отладчика.
Откройте опции для target\debug меню и нажмите кнопку настроек (Рис. 11.6).
Разработка через тестирование 393

Рисунок 11.6
Для аппаратной отладки необходимо позволить Единице Трассировки ITM
получить результаты испытаний.

Выберите меню трассировки.


Установите базовую тактовую частоту для соответствия частоте процессора CPU.
Включите трассировку и включите канал 31 ITM.

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


объема данных, отправляемого через Последовательный канал Проводной трассы.

Данные ITM отправляются в отладчик через контакт отладки SWO. На некоторых


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

Конфигурирование целей сборки проекта

Наш проект должен теперь иметь компонент Единицы, добавленный вместе с


кодом приложения. Теперь мы должны настроить проект, таким образом, мы
можем легко переключиться между созданием полного кода приложения и
созданием тестовой версии.
Выберите project\manage\project объекты (Рис. 11.7).
394 Главы 11

Рисунок 11.7
Справьтесь проекты позволяет Вам определять папки проекта и версии
сборки.

В настоящее время у нас есть единственная версия сборки проекта, который создает
код приложения. Используя окно проекта мы можем определить различные версии
сборки и дополнительные папки проекта (Рис. 11.8).

Рисунок 11.8
Мы можем определить тест целевые и дополнительные папки
проекта.

В “Project Targets” окно нажимают кнопку вставки и добавляют Тестовую сборку.

В “Groups” раздел добавляет, что две новых группы “Разработка” и “Тест” затем
нажимают хорошо для возврата к IDE (Рис. 11.9).
Разработка через тестирование 395

Рисунок 11.9
Переключитесь на сборку приложения с помощью выпадающей панели
инструментов.

Теперь мы можем переключиться между версиями сборки с помощью


выпадающего тестового поля на панели инструментов. У нас также есть
дополнительные папки проекта к расположению проект.
С набором сборки проекта к Приложению выбирают папку Test.
Щелкните правой кнопкой и выберите опции для папки Test.

В свойствах меню сняли флажок с опциями “Include in Target Build” и “Always


Build” (Фиги. 11.10 и 11.11).

Рисунок 11.10
Откройте локальные опции для тестовой папки группы.

Рисунок 11.11
Снимите флажок с опциями сборки удалить эту папку из
сборки.
396 Глав 11

Повторите это для Test Framework Group.

Теперь, когда мы находимся в сборке приложения, все тестовые компоненты


удалены, и код приложения будет создан как нормальный.
На панели инструментов переключаются из “Приложения”, чтобы
“Протестировать”.
В настоящее время Тестовая версия сборки имеет исходные опции сборки по
умолчанию.

Выберите щелчок правой кнопкой группы приложений и откройте опции для сборки
“Приложения” группы.

Снимите флажок с опциями “Always Build” и “Include in Target Build” и нажмите ОК.

Теперь то, когда мы выбираем “Тестовую Цель” код приложения, будет удалено, и
тестовые компоненты будут активны в проекте (Рис. 11.12).

Рисунок 11.12
“Знаки Стоп” на папках проекта указывают, что папка не является частью Целевой
сборки.

Любой код, который находится в папке Development, будет включен в оба проекта.

Мы в настоящее время разрабатываем код в lookup.c модуле. Откройте папку


приложения, выберите lookup.c и перетащите его к папке разработки. Теперь мы
можем разработать проект в любой Цели, и lookup.c будет включен в обе сборки
(Рис. 11.13).
Рисунок 11.13
Выберите lookup.c и перетащите его к папке Development.
Разработка через тестирование 397

Добавление тестов
Выберите папку Test, щелкните правой кнопкой и выберите, “Добавьте Новый Объект
к Тесту Группы”
(Рис. 11.14).

Рисунок 11.14
Пользовательский код обрабатывает по шаблону для Тестовой
обвязки Единицы.

Выберите “Пользовательские Шаблоны Кода”, и в Утилитах добавляют Test Group и


Основную Test
(Рис. 11.15).

Рисунок 11.15
Проект с добавленной Тестовой обвязкой.

Откройте Test Main.c.

Этот файл обеспечивает основное () функция для Тестовой Цели и называет


среду тестирования Единицы. То, когда тесты будут законченным
выполнением, достигнет остановки () функция.

После того как Единица начинает работать, она начнет выполнять любые тесты,
которые были определены. Они объявляются как тестовые сценарии, которые затем
собраны в тестовые группы. Мы можем создать эту иерархию тестов путем изменения
runAllTests () и TEST_GROUP_RUNNER () функции.
В runAlltest () функция переименовывают тестовую группу к поиску.
398 Глав 11

В TEST_GROUP_RUNNER () функция переименовывает “testgroup” к “поиску” и


добавляет тестовый сценарий “correctTickValues” и “failingTickValues”.
TEST_GROUP_RUNNER (поиск)
{
RUN_TEST_CASE (поиск, correctTickValues);
RUN_TEST_CASE (поиск, failingTickValues);
}
статический пустой RunAllTests (пусто)
{
RUN_TEST_GROUP (поиск);
}

Откройте TestGroup.c.

В этом файле мы можем определить группу тестов для нашей функции lookup.c.
Этот файл определяет тестовое название группы и обеспечивает установку, и
разъедините функции, которые работают прежде и за тестами. TEST_SETUP ()
функционируют выполнения однажды каждый тест в тестовой группе
и используется для подготовки аппаратных средств приложения к тестовым
сценариям. Слеза вниз функционирует, используется для возврата проекта состоянию
по умолчанию так, чтобы любые другие тестовые группы могли работать.
Заключительная функция является нашим тестовым сценарием, который позволяет
нам создавать массив тестов для нашей новой функции.
TEST_GROUP (поиск);
TEST_SETUP (поиск)
{
}
TEST_TEAR_DOWN (поиск)
{
}

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


разрушения.
Скопируйте и вставьте ТЕСТОВУЮ функцию, таким образом, у нас есть две
тестовых функции.
Переименуйте первый следующим образом ТЕСТ (поиск, correctTickValues).
И второе как показано ниже ТЕСТА (поиск, failingTickValues).
Теперь мы можем создать тестовые сценарии в обеих из этих функций как показано
ниже.
ТЕСТ (поиск, correctTickValues)
{
TEST_ASSERT_EQUAL (1, checkTick (34));
TEST_ASSERT_EQUAL (2, checkTick (55));
TEST_ASSERT_EQUAL (3, checkTick (66));
TEST_ASSERT_EQUAL (4, checkTick (32));
TEST_ASSERT_EQUAL (5, checkTick (11));
TEST_ASSERT_EQUAL (6, checkTick (44));
TEST_ASSERT_EQUAL (7, checkTick (77));
TEST_ASSERT_EQUAL (8, checkTick (123));
}
Разработка через тестирование 399

Первый набор тестовых сценариев вызовет функцию с допустимыми входными


значениями и проверит, что правильное значение возвращено.
ТЕСТ (поиск, failingTickValues)
{
TEST_ASSERT_EQUAL (0, checkTick (22));
TEST_ASSERT_EQUAL (0, checkTick (93));
}

Второй набор тестовых сценариев вызовет функцию с недопустимыми


значениями и проверит, что корректное ошибочное значение возвращено.

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


сценарии. Мы можем теперь создать код и выполнить код, и тестовые сценарии
должны перестать работать, поскольку нет никакого кода реального приложения.
Создайте код.
Запустите отладчик.
Откройте view\serial windows\printf окно.
Выполните код.
О тестовом сбое сообщат в последовательном окне (Рис. 11.16).

Рисунок 11.16
О провальном тесте сообщают в окне консоли ITM.

Автоматизация цикла TDD

Прежде чем мы пойдем и начнем писать код приложения, мы можем далее


автоматизировать эту процедуру тестирования, таким образом, мы можем обойти
сборку и цикл испытаний одним щелчком в IDE.
Поставьте цель проекта, чтобы быть “Тестовой” сборкой.

Откройте опции для целевого меню и выберите пользовательское меню и


включите опцию “Start Debugging” (Рис. 11.17).
400 Глав 11

Рисунок 11.17
Вкладка User позволяет Вам запускать отладчик, как только сборка
закончена.

Теперь после сборки код будет загружен в цель, и отладчик будет запущен.

Затем выберите опции для target\debug меню и добавьте файл сценария test_go.ini,
который расположен в, проект. каталог \RTE\utilities как файл инициализации
средства моделирования.
(Рис. 11.18).

Рисунок 11.18
Добавьте сценарий автоматизации как файл инициализации
средства моделирования.
Разработка через тестирование 401

Затем снимите флажок “Run to main ()”. Или это остановит сценарий, работающий
правильно.
Теперь этот скрипт будет запущен, как только отладчик запускается.
ясное покрытие
СИЛЬНО УДАРЬТЕ
..testResults.txt g,
остановитесь

СИЛЬНЫЙ УДАР ПРОЧЬ


ЗАРЕГИСТРИРУЙТЕ покрытие
..testResults.txt \testgroup,
ДЕТАЛИ ВЫХОДЯТ ИЗ
СИСТЕМЫ

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

Теперь при восстановлении кода, он скомпилирует ссылку, запустить отладчик


и выполнить тесты.

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

Теперь откройте lookup.c файл. Прочитайте функциональное описание и напишите


код, требуемый сделать функциональную работу.

Создайте код и проверьте всю тестовую передачу. Если существует отказ,


корректный ошибка и повторение, пока тесты не передают (Рис. 11.19).

Рисунок 11.19
После того как правильный код добавляется, у нас есть
проходящие тесты.
402 Главы 11

После того как мы достигли этого счастливого состояния, которое мы можем


переключить на приложение, создают и добавляют новую функцию к коду в
thread.c.
в то время как (1)
{
ledData 50;
для (я 5 0; я, 8; i11)
{
extendedDelay5checkTick (галочка);//называют checkTick для вычисления расширенного totalDelay 5
100 1 задержки (100*extendedDelay);
osDelay (totalDelay); osMessagePut
(Q_LED, ledData, 0); отсчитайте 5
(отсчитайте 1 1), и 0xDFF; ledData 5
ledData 1 1;

}
}

Переключитесь на Цель Приложения и создайте код.


Запустите отладчик и выполните новую версию blinky программы.

Тестирование потоков RTOS


Эта форма тестирования также работает очень хорошо с потоками RTOS. В нашем
примере у нас есть четыре потока, основные плюс эти три потока приложения.
Каждый из потоков является автономным “объектом” с очень четко определенными
вводами и выводами. Это позволяет нам тестировать каждый из потоков в изоляции,
так как мы можем запустить каждый поток индивидуально и создать тестовую
обвязку, которая “дразнит” остальную часть системы (Рис. 11.20).

Рисунок 11.20
Основанный на RTOS проект состоит из объектов потока с четко определенными
вводами и выводами. Поток является превосходной целью
для тестирования.
Разработка через тестирование 403

Наши потоки приложения состоят из потока Tx, который пишет значения в очередь
сообщений, поток Rx, который читает значения из очереди сообщений и пишет их в
банк светодиодов. Когда все светодиоды были включены, поток Tx сигнализирует о
потоке Сброса, который выключает все светодиоды (Рис. 11.21).

Рисунок 11.21
Тестовый поток может использовать API RTOS для управления потоками приложения.
Здесь мы можем завершить поток и применить тестовые сценарии к остающемуся
потоку с помощью почтовой очереди и сигнальных флагов.

Мы можем протестировать приложение на уровне потока при помощи той же среды


тестирования. Тестовый поток может запустить каждый поток индивидуально, и
затем мы можем применить данные тестирования с помощью вызовов RTOS
(очередь сообщений и сигналы). В нашем основном тестовом проекте () работает как
поток RTOS, таким образом, в наших тестовых сценариях мы можем также получить
доступ ко всем вызовам API RTOS для создания тестовых сценариев уровня потока.
ТЕСТ (поток, rxThread)
{
LED_Initialize ();
Init_queue ();
Init_rxThread ();
. . .. . .. . .. . .. . .. . .. . .. . .. . .. . ..

Здесь мы создаем тестовую группу, которая инициализирует светодиоды и очередь


сообщения приложения. Мы можем затем запустить rxThread () выполнение. Этот
поток теперь ожидает сообщений, которые будут отправлены в почтовую очередь. Это
позволяет нам создавать тестовые сценарии, которые добавляют сообщения в
почтовую очередь вместо txThread (). Мы можем затем проверить поведение rxThread
().
osMessagePut (Q_LED, (0x00), 0);
osDelay (10);
TEST_ASSERT_EQUAL ((1, 28), (GPIO_PortRead (1) и 0xB0000000));

В нашем тестовом сценарии мы можем отправить некоторые данные в rxThread ()


очередь сообщений и затем считать светодиодные Параметры порта, чтобы
проверить, что корректные светодиоды включаются. osDelay () вызов
404 Главы 11

гарантирует, что планировщик RTOS определит задачу для переключателя и


выполнит rxThread () код. В конце тестовых сценариев мы можем уничтожить
rxThread () и продвинуться, чтобы создать и протестировать другой из потоков
приложения.
ТЕСТ (поток, clrThread)
{
Init_clrThread ();
osSignalSet (tid_clrThread, 0x01); osDelay (10);

TEST_ASSERT_EQUAL (0, (GPIO_PortRead (2) и 0x0000007C));


TEST_ASSERT_EQUAL (0, (GPIO_PortRead (1) и 0xB0000000));
osThreadTerminate (tid_clrThread);
}

В следующем тестовом сценарии мы запускаем clrThread () и инициировали его с


osSignalSet () функция. Мы можем затем считать порт GPIO, чтобы гарантировать,
что светодиод контакты GPIO был записан для обнуления; в конце теста мы можем
снова завершить поток.

Упражнение 11.2 Тестирование потоков RTOS


Возвратитесь к 11,1 проектам TDD, используемым в последнем примере.
Выделите папку Test и выбор, “Добавьте существующий объект к проекту”.
Добавьте файл testGroupRTX.c.
Откройте TestMain.c.
Добавьте тестовую группу потока и назовите ее от RunAllTests () как показано ниже.
TEST_GROUP_RUNNER (поток)
{
RUN_TEST_CASE (поток, rxThread);
RUN_TEST_CASE (поток, clrThread);
RUN_TEST_CASE (поток, txThread);
}
статический пустой RunAllTests (пусто)
{
printf (" \nRunning тестовый сценарий поиска \n");
RUN_TEST_GROUP (поиск); printf (" \nRunning
тестовый сценарий Потока \n");
RUN_TEST_GROUP (поток);

}
Разработайте проект и позвольте ему пробежать ссылку компиляции и
испытательный шлейф (Рис. 11.22).
Разработка через тестирование 405

Рисунок 11.22
Теперь исходный и новый тестовый прогон RTOS и передача.

Это выполнит исходный набор тестовых сценариев на коде в lookup.c. Если


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

Отделение низкоуровневых функций

Идеально мы не хотим изменять код под тестом. Однако в какой-то момент мы


встретимся с проблемой, что функция при проверочных вызовах стандартная
программа, которая требует результата периферийного устройства.
интервал detectPacketHeader (пусто)
{
в то время как (! packetHeader)
{
cmd 5 receiveCharacter (USARTdrv);
. . .. . .. . ..

В этом случае receiveCharacter () стандартная программа ожидает для получения


символа из микроконтроллера USART. Это делает автоматизированное
тестирование detectPacketHeader () функцией трудный протестировать, потому что
это уверено в receiveCharacter () стандартная программа. Для обхода этого, мы
должны сделать “ложную” версию receiveCharacter (), который можно назвать во
время тестирования вместо реальной функции. Мы могли прокомментировать
реальный receiveCharacter () функция, но это означает изменять код приложения или
добавлять условную компиляцию с помощью #ifdef команды препроцессора. Оба из
этих подходов являются нежелательным, поскольку они могут привести к ошибкам
при создавании полного приложения. Один окольный путь эта проблема должен
использовать __ слабая директива, предоставленная компилятором.
__ слабый символ receiveCharacter (ARM_DRIVER_USART *USARTdrv)
406 Глав 11

Когда код приложения будет создан, эта функция будет скомпилирована как
нормальная. Однако во время тестирования мы можем объявить “ложную”
функцию с тем же прототипом функции минус __ слабая прагма. Компоновщик
будет затем “перегружать” исходную функцию со слабым объявлением и
использовать “ложную” версию в ее месте.
int8_t mockSerialData [] 5 "Привет Мир";
символ receiveCharacter (ARM_DRIVER_USART *USARTdrv)
{
int8_t val, количество 5 0;
val 5 mockSerialData[count11];
если (считают .sizeof (mockSerialdata)), количество 5 0;
возвратите val;
}

Теперь мы можем создать тест для detectPacketHeader (), функционируют и


используют “ложную” версию receiveCharacter () для обеспечения соответствующих
данных во время тестового сценария.

Тестирование прерываний

Встроенный проект микроконтроллера будет иметь тенденцию иметь код, который


глубоко взаимосвязан с аппаратными средствами микроконтроллера. Некоторые
функции в рамках кода приложения будут уверены в периферийном устройстве
микроконтроллера. В большинстве проектов у нас может также быть много
активных прерываний ввода-вывода. Мы можем использовать тот же метод
перегрузки функций для тестирования прикладных функций, которые зависят от
аппаратных прерываний. Если у нас есть функция ISR, мы можем объявить это как
__ слабый и затем перегрузить ее с “ложной” функцией, которая не аппаратно-
зависима.
__ слабая пустота ADC_IRQHandler (пусто) {
энергозависимый uint32_t adstat;
adstat 5 LPC_ADC-.ADSTAT; /* Читайте ADC очищает прерывание */
/* Сохраните преобразованное значение
AD_last 5 (LPC_ADC-.ADGDR.. 4) и 0xFFF; */
AD_done 5 1;
}

Таким образом, вышеупомянутый обработчик прерываний ADC, который


зависит от микроконтроллера периферийное устройство ADC, может быть
заменен упрощенной “ложной” функцией.
освободите ADC_IRQHandler (пусто)
{
AD_last 5 testValue;
AD_done 5 1;
}

“Ложная” функция подражает функциональности исходного ISR, но никоим образом


не зависит от фактических аппаратных средств ADC. Поскольку мы называем
функцию с помощью прототипа
Разработка через тестирование 407

зарезервированный для обработчика прерываний CMSIS-ADC функция будет


инициирована прерыванием на канале NVIC ADC. Для использования этой
функции во время тестирования, мы можем также перегрузить исходный
ADC_StartConversion () функция.
__ слабый int32_t ADC_StartConversion (пусто) {
/* остановите
LPC_ADC-.ADCR И 5 B (7, 24); преобразование */
LPC_ADC-.ADCR | 5 (1, 24); /* запустите преобразование */
возвратитесь 0;
}

Снова функция “насмешки” перегрузки не обращается к аппаратным средствам,


периферийное устройство ADC регистрирует, но использует CMSIS-
NVIC_setPending () функция для порождения прерывания на канале ADC NVIC.
int32_t ADC_StartConversion (пусто)
{
NVIC_SetPendingIRQ (ADC_IRQn); //инициировали канал прерывания ADC
}

Теперь мы можем создать тестовые сценарии вокруг функций, которые используют


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

Упражнение 11.3 Тестирование с прерываниями


В этом примере мы включим 12-разрядный ADC и его прерывание. Затем в
фоновой функции мы запустим преобразование ADC. После того как
преобразование ADC закончилось, мы считаем результат, сместим результат 4
бита направо и затем скопируем результат в банк 8 светодиодов.
Откройте установщик пакета.
Выберите Советы:: MCB1700.
Выберите вкладку в качестве примера и Копию “Тестирование Прерывания
Платформы Единицы”.

Проект создается с приложением и тестовыми сборками, которые мы устанавливаем в


первом примере в этой главе (Рис. 11.23).
408 Глав 11

Рисунок 11.23
Проект является установкой для работы со средой
тестирования.

Открытый testGroup.c.

В этом файле у нас есть версии перегрузки ADC_IRQHandler () и


ADC_StartConversion () функции.
Код под тестом является функцией displayADC () в DisplayADC.c
освободите displayADC (пусто)
{
результат uint32_t; ADC_StartConversion (); в
то время как (ADC_ConversionDone ()! 5 0);
закончитесь 5 ADC_GetValue ();

закончитесь 5
результатов.. 4;
LED_SetOut (результат);
}

В тестовом сценарии мы можем загрузить значение результата ADC и затем назвать


displayADC () функцией.
testValue 5 0x01, 4;
displayADC ();
TEST_ASSERT_EQUAL (1, 28, (GPIO_PortRead (1) и 1, 28));

displayADC () будет использовать значение от ADC и писать это значение в


контакты порта LED. Мы можем затем проверить, что корректные биты были
установлены путем чтения состояния соответствующего порта.
Исследуйте код в displayADC.c и ADC_IRQ.c.
Создайте код и выполните тестовые сценарии (Рис. 11.24).
Разработка через тестирование 409

Рисунок 11.24
Тестовые сценарии выполняются с ложными перегруженными
функциями.

Заключение
Надо надеяться, это было полезной главой. Если Вы плохо знакомы с TDD, он должен
дать Вам некоторую пищу для размышления. Единственный реальный способ
получить реальный смысл того, как использовать TDD в реальном дизайне, состоит в
том, чтобы на самом деле сделать это. Первоначально Вы пойдете медленнее,
поскольку необходимо создать опыт в том, как создать подходящие тесты. После того
как Вы создали некоторое полезное тестирование “шаблоны”, Вы начнете делать
более быстрые успехи. С практикой и степенью дисциплины Вы начнете видеть
некоторую реальную выгоду путем принятия подхода TDD к разработке кода.
Эта страница, намеренно
оставленная незаполненный
CHPTER12

Компоненты программного
обеспечения

Введение
За прошлые 25 лет фокус средств разработки встроенных систем видел перемещение
от встроенного микропрограммного обеспечения приложения, записанного полностью
в ассемблере к введению компиляторов для “C” и языков “C11”. Это сопровождалось
все больше сложными средами разработки и отладчиками. Сегодня с появлением
навсегда сложных микроконтроллеров, проект может потребовать, чтобы несколько
программного обеспечения “стеки” управляли периферийными устройствами, такими
как USB-устройство и Хост, Ethernet, Мультимедийная карта и жидкокристаллический
дисплей. Написание необходимого кода для любого из этих периферийных устройств
является проектом самостоятельно. Следовательно, это становится фактом жизни, что
необходимо будет использовать сторонний код в проекте, быть им открытый
исходный код, библиотека Silicon Vendor или коммерческая библиотека. Кроме того,
необходимо будет смочь интегрировать несколько из этих библиотек, возможно из
других источников, в единственный проект и заставить их всех работать счастливо
вместе (Рис. 12.1).

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

Поскольку мы видели в Главе 4 “Стандарт Программного интерфейса


Микроконтроллера Коры”, CMSIS-ядро стандартизирует, как “C” используется на
процессоре Cortex-M. В этой главе мы собираемся посмотреть на следующие две
спецификации Стандарта программного интерфейса микроконтроллера коры
(CMSIS), Драйвер CMSIS и Пакет CMSIS. Драйвер CMSIS определяет стандартный
интерфейс прикладного программирования (API) для доступа к общим
периферийным устройствам микроконтроллера.

Руководство разработчика по семейству процессоров Cortex-M.


DOI: http://dx.doi.org/10.1016/B978-0-08-100629-0.00022-0 411
© 2016 Elsevier Ltd. Все права защищены.
412 Глав 12

Намерение Драйвера CMSIS состоит в том, чтобы предоставить стандартизированный


интерфейс низкого уровня библиотекам промежуточного программного обеспечения.
Так, компания, которая производит стопку промежуточного программного
обеспечения, такую как USB или TCP \IP библиотека, может использовать Драйвер
CMSIS API, это затем позволяет их программному обеспечению работать на любом
микроконтроллере Коры, который поддерживает соответствие Драйвер CMSIS. Для
разработчика приложений Драйверы CMSIS могут использоваться для разработки
универсальных компонентов программного обеспечения, которые могут быть снова
использованы через будущие проекты, даже если они используют другое семейство
микроконтроллеров. Спецификация Пакета CMSIS позволяет нам брать любой код,
что мы хотим снова использовать и связать его в программный пакет так, чтобы это
могло быть легко распределено другим пользователям. После того, как
установленный, компонент Пакета CMSIS доступен для добавления к проекту через
Среду выполнения (RTE). Чтобы видеть, как это работает на практике, мы пройдем
дизайн простого компонента программного обеспечения, который получает
последовательные данные от GPS-приемника через Универсальный синхронный
асинхронный приемопередатчик (USART). Компонент проверит и проанализирует
данные и сделает их доступными для других частей нашего приложения. Мы будем
использовать драйвер CMSIS USART для создания кодирующего устройства GPS
независимым. После того как у нас есть некоторый функционирующий код, мы можем
превратить его в допускающий повторное использование компонент программного
обеспечения с помощью спецификации Пакета CMSIS.

Драйвер CMSIS
Спецификация Драйвера CMSIS определяет универсальный периферийный интерфейс
драйвера. Это создает абстракцию из аппаратных средств микроконтроллера. Любой код,
который написан с помощью Драйвера CMSIS, может быть снова использован на любом
микроконтроллере Cortex-M, который имеет соответствие Драйвер CMSIS (Рис. 12.2).

Рисунок 12.2
Драйвер CMSIS и CMSIS RTOS позволяют Вам создавать компонент программного
обеспечения, который может быть снова использован
через различные аппаратные платформы.

Это имеет много преимуществ в этом, после того как Вы знакомы с Драйвером CMSIS
API, можно снова использовать то знание через многие микроконтроллеры и проекты.
Можно также переместить код между различными микроконтроллерами и даже
различными наборами инструментальных средств. Оборотная сторона то, что,
поскольку Вы используете универсальный интерфейс, который должен смочь работать
над любым микроконтроллером.
Это означает, что функции, предлагаемые Драйвером CMSIS API, ограничены.
Поскольку Драйвер CMSIS может быть реализован как обертка по Кремниевой
периферийной библиотеке Поставщика, коду
Компоненты программного обеспечения 413

размер и производительность не могут быть оптимальными. Наконец, если


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

Рисунок 12.3
Драйвер CMSIS обеспечивает стандартный API для диапазона
периферийных устройств, характерных для
многих микроконтроллеров.

Драйвер CMSIS в настоящее время поддерживает коммуникационные периферийные


устройства, такие как Межтершая связь Интера (I2C), Последовательный
периферийный интерфейс (SPI), универсальный синхронный асинхронный
приемопередатчик (USART), контроллерная сеть (CAN), и Последовательный
аудиоинтерфейс (SAI), а также более сложные периферийные устройства, такие как
Ethernet, USB-устройство и Хост USB. Драйвер CMSIS также имеет спецификации
для интерфейса Multi Media Card и указывает драйверы для NAND и Флэш-памяти
NOR для поддержки встроенных файловых систем.

Драйвер CMSIS API

Каждый Драйвер CMSIS содержит ряд API-функций, которые используются для


конфигурирования каждого драйвера. Функции Драйвера CMSIS имеют общую
структуру через каждое из поддерживаемых периферийных устройств, после того как
Вы знакомы с тем, как использовать один тип драйвера, та же логика относится ко
всему другие. Каждый Драйвер CMSIS способен к поддержке нескольких
экземпляров, таким образом, в рамках проекта возможно инстанцировать нескольких
драйверов для поддержки нескольких периферийных устройств a
414 Глав 12

учитывая тип, например, три периферийных устройства SPI. Общие функции


Драйвера CMSIS показывают ниже в универсальной форме. Эти функции варьируются
немного между различными типами драйвера, но после того как Вы знакомы с тем,
как Драйвер CMSIS работы API, перемещающиеся между различными
периферийными устройствами, представляет немного проблем (Таблица 12.1).

Таблица 12.1: Драйвер CMSIS универсальный API

Функция Описание
получите Версию () Возвращает версию драйвера
Возвращает поддерживаемые возможности
получите Возможности () драйвера
Возвращает текущее периферийное
getStatus () состояние
Начальная установка драйвера и регистры
инициализируйте () обратный вызов драйвера
Возвратите периферийное устройство его
деинициализация () состоянию сброса
Позвольте/запретите периферийное
powerControl () состояние электропитания
Настраивает периферийные устройства
управление () операционные параметры
Пользователь определяет обратный вызов для
signalEvent обработки периферийных событий
Периферийные функции передачи Дополнительный набор функций для
данных отправляют () управления
получите () передача данных

Драйверы CMSIS для данного микроконтроллера обеспечиваются как часть пакета


семейства устройств. После того, как установленный, каждый из драйверов будет
доступен через RTE. Типичную вызывающую последовательность показывают на
Рис. 12.4.
Рисунок 12.4
Драйвер CMSIS API является (довольно) ортогональным. После того как Вы
использовали драйвер CMSIS USART, Вы сможете
использовать любой другой драйвер CMIS.

Упражнение 12.1 CMSIS-драйвер

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


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

Этим примером является многопроектная рабочая область. Один проект является


установкой для микроконтроллера NXP, второе для микроконтроллера
Микроэлектроники ST. Мы собираемся использовать тот же код на обоих
микроконтроллерах для демонстрации использования драйвера CMSIS USART (Рис.
12.5).

Рисунок 12.5
Сделайте “Драйвер USART NXP” активный проект.

Выберите проект NXP. Щелкните правой кнопкой и выберите “Набор как Активный
проект”.

Во-первых, мы можем добавить, что драйвер CMSIS USART к нашему проекту


путем выбора его в RTE затем разрешает любые необходимые субкомпоненты и
добавляет его к нашему проекту (Рис. 12.6).
Рисунок 12.6
Выберите драйвер CMSIS USART в менеджере по среде выполнения.
416 Глав 12

Откройте RTE и выберите Драйвер CMSIS: USART:: UART.


Нажмите кнопку твердости и затем хорошо добавить драйвер UART к проекту.

Во-первых, мы должны настроить контакты микроконтроллера для переключения от


GPIO до контактов Tx и Rx USART. Контакты микроконтроллера настроены в
Устройстве:: файл RTE_Device.h (Рис. 12.7).

Рисунок 12.7
Настройте контакты USART в файле RTE_Device.h.

В окне проекта откройте устройство:: RTE_Device.h и выбор мастер


конфигурации.
Включите UART1 и отключите опции DMA.

Этот пример использует средство моделирования, таким образом, фактическое


расположение выводов не имеет значения. На реальной аппаратной плате мы должны
были бы настроить корректные контакты для Tx и Rx. DMA отключен, потому что
средство моделирования не поддерживает это периферийное устройство.
Теперь откройте Thread.c. Этот файл характерен для STM и проектов NXP.

Для доступа к Драйверу CMSIS API мы можем затем добавить заголовочный файл
драйвера USART к нашему исходному коду. Драйвер CMSIS оказывает поддержку
для каждого периферийного устройства данного типа, доступного на выбранном
микроконтроллере. Каждый экземпляр драйвера определяется структурой доступа,
которая содержит определение Драйвера CMSIS API для данного периферийного
устройства.
ARM_DRIVER_USART Driver_USART3 5 {
USARTx_GetVersion,
USART3_GetCapabilities,
USART3_Initialize,
USART3_Uninitialize,
USART3_PowerControl,
USART3_Send,
Компоненты программного обеспечения 417

USART3_Receive,
USART3_Transfer,
USART3_GetTxCount,
USART3_GetRxCount,
USART3_Control,
USART3_GetStatus,
USART3_SetModemControl,
USART3_GetModemStatus
};

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


файл в наш исходный код и добавляет объявление “экстерна” для периферийного
устройства Универсального синхронного асинхронного приемопередатчика
(USART), к которому мы хотим получить доступ.
#include "Driver_USART.h"
ARM_DRIVER_USART Driver_USART1 экстерна;

В thread.c мы можем сделать первый вызов API для инициализации драйвера.


Driver_USART1-.Initialize(myUSART_callback);

Вызов инициализации запускает драйвер и регистрирует функцию обратного вызова.


После того как функция обратного вызова была зарегистрирована в драйвере, она
будет инициирована аппаратными событиями в процедурах обработки прерывания
периферийного устройства и драйвера USART. Каждый раз, когда эта функция
инициирована, она передаст параметр, который указывает на определенное
аппаратное событие USART (Таблица 12.2).

Таблица 12.2: события обратного вызова USART


Аппаратные события USART
ARM_USART_EVENT_SEND_COMPLETE
ARM_USART_EVENT_RECEIVE_COMPLETE
ARM_USART_EVENT_TRANSFER_COMPLETE
ARM_USART_EVENT_TX_COMPLETE
ARM_USART_EVENT_TX_UNDERFLOW
ARM_USART_EVENT_RX_OVERFLOW
ARM_USART_EVENT_RX_TIMEOUT
ARM_USART_EVENT_RX_BREAK
ARM_USART_EVENT_RX_FRAMING_ERROR
ARM_USART_EVENT_RX_PARITY_ERROR

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


аппаратных событий USART, которые мы хотим обработать.
освободите myUSART_callback (uint32_t событие)
{
переключатель (событие)
418 Глав 12

{
случай
ARM_USART_EVENT_RECEIVE_COMPLETE:
случай ARM_USART_EVENT_SEND_COMPLETE:
osSignalSet (tid_Thread, 0x01);

повреждение;

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

После того как мы инициализировали драйвер и установили обратный вызов,


мы можем включить периферийное устройство путем вызова функции
управления питанием.
USARTdrv-.PowerControl (ARM_POWER_FULL);

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


USART в рабочий режим. Как правило, это включает конфигурирование системного
блока управления микроконтроллера, чтобы включить дерево часов и выпустить
периферийное устройство от сброса. После того как USART был включен, мы можем
настроить его рабочие параметры с помощью функции управления.
USARTdrv-.Control (ARM_USART_MODE_ASYNCHRONOUS |

ARM_USART_DATA_BITS_8 |

ARM_USART_PARITY_NONE |

ARM_USART_STOP_BITS_1 |

ARM_USART_FLOW_CONTROL_NONE, 9600);

Теперь, когда рабочие параметры USART были настроены, мы можем


использовать отправление и получить функции для передачи данных.
USARTdrv-.Send ("Сообщение 26 символов", 26);
USARTdrv-.Receive (&cmd, 1);

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


выполнена ЦП или внутренней единицей DMA, обеспеченной микроконтроллером.
Исследуйте код Драйвера CMSIS в Thread.c.
Выберите проект “Пакетная Сборка” для разрабатывания обоих проектов.
Запустите отладчик.
Компоненты программного обеспечения 419

В проекте NXP откройте “view\serial window\serial 2”.


Откройте peripherals\usart\usart1 окно.
Выполните код.
Проверьте конфигурацию USART в периферийное окно.
Начальная буква “Привет Мировое” сообщение будет отображена в окне
последовательной консоли.
Выйдите из отладчика.
Переключитесь на второй проект и повторите вышеупомянутый сеанс отладки.

Из-за различных соглашений о присвоении имен, используемых кремниевыми


производителями, последовательные данные STM будут произведены к “view\serial
window\serial 1”.

Мы теперь выполняем точно тот же код USART микроконтроллеров двух


различных Кремниевых Поставщиков.

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


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

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

В этом осуществлении мы настроим Пакет Проверки Драйвера CMSIS и создадим


проект проверки протестировать возможности I2C, SPI и драйверов USART.
Откройте установщик пакета и выберите ARM:: пакет CMSIS-Driver_Validation (Рис.
12.8).
420 Глав 12

Рисунок 12.8
Выберите и установите пакет Проверки Драйвера CMSIS.

В учебных примерах откройте проект “CMSIS-драйвер Упражнения 12.1”.

Этот проект имеет SPI, I2C и драйверы USART, выбранные и настроенные в


проекте (Рис. 12.9).

Рисунок 12.9
Включите драйверы, которые Вы хотите протестировать в менеджере
RTE и RTE_Device.h.

Отчет о проверке будет, отправляют канал STDIO. ARM:: установка compiler:IO в


RTE настроена для перенаправления вывода STDIO к ITM поэтому теперь, все наши
результаты появятся в view\serial windows\printf средство просмотра (Рис. 12.10).
Компоненты программного обеспечения 421

Рисунок 12.10
Установите ITM, чтобы быть каналом STDIO.

В RTE выберите проверку Драйвера CMSIS и включите Платформу, I2C, SPI и опции
USART (Рис. 12.11).

Рисунок 12.11
В менеджере RTE выберите среду тестирования и драйверы для
тестирования.

Нажмите "OK" для добавления компонентов проверки к проекту (Рис. 12.12).

Рисунок 12.12
Проекту теперь добавили платформу проверки.
422 Главы 12

Откройте CMSIS Driver Validation:: DV_Config.h и выбор Мастер конфигурации. Для


каждого из Драйверов CMSIS выберите экземпляр Драйвера 1 (Рис. 12.13).

Рисунок 12.13
DV_Config.h позволяет Вам настраивать тестовую конфигурацию
Драйвера CMSIS.

Затем откройте раздел тестовых сценариев для каждого драйвера и включите некоторые
тестовые сценарии (Рис. 12.14).

Рисунок 12.14
Каждый Драйвер CMSIS имеет диапазон предопределенных
тестов.
Компоненты программного обеспечения 423

Это настраивает валидацию, для запущения тестов, которые мы должны назвать


средой тестирования.
Откройте main.c в проекте и cmsis_dv () функция для вызова платформы проверки.
международное основное (пустота)
{osKernelInitialize ();
cmsis_dv (); osKernelStart ();

Разработайте проект.
Запустите отладчик и выполните код.

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


view\serial windows\debug (printf) окно (Рис. 12.15).

Рисунок 12.15
Результаты испытаний производятся к окну консоли ITM. Локальные опции
позволяют Вам сохранять результаты в файл.

В dv_config.h конфигурационном файле “Общие Тестовые Настройки” позволяют


этому отчету быть сгенерированным как простой текст или XML (Рис. 12.16).

Рисунок 12.16
Результаты испытаний могут быть произведены как простой текст
или XML.
424 Главы 12

Разработка компонента программного обеспечения


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

Упражнение 12.3 Компонент GPS


Откройте установщик пакета.
Выберите Советы:: разработчики ведут учебное руководство.
Выберите вкладку Example и Копию “Компонент EX 12.2 GPS”.

Этот проект использует Драйвер CMSIS USART для получения данных из внешней
единицы GPS. Единица GPS, используемая в этом примере, является “модулем” GPS
Ublox NEO-6M. Это - недорогой модуль, который широко доступен (Рис. 12.17).

Рисунок 12.17
UBLOX NEO-6M является недорогим модулем GPS, который может быть
подключен к микроконтроллеру через USART.

Данные GPS отправляются в форме последовательного протокола, названного NMEA


0183 (Национальная Ассоциация Судового оборудования). Данные NMEA
отправляются в форме ASCII последовательную строку. Каждое последовательное
предложение NMEA запускается с “$GP”, сопровождаемого рядом букв для
идентификации типа предложения. Этот заголовок затем сопровождается
разграниченными данными запятой. Каждое предложение заканчивается “”
сопровождаемый двухразрядной контрольной суммой. Типичное предложение
показывают на Рис. 12.18.
Компоненты программного обеспечения 425

Рисунок 12.18
GPS-приемник будет обычно производить предложение текста ASCII с помощью
протокола NMEA 0183.

Весь код GPS находится в модуле gpsThread.c. Параметры конфигурации


находятся в gps_config.h. Пользовательские API-функции объявляются в gps.h
(Рис. 12.19).

Рисунок 12.19
Проект компонента GPS имеет тестовые сборки и приложение.

Как обсуждено в Главе 11 "Test-Driven Development", код был разработан с помощью


метода “Разработки через тестирование”, таким образом, мы можем переключиться от
сборки приложения до тестовой сборки, чтобы исследовать, как код работает.
статический GPS_Thread пустоты (освобождают константу
*аргумент) {статический ARM_DRIVER_USART * USARTdrv 5
&SELECTED_USART; допустимый символ;
gpsMutexCreate ();
initilizeUSART (USARTdrv); в то
время как (1) {
detectGpsHeader (USARTdrv);
допустимые 5 receiveNmeaData (USARTdrv);
если (допустимый 55 0) {
processNmeaData ();
}}}

Компонент GPS работает первой инициализацией Драйвера CMSIS USART.


Компонент затем прислушивается к заголовку предложения GPS ($GP). Когда это
получено, символы читаются
426 Глав 12

в буфер до конца предложения () или время получен. Мы затем получаем две


символьных контрольных суммы. Если контрольная сумма допустима, предложение
ASCII разобрано в структуру “gpsData”. К gpsData структуре можно затем получить
доступ с помощью функции помощника getGPSValue ().

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


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

Код GPS был написан так, чтобы это был автономный модуль, который отделяется от
любых других частей приложения. Это помогает протестировать и также легкий к
повторному использованию
(Рис. 12.20).
Переключитесь на цель приложения.
Разработайте проект.
Запустите средство моделирования.
Откройте окно Symbol и добавьте gpsData к окну часов.
Откройте View\Toolbox.

Рисунок 12.20
Функции в сценариях моделирования могут быть инициированы
используемым, определяют кнопки.

Нажатие одной из этих кнопок отправит соответствию предложение NMEA в


моделируемый последовательный порт микроконтроллера.

После того как предложение NMEA было получено, проанализированные данные


будут обновлены в gpsData структуре.
Теперь, у нас есть универсальный программный модуль, который может
использоваться на любом микроконтроллере Cortex-M, который имеет
Драйвер CMSIS USART.
Компоненты программного обеспечения 427

Создание программного пакета


В последнем примере мы видели, как мы можем использовать Драйвер CMSIS для
разработки компонента программного обеспечения, который может быть снова
использован через несколько семейств микроконтроллеров. Мы также видели, как
программные пакеты используются для установки поддержки микроконтроллеров.
Программные пакеты могут также использоваться для установки библиотек
программного обеспечения и других компонентов программного обеспечения в наш
набор инструментальных средств (Рис. 12.21).

Рисунок 12.21
Система Пакета CMSIS может использоваться для установки компонентов
программного обеспечения в набор инструментальных средств. Это может быть
поддержкой конкретного семейства микроконтроллеров, другое использование
должно установить вспомогательные библиотеки платы или промежуточное
программное обеспечение. В доме программные пакеты могут также быть созданы
для многократного использования кода.

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


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

Программный пакет CMSIS является просто набором программных файлов, которые


Вы хотите добавить к менеджеру RTE плюс дополнительные вспомогательные
файлы, такие как документация, информация о лицензии, примеры и шаблоны. Для
создания компонента программного обеспечения необходимо генерировать только
один
428 Глав 12

дополнительный файл. Это - XML “файл описания пакета”, который описывает


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

Software Pack Utilities

Прежде чем мы сможем начать создавать программный пакет, необходимо


установить много программ, чтобы помочь разработать пакет.
Загрузите и установите следующие программы, данные в Таблице 12.3.

Таблица 12.3: Утилиты, требуемые генерировать Пакет CMSIS

Утилита Описание Местоположение


7Zip Утилита Compression www.7-zip.org
Notepad11 XML-редактор notepad-plus-plus.org

Откройте каталог проекта Осуществления компонента GPS с помощью Windows


Explorer.
Переместите в подкаталог “пакет” (Рис. 12.22).

Рисунок 12.22
От перемещения проекта GPS в каталог Pack.

Каталог, содержащий все файлы, необходимые для создания программный


пакет, дан в Таблице 12.4.

Таблица 12.4: файлы типа "build" Пакета CMSIS

Файл Описание
Пакетный файл
Gen_pack.bat поколения пакета
PackChk.exe Упакуйте программу
проверки синтаксиса
Pack.xsd Упакуйте XML-схему
Шаблон описания
Vendor.pack.pdsc пакета
Компоненты программного обеспечения 429

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


Существует четыре требуемые шага. Во-первых, необходимо решить то, чем будет
содержание пакета. В нашем случае мы хотим сделать программный пакет для
компонента GPS. Таким образом, первый шаг должен будет удалить код из проекта и
превратить его в автономный компонент. Это обычно будет модулем кода “C” или
библиотекой и включать заголовочным файлом. Наш компонент GPS состоит из
файлов, перечисленных в Таблице 12.5.

Таблица 12.5: исходные файлы Компонента программного


обеспечения

Файл Описание
gpsThread.c Исходный код компонента
gps.h Заголовочный файл API
Конфигурационный файл
Gps_config.h библиотеки
gpsUserThread.c Шаблон User компонента

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


связанную документацию, примеры и шаблонные файлы в разумную структуру
каталогов. После того как у нас есть все расположенные файлы компонента
программного обеспечения, мы должны создать дополнительный XML-файл, который
содержит описание содержания компонента программного обеспечения. Затем
заключительный этап должен создать пакет путем выполнения “gen_pack.bat”
пакетного файла, это проверяет описание пакета XML по файлам компонента. Если не
будет никаких ошибок, то программный пакет будет сгенерирован (Рис. 12.23).
Рисунок 12.23
Программный пакет может быть создан на четырех шагах: (1) Изолируйте код, который
Вы хотите снова использовать; (2) Создайте файловую структуру для компонента
программного обеспечения; (3) Создайте файл описания пакета XML; (4) Выполните
утилиту поколения пакета.
430 Глав 12

Каталог “файлов” содержит все файлы, которые будут включены в наш пакет.
Мы можем создать любую структуру каталогов, мы хотим расположить файлы пакета
(Рис. 12.24).

Рисунок 12.24
Структура каталогов Компонента в качестве примера.

Эта структура каталогов является абсолютно свободной формой, таким образом,


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

Рисунок 12.25
Содержание пакета описано .pdsc файлом в основном каталоге пакета.

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


отражения содержания нашего компонента программного обеспечения. Первая вещь,
которую мы должны сделать, переименовывают шаблонный файл описания пакета
для соответствия нашему имени поставщика и названию компонента программного
обеспечения, в этом случае “Hitex. Components.pdsc”. Заключительное имя пакета
создается с помощью шаблонного имени файла (Рис. 12.26).
Компоненты программного обеспечения 431

Рисунок 12.26
Файл описания программного пакета является XML-файлом. Это имеет много
контейнеров, которые могут использоваться для описания
содержания программного пакета.

Файл описания пакета состоит из многих контейнеров XML, которые описывают и


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

Теперь откройте файл описания пакета с notepad11 или другим XML-редактором, и


мы исследуем, как файл описания структурирован.
Первый раздел файла предоставляет первоначальное описание файла.
? версия 5 "1.0" xml, кодирующая 5 "utf-8"?.

, пакет "http://www.w3.org/2001/XMLSchema-instance" schemaVersion 5 "1.2" xmlns:xs 5


xs:noNamespaceSchemaLocation 5 "PACK.xsd".
, поставщик. Hitex, / поставщик., имя.
Компоненты, / имя.

, описание. Набор библиотек драйвера устройства, / описание., url.www.hitex.co.uk/repository, / URL.,

supportContact.tmartin@hitex.co.uk,/supportContact.
! - дополнительный файл лицензии-.
, лицензия.
432 Главы 12

License\License.txt
, / лицензия.

, выпуски.
, версия выпуска 5 "1.0.0".
Первоначальная версия с драйвером
GPS
, / выпуск., /
выпуски.

, ключевые слова.
! - ключевые слова для индексации-., ключевое слово
insert_keyword_for_search_engines, / ключевое слово.
, / ключевые слова.

Первая запись используется для применения XML-схемы, используемой системой


пакета. Это описано в файле PACK.xsd. Были некоторые дополнения к этому файлу
поэтому при создании пакета всегда проверяйте, что у Вас есть актуальная версия.
Следующий раздел содержит информацию о поставщике. Это обычно будет
названием компании и названием программного пакета. Имя программного пакета
должно соответствовать имени, используемому в разделе описания пакета имени
файла пакета. Если эти два будут отличаться, то ошибка будет сгенерирована, когда
мы попытаемся создать пакет. Мы можем также предоставить описание пакета,
который появится в установщике пакета. Запись URL описывает местоположение, где
пакет может быть расположен. Это может быть файловым сервером компании или
интернет-веб-сервером. После того как пакет установлен, это местоположение будет
проверено на пакет обновления каждый раз µVision, IDE или установщик пакета
запускаются. Это позволяет Вам выпускать новую версию своего пакета путем
простого обновления файла пакета на веб-сервере, теперь новая версия будет доступна
любому пользователю, который установил исходный пакет. Существует также раздел
для номера выпуска, который структурирован как показано в
Таблица 12.6.

Таблица 12.6: Соглашение о присвоении имен для номера версии


пакета
Формат, ГЛАВНЫЙ.., НЕЗНАЧИТЕЛЬНЫЙ..,
Номер выпуска драйвера Патч.
Главная версия, может не быть обратно
ГЛАВНЫЙ совместимым
Незначительный выпуск, обратно
НЕЗНАЧИТЕЛЬНЫЙ совместимый
Возрастающий выпуск для исправлений
ПАТЧ ошибок
Если Вы хотите распределить пакет по Интернету, можно также включать
информацию о лицензии и искать ключевые слова. Здесь, у нас есть путь к нашему
каталогу лицензии и документу лицензии. Это будет установлено вместе с
компонентом и будет также отображено, когда компонент будет установлен. В разделе
ключевых слов можно обеспечить диапазон поисковых слов для создания пакета более
видимым к поисковым системам.
Компоненты программного обеспечения 433

, таксономия.

, описание Cclass 5 "Компонентов". Библиотеки драйвера для общих аппаратных компонентов, / описание.

, / таксономия.

Теперь, мы можем начать настраивать файл описания пакета для описания наших
компонентов программного обеспечения. RTE имеет много стандартных категорий,
что мы можем добавить наши компоненты также. Однако наш компонент GPS
действительно не вписывается ни в какую существующую категорию. В языке
описания пакета существует раздел таксономии, который позволяет нам расширять
диапазон категорий компонента. Здесь, мы создаем раздел “Components” в RTE
(Рис. 12.27).

Рисунок 12.27
Тег таксономии создает новую категорию в менеджере по Среде выполнения.

После того как пакет установлен, новая категория будет видима, когда менеджер
RTE будет открыт.

Теперь, мы можем начать описывать компоненты программного обеспечения.


Каждый компонент имеет свой собственный раздел в контейнере компонента.
, компоненты.
, Cclass компонента 5 "компонентов" Cgroup 5 "Csub 5 "Ublox NEO-6M" Cversion 5 "1.0.0""
модуля GPS.
, описание. Библиотека GPS для получателя Ublox NEO-6M, / описание., файлы.

, категория файла 5 "исходных" имен 5 "Component\GPS\gpsThread.c"/.,


категория файла 5 названий "заголовка" 5 "Component\GPS\gps.h"/.
, категория файла 5 названий "заголовка" 5 "Component\GPS\gps_config.h" attr 5 "конфигурация"/., /
файлы.

, / компонент., /
компоненты.
434 Главы 12

Во-первых, мы определяем его местоположение в RTE. В этом примере компонент


GPS будет добавлен к разделу Components и подгруппе под названием GPS, мы можем
затем предоставить заголовок и описание для компонента. Затем, мы можем добавить
файлы, которые составляют компонент. Это означает определять их тип и путь и
название файла (Таблица 12.7).

Таблица 12.7: Поддерживаемые типы файлов Пакета CMSIS

Категория Описание
Документ Документация
Заголовочный файл используется в компоненте. Наборы включать путь к
Заголовок файлу
Включать Наборы включать путь к файлу
Библиотека Файл библиотеки
Объект Объектный файл, который может быть добавлен к приложению
Источник Запуск - система - и другой C/C11, ассемблер, и т.д. исходные файлы
Источник C C исходный файл
Источник Cpp Исходный файл C11
Источник
ASM Исходный файл блока
Сценарий
компоновщик Файл сценария компоновщика, который может быть выбран наборами
а инструментальных средств
Инструмент командной строки, который может быть настроен для пред - или
Утилита постобрабатывающий во время
процесс сборки
Файлы типа изображения отмечены для специальной обработки в
Изображение Изображение Файловой системы
встроенный в приложение. Эта категория требует attr, устанавливаемого
обрабатывать по шаблону
Другое Другие типы файлов, не охваченные в списке выше

Существует диапазон поддерживаемых типов файлов для нашего компонента, мы


должны определить наши файлы как “заголовок” и “источник”. Каждому файлу
можно дать атрибут, который влияет, как файл добавляется к проекту (Таблица 12.8).

Таблица 12.8: атрибуты исходного файла Пакета CMSIS

Атрибут Описание
Файл является конфигурационным файлом компонента. Это ожидается та
конфигурация единственная конфигурация
опции изменяются. Файлом управляют как часть компонента как определенное для
проекта
файл обычно скопирован в раздел компонента проекта
Файл используется в качестве шаблонного файла исходного кода. Это, как ожидают,
шаблон будет отредактировано и расширено
разработчик программного обеспечения. Файл может быть скопирован в
пользовательский раздел проекта
В каждом из наших компонентов заголовочному файлу дали конфигурацию атрибута.
Это означает, что, когда мы используем менеджера RTE для добавления компонента
к нашему проекту, копия заголовочного файла будет скопирована в каталог проекта,
таким образом, мы сможем отредактировать его. Исходный файл не был дан и
атрибут, таким образом, он будет сохранен как файл только для чтения в репозитории
пакета в наборе инструментальных средств. Когда компонент будет выбран, путь
будет установлен для включения исходного файла. Это означает, что при
использовании системы управления версиями, необходимо будет включать весь
Компоненты программного обеспечения 435

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


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

Начальный пакет может быть сгенерирован путем открытия окна командной строки
в каталоге разработки и затем выполнения “gen_pack” пакетного файла. Это
проанализирует файл описания пакета и проверку по сравнению с содержанием
каталогов компонента программного обеспечения. Если не будет никаких ошибок,
то файл пакета будет создан. Этот файл пакета является файлом сжатия каталогов
компонента программного обеспечения и файлами плюс файл описания пакета (Рис.
12.28).

Рисунок 12.28
gen_pack пакетный файл проверяет, что файлы пакета против файла описания
пакета затем генерируют заключительный файл
пакета.

После того как это было сгенерировано, мы можем установить наш компонент GPS
путем двойного щелчка по файлу пакета (Рис. 12.29).

Рисунок 12.29
Файл пакета может быть установлен локально путем двойного щелчка по файлу
пакета или путем выбора файла/импорта в
установщике пакета.
Теперь, мы можем открыть менеджер RTE и видеть новый раздел модулей с
компонентом GPS. Если мы выберем компонент GPS, то его файлы будут
добавлены к проекту (Рис. 12.30).
436 Глав 12

Рисунок 12.30
После того как пакет установлен, компонент GPS доступен, чтобы быть добавленным к
новому проекту.

В то время как это полезно на этом уровне, это - просто “симпатичный” способ
добавить файлы к Вашему проекту. Для создания нашего компонента более
интеллектуальным мы можем начать добавлять некоторые условия, которые
предусматривают, требует ли компонент GPS, чтобы какие-либо другие компоненты
работали в рамках проекта.
, условия.
, идентификатор условия 5 "USART".
, потребуйте Cclass 5 "Cgroup 5 "USART"" Драйвера CMSIS/.,
потребуйте Cclass 5 "CMSIS" Cgroup 5 "ЯДРО"/., потребуйте
Cclass 5 "CMSIS" Cgroup 5 "RTOS"/., / условие.

, / условия.

В контейнере условий мы можем создать правило, которое определяет, какие


дополнительные компоненты должны быть выбраны. Здесь, мы создали условие
под названием “USART”, который требует, чтобы CMSIS RTOS и CMSIS-базовая
спецификация были выбраны наряду с драйвером CMSIS USART.
, Cclass компонента 5 "компонентов" Cgroup 5 "условие Csub 5 "Ublox NEO-6M" Cversion 5
"1.0.0"" Модуля GPS 5 "USART".

Теперь в описании компонентов компонента GPS мы можем добавить условия. Если


пакет является новым, повторно создан и переустановленный, мы можем
протестировать правило путем выбора компонента GPS (Рис. 12.31).
Рисунок 12.31
Теперь, когда компонент выбран, он потребует драйвера CMSIS USART.
Компоненты программного обеспечения 437

Когда выбор GPS (Sel). поле отмечается, это повернет оранжевое значение, что это
требует субкомпонента, и окно проверки говорит нам, что мы должны включать RTOS
и Драйвер CMSIS:: USART в нашем проекте. Теперь нажмите кнопку Resolve, и RTOS
будет выбран. Существует несколько опций для драйвера CMSIS USART, таким
образом, мы должны вручную выбрать подходящий драйвер (Рис. 12.32).

Рисунок 12.32
Выберите доступный Драйвер CMSIS USART.

После того как мы выбрали все необходимые компоненты, все активные элементы в
Выборе (Sel). столбец будет окрашен в зеленый. Теперь, мы можем нажать "OK", и
законченный выбор компонента будет добавлен к нашему проекту.
, выпуски.
, версия выпуска 5 "1.0.0".
Первоначальная версия с драйвером
GPS
, / выпуск., /
выпуски.

Поскольку мы создаем новые версии программного пакета, мы можем увеличить


номер версии. Поскольку мы устанавливаем новые версии компонента, история
версий видна в установщике пакета. После того, как установленный, каждая версия
сохранена в репозитории пакета, таким образом, возможно поддержать проекты,
разработанные с различными версиями компонента программного обеспечения.
, файлы.
, категория файла 5 "исходных" имен 5 "Component\GPS\gpsThread.c"/.,
категория файла 5 названий "заголовка" 5 "Component\GPS\gps.h"/.
, категория файла 5 названий "заголовка" 5 "Component\GPS\gps_config.h" attr 5 "конфигурация"/.,
категория файла 5 названий "документа" 5 "Component\Documentation\GPS\nmea.htm"/.
, / файлы.

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


документацию. Это использует категорию файла документа и предоставляет ссылку
на описание протокола NMEA.
, файлы.
, категория файла 5 "исходных" имен 5 "Component\GPS\gpsThread.c"/., категория
файла 5 названий "заголовка" 5 "Component\GPS\gps.h"/.
, категория файла 5 названий "заголовка" 5 "Component\GPS\gps_config.h" attr 5 "конфигурация"/.,
категория файла 5 "исходных" имен 5 "Component\GPS\gpsUserThread.c" attr 5 "шаблон"
выберите 5 "Пользовательских
Потоков GPS"/, / файлы.
438 Глав 12

Также возможно добавить шаблонный файл. Это - фрагмент кода, который


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

Рисунок 12.33
Запись описания является теперь гиперссылкой к документации компонента.

Теперь, когда пакет повторно создан и переустановлен, документация будет


доступна через гиперссылку (Рис. 12.34).

Рисунок 12.34
Код шаблона доступен в, “Добавьте Новый Объект” диалоговое
окно.

Если мы добавим компонент GPS к проекту, то его шаблон будет доступен в,


“Добавьте новый Объект к Группе” диалоговое окно, когда мы добавляем новый
исходный файл к проекту.

Пакет CMSIS также позволяет включать проекты в качестве примера


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

, имя в качестве примера 5 папок "GPS component configuration Example" 5 документов 5


"Examples\GPS \Configuration" версия 5 "1.0" "Abstract.txt".
, описание. Этот пример демонстрирует, как настроить компонент GPS, / описание.

, поставщик плат 5 "Keil" называет 5 "MCB1700"/.,


проект.

, имя среды 5 "UV" загружает 5 "configuration.uvprojx"/., / проект.

, атрибуты.
, Cclass 5 "CMSIS" Cgroup 5 компонента "ЯДРО"/.,
"устройство" Cclass 5 Cgroup 5 компонента "Запуск"/.
, / атрибуты., /
пример.

Шаблон пакета содержит контейнер в качестве примера, который позволяет Вам


добавлять любое количество проектов в качестве примера. Каждый пример описан как
показано выше. Название и местоположение в качестве примера папки в качестве
примера определяется наряду с файлом документации. Затем, описание примера
добавляется; это появится в столбце описания установщика пакета в качестве примера.
Для завершения описания в качестве примера мы предоставляем информацию о
поставщике плат разработка проекта используемый IDE и название проекта для
загрузки. В разделе атрибутов мы можем предоставить подробную информацию
любых дополнительных компонентов, которые должны быть загружены, чтобы
позволить проекту быть восстановленным (Рис. 12.35).

Рисунок 12.35
Примеры компонента доступны через установщик пакета.

Теперь, когда пакет установлен, наши примеры будут видимы на вкладке


установщика пакета в качестве примера.

Мастер конфигурации
После того как файлы компонента были добавлены к проекту, мы должны будем
сначала настроить любые параметры конфигурации. В типичном компоненте
параметры конфигурации будут группироваться как ряд #defines в заголовочном
файле. Сделать компонент более интуитивным для использования его возможно
добавить некоторые аннотации в рамках комментариев, которые позволяют
заголовочному файлу просматриваться как мастер конфигурации. Затем выборы,
сделанные в мастере конфигурации, изменят связанный #define. Таблица 12.9
предоставляет обзор доступных тегов.
440 Глав 12

Таблица 12.9: XML-тэги используются для создания мастера


конфигурации

Тег шаблона Описание


, h. Создайте раздел заголовка
, e. Создайте раздел заголовка с, включают
Создайте раздел заголовка с, включают и изменяют
, e.i. определенный бит
, я. Текст всплывающей подсказки
, q. Битовые значения установлены текстовым полем
, o. Текстовое поле для числового значения
, o.i. Измените единственный бит в следующем #define
Текстовое поле для числового значения с
, o.x.. y. диапазоном
, s. Строка ASCII
, s.i. Строка ASCII с символьным пределом
Пропустите i #defines и измените следующий
, qi., oi., oi.x., СИ., si.x. #define

После того как Вы знакомы с аннотациями мастера конфигурации, создание


новых шаблонных файлов является относительно быстрым процессом.

Упражнение 12.4 Мастер конфигурации

В этом осуществлении мы добавим аннотации мастера конфигурации к


заголовочному файлу GPS_Config.h.
Возвратите Упражнению 12.2 компонент GPS.
Откройте проект GPS.
Откройте заголовочный файл gps_config.h.

Параметры конфигурации для нашего компонента программного обеспечения


сохранены в заголовочном файле gps_config.h. Этот файл содержит ряд #defines,
которые используются кодом главного приложения. Этот файл также содержит
необходимые аннотации, которые будут просматриваться как мастер конфигурации. В
этом примере мы прочитаем этот файл, чтобы видеть, как они работают.

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

В конце файла добавьте следующий комментарий для закрытия мастера


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

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


параметров конфигурации. Заголовок раздела может быть создан со следующим
комментарием:
//, h. разделяют заголовок
Компоненты программного обеспечения 441

Конец раздела должен быть закрыт;


//,/h.

Также возможно создать заголовок раздела с разрешать опцией.


//, e. раздел с включают #define,
ВКЛЮЧАЮТ 0

Этот тег должен сопровождаться #define. Это определяет, будет изменен к 1, если
выбор будет отмечен. Этот раздел должен быть закрыт:
,/e.

Путем добавления заголовков раздела мы можем начать структурировать включать


шаблон файла (Рис. 12.36).
// , используйте мастер конфигурации в контекстном меню...
// , h. NEO-6M конфигурация GPS
//, h. Выберите предложения
NMEA//,/h.

//, h. Выберите последовательный


интерфейс//,/h.

//,/h.

Рисунок 12.36
Теги мастера конфигурации помещаются в комментарии. Редактор может затем
просмотреть исходный код как мастер
конфигурации.

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


раздела предложения NMEA мы можем указать сообщения GPS, которые мы хотим
получить. Используя следующий тег, возможно создать поля галочки, которые
изменяют #define, который сразу следует за ними.
//, q. выбирают опцию
#define ОПЦИЯ 0

Используя этот тег, мы можем развернуть раздел предложений с параметрами


конфигурации выбрать сообщения NMEA, которые будут обработаны.
//, h. Выберите предложения
NMEA//, q. GPGGA
#define GPS_GPGGA 1//,
q. GSA
#define GPS_GSA 0
442 Главы 12

//, q. GSV #define


GPS_GSV 0//, q. PRMC
#define GPS_PRMC
0//,/h.

Затем, мы можем расширить раздел последовательных интерфейсов. Здесь, мы можем


создать выпадающую рамку выделения при помощи следующих тегов:
// , o. Рамка выделения
// , 1 5. выбор 1
// , 2 5. выбор 2
// , 3 5. выбор 3
// , 4 5. выбор 4 #define
ВЫБОРА 1

Используя тег рамки выделения, мы можем теперь создать опции выбора для
последовательных интерфейсов USART.
// , o. Выберите периферийное устройство USART
// , 1 5. USART 1
// , 2 5. USART 2
// , 3 5. USART 3
// , 4 5. USART 4 #define
GPS_USART_PERIF 3
// , o. Выберите скорость в бодах USART
// , 2400 5. 2400
// , 4300 5. 4300
// , 9600 5. 9600
// , 34000 5. 34 000 #define
GPS_USART_BAUD 9600

После того как у нас есть функционирующий мастер конфигурации, мы можем


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

Рисунок 12.37
Мастер конфигурации с подсказкой.
Компоненты программного обеспечения 443

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


сложные параметры конфигурации, он действительно полагается на пользователя,
имеющего основное понимание компонента программного обеспечения. Если,
например, единица GPS имела два типа последовательных интерфейсов, SPI и
USART, который не мог использоваться одновременно. Мастер конфигурации
показал бы Вам варианты для обоих, но не сделает ничего, чтобы мешать
пользователю выбрать обоих. Чтобы дать пользователю некоторое предупреждение,
возможно добавить сообщения об ошибках, которые будут испускаться во время
процесса сборки. Так, например, в случае двух последовательных интерфейсов:
#if (GPS_SPI_EN 55 1 && GPS_USART_EN 55 1)
#error ":: GPS Driver:Too много последовательных интерфейсов
включил" #endif

Если конечный пользователь компонента программного обеспечения выберет оба


последовательных интерфейса, то проект не создаст, и предупреждение будет
выдано в окне вывода сборки.

Развертывание компонентов программного обеспечения


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

В настоящее время установщик пакета автоматически проверит веб-сайт Keil на


текущий список пакета общедоступного и третьего лица. Можно просмотреть
текущий список здесь:
http://www.keil.com/dd2/pack/

Любые новые пакеты, добавленные к этому списку, будут автоматически


отображены в рамках установщика пакета. Можно отправить пакет, который будет
проверен, и затем он может быть добавлен к этому списку, делающему это видимый
к любому инструменту с помощью системы пакета. Пакет может быть размещен
двумя способами. После того как пакет проверен, он может быть перечислен и
сохранен на веб-сайте Keil. Это - самый легкий путь, но более твердо поддержать.
Второй метод должен перечислить пакет на веб-сайте Keil, таким образом, он может
быть обнаружен, но пакет может быть размещен на Вашем собственном сервере.
Таким образом, можно сделать пакет видимым ко всей базе пользователей, но все
еще смочь поддержать и обновить пакет на собственном локальном сервере.
444 Главы 12

Заключение
В этой главе мы посмотрели на важный шаг вперед для основанных на
микроконтроллере встроенных систем. Вместе, Драйвер CMSIS и Пакет CMSIS
впервые обеспечивают стандартизированный API для общих периферийных
устройств и средства создания и распределения компонентов программного
обеспечения. Во время записи ARM только что опубликовал плагин пакета для
Eclipse IDE. Это также сделает систему пакета доступной для многих других наборов
инструментальных средств и инструментов с открытым исходным кодом. Поскольку
система пакета становится доступной в нескольких средствах разработки, она
поощрит принятие стандарта Пакета CMSIS как способ совместно использовать и
распределить компоненты программного обеспечения Cortex-M.
CHPTER13

ARMv8-M

Введение
Как мы видели во введении, текущие процессоры Cortex-M основаны на ARMv6-M
(Cortex-M0/M01) и ARMv7-M (Cortex-M3/M4/M7) архитектура. К концу 2015 ARM
объявил о следующем поколении процессоров Cortex-M, которые являются на основе
новый архитектурный стандартный ARMv8-M. Архитектура ARMv8-M является 32-
разрядной архитектурой на основе существующего ARMv6-M и архитектурой ARMv7-
M и наследовала большинство функций существующей модели программиста Cortex-
M. Это позволяет большей части кода приложения быть легко портированной на
новую архитектуру с минимальными изменениями. В то время как ARMv8-M является
последним дизайном процессора от ARM, он не делает ARMv7-M или устройства
ARMv6-M устаревшими. Они будут вокруг в течение долгого времени все же, но
ARMv8-M прокладывает путь к хорошо масштабируемым, экономически
эффективным семействам микроконтроллера и представляет аппаратную модель
обеспечения безопасности, которая является основой для безопасных подключенных
устройств (Рис. 13.1).

Рисунок 13.1
Архитектура ARMv8-M состоит из двух Магистралей профилей и Базовой линии,
которые походят на существующий ARMv7-M и архитектуру
ARMv6-M.

ARMv8-M разработан, чтобы быть хорошо масштабируемой архитектурой и состоит


из профиля Магистрали и Базового подпрофиля. В то время как эти два профиля
походят на исходное ARMv7-M и ARMv6-M разделение, ARMv8-M создает
унифицированную архитектуру для процессоров микроконтроллера с существенно
новыми функциями. Архитектура ARMv8-M также разработана, чтобы быть очень
модульной для кремниевых разработчиков; это позволяет большей гибкости войти

Руководство разработчика по семейству процессоров Cortex-M.


DOI: http://dx.doi.org/10.1016/B978-0-08-100629-0.00023-2 445
© 2016 Elsevier Ltd. Все права защищены.
446 Глав 13

выбор функции процессора в двух профилях. Архитектура ARMv8-M также


представляет важное новое аппаратное расширение безопасности под
названием TrustZone, который доступен и в Магистрали и в Базовых
профилях.

Общие архитектурные улучшения


Два профиля ARMv8-M имеют единый набор архитектурных улучшений (Таблица
13.1).

Таблица 13.1: Общие архитектурные


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

Загрузка получает инструкции по выпуску хранилища


Новые инструкции для поддержки TrustZone
Модернизированная модель программистов единицы защиты памяти
Лучшая возможность отладки

ARMv8-M представляет новую группу “загрузки, получают хранилище и выпуск”


инструкции, которые требуются, чтобы обеспечивать поддержку оборудования для
последних стандартов языка “C”. Эти инструкции обеспечивают атомарную
переменную, обрабатывающую, который требуется последним “C” и стандартами
“C11”. Архитектура ARMv8 включает единицу защиты памяти (MPU) как
дополнительную единицу и в Магистрали и в Базовых профилях. В ARMv8-M MPU
имеет модель нового программиста, названную “Защищенной Архитектурой Системы
памяти” (PMSAv8). Новая модель PMSAv8 позволяет большую гибкость в
определении регионов защиты памяти. В ARMv7 MPU регион должен иметь
начальный адрес, который является кратным размеру региона, и размер региона
должен быть питанием два. Это ограничение могло часто означать использовать два
или больше региона MPU для покрытия единственного непрерывного блока памяти. В
модели PMSAv8 регион MPU определяется с начальным адресом и конечным адресом.
Единственное ограничение - то, что запуск и конечный адрес имеют 32-байтовую
гранулярность. Существуют также улучшения к часам данных и устанавливают
контрольные точки единицы отладки наряду с включением всесторонних функций
трассировки. Во время записи ARM не полностью объявил об этих функциях.

Базовые улучшения ARMv8


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

Таблица 13.2: Архитектурные улучшения


для базового профиля

Аппаратные средства делят инструкцию


Сравните и Ответвление и 32-разрядная
инструкция по Эксклюзивному доступу команд
перехода
16-разрядная Непосредственная
Поддержка инструкций по обработке
данных большего количества
прерываний
ARMv8-M 447

Архитектура ARMv6 использует исходную 16-разрядную систему команд Ползунка. В


Базовой линии ARMv8-M система команд Ползунка заменяется подмножеством
Ползунка 2 32-разрядных системы команд. Это будет означать что-то как 40%-е
увеличение производительности по текущей Коре-M0 и M01. Базовый Ползунок 2
системы команд теперь добавляют много полезных инструкций, что ARMv6-M
отсутствовал. Некоторые из этих инструкций, таких как аппаратные средства делятся,
и улучшенная команда перехода даст очевидное повышение базовой
производительности. Однако включение в 16-разрядные инструкции по обработке
данных (MOVT и MOVW) является более тонким. Эти две инструкции используются
для загрузки двух 16-разрядных непосредственных значений в верхнюю и более
низкую половину регистра для формирования 32-разрядного слова. Это позволяет Вам
создавать большие непосредственные значения очень эффективно, но что еще более
важно так как непосредственное значение является частью закодированной
инструкции, от которой это может быть выполнено, выполняют Только Память
(XOM). Это позволяет и Магистрали и Базовым профилям создавать код приложения,
который может работать в XOM как защищенное встроенное микропрограммное
обеспечение, которое не может быть перепроектировано через доступы отладки или
данные. Архитектура ARMv8-M также добавляет инструкции по эксклюзивному
доступу к Базовому профилю. Это должно увеличить поддержку многоядерных
устройств. Уже было несколько многоядерных Основанных на Cortex-M
микроконтроллеров особенно NXP LPC43xx и семейства LPC15000. Это
асимметричная многопроцессорная система (AMP) проекты, которые состоят из
Коры-M4 и Коры-M0 (LPC43xx) или Кора-M4 и Кора-M01. В обоих случаях
разработчики в NXP должны были реализовать свою собственную межпроцессорную
систему обмена сообщениями, потому что текущая Кора-M0 и M01 не имеют
инструкций по эксклюзивному доступу. Устройства ARMv8-M-based будет намного
легче интегрировать в многоядерную систему быть этим стандартный
микроконтроллер или пользовательская Система на микросхеме. Наконец, базовая
линия ARMv8-M также расширит количество каналов прерывания, доступных на
NVIC. Процессоры ARMv6-M-based (Кора-M0 и Кора-M01) ограничены 32 каналами
прерывания, и на некоторых устройствах это становится ограничением.

Улучшения магистрали ARMv8-M


Профиль Магистрали имеет следующие улучшения (Таблица 13.3).

Таблица 13.3: Архитектурные улучшения для


профиля магистрали

Дополнительная Архитектура С плавающей точкой v5


Дополнительное добавление инструкций по DSP

В то время как профиль Магистрали включает все общие упомянутые выше


архитектурные улучшения, это также получает новый сопроцессор для операций с
плавающей точкой и опцию включать инструкции по DSP с или без сопроцессора
для операций с плавающей точкой.
448 Глав 13

TrustZone
С ARMv6-M или ARMv7-M-based устройством совершенно возможно разработать
безопасную программную архитектуру. Однако ARMv8-M обеспечивает поддержку
оборудования для защищенной зоны в форме TrustZone. TrustZone является
установленной технологией на процессорах Cortex-A, и с ARMv8-M это будет
доступно микроконтроллерам Cortex-M впервые. TrustZone является рядом
аппаратных расширений, который позволяет Вам создавать границу между
Безопасным и Незащищенным ресурсом с минимумом кода приложения. TrustZone
оказывает незначительное влияние на производительность процессора ARMv8-M,
этого всего средства, простой эффективный код, который легче разработать,
отлаживает и проверяет (Рис. 13.2).

Рисунок 13.2
TrustZone создает защищенную зону в системе микроконтроллера.

TrustZone расширяет модель программистов для включения Безопасных и


Незащищенных состояний каждый с их собственным режимом Handler и Thread. Это
означает, что каждое состояние имеет свой собственный набор указателей вершины
стека, MPU и таймера SysTick. Карта памяти процессора может также быть разделена
в Безопасные и Незащищенные регионы. Когда процессор работает в Безопасном
состоянии, он может получить доступ к Безопасным и Незащищенным областям
памяти. Когда это работает в Незащищенном состоянии, это может только получить
доступ к Незащищенным областям памяти. И Безопасные и Незащищенные состояния
имеют свой собственный MPU, который может быть настроен для управления на
основе политик доступом к другому региону памяти в зависимости от состояния
процессора (Рис. 13.3).
Рисунок 13.3
TrustZone создает два новых состояния, Безопасное состояние и
Незащищенное состояние.
ARMv8-M 449

Мы можем создать код для выполнения в Незащищенном состоянии. Назовите


доступ функций Незащищенными периферийными устройствами и сервисом
Незащищенные прерывания как нормальный. Незащищенный код может также
сделать вызовы функции к коду доступа в Безопасном состоянии. Когда
Незащищенный код звонит Безопасному коду, он должен сделать запись в
Безопасный код через точку действительного доступа. Эти точки действительного
доступа являются новой инструкцией, названной инструкцией по Защищенному
шлюзу (SG). Если Незащищенный код попытается ввести защищенную зону путем
доступа к чему-нибудь кроме инструкции SG, то исключение SecureFault будет
повышено. Инструкция SG также очищается меньше всего
значимый бит регистра Ссылки (обычно набор к одному). Две новых инструкции
предоставлены для возврата от Безопасного состояния до Незащищенного состояния.
Безопасный код может использовать Учрежденческую АТС для Незащищенного кода
(BXNS) или Exchange Ссылки ответвления к Незащищенному коду (BLXNS). Эти
инструкции используют младший значащий бит (LSB) обратного адреса для указания
на переход от Безопасного до Незащищенного состояния (Рис. 13.4).

Рисунок 13.4
Незащищенный код может назвать Безопасный код, но он должен ввести Безопасное
состояние с помощью инструкции SG.

Для Безопасного кода также возможно назвать Незащищенный код. Когда это
происходит, обратный адрес Безопасного состояния хранится на стеке Secure и
специальном коде, FNC_RETURN хранится в регистре Ссылки. Когда
Незащищенная функция закончится, она перейдет на регистре Ссылки. Эта команда
перехода будет видеть, что FNC_RETURN кодирует, это инициировало неукладку
истинного обратного адреса от стека Secure и возврата к Безопасной функции (Рис.
13.5).
Рисунок 13.5
Безопасный код может назвать Незащищенный код. Его обратный адрес скрыт от
Незащищенного кода.
450 Глав 13

В основе TrustZone технология является Единицей атрибуции безопасности (SAU) и


дополнительной Единицей атрибуции определения реализации (IDAU). Процессор
ARMv8-M с TrustZone будет всегда загружаться в режиме Secure, и программное
обеспечение Secure может затем определить Безопасные и Незащищенные разделы путем
программирования SAU подобным способом к MPU. SAU может определить регион
памяти с тремя уровнями безопасности. Мы можем определить регион памяти как
Безопасный или Незащищенный, но существует также дополнительный уровень
“Незащищенного Вызываемый” (СНБ) (Рис. 13.6).

Рисунок 13.6
Модель обеспечения безопасности реализует три зоны. Безопасный, Незащищенный, и
Незащищенный вызываемый.

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


тот же двоичный шаблон как инструкция SG. Это создало бы ложную точку входа в
защищенную зону, которая могла быть использована. SAU позволяет нам определять
регион СНБ, который будет содержать все инструкции SG и может более легко
управляться на основе политик для ложных точек входа. Любой шаблон инструкции SG за
пределами региона СНБ повысит исключение безопасности, если получено доступ. На
практике регион СНБ заполняется рядом таблиц переходов к Безопасному коду. Эти
местоположения фиксируются в памяти СНБ и позволяют нам публиковать
фиксированный Безопасный API для Незащищенного кода к доступу. Это также означает,
что мы можем изменить и обновить Безопасный код, не имея необходимость обновлять
адреса вызова в Незащищенном коде. На практике регион СНБ, вероятно, займет
небольшой регион памяти, которая может быть легко проанализирована для побочных
шаблонов SG.

TrustZone также включает дополнительную инструкцию, которая позволяет Вам


проверять границы объекта данных. Инструкция по Тестовой цели (TT) может
использоваться для возврата номера региона SAU для выбранного адреса. Мы можем
использовать инструкцию TT запросить номер региона SAU на запуск и конечный
адрес объекта памяти гарантировать, что это не охватывает через Безопасные и
Незащищенные регионы. Инструкция TT позволяет нам создавать эффективные
границы, проверяющие код на любые объекты с динамическими диапазонами, такими
как указатели.

Безопасное состояние добавляет дополнительную пару указателей вершины стека


(MSP_S и PSP_S) для безопасных стеков и пары предельных регистров стека и в
Безопасных и в Незащищенных состояниях. Предельные регистры используются
для определения размера каждого стекового пространства, и отказ безопасности
будет сгенерирован, если какое-либо стековое пространство будет превышено (Рис.
13.7).
ARMv8-M 451

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

Периферийные устройства процессора ARMv8-M также расширяются с помощью


Безопасного и Незащищенного MPU, SysTick и Системных Блоков управления. Когда
процессор находится в Безопасном состоянии, он может получить доступ к
Незащищенным периферийным устройствам через регистры псевдонима.

Прерывания и исключения

Архитектура ARMv8-M сохраняет NVIC как блок обработки прерывания и обеспечивает


некоторые расширения для поддержки TrustZone Безопасные и Незащищенные состояния.
Исключения процессора совпадают с для ARMv7-M с добавлением исключения
SecurityFault (Таблица 13.4).
Таблица 13.4: таблица исключений процессора ARMv8-M. Добавляется новое
securefault исключение

Исключение Обработка состояния


Значение по умолчанию: Безопасное состояние может быть
NMI направлено к Незащищенному состоянию
Значение по умолчанию: Безопасное состояние может быть
Серьезный отказ направлено к Незащищенному состоянию
MemManager Окруженный валом
Значение по умолчанию: Безопасное состояние может быть
Отказ шины направлено к Незащищенному состоянию
Отказ
использования Окруженный валом
SecureFault Безопасное состояние
Может предназначаться для Безопасного или Незащищенного
DebugMonitor состояния (Определенный аппаратными средствами)
PendSV Окруженный валом
SysTick Окруженный валом
Прерывания Программируемый через новый NVIC “Цель Прерывания Незащищенные”
ввода-вывода регистры состояния
452 Главы 13

Поведение каждого исключения определяется для каждого состояния защиты. NMI,


Серьезный отказ и значение по умолчанию исключений Отказа Шины к Безопасному
состоянию, но могут быть настроены для выполнения в Незащищенном состоянии.
MemManager, Использование, PendSV и исключения SysTick имеют две служебных
программы, когда одно из этих исключений произойдет, NVIC вызовет служебную
программу, соответствующую источнику исключения. Так, например, если
Незащищенный MPU генерирует отказ, то исключение MemManager будет повышено,
и Незащищенная служебная программа диспетчера памяти будет вызвана. Обработчик
исключений SecureFault всегда работает в Безопасном состоянии. Прерываниям ввода-
вывода можно присвоить Защитить на Незащищенном состоянии новой группой
регистров в NVIC, названном “Целью Прерывания Незащищенные” регистры
состояния. Также возможно чередовать приоритеты Безопасных и Незащищенных
прерываний. Однако регистр AICR имеет дополнительный бит, который может быть
установлен расположить по приоритетам Безопасные прерывания по Незащищенным
прерываниям (Рис. 13.8).

Рисунок 13.8
Прерывания могут быть настроены как Безопасные или Незащищенные и могут
быть поданы независимо от текущего состояния
процессора.

Для Незащищенного кода возможно вызвать Безопасные функции и для Безопасного


кода для вызова Незащищенного кода. Так же любое прерывание может работать в
Безопасном или Незащищенном состоянии независимо от состояния работы текущего
потока. Модель обеспечения безопасности TrustZone не представляет дополнительной
аппаратной задержки кроме тех случаев, когда процессор работает в Безопасном
состоянии и должен обслужить Незащищенное прерывание. В этом случае процессор
продвигает все регистры ЦП к стеку Secure и затем пишет нуль в регистры ЦП для
сокрытия данных Безопасного состояния из Незащищенного кода. Это дает
процессору больше работы, чтобы сделать и представляет “немного более длинную”
задержку прерывания.

Если у нас есть смесь Безопасных и Незащищенных прерываний и исключений, из


этого следует, что мы должны изолировать Безопасные векторы прерывания, таким
образом, они не видимы из Незащищенного кода. Чтобы сделать, этот TrustZone
создает две таблицы векторов прерываний Безопасная таблица векторов и
Незащищенная таблица векторов. Местоположением каждой таблицы векторов в карте
памяти процессора управляет пара регистров смещения таблицы векторов, один для
Незащищенного состояния (VTOR_NS) и один для Безопасного состояния (VTOR_S)
(Рис. 13.9).
ARMv8-M 453

Рисунок 13.9
В Безопасном состоянии все ресурсы процессора доступны. Искаженные адреса
обеспечиваются для периферийных устройств
процессора Non-Secure.

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


памяти, таким образом, процессор сможет загрузиться в режим Secure. Безопасный
код запуска может затем программировать SAU для определения Безопасных и
Незащищенных регионов, и затем мы можем определить местоположение
Незащищенной таблицы векторов в начале Незащищенного пространства кода (Рис.
13.10).
Рисунок 13.10
В Незащищенном состоянии только Незащищенные ресурсы видимы.
454 Главы 13

Разработка программного обеспечения


Для создания перемещения к процессорам ARMv8-M мы должны будем рассмотреть
изменения, которые мы должны будем внести в наш текущий набор инструментов.
ARMv8-M будет влиять на наш набор инструментальных средств во многих областях,
в основном это Компилятор, Операционная система реального времени (RTOS) и
Отладчик. Также будет необходимо рассмотреть и расширить CMSIS (Стандарт
Программного интерфейса Микроконтроллера Коры) стандарты для слияния новых
инструкций ARMv9-M.

Компилятор

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


приложений для процессоров ARMv8-M, если приложение работает исключительно в
Незащищенном или Безопасном состоянии состояния. Любой код, работающий на
Базовых устройствах, извлечет выгоду из того, чтобы быть восстановленным
компилятором, который поддерживает полную Базовую систему команд. Если Вы
запланируете использовать расширение безопасности TrustZone для смешивания
Безопасного и Незащищенного кода, то Вам будет нужен компилятор, который
поддерживает полную систему команд ARMv8-M. Во время записи компилятор C
ARM (версия 6) является ссылочным компилятором для ARMv8-M. Эта версия
компилятора также поддерживает C1111, C1114 и стандарты C11. К тому времени,
когда физические устройства были выпущены, нужно ожидать, что все основные
компиляторы будут поддерживать новые процессоры.

Операционная система реального времени

Изменения в RTOS будут зависеть, как Вы используете процессор ARMv8-M.


Возможно выполнить вызовы к и от Безопасного состояния для выполнения функций,
это окажет минимальное влияние на RTOS. Если RTOS будет работать в Безопасном
состоянии, то он будет иметь полное представление устройства и сможет управлять
потоками, работающими в Безопасном и Незащищенном состоянии. Однако наиболее
распространенный случай дизайна, как ожидают, будет иметь RTOS, работающий в
Незащищенном состоянии. В этом случае ядро RTOS не сможет управлять потоками,
работающими в Безопасном состоянии. Это означает, что RTOS должен будет
получить доступ к встроенному микропрограммному обеспечению поддержки,
работающему в Безопасном состоянии, которое способно к управлению безопасным
стеком и оказанию поддержки контекстного переключения потока. В то время как
поставщики RTOS могут решить это с собственными решениями, будет намного
более эффективно иметь стандартизированный API для поддержки операций
TrustZone.

Отладчик

Архитектура отладки ARMv8-M CoreSight продолжит работать с существующими


адаптерами отладки. Программное обеспечение отладчика должно будет быть
обновлено для поддержки дополнительных регистров ЦП и дополнений к
системному блоку управления процессора.
ARMv8-M 455

Стандарт программного интерфейса микроконтроллера коры

Как отмечено выше, спецификация CMSIS должна будет быть обновлена, чтобы
поддерживать новые функции, представленные архитектурой ARMv8-M. Как уже
отмечалось выше, API CMSIS-RTOS потребует стандартного API, который позволяет
разработчикам включать Безопасные и Незащищенные потоки в рамках приложения.
Это также позволит поставщикам программного обеспечения разрабатывать
основанные на RTOS компоненты программного обеспечения, которые будут работать
в Безопасном состоянии. CMSIS-ядро должно будет также быть обновлено для
поддержки дополнительных регистров процессора ATMv8-M. Библиотека CMSIS-DSP
должна будет также быть оптимизирована для использования в своих интересах
процессора ARMv8-M.

Заключение
Архитектура ARMv8-M является большим количеством эволюции, чем оборот. Это
предоставляет легкую миграцию следующему поколению микроконтроллеров Cortex-
M. Введение TrustZone в профиль Cortex-M обеспечивает простую в использовании
модель обеспечения безопасности, которая жизненно важна, поскольку устройства
становятся более подключенными, и Интернет Вещей начинает становиться
действительностью.
Эта страница, намеренно
оставленная незаполненный
Приложение

Контактная информация
Я надеюсь, что Вы любили работать через эту книгу и нашли это полезным. Если у
Вас есть какие-либо вопросы или комментарии, свяжитесь со мной на адресе
электронной почты ниже:
tmartin@hitex.co.uk
Дополнительная информация и обновления публикуются на моем блоге в:
www.while-1.co.uk

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

Отладчики и программное обеспечение


Существует много средств разработки, доступных для ARM микроконтроллеры
Cortex-M. Следующее ни в коем случае не является эксклюзивным списком. Я только
что попытался перечислить некоторые ключевые доступные программные ресурсы.

Коммерческие основанные на GNU наборы инструментальных средств

Таблица A.1: Коммерческие наборы инструментальных


средств GNU

Atollic www.atollic.com
Rowley www.rowley.co.uk
457
458
Приложений

Коммерческие наборы инструментальных средств

Таблица A.2: Коммерческие наборы инструментальных


средств
IAR www.iar.com
Keil www.keil.com
Управление
задачами www.tasking.com

Быстрое прототипирование и модули оценки

Таблица A.3: модули

Mbed mbed.org
Встроенные
художники www.embeddedartists.com/

MBED является диапазоном недорогих Основанных на Cortex-M модулей с веб-


средой разработки. Это имеет процветающее сообщество с большим количеством
бесплатных ресурсов.

MBED ОС является открытым исходным кодом, встроил операционную систему,


разработанную для “Вещей” в Интернете Вещей.

Операционные системы реального времени


Как наборы инструментальных средств компилятора, существуют многие
Операционная система реального времени (RTOS) для процессора Cortex-M.
Здесь, я перечислил некоторых наиболее широко используемых поставщиков
RTOS.
Таблица A.4: Операционная система реального времени
(RTOS)
Свободный
RTOS www.freertos.org
Keil www.keil.com
Micrium www.micrium.com
Segger www.segger.com
CMX www.cmx.com

Обработка цифровых сигналов


Таблица A.5: Обработка цифровых сигналов (DSP)

Ресурсы DSP www.dspguru.com


Дизайн фильтра www.iowegian.com
Разработка алгоритмов
DSP www.mathworks.co.uk
www.scilab.org/
Приложение
459

Книги
Программирование

Таблица A.6: C программирующие книги

Язык программирования C ISBN-10: 0131103628


Kernighan и Ritchie
Разработка через тестирование для встроенного C ISBN-10: 193435662X
James W. Grenning
Чистый код: руководство гибкого мастерства
программного обеспечения ISBN-10: 0132350882
Robert C Martin

Процессор Cortex-M

Таблица A.7: книги процессора Cortex-M


Руководства технического
справочника Cortex-M www.arm.com/products/processors/cortex-m/index.php
Полное руководство к Коре-M3 ISBN-10: 0124080820
и M4
Joseph Yui
Полное руководство к Коре-M0 ISBN-10: 0128032774
и M01
Joseph Yui
Инсайдеры ведут к STM32 www.hitex.co.uk/index.php? id5download-insiders-guides00
Trevor Martin

Стандарты
Таблица A.8: Кодирование
стандартов
Спецификация
CMSIS http://www.arm.com/products/processors/cortex-m/cortex-microcontroller -
software-interface-standard.php
MISRA C www.misra.org.uk
Барристер,
кодирующий www.barrgroup.com/
стандарт

Обработка цифровых
сигналов
Таблица A.9: книги Обработки цифровых сигналов
(DSP)
Обработка цифровых сигналов: практическое руководство для инженеров и ученых ISBN-
10: 075067444X
Stephen Smith
Понимание обработки цифровых
сигналов ISBN-10: 0137027419
Richard G Лион
460
Приложений

Операционная система реального времени

Таблица A.10: книги Операционной системы реального времени


(RTOS)
Понятия в реальном времени для
встроенных систем ISBN-10: 1578201241
Qing Li и Caroline Yao
Мало книги семафоров www.greenteapress.com/semaphores/
Downey

Кремниевые поставщики
Существует теперь более чем 3 500 Основанных на Cortex-M микроконтроллеров, и
список все еще растет. Ссылка ниже является базой данных устройств,
поддерживаемых MDK-ARM. Это - актуальный список всех основных устройств и
является хорошим местом для запуска при выборе устройства. База данных Cortex-M-
device.
Таблица A.11: кремниевые поставщики

База данных www.keil.com/dd/ устройства Keil

Обучение
Следующие компании обеспечивают руки на учебные курсы встроенных систем:
Таблица A.12: обучение

Hitex www.hitex.co.uk/index.php? id53431


Feabhas www.Feabhas.com
Doulos www.Doulos.com
Индекс
Примечание: Номера страниц, сопровождаемые “f” и “t”, относятся к числам и
таблицам, соответственно.
процессор, 71
A соединение бита специализированные
Активный выбор указателя (осуществление), 91 92 инструкции по
вершины стека побитовых обработки, 89 побитовой обработке,
(ASPEL), 156 157 91 загрузчик, 115 116 92
Функция ADC_Init, 160 осуществление, модель исключения, 107 110
Добавьте и вычтите с 116 121 Коры- NVIC, поздно прибывающие,
обменом (ASX), 266 M0, 127 128 109 вытеснений POP NVIC,
267 Коры-M0 1, 129 110 объединений в цепочку
Усовершенствованные Коры-M4, 127 хвоста NVIC, 108 109
архитектурные функции, исключения, 102 104
процессора Cortex-M, 7 отказа шины, 103
10 включение исключений
Усовершенствованный отказа, 104 серьезных отказов,
расширяемый 104
интерфейс (AXI-M), отказ диспетчера памяти,
21 104 отказа использования,
Усовершенствованная 103
высокоскоростная шина группы и подгруппа
(AHB), 15, 185 187 (приоритет NVIC), 106
AHB соединяют шиной ЕСЛИ ЗАТЕМ блоки, 76
облегченную матрицу, 380 78 систем команд, 71 72
381 облегченных шинных обработки прерываний
интерфейсов AHB,
запись, 95 96
185 187, 194
выходов, 96
Периферийная шина AHB 97
(AHBP), 194
прерывания и
Ведомое устройство AHB инструкции по
(AHBS), 194 мультициклу, 76
Усовершенствованных
периферийных шины (APB), инструкции по барьеру памяти,
87 карт распределения памяти и
185
шины, 84 87 прерываний
Регистры псевдонима, 74 75, вложенного вектора
74f стандарт ANSI, 55 контроллер, 94
прерываний Приложения и рабочих режима, 94
сброс
управление питанием, 121 126
управление (AIRC), 88 т, режим низкой мощности,
114 Интерфейсов прикладного 123 126
программирования
приоритет и вытеснение, 104 105
(API), 24 25, 411 412
регистра состояния программы
драйверов CMSIS, 412 414
(PSR), модель 74 программистов и
Приложение PSR (APSR), ЦП
74 архитектуры Cortex-M регистры, 72 74
Q укусил и насыщаемые
математические системный блок
инструкции, 75
управления, 87 89
управление приоритетами прерываний systick
времени выполнения, 107 (осуществление),
насыщаемой математики и 97 102
условное выражение systick
выполнение (осуществление), 78 таймеров, 93
84
работа с несколькими
прерываниями
(осуществление), 110
115
буфер записи, 87
ARM 32-разрядная
система команд, 8 ARM
шина AXI-M, 194 ARM
“C” компилятор, 24 25
Система команд ARM, 8,
71, 72f ARM Библиотеки
ISO и Микробиблиотека
Keil, 55 т
ARM7, 3 8
ARM9, 3, 8
Основанные на ARM
микроконтроллеры,
16, 185, 185f
ARMv6-M, 445
ARMv7-M, 445
ARMv8-M, 445
базовые улучшения,
446 447
общие
архитектурные
улучшения, 446
CoreSight отлаживают
архитектуру, 454 улучшения
магистрали, 447 разработок
программного обеспечения,
454 455
компилятор, 454
Стандарт программного
интерфейса
микроконтроллера
коры (CMSIS), 455
отладчик, 454
Операционная система
реального времени
(RTOS), 454
TrustZone, 448 453
прерываний и
исключения,
451 453
461
462
Индекса
158
Процессоры ARMv6-M-based, Инструкции по Состоянию создание и управление
447 Асимметричных процессора потоками
многопроцессорных систем изменения (CPS), (осуществление), 307
(AMP), 447 156 157 310
Автоматическое Сохранение Очистите эксклюзивную создание потоков, 306
состояния Включает бит инструкцию 307 первых проектов,
(АСПЕНА), 258 259 (CLREX), 171 172 297 306 первых шагов с,
Вспомогательное CMSIS. См. Стандарт 294
управление, шина программного бездействуйте
AXI-M на 88 т, 194 интерфейса демон, 319 320
микроконтроллера коры осуществлений,
(CMSIS) 320 322
B CMSIS-RTOS, 293, 354 коммуникация межпотока, 323
Регистр BASEPRI, 73 74, доступа, 294 CMSIS сигнала, 323 324
Разрядное соединение на 107 RTX и SVC несколько экземпляров,
т, 89 исключения 312 313 несколько
осуществление, 91 92 (осуществление) экземпляров потока
Побитовая обработка, 89 семафоры, 325 326 (осуществление), 313
91 выделенная 314 зданий кода и
побитовая обработка запуск
инструкции, 92, отладчик, 313
проект Blinky на 93 т, 28
запуск с RTOS, 296 297
52
задержек подмиллисекунды,
Обработка блока (DSP), 285, 319 потоков, 295 296
285f феркин фильтрует с
(осуществлением), управление и
приоритет, 310 311
286 289
Загрузчиков, 115 задержка, 314 315
116 осуществлений, тайм-менеджмента,
116 121 314 осуществлений,
315 316 виртуальных
Учрежденческая АТС к
Незащищенному коду таймеров, 316 317
(BXNS), 449 осуществлений, 317
Exchange Ссылки ответвления к 319 ожидания
Незащищенному коду события, 315
(BLXNS), 449 CMSIS-базовый кэш, 205
Цель ответвления CMSIS-базовых
обращается к кэшу спецификаций, 203
(BTAC), 191, 191f процессора Access Control Co
Буферизация методов Регистр (CPARC), 258
двойной или кольцевой зданий Кода и запуск
буфер, отладчик, 313
370 371 Повторных
Очередь сообщений FIFO, использований кода,
371 374 адрес отказа Шины, 88 427f Командное
т окно, 43 меню
Исключение отказа шины, 103 Compiler, 55
Документация безопасности
компилятора, 216 т
C
Настраиваемое состояние
Перегрузка кэша, отказа, Конфигурация на 88 т и
202 дерева Вызова, регистр управления,
88 т кодируя правила, 137
Опция подключения, в архитектура отладки, 219f, значений
226 раз Контекстного 221 осуществление, 221 конфигурации, ядро на
переключения, 295 222 143 т, 134, 140f
Регистр управления, 156 157, функции отладки, 254, ядро процессора внутренние
156f инструкции, 149 150,
254 т отлаживают
149 т
Кооперативная ограничения, 229
многозадачность, 348 аппаратных средств базовые функции отладки,
Совместного переключения отладчика, 220 152, базовые заголовочные
потока, 311 CoreSight, 217 встроенных макроячеек файлы на 152 т, 143 144 ядра
CMSIS DAP, 244 245 трассировки регистрируют доступ, 148
149,
CMSIS SVD, 248 249 (ETM), 239 241
осуществлений, 249 аппаратных 148 т
253 конфигураций, базовая спецификация, 133
Кора-M0 1 MTB, 245 246 222 223 134 базовых структуры, 139
140 Corex-M7, ядро
макроячейка трассировки
инструментария (ITM), функционирует для,
229 230 153
установка
(осуществления),
230 233
Аппаратный сокет JTAG,
220 MTB
(осуществление), 246 248
исключений отказа
процессора
(осуществление), 235 239
конфигурация
программного
обеспечения, 223
229
системный блок
управления
отлаживает
поддержку, 233 234
при отслеживании отказов
234 235 CoreSight отлаживают
архитектуру, 6 7 Corex-M7,
базовые функции для, 153
программного обеспечения
микроконтроллера Коры
соедините интерфейсом
со стандартом (CMSIS),
24 25, 131
CMSIS спецификация DAP,
135 136, 136f, 244 245,
244f, 245f, 455
Спецификации CMSIS-
драйвера, 135
Библиотека CMSIS-
DSP, 279
осуществлений, 280
284 функций, 279
CMSIS-RTOS. См.
CMSIS-RTOS
Индекс
463
утилит, 428 439
основанные на коре проверок, 419 423 Профиль коры-A, 2
микроконтроллеры, осуществлений, 419
Кора-M0, 2, 11 12, 127 128
132f 423 коры-M0 1, 2, 13 16, 129
определенный, 131 Единица прерывания микропроследите
заголовочный файл вложенного вектора буфер (MTB), 245
устройства, 141 143 коры, 78 246
документация, 134f Рабочие режимы процессора Кора-M1, 2 коры-
Алгоритмы DSP, 135 Cortex, 155 158 M3, 1 7, 239
основ, 136 137 Стопка процессора Кора-M4, 2, 16 17, 127,
функциональных Cortex, 307 инструкции на 239 дес.
групп, аппаратная Профили коры, 1 3 ложек, 16 17
точка останова на 144 т, приложения, 1f Кора-M7, 19 21
152 микроконтроллер, Кора-M7 FPU, 258
единица трассировки 1f реальное время, процессоров Cortex-M7, 189,
инструментария (ITM) 1f 189f
(осуществление), 152 предсказание
прерывания и ветвлений, 191
исключения, 144 структура шины, 193
147, 144 т 195 конфигурации кэша,
внутренняя побитовая 206 операций кэша, 200
обработка 202 политик кэша, 207
(осуществление), 208 блоков кэш-памяти,
150 151
199 200
Спецификаторы IO, 139
документация безопасности
т MISRA C, 137 139, компилятора, 216 т
137f спецификации
Пакета, 136 Кэш данных, 204 205
конфигурации
Спецификация RTOS, 134 (осуществление),
135 инструкции SIMD, 151
209 213
152 спецификация, 133 134,
примеров, 206
133f запускают код, 140
управлений, 209
системный код, 141
средства разработки, 216
системное описание средства плавающих точек двойной
просмотра (SVD), 135 точности
136, 248 249 единица, 213 214
осуществление, 249
двойной конвейер
253 функций systick, 145
проблемы, 190, 190f
т и пользователь
кодируют сравнение функциональная
безопасность, 214 Кэшей
(осуществление), Инструкции, 203 204
147 149 тип
барьера памяти, 205 206
переменных, 138 т
иерархий памяти, 195 196,
Драйвер Стандарта 196f
программного интерфейса
микроконтроллера коры Единица защиты памяти
(CMSIS), 411 419 (MPU), 206
API, 413 414 документация безопасности,
215 216, 215 т
откройте осуществление,
414 419 систем пакета, 427 функции безопасности, 215,
439, 427f простой цикл на 215 т
(осуществление), 191 193
структура, 427 428
суперскалярная архитектура,
190 191 Алгоритмы DSP,
оптимизируя
код определения D (тренируются), 272
местоположения сильно Кэш данных, 199 200, 204 205
связанной памяти (TCM) 278
конфигурации Инструкции по DSP, фильтр
и данные в,
осуществление, 209 213 на 265 268 феркинов с
197 199
проблемы когерентности обработкой блока
процессоров Cortex-
данных, 204f пример, 206 (осуществление),
M, 352 процессора
Cortex-R, 1f, 2 функции, 204, 286 289 фиксированных
CppUtest, 389 управление на 205 точек FFT
т, 209 (осуществление),
Идентификатор ЦП, 88 т
Барьер синхронизации 290 292
Регистры ЦП, 73 74, 107
памяти данных Интеграция FPU, 256 257
(DMD), 87 т
Барьер синхронизации
данных (DSB), 87 т
Данные Сильно связанные
памяти (D-TCM), 21,
196
Контрольная точка данных и
трассировка (DWT)
единица, 6 7
Файл Dbg_sim.ini,
40 шин DCODE,
86
Порт доступа отладки
(DAP), 135 136
CMSIS DAP, 135 136,
244 245
Меню отладки, 39, 65
69 Отладчиков, 454
режима DEEPSLEEP,
122 размера стека
Default, 307
Отчет об интерфейсе
Development, Контроллеры
цифрового сигнала (DSC) на 215
т,
16
Обработка цифровых сигналов
(DSP) для Коры-M4, 2
Инструкции по DSP, 16 17
Обработки цифровых сигналов
(DSP) для
Кора-M4 и кора-M7, 255
алгоритмы,
оптимизируя
(тренируются), 272
278
Библиотека CMSIS-
DSP, 279
осуществлений, 280
284 функций, 279
методы обработки
данных, 285 286
464
Индекса
фиксированных точек FFT
(осуществление),
Обработка цифровых сигналов Регистр FAULTMASK, 73 74,
290 292 107 т, 156 157
(DSP) для Коры-M4 и
(Продолженной) Коры- Регистры конфигурации Конечная импульсная
M7 исключения отказа, характеристика
233 т
Регистры FPU, 257 (FIR) фильтр, 16, 272
258 включений, 258 Исключения отказа, 233 234, 278, 272f
233 т соединяют шиной
исключения и, 258 259 отказ, 103 с обработкой блока
осуществлений, 259 265 (осуществление), 286 289
использование, 259 включение,
104 Фиксированная точка
аппаратный сопроцессор серьезных FFT
для операций с отказа, 104 (осуществление),
плавающей точкой, 290 292
255 256 отказ диспетчера памяти,
104 регистра, 233 т Акселератор флэш-
инструкции, 265 268 памяти, 199
отказ использования, 103
Q числа, DSP Адресный регистр
фиксированной точки контекста с
с, 289 290 плавающей точкой
Инструкции SIMD, 265 268 (FPCAR), 258 259
осуществлений, 269 271 Регистр управления
Прямой доступ к памяти контекста с
(DMA), 185 187, 380 плавающей точкой,
381 258 259
Сопроцессор для операций с Регистр управления
плавающей точкой состояния с
двойной точности, плавающей точкой
213 214 (FPSCR), 149, 257
Doxegen, 139 258
Сопроцессор для операций
с плавающей точкой
E (FPU), 17f, 255 256
Встроенная макроячейка включение, 258
трассировки (ETM), 6 7,
исключения и, 258 259
239 244, 322
осуществлений, 259
Стираемая программируемая 265 интеграции, 256
постоянная память 257 регистров, 257 258
(EPROM), 217, 217f
использование,
Модель Exception, 107 110 259 руководств
NVIC, поздно FMEA,
прибывающие, 109 FNC_RETURN на
вытеснений POP NVIC, 110 215 т, 449
объединений в цепочку
хвоста NVIC, 108 109
Эксклюзивный доступ, 169 G
172, 170 т выполняют Только
Память (XOM), Компилятор
447 GCC, 23 GNU
Выполнение PSR (EPSR), 74 GCC, 23, GPS на
23 т, 434 gpsData,
425 426
F Greenhills, 23 т
Быстрое преобразование
Фурье (FFT), 16
H интеграции, 363 364
Режим Handler, 94, 155 157, Я “Цель прерывания
161 управление Жестким Незащищенные”
IAR встроил
диском (HDD), 2 исключения регистры состояния,
инструментальные 452
Серьезного отказа, 104 средства для ARM, 23
т Прерывания и
Состояние серьезного инструкции по
отказа, Аппаратная точка Шина ICODE, 86, 95 мультициклу,
останова на 88 т, 152 демонов Idle, 319 76
Аппаратных Сопроцессора 320
для операций с плавающей осуществление, 320 322 Коммуникация межпотока,
точкой 323 сигнала, 323 324
IEC 61508-3 системы уровня осуществление, 324 325
(FPU), 213 (SIL3), 214
Аппаратных ЕСЛИ ЗАТЕМ блоки условия, 76
сопроцессоров для 78 БИХ-фильтров, 375, 376f
операций с плавающей Определение Реализации
точкой
Единица атрибуции
(аппаратные средства (IDAU), 450
FPU), 255 256 HFNMIENA
укусили, 175 Внутрисхемный эмулятор, 218,
218f, 240 Независимых потоков,
323 Кэша Инструкции, 199 200,
202 203
осуществления,
203 204
Коды условий инструкции,
барьер синхронизации
Инструкции на 77 т
(ISB), Сильно
связанная Инструкция на
87 т
памяти (I-TCM), 21,
196, 203 204
Окно трассировки
инструкции, 50 макроячеек
трассировки Инструментария
(ITM) единица, 6 7,
152, 229 230, 381 382
установка
(осуществления),
230 233
Интегрированная среда
разработки (IDE), 23
Прерывание continuable
инструкция (ICI), 74f
поле, 76
Управление прерыванием и
состояние, Обработка
прерываний на 88 т
запись, 95
96 выходов,
96 97
Прервите PSR (IPSR), 74
Процедуры обработки
прерывания (ISR), 5,
95, 145, 173
Индекс
465
(MSP), 42, 88 89, 157,
157f
J Единица защиты памяти
РУКА MDK, 216
Совместная тестовая (MPU), 7 8, 104, 173 174,
инициативная группа Акселератор памяти, 86 87 173f, 174f, 175f, 206
(JTAG), 6 7, 218 инструкций по Барьеру
конфигурация кэша,
памяти, 87 адресов отказа
отладьте интерфейс, 218 206 конфигураций, 175
Диспетчера памяти,
преимуществ, 218 219 178 осуществлений,
88 т 178 184
недостатков, 218 219
аппаратный сокет, 220 Исключение отказа диспетчера ограничения, 185
памяти, 104, 234 подобластей, 184
Карта распределения памяти и 185
K шины, 84 87 Пулов памяти, Очередь сообщений, 336
Комплект разработчика 339 338, 341 осуществление,
микроконтроллера Keil осуществление, 340 338
для ARM (MDK-ARM), Буфер микротрассировки
23 24, 23 т (MTB), 16f, 245 246
облегченный набор осуществление, 246 248
инструментальных µvision (Микровидение), 24,
средств, установка, 41 отладчик, 41
25 27 IDE, 117
Keil RTX RTOS, 134 135, 293, MIRA (“агентство по
335, 348 исследованию
Веб-сайт Keil, 443 автомобильной
Поддержка отладки ядра, 344 промышленности”), 137
345 Спецификация MISRA-C, 137
139 “Ложных” функций, 406
407 Перемещений общий
L регистр к специальному
Ленивая укладка, 258 259 предложению
Ленивое Сохранение регистр (MRS), 73 74
состояния Включает Перемещения специальный
бит (LSPEN), 258 259 регистр генералу
“Загрузка получает регистр (MSR), 73 74
хранилище и выпуск” Несколько прерываний,
инструкции, 446 работающих с
Логическое окно трассировки,
(осуществление),
46 110 115 Умножаются,
Развертывание цикла, 276 накапливаются (MAC),
277, 277f режимы Низкой 16 17
мощности, 5
Поддержка многозадачности,
конфигурирование, 169 170 Взаимных
123 124 ввода, 123 исключений, 294, 333
осуществления, 124 протесты, 335
126
обмен данными, 335
336 осуществлений,
333 335
M
Почтовая очередь, 336, 341
342 Почтовый ящик N
(осуществление), 342 343 Контроллер прерываний
конфигурации, 343 344 вложенного вектора
Основной указатель (NVIC), 94, 107 108, 144,
вершины стека 155, 166, 226
группа, 144, 146 пример, 167 169
147 последних Память СНБ, 450 полей “Pins”, 40, 48
прибытий, 109 ПУСТОЙ УКАЗАТЕЛЬ вытеснений POP,
вытеснений POP, определяет, 308 110
110 Питание и сторожевое
NVIC, 451 452
объединение в цепочку осуществление управления,
хвоста, 108 109 NMEA 0183 364 368
(Национальный морской O
Управление питанием, 121 126,
пехотинец Рабочие режимы, 94, 155 158 358 первых шагов, 358 360
Ассоциация облегченных шинных
режимы низкой
оборудования), 424 интерфейсов AHB, 185 187
мощности, 123 126
работ процессора Cortex-M стратегии, 360 362
Никакая операция (только для
указанных целей) режимы, 155 158
инструкции, 76 78 эксклюзивный доступ, 169
Незащищенный вызываемый 172, осуществление на 170
(NSC), 450 Незащищенных т, 172 173
кодов, 449, 449f, 452 межпроцессорные события,
Незащищенных области 169 единиц защиты памяти
памяти, 448 (MPU),
173 174, 173f, 174f, 175f
ограничения, 185
подобласти, 184 185
единицы защиты памяти
(MPU)
конфигурация, 175
178 осуществлений, 178
184
Исключение Pend_SV,
166 примеров, 167
169
конфигурация стека
(осуществление), 158
161
Вызов контролера
(SVC) инструкция,
161 163
осуществление, 163 166
“Опции для Целевого”
диалогового окна, 38, 52
OsDelay () функция, 319
переменная osEvent, 337
os_Idle_demon (), 358 359
функций osKernelStart, 296 297
osMessageGet () функция, 375
OsPriorityNormal, 310
osThreadCreate (), 307
OsThreadGetId (), 306
osThreadTerminate (), 335
osWait (), 315

P
ОЖИДАЙТЕ
прерывание, 352
исключения Pend_SV,
166
466
Индексов
инструкции, 75
Упреждающее Q определение на Cortex-M, 293
основанное на чисел, 289 разработка для отладки, 381
приоритете DSP фиксированной точки с, 382 разработка в течение
планирование, 289 290 реального времени, 370 375
297 Прямых доступов к памяти
Упреждающее R (DMA)
планирование, 347 Методы операционной единицы, 380 381
PRIMASK, 73 74, 107 системы реального обработок прерываний,
регистр, 156 157 времени (RTOS), 5, 11, 352 354
Приоритет и вытеснение, 104 24, 169, 351, 454 осуществление, 354
105 Приоритетных группы и балансировка 355 Процедуры
подгруппа загрузки, 375 методов обработки прерывания
значения, 106 буферизации (ISRs),
PRIVDEFENABLE двойной или кольцевой интеграция, 363
укусили, 175 значений по буфер, 370 371 364
умолчанию Полномочия Очередь сообщений FIFO, и прерывания, 351 352
Включают 371 374 CMSIS-RTOS, 134 135 коммуникация Межпотока,
(PRIVDEFENA), 175f 323 ядра, 294f
режим Privileged, 6 7, 156, 160f, несколько экземпляров,
162 163 312 313 питания и
Указатель стека процесса (PSP), сторожевой таймер
42, 88 89, 156 157 ProcessBuffer осуществление
() функция, 329 Регистров управления, 364 368
состояния программы (PSR), управления питанием,
42, 358 первых шагов, 358
74 75, 268 360 стратегий, 360 362
приложений PSR (APSR), Осуществление
74 выполнения PSR реального
(EPSR), 74 результата времени RTX,
битового поля GE, 268 375 380
прерываний PSR (IPSR), осуществление
74 диагностики во
Модель программиста, 72 74 время выполнения,
Проекта создают цели, 382 384 семафора,
конфигурирование, 332 333
393 396 запуск, 296 297
Конфигурация проекта, для барьеров запуска, 369
семейства Cortex-M, 52 370 пользовательских
65 функций супервизора,
Алгоритм управления 355 356
Пропорционального осуществлений,
интегрального 356 357
дифференциала (PID), сторожевое
280 управление, 362
Защищенная архитектура системы 363
памяти (PMSAv8), 446 Компьютер с сокращенной
системой команд, 4 Архитектуры
Q сокращенной системы команд
Q укусил и (RISC), 71
насыщаемые приоритетный
математические Циклический
алгоритм
планирование, 348 осуществление, 330
Основанного на циклическом S 331 циклического
алгоритме планирования, упреждающего
Руководство по безопасности,
347 348 планирования, 348
215 т
RTX, 24, 134 135 основанное на циклическом
Влажные математические алгоритме
Лицензии RTX, в инструкции, 75 и условное
349 раз RTX планирование, 347 348
выполнение,
осуществление, 375 380 Лицензия RTX, 349
78 84
Исходный код RTX, в 348 осуществления, Исходный код RTX, 348
349 Раз управление 78 84 349 опций планирования,
приоритетами, 107 Точечный файл, 64 346 348 передач сигналов,
Диагностики во время 328
Планирование опций, 346 348 осуществление, 326 328
выполнения Безопасных и Незащищенных
осуществление, 382 384 прерываний системная конфигурация
Среды выполнения (RTE), таймера, 346 определений
и исключения, 452
потока, 344
433 434 инструкции по Защищенному
менеджера, шлюзу (SG),
30 лет 449
Безопасный код запуска, 453
обработчика исключений
SecureFault, 452 Единицы
атрибуции безопасности (SAU),
450
Исключение SecurityFault,
451 Семафор, 325 326
барьер (осуществление),
332 турникета барьера, 331
332 протест, 332 333
конфигурации, 343 344
кооперативной
многозадачности, 348
поддержка отладки ядра, 344
345 почтовых очереди, 341
342
почтовый ящик
осуществление, 342
343 пула памяти, 339
очередей сообщений,
337 338
осуществлен
ие, 338
мультиплексир
ования, 329
осуществление,
329 330 взаимных
исключений, 333
обмен данными, 335
336 осуществлений,
333 335
взаимоисключающих
протеста, 335
упреждающее
планирование, 347
рандеву, 330
Индекс
467
наборы инструментальных Разработка через тестирование
конфигурация интервала, 346 средств, 23, 23 т (TDD),
использование семафоров, 328 учебные упражнения, 24 25 387, 425
Средство моделирования добавление тестовых
SemMultiplex, 329 программного обеспечения, 24 25 сценариев, 397 399
Последовательный провод (SWO), добавление среды
220 Окно исходного кода, 43 тестирования единицы,
__ set_BASEPRI () функция, 149 Специальные регистры, 72 74 391 393
__ set_FAULTMASK () функция, SRAM, 7 8, 53 автоматизация цикла TDD,
Конфигурация стека
149 (осуществление), 399 402
конфигурирование сборки
__ set_PRIMASK () функция, 149 158 161 проекта
Кремниевая библиотека Vendor, Плата исследования STM32F7,
411 25f, цели, 393 396
отделение низкоуровневых
Сценарий моделирования, 46 65, 222f, 223 функций,
Единственная инструкция
несколько данных Потоковая обработка, 285, 285f 405 406
(SIMD), 10 Задержки подмиллисекунды, 319 цикл разработки, 389
CMSIS intrinsics, 151 152 Поле Subregion Disable (SRD), осуществление, 390 402
установка платформы
Кора-M4 и DSP коры-M7 184 единицы,
и, 265 268 Вычтите и добавьте с обменом 390
автоматизация тестирования,
инструкции, 265 268 (SAX), 266 267 389 390
осуществление, 269 271 Вызов контролера (SVC), 161 163, среда тестирования, 389
16-разрядная система команд тестирование прерываний, 406
Ползунка, 8, 71 162f 407
Поле Size, 176 осуществление, 163 166 пример, 407 408
тестирование потоков RTOS,
Режим ожидания, 122 инструкция, 351 352 402 404
Сигнал SLEEPDEEP, 358 SVC_DEAD, 166 пример, 404 407
Компоненты программного Инструкция по Тестовой цели
обеспечения, 411 Код SVC_Handler, 165 166 (TT), 450
Драйвер CMSIS, 412 419 Опция SYSRESET, 226 TEST_SETUP () функция, 398
API, 413 414 Раздел System Configuration, Небольшая книга семафоров,
Осуществление USART, 414
419 318 328
Системный блок управления Распараллельте блок управления,
проверка, 419 423 (SCB), 296
мастер конфигурации, 439 443 87 89, 88 т Определение потока, 344
осуществление, 440 443 отладьте поддержку, 233 234 Блокировка потока, 172
Системный регистр управления
развертывание, 443 (SCR), Режим потока, 94, 155 156,
разработка, 424 426 123 160 163
Компонент GPS Управление обработчиком систем
(осуществление), и состояние, Потоки, 295 296, 332, 348
424 426 88 т создание, 306 307, 311 312
Приоритет обработчика систем,
программный пакет 88 т управление, 307 310
Системная конфигурация
создание, 427 439, 429f таймера, 346 Ползунок 2, 8, 11, 72, 72f, 86 87,
Системное описание средства
структура, 427 428 просмотра (SVD) 161, 265
утилиты, 428 439 файл, 135 Система команд DSP, 265
Разработка программного Переменная SystemCoreClock,
обеспечения, для Коры - 141, система команд, 8
M 145 146 Ползунок укусил, 78
Семейство, 23 SystemCoreClockUpdate (), 141 Система команд ползунка, 71, 72f
проект blinky, 28 52 SystemInit () функция, 141 Сильно связанная память (TCM),
окно дизассемблирования, 42
43 Количество SysTick, 319 190, 193, 196 199, 196f
окно регистра, 42 Функция Systick, 145 т Задержка, для RTOS, 314 315
Прерывание Systick
создание первой программы (осуществление), ожидание события, 315
(осуществление), 27 28 97 102, 112 Тайм-менеджмент
аппаратная отладка, 65 69 Таймер Systick, 5, 93, 145 146, осуществление, 315 316
Тайм-менеджмент, для RTOS,
установка, 25 27 346, 352 314
Микроконтроллер Keil Конфигурация интервала, 346
комплект разработчика, 23
24 T TrustZone, 448 453
Объединение в цепочку хвоста,
конфигурация проекта, 52 65 NVIC, 108 109 прерывания и исключения,
Определяя задачу для набора
программные пакеты, 24 инструментов VX для ARM, 23 т 451 453
468
Индексов

Функция Twatch, 40 V Инструкции WFE, 123


Введите Дополнительные Поле VECTKEY, 146 147 Инструкции WFI, 123
биты (TEX), 207 смещений Таблицы векторов, Буфер записи, 87
88 т, 116, 120 Виртуальных
таймеров, 316 317 X
U
осуществление, 317 319 xPSR. См. Регистр состояния
Универсальный синхронный
асинхронный программы (PSR)
приемопередатчик W
(USART), 411 412, Контроллер прерываний Z
417, 424, 436 пробуждения “Нуль копирует” очередь
Непривилегированный режим, (WIC), 5, 122, 122f памяти, 340
156 157, 173 исключения отказа Сторожевое управление, 362
Использования, 103 363 СЛАБЫХ маркировки, 96

Вам также может понравиться