- •Оглавление
- •Предисловие
- •Почему я написал книгу?
- •Для кого эта книга?
- •Как использовать эту книгу?
- •Как организована книга?
- •Об авторе
- •Ошибки и предложения
- •Поддержка книги
- •Как помочь автору
- •Отказ от авторского права
- •Благодарность за участие
- •Перевод
- •Благодарности
- •I Введение
- •1. Введение в ассортимент микроконтроллеров STM32
- •1.1. Введение в процессоры на базе ARM
- •1.1.1. Cortex и процессоры на базе Cortex-M
- •1.1.1.10. Внедренные функции Cortex-M в ассортименте STM32
- •1.2. Введение в микроконтроллеры STM32
- •1.2.1. Преимущества ассортимента STM32….
- •1.2.2. ….И его недостатки
- •1.3. Краткий обзор подсемейств STM32
- •1.3.1. Серия F0
- •1.3.2. Серия F1
- •1.3.3. Серия F2
- •1.3.4. Серия F3
- •1.3.5. Серия F4
- •1.3.6. Серия F7
- •1.3.7. Серия H7
- •1.3.8. Серия L0
- •1.3.9. Серия L1
- •1.3.10. Серия L4
- •1.3.11. Серия L4+
- •1.3.12. Серия STM32WB
- •1.3.13. Как правильно выбрать для себя микроконтроллер?
- •1.4. Отладочная плата Nucleo
- •2. Установка инструментария
- •2.1. Почему выбирают Eclipse/GCC в качестве инструментария для STM32
- •2.1.1. Два слова о Eclipse…
- •2.2. Windows – Установка инструментария
- •2.2.1. Windows – Установка Eclipse
- •2.2.2. Windows – Установка плагинов Eclipse
- •2.2.3. Windows – Установка GCC ARM Embedded
- •2.2.4. Windows – Установка инструментов сборки
- •2.2.5. Windows – Установка OpenOCD
- •2.2.6. Windows – Установка инструментов ST и драйверов
- •2.3. Linux – Установка инструментария
- •2.3.2. Linux – Установка Java
- •2.3.3. Linux – Установка Eclipse
- •2.3.4. Linux – Установка плагинов Eclipse
- •2.3.5. Linux – Установка GCC ARM Embedded
- •2.3.6. Linux – Установка драйверов Nucleo
- •2.3.7. Linux – Установка OpenOCD
- •2.3.8. Linux – Установка инструментов ST
- •2.4. Mac – Установка инструментария
- •2.4.1. Mac – Установка Eclipse
- •2.4.2. Mac – Установка плагинов Eclipse
- •2.4.3. Mac – Установка GCC ARM Embedded
- •2.4.4. Mac – Установка драйверов Nucleo
- •2.4.5. Mac – Установка OpenOCD
- •2.4.6. Mac – Установка инструментов ST
- •3. Hello, Nucleo!
- •3.1. Прикоснитесь к Eclipse IDE
- •3.2. Создание проекта
- •3.3. Подключение Nucleo к ПК
- •3.5. Изучение сгенерированного кода
- •4. Инструмент STM32CubeMX
- •4.1. Введение в инструмент CubeMX
- •4.1.1. Представление Pinout
- •4.1.2. Представление Clock Configuration
- •4.1.3. Представление Configuration
- •4.1.4. Представление Power Consumption Calculator
- •4.2. Генерация проекта
- •4.2.1. Генерация проекта Си при помощи CubeMX
- •4.2.2. Создание проекта Eclipse
- •4.2.3. Ручное импортирование сгенерированных файлов в проект Eclipse
- •4.3. Изучение сгенерированного кода приложения
- •4.3.1. Добавим что-нибудь полезное в микропрограмму
- •4.4. Загрузка исходного кода примеров книги
- •5. Введение в отладку
- •5.1. Начало работы с OpenOCD
- •5.1.1. Запуск OpenOCD
- •5.1.2. Подключение к OpenOCD Telnet Console
- •5.1.3. Настройка Eclipse
- •5.1.4. Отладка в Eclipse
- •5.2. Полухостинг ARM
- •5.2.1. Включение полухостинга в новом проекте
- •5.2.2. Включение полуохостинга в существующем проекте
- •5.2.3. Недостатки полухостинга
- •5.2.4. Как работает полухостинг
- •II Погружение в HAL
- •6. Управление GPIO
- •6.2. Конфигурация GPIO
- •6.2.1. Режимы работы GPIO
- •6.2.2. Режим альтернативной функции GPIO
- •6.2.3. Понятие скорости GPIO
- •6.3. Управление GPIO
- •6.4. Деинициализация GPIO
- •7. Обработка прерываний
- •7.1. Контроллер NVIC
- •7.1.1. Таблица векторов в STM32
- •7.2. Разрешение прерываний
- •7.2.1. Линии запроса внешних прерываний и контроллер NVIC
- •7.2.2. Разрешение прерываний в CubeMX
- •7.3. Жизненный цикл прерываний
- •7.4. Уровни приоритета прерываний
- •7.4.1. Cortex-M0/0+
- •7.4.2. Cortex-M3/4/7
- •7.4.3. Установка уровня прерываний в CubeMX
- •7.5. Реентерабельность прерываний
- •8. Универсальные асинхронные последовательные средства связи
- •8.1. Введение в UART и USART
- •8.2. Инициализация UART
- •8.3. UART-связь в режиме опроса
- •8.3.1. Установка консоли последовательного порта в Windows
- •8.3.2. Установка консоли последовательного порта в Linux и MacOS X
- •8.4. UART-связь в режиме прерываний
- •8.5. Обработка ошибок
- •8.6. Перенаправление ввода-вывода
- •9. Управление DMA
- •9.1. Введение в DMA
- •9.1.1. Необходимость DMA и роль внутренних шин
- •9.1.2. Контроллер DMA
- •9.2. Модуль HAL_DMA
- •9.2.1. DMA_HandleTypeDef в HAL для F0/F1/F3/L0/L1/L4
- •9.2.2. DMA_HandleTypeDef в HAL для F2/F4/F7
- •9.2.3. DMA_HandleTypeDef в HAL для L0/L4
- •9.2.4. Как выполнять передачи в режиме опроса
- •9.2.5. Как выполнять передачи в режиме прерываний
- •9.2.8. Разнообразные функции модулей HAL_DMA и HAL_DMA_Ex
- •9.3. Использование CubeMX для конфигурации запросов к DMA
- •10. Схема тактирования
- •10.1. Распределение тактового сигнала
- •10.1.1. Обзор схемы тактирования STM32
- •10.1.1.1. Многочастотный внутренний RC-генератор в семействах STM32L
- •10.1.3.1. Подача тактового сигнала от высокочастотного генератора
- •10.1.3.2. Подача тактового сигнала от 32кГц генератора
- •10.2. Обзор модуля HAL_RCC
- •10.2.1. Вычисление тактовой частоты во время выполнения
- •10.2.2. Разрешение Выхода синхронизации
- •10.2.3. Разрешение Системы защиты тактирования
- •10.3. Калибровка HSI-генератора
- •11. Таймеры
- •11.1. Введение в таймеры
- •11.1.1. Категории таймеров в микроконтроллере STM32
- •11.1.2. Доступность таймеров в ассортименте STM32
- •11.2. Базовые таймеры
- •11.2.1. Использование таймеров в режиме прерываний
- •11.2.2. Использование таймеров в режиме опроса
- •11.2.3. Использование таймеров в режиме DMA
- •11.2.4. Остановка таймера
- •11.3. Таймеры общего назначения
- •11.3.1.1. Режим внешнего тактирования 2
- •11.3.1.2. Режим внешнего тактирования 1
- •11.3.2. Режимы синхронизации ведущего/ведомого таймеров
- •11.3.2.1. Разрешение прерываний, относящихся к триггерной цепи
- •11.3.2.2. Использование CubeMX для конфигурации синхронизации ведущего/ведомого устройств
- •11.3.3. Программная генерация связанных с таймером событий
- •11.3.4. Режимы отсчета
- •11.3.5. Режим захвата входного сигнала
- •11.3.5.1. Использование CubeMX для конфигурации режима захвата входного сигнала
- •11.3.6. Режим сравнения выходного сигнала
- •11.3.6.1. Использование CubeMX для конфигурации режима сравнения выходного сигнала
- •11.3.7. Генерация широтно-импульсного сигнала
- •11.3.7.1. Генерация синусоидального сигнала при помощи ШИМ
- •11.3.7.2. Использование CubeMX для конфигурации режима ШИМ
- •11.3.8. Одноимпульсный режим
- •11.3.8.1. Использование CubeMX для конфигурации одноимпульсного режима
- •11.3.9. Режим энкодера
- •11.3.9.1. Использование CubeMX для конфигурации режима энкодера
- •11.3.10.1. Режим датчика Холла
- •11.3.10.2. Комбинированный режим трехфазной ШИМ и другие функции управления двигателем
- •11.3.10.3. Вход сброса таймера и блокировка регистров таймера
- •11.3.10.4. Предварительная загрузка регистра автоперезагрузки
- •11.3.11. Отладка и таймеры
- •11.4. Системный таймер SysTick
- •12. Аналого-цифровое преобразование
- •12.1. Введение в АЦП последовательного приближения
- •12.2. Модуль HAL_ADC
- •12.2.1. Режимы преобразования
- •12.2.1.1. Режим однократного преобразования одного канала
- •12.2.1.2. Режим сканирования с однократным преобразованием
- •12.2.1.3. Режим непрерывного преобразования одного канала
- •12.2.1.4. Режим сканирования с непрерывным преобразованием
- •12.2.1.5. Режим преобразования инжектированных каналов
- •12.2.1.6. Парный режим
- •12.2.2. Выбор канала
- •12.2.3. Разрядность АЦП и скорость преобразования
- •12.2.4. Аналого-цифровые преобразования в режиме опроса
- •12.2.6. Аналого-цифровые преобразования в режиме DMA
- •12.2.6.1. Многократное преобразование одного канала в режиме DMA
- •12.2.6.3. Непрерывные преобразования в режиме DMA
- •12.2.7. Обработка ошибок
- •12.2.8. Преобразования, управляемые таймером
- •12.2.9. Преобразования, управляемые внешними событиями
- •12.2.10. Калибровка АЦП
- •12.3. Использование CubeMX для конфигурации АЦП
- •13.1. Введение в периферийное устройство ЦАП
- •13.2. Модуль HAL_DAC
- •13.2.1. Управление ЦАП вручную
- •13.2.2. Управление ЦАП в режиме DMA с использованием таймера
- •13.2.3. Генерация треугольного сигнала
- •13.2.4. Генерация шумового сигнала
- •14.1. Введение в спецификацию I²C
- •14.1.1. Протокол I²C
- •14.1.1.1. START- и STOP-условия
- •14.1.1.2. Формат байта
- •14.1.1.3. Кадр адреса
- •14.1.1.4. Биты «Подтверждено» (ACK) и «Не подтверждено» (NACK)
- •14.1.1.5. Кадры данных
- •14.1.1.6. Комбинированные транзакции
- •14.1.1.7. Удержание синхросигнала
- •14.1.2. Наличие периферийных устройств I²C в микроконтроллерах STM32
- •14.2. Модуль HAL_I2C
- •14.2.1.1. Операции I/O MEM
- •14.2.1.2. Комбинированные транзакции
- •14.3. Использование CubeMX для конфигурации периферийного устройства I²C
- •15.1. Введение в спецификацию SPI
- •15.1.1. Полярность и фаза тактового сигнала
- •15.1.2. Управление сигналом Slave Select
- •15.1.3. Режим TI периферийного устройства SPI
- •15.1.4. Наличие периферийных устройств SPI в микроконтроллерах STM32
- •15.2. Модуль HAL_SPI
- •15.2.1. Обмен сообщениями с использованием периферийного устройства SPI
- •15.2.2. Максимальная частота передачи, достижимая при использовании CubeHAL
- •15.3. Использование CubeMX для конфигурации периферийного устройства SPI
- •16. Циклический контроль избыточности
- •16.1. Введение в расчет CRC
- •16.1.1. Расчет CRC в микроконтроллерах STM32F1/F2/F4/L1
- •16.2. Модуль HAL_CRC
- •17. Независимый и оконный сторожевые таймеры
- •17.1. Независимый сторожевой таймер
- •17.1.1. Использование CubeHAL для программирования таймера IWDG
- •17.2. Системный оконный сторожевой таймер
- •17.2.1. Использование CubeHAL для программирования таймера WWDG
- •17.3. Отслеживание системного сброса, вызванного сторожевым таймером
- •17.4. Заморозка сторожевых таймеров во время сеанса отладки
- •17.5. Выбор сторожевого таймера, подходящего для вашего приложения
- •18. Часы реального времени
- •18.1. Введение в периферийное устройство RTC
- •18.2. Модуль HAL_RTC
- •18.2.1. Установка и получение текущей даты/времени
- •18.2.1.1. Правильный способ чтения значений даты/времени
- •18.2.2. Конфигурирование будильников
- •18.2.3. Блок периодического пробуждения
- •18.2.5. Калибровка RTC
- •18.2.5.1. Грубая калибровка RTC
- •18.2.5.2. Тонкая калибровка RTC
- •18.2.5.3. Обнаружение опорного тактового сигнала
- •18.3. Использование резервной SRAM
- •III Дополнительные темы
- •19. Управление питанием
- •19.1. Управление питанием в микроконтроллерах на базе Cortex-M
- •19.2. Как микроконтроллеры Cortex-M управляют рабочим и спящим режимами
- •19.2.1. Переход в/выход из спящих режимов
- •19.2.1.1. «Спящий режим по выходу»
- •19.3. Управление питанием в микроконтроллерах STM32F
- •19.3.1. Источники питания
- •19.3.2. Режимы питания
- •19.3.2.1. Рабочий режим
- •19.3.2.2. Спящий режим
- •19.3.2.3. Режим останова
- •19.3.2.4. Режим ожидания
- •19.3.2.5. Пример работы в режимах пониженного энергопотребления
- •19.4. Управление питанием в микроконтроллерах STM32L
- •19.4.1. Источники питания
- •19.4.2. Режимы питания
- •19.4.2.1. Рабочие режимы
- •19.4.2.2. Спящие режимы
- •19.4.2.2.1. Режим пакетного сбора данных
- •19.4.2.3. Режимы останова
- •19.4.2.4. Режимы ожидания
- •19.4.2.5. Режим выключенного состояния
- •19.4.3. Переходы между режимами питания
- •19.4.4. Периферийные устройства с пониженным энергопотреблением
- •19.4.4.1. LPUART
- •19.4.4.2. LPTIM
- •19.5. Инспекторы источников питания
- •19.6. Отладка в режимах пониженного энергопотребления
- •19.7. Использование калькулятора энергопотребления CubeMX
- •20. Организация памяти
- •20.1. Модель организации памяти в STM32
- •20.1.1. Основы процессов компиляции и компоновки
- •20.2.1. Исследование бинарного ELF-файла
- •20.2.2. Инициализация секций .data и .bss
- •20.2.2.1. Пара слов о секции COMMON
- •20.2.3. Секция .rodata
- •20.2.4. Области Стека и Кучи
- •20.2.5. Проверка размера Кучи и Стека на этапе компиляции
- •20.2.6. Различия с файлами скриптов инструментария
- •20.3. Как использовать CCM-память
- •20.3.1. Перемещение таблицы векторов в CCM-память
- •20.4.1. Программирование MPU с использованием CubeHAL
- •21. Управление Flash-памятью
- •21.1. Введение во Flash-память STM32
- •21.2. Модуль HAL_FLASH
- •21.2.1. Разблокировка Flash-памяти
- •21.2.2. Стирание Flash-памяти
- •21.2.3. Программирование Flash-памяти
- •21.3. Байты конфигурации
- •21.3.1. Защита от чтения Flash-памяти
- •21.4. Дополнительные памяти OTP и EEPROM
- •21.5. Задержка чтения Flash-памяти и ускоритель ART™ Accelerator
- •21.5.1. Роль TCM-памятей в микроконтроллерах STM32F7
- •22. Процесс начальной загрузки
- •22.1.1. Программное физическое перераспределение памяти
- •22.1.2. Перемещение таблицы векторов
- •22.1.3. Запуск микропрограммы из SRAM с помощью инструментария GNU MCU Eclipse
- •22.2. Встроенный загрузчик
- •22.2.1. Запуск загрузчика из встроенного программного обеспечения
- •22.2.2. Последовательность начальной загрузки в инструментарии GNU MCU Eclipse
- •22.3. Разработка пользовательского загрузчика
- •22.3.2. Как использовать инструмент flasher.py
- •23. Запуск FreeRTOS
- •23.1. Введение в концепции, лежащие в основе ОСРВ
- •23.2.1. Структура файлов с исходным кодом FreeRTOS
- •23.2.1.2. Как импортировать FreeRTOS с использованием CubeMX и CubeMXImporter
- •23.3. Управление потоками
- •23.3.1. Состояния потоков
- •23.3.2. Приоритеты потоков и алгоритмы планирования
- •23.3.3. Добровольное освобождение от управления
- •23.3.4. Холостой поток idle
- •23.4. Выделение памяти и управление ею
- •23.4.1. Модель динамического выделения памяти
- •23.4.1.1. heap_1.c
- •23.4.1.2. heap_2.c
- •23.4.1.3. heap_3.c
- •23.4.1.4. heap_4.c
- •23.4.1.5. heap_5.c
- •23.4.2. Модель статического выделения памяти
- •23.4.3. Пулы памяти
- •23.4.4. Обнаружение переполнения стека
- •23.5. Примитивы синхронизации
- •23.5.1. Очереди сообщений
- •23.5.2. Cемафоры
- •23.5.3. Сигналы потоков
- •23.6. Управление ресурсами и взаимное исключение
- •23.6.1. Мьютексы
- •23.6.2. Критические секции
- •23.6.3. Обработка прерываний совместно с ОСРВ
- •23.7. Программные таймеры
- •23.7.1. Как FreeRTOS управляет таймерами
- •23.8. Пример из практики: Управление энергосбережением с ОСРВ
- •23.8.1. Перехват холостого потока idle
- •23.8.2. Бестиковый режим во FreeRTOS
- •23.9. Возможности отладки
- •23.9.1. Макрос configASSERT()
- •23.9.2. Статистика среды выполнения и информация о состоянии потоков
- •23.10. Альтернативы FreeRTOS
- •23.10.1. ChibiOS
- •23.10.2. ОС Contiki
- •23.10.3. OpenRTOS
- •24. Продвинутые методы отладки
- •24.1. Введение в исключения отказов Cortex-M
- •24.1.1.1. Как инструментарий GNU MCU Eclipse обрабатывает исключения отказов
- •24.1.1.2. Как интерпретировать содержимое регистра LR при переходе в исключение
- •24.1.2. Исключения отказов и их анализ
- •24.2.1. Представление Expressions
- •24.2.1.1. Мониторы памяти
- •24.2.2. Точки наблюдения
- •24.2.3. Режим Instruction Stepping Mode
- •24.2.4. Keil Packs и представление Peripheral Registers
- •24.2.5. Представление Core Registers
- •24.3. Средства отладки от CubeHAL
- •24.4. Внешние отладчики
- •24.4.1. Использование SEGGER J-Link для отладчика ST-LINK
- •24.4.2. Использование интерфейса ITM и трассировка SWV
- •24.5. STM Studio
- •24.6. Одновременная отладка двух плат Nucleo
- •25. Файловая система FAT
- •25.1. Введение в библиотеку FatFs
- •25.1.1. Использование CubeMX для включения в ваши проекты библиотеки FatFs
- •25.1.2. Наиболее важные структуры и функции FatFs
- •25.1.2.1. Монтирование файловой системы
- •25.1.2.2. Открытие файлов
- •25.1.2.3. Чтение и запись файла
- •25.1.2.4. Создание и открытие каталога
- •25.1.3. Как сконфигурировать библиотеку FatFs
- •26. Разработка IoT-приложений
- •26.2. Ethernet контроллер W5500
- •26.2.1. Как использовать шилд W5500 и модуль ioLibrary_Driver
- •26.2.1.1. Конфигурирование интерфейса SPI
- •26.2.1.2. Настройка буферов сокетов и сетевого интерфейса
- •26.2.2. API-интерфейсы сокетов
- •26.2.2.1. Управление сокетами в режиме TCP
- •26.2.2.2. Управление сокетами в режиме UDP
- •26.2.3. Перенаправление ввода-вывода на сокет TCP/IP
- •26.2.4. Настройка HTTP-сервера
- •26.2.4.1. Веб-осциллограф
- •27. Начало работы над новым проектом
- •27.1. Проектирование оборудования
- •27.1.1. Послойная разводка печатной платы
- •27.1.2. Корпус микроконтроллера
- •27.1.3. Развязка выводов питания
- •27.1.4. Тактирование
- •27.1.5. Фильтрация вывода сброса RESET
- •27.1.6. Отладочный порт
- •27.1.7. Режим начальной загрузки
- •27.1.8. Обратите внимание на совместимость с выводами…
- •27.1.9. …и на выбор подходящей периферии
- •27.1.10. Роль CubeMX на этапе проектирования платы
- •27.1.11. Стратегии разводки платы
- •27.2. Разработка программного обеспечения
- •27.2.1. Генерация бинарного образа для производства
- •Приложение
- •Принудительный сброс микроконтроллера из микропрограммы
- •B. Руководство по поиску и устранению неисправностей
- •Проблемы с установкой GNU MCU Eclipse
- •Проблемы, связанные с Eclipse
- •Eclipse не может найти компилятор
- •Eclipse постоянно прерывается при выполнении каждой инструкции во время сеанса отладки
- •Пошаговая отладка очень медленная
- •Микропрограмма работает только в режиме отладки
- •Проблемы, связанные с STM32
- •Микроконтроллер не загружается корректно
- •Невозможно загрузить микропрограмму или отладить микроконтроллер
- •C. Схема выводов Nucleo
- •Nucleo-F446RE
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-F411RE
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-F410RB
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-F401RE
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-F334R8
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-F303RE
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-F302R8
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-F103RB
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-F091RC
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-F072RB
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-F070RB
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-F030R8
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-L476RG
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-L152RE
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-L073R8
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-L053R8
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •D. Корпусы STM32
- •LFBGA
- •LQFP
- •TFBGA
- •TSSOP
- •UFQFPN
- •UFBGA
- •VFQFP
- •WLCSP
- •E. Изменения книги
- •Выпуск 0.1 – Октябрь 2015
- •Выпуск 0.2 – 28 октября 2015
- •Выпуск 0.2.1 – 31 октября 2015
- •Выпуск 0.2.2 – 1 ноября 2015
- •Выпуск 0.3 – 12 ноября 2015
- •Выпуск 0.4 – 4 декабря 2015
- •Выпуск 0.5 – 19 декабря 2015
- •Выпуск 0.6 – 18 января 2016
- •Выпуск 0.6.1 – 20 января 2016
- •Выпуск 0.6.2 – 30 января 2016
- •Выпуск 0.7 – 8 февраля 2016
- •Выпуск 0.8 – 18 февраля 2016
- •Выпуск 0.8.1 – 23 февраля 2016
- •Выпуск 0.9 – 27 марта 2016
- •Выпуск 0.9.1 – 28 марта 2016
- •Выпуск 0.10 – 26 апреля 2016
- •Выпуск 0.11 – 27 мая 2016
- •Выпуск 0.11.1 – 3 июня 2016
- •Выпуск 0.11.2 – 24 июня 2016
- •Выпуск 0.12 – 4 июля 2016
- •Выпуск 0.13 – 18 июля 2016
- •Выпуск 0.14 – 12 августа 2016
- •Выпуск 0.15 – 13 сентября 2016
- •Выпуск 0.16 – 3 октября 2016
- •Выпуск 0.17 – 24 октября 2016
- •Выпуск 0.18 – 15 ноября 2016
- •Выпуск 0.19 – 29 ноября 2016
- •Выпуск 0.20 – 28 декабря 2016
- •Выпуск 0.21 – 29 января 2017
- •Выпуск 0.22 – 2 мая 2017
- •Выпуск 0.23 – 20 июля 2017
- •Выпуск 0.24 – 11 декабря 2017
- •Выпуск 0.25 – 3 января 2018
- •Выпуск 0.26 – 7 мая 2018
Введение в отладку |
152 |
5.2.2. Включение полуохостинга в существующем проекте
Если у вас есть существующий проект и вы хотите включить полухостинг, вам необходимо выделить два случая.
Первый более простой. Если вы сгенерировали проект с помощью плагина GNU MCU, вам нужно всего лишь добавить следующий глобальный макрос в настройках проекта:
•Если вы хотите использовать только функции trace_printf() от Ливиу Ионеску,
добавьте макросы TRACE и OS_USE_TRACE_SEMIHOSTING_DEBUG.
•Если вы хотите использовать функции манипулирования вводом/выводом из стандартной библиотеки Си, добавьте макрос OS_USE_SEMIHOSTING и снимите фла-
жок Assume freestanding environment (-ffreestanding).
Второй случай более сложный. У вас есть существующий проект, импортированный в Eclipse, который не был создан с помощью плагина Eclipse GNU MCU. Если достаточно использовать функцию trace_printf(), то вы можете импортировать в свой проект следующие файлы, взятые из проекта, сгенерированного с помощью плагина GNU MCU:
•src/diag/trace_impl.c
•src/diag/Trace.c
•include/diag/Trace.h
Затем вы должны определить макросы TRACE и OS_USE_TRACE_SEMIHOSTING_DEBUG на уровне проекта и вызвать процедуру initialise_monitor_handles() в вашей процедуре main().
Если вы хотите использовать все стандартные процедуры ввода/вывода библиотеки Си, вам необходимо:
•импортировать в свой проект файл src/newlib/_syscalls.c;
•определить макрос OS_USE_SEMIHOSTING на уровне проекта;
•снять флажок Assume freestanding environment (-ffreestanding);
•вызвать процедуру initialise_monitor_handles() в вашей процедуре main().
5.2.3. Недостатки полухостинга
Полухостинг – отличная функция, но он также имеет несколько недостатков. Прежде всего, он работает только во время сеанса отладки, и полностью «подвешивает» микропрограмму, если она не работает под управлением GDB. Например, загрузите один из предыдущих примеров на вашу плату Nucleo и завершите сеанс отладки. Если вы перезагрузите плату, нажав кнопку RESET, светодиод LD2 не будет мигать. Это происходит потому, что микропрограмма зависла в процедуре trace_printf() (подробнее о том, почему это происходит в следующем параграфе). Это достаточно распространенная проблема, с которой сталкивается каждый новичок всякий раз, когда начинает работать с платформой STM32.
Еще один важный аспект, который следует иметь в виду, заключается в том, что полухостинг оказывает большое влияние на производительность программного обеспечения. Каждый вызов полухостинга затрачивает несколько тактовых циклов ЦПУ, и он влияет на общую производительность. Более того, эти затраты непредсказуемы, поскольку они включают в себя действия, которые происходят вне потоков выполнения микроконтроллера (подробнее об этом в следующем параграфе).
Введение в отладку |
153 |
В Главе 8 мы увидим еще один интересный способ обмена сообщениями с хост-ПК с помощью одного из USART STM32.
5.2.4. Как работает полухостинг
Если вы новичок в мире STM32 и вас немного смущает его первоначальная сложность, вы можете перестать читать данный параграф и перейти к следующей главе. Здесь мы будем описывать сложную тему, которая требует небольшого понимания того, как работает архитектура ARM, и некоторых продвинутых функций GCC. Вам не обязательно читать данный параграф, но если вы рассмотрите его, это может улучшить ваше общее понимание.
Существует несколько способов реализовать возможности полухостинга. Одним из них является использование программных точек останова. ARM Cortex-M предлагает два типа точек останова: аппаратные (HBP) и программные (SBP).
HBP устанавливаются программированием модуля точек останова (аппаратного модуля внутри каждого ядра Cortex-M) для мониторинга шин ядра с целью выборки команд из определенной ячейки памяти. HBP могут быть установлены в любом месте в ОЗУ или ПЗУ с использованием внешнего физического программатора, подключенного к интерфейсу отладки. В случае платы Nucleo встроенный программатор ST-LINK подключен к интерфейсу отладки микроконтроллера, и он, в свою очередь, управляется OpenOCD. На рисунке 20 показана взаимосвязь между внешним отладчиком и внутренним модулем отладки микроконтроллера.
Рисунок 20. Компоненты отладки в микроконтроллерах Cortex-M
SBP реализуются добавлением специальной инструкции bkpt непосредственно перед кодом, который мы хотим проверить. Когда ядро выполняет инструкцию точки останова, оно переводится в состояние отладки. Отладчик видит, что микроконтроллер приостановлен, и начинает его отладку. Инструкция bkpt принимает немедленный 8-бит- ный код операции (immediate 8-bit opcode), который может использоваться для указания какого-либо условия прерывания. Если вы хотите остановить выполнение вашей микропрограммы и передать управление отладчику, то инструкция:
asm("bkpt #0")
Введение в отладку |
154 |
то, что вам нужно. Данный метод используется для реализации программной условной точки останова. Например, предположим, что у вас есть странное условие (condition) отказа, которое вам нужно проверить. Вы можете применить фрагмент кода, подобный следующему:
if(cond == 0) {
...
}else if(cond > 0) {
...
}else { /* Ненормальное состояние, давайте отладим его */
asm("bkpt #0");
}
В приведенном выше коде, если переменная cond принимает отрицательное значение, микроконтроллер останавливается и управление передается GDB, что позволяет нам проверять стек вызовов и текущий стековый кадр.
Полухостинг реализован с использованием специального немедленного кода операции 0xAB. То есть инструкция:
asm("bkpt #0xAB")
вызывает останов микроконтроллера, но на этот раз OpenOCD видит специальный код операции и интерпретирует его как операцию полухостинга. По соглашению регистр r0 содержит тип операции (_write(), _read() и т. д.), а регистр r1 содержит указатель на область памяти, содержащую параметры функции. Например, если мы хотим записать строку с завершающим нулем на консоли хост-ПК, мы можем написать следующий ассемблерный код:
asm (
"mov r0, 0x4 \n /* код операции для записи строки с завершающим нулем */ "mov r1, 0x20001400 \n" /* адрес строки для передачи в OpenOCD */
"bkpt #0xAB"
);
В таблице 3 приведены поддерживаемые операции полухостинга. Пожалуйста, обратите внимание, что OpenOCD в настоящее время не поддерживает все из них.
Следующий полный код Cи показывает, как реализовать функцию trace_printf().
Имя файла: src/main-ex3.c
34 #include "stm32f4xx_hal.h"
35
36void SystemClock_Config(void);
37static void MX_GPIO_Init(void);
39int main(void)
40{
41char msg[] = "Hello STM32 lovers!\n";
43HAL_Init();
44SystemClock_Config();
45MX_GPIO_Init();
|
Введение в отладку |
155 |
46 |
|
|
47 |
asm volatile ( |
|
48 |
" mov |
r0, 0x4 \n" |
49 |
" mov |
r1, %[msg] \n" |
50 |
" bkpt #0xAB" |
|
51 |
: |
|
52 |
: [msg] |
"r" (msg) |
53 |
: "r0", |
"r1" |
54 |
); |
|
55 |
|
|
56while(1);
57}
Здесь мы используем возможности функции GCC asm() для передачи указателя на бу-
фер msg, содержащий строку "Hello STM32 lovers!\n".
Теперь вы можете понять, почему при полухостинге микроконтроллер зависает, если отладчик не активен. Инструкция bkpt останавливает выполнение микроконтроллера, и восстановить его невозможно без использования внешнего отладчика (или аппаратного сброса). Более того, каждый раз, когда выдается команда bkpt, внутренние действия микроконтроллера приостанавливаются до тех пор, пока управление не перейдет к отладчику. В течение этого времени важные асинхронные события (например, прерывания, генерируемые периферийными устройствами) могут быть потеряны. Этот интервал времени абсолютно непредсказуем и зависит от многих факторов (скорость аппаратного интерфейса, текущая загрузка хост-ПК, скорость микропрограммы ST-LINK и т. д.).
|
Таблица 3: Сводка операций полухостинга |
|
Операция полухостинга |
Немедленный оп. код |
Описание |
|
|
|
EnterSVC |
0x17 |
Устанавливает процессор в режим супервизора |
|
|
и отключает все прерывания, устанавливая обе |
|
|
битовые маски прерываний в новом CPSR. |
ReportException |
0x18 |
Данный SVC может вызываться приложением, |
|
|
чтобы напрямую сообщить об исключении от- |
|
|
ладчику. Наиболее распространенное использо- |
|
|
вание – сообщить о завершении выполнения, |
|
|
используя ADP_Stopped_ApplicationExit. |
SYS_CLOSE |
0x02 |
Закрывает файл в хост-системе. Обработчик |
|
|
должен ссылаться на файл, который был открыт |
|
|
с помощью SYS_OPEN. |
SYS_CLOCK |
0x10 |
Возвращает количество сотых долей секунды с |
|
|
момента начала выполнения. |
SYS_ELAPSED |
0x30 |
Возвращает количество прошедших целевых |
|
|
тиков с момента начала выполнения. Исполь- |
|
|
зуйте SYS_TICKFREQ, чтобы определить частоту |
|
|
тиков. |
SYS_ERRNO |
0x13 |
Возвращает значение переменной errno биб- |
|
|
лиотеки Си, связанной с реализацией хоста для |
|
|
SVC полухостинга. |
SYS_FLEN |
0x0C |
Возвращает длину указанного файла. |
SYS_GET_CMDLINE |
0x15 |
Возвращает командную строку, используемую |
|
|
для вызова исполняемого файла, то есть argc и |
|
|
argv. |
Введение в отладку |
156 |
Таблица 3: Сводка операций полухостинга (продолжение)
Операция полухостинга |
Немедленный оп. код |
Описание |
|
|
|
SYS_HEAPINFO |
0x16 |
Возвращает системный стек и параметры кучи. |
|
|
Возвращаемые значения обычно являются зна- |
|
|
чениями, используемыми библиотекой Си во |
|
|
время инициализации. |
SYS_ISERROR |
0x08 |
Определяет, является ли код возврата от другого |
|
|
вызова полухостинга состоянием ошибки или |
|
|
нет. Этот вызов передает блок параметров, со- |
|
|
держащий код ошибки для изучения. |
SYS_ISTTY |
0x09 |
Проверяет, подключен ли файл к интерактив- |
|
|
ному устройству. |
SYS_OPEN |
0x01 |
Открывает файл в хост-системе. Путь к файлу |
|
|
указывается либо относительно текущего ката- |
|
|
лога хост-процесса, либо как абсолютный, ис- |
|
|
пользуя соглашения о путях операционной си- |
|
|
стемы хоста. |
SYS_READ |
0x06 |
Считывает содержимое файла в буфер. |
SYS_READC |
0x07 |
Считывает байт из консоли. |
SYS_REMOVE |
0x0E |
Удаляет указанный файл в системе регистрации |
|
|
документов (filing system) хоста. |
SYS_RENAME |
0x0F |
Переименовывает указанный файл. |
SYS_SEEK |
0x0A |
Ищет указанную позицию в файле, используя |
|
|
смещение, указанное с начала файла. Предпола- |
|
|
гается, что файл является байтовым массивом, а |
|
|
смещение задается в байтах. |
SYS_SYSTEM |
0x12 |
Передает команду интерпретатору командной |
|
|
строки хоста. Это позволяет вам выполнить си- |
|
|
стемную команду, такую как dir, ls или pwd. |
|
|
Ввод/вывод терминала находится на хосте и не |
|
|
виден для целевого устройства. |
SYS_TICKFREQ |
0x31 |
Возвращает частоту тиков. |
SYS_TIME |
0x11 |
Возвращает количество секунд с 00:00 1 января |
|
|
1970 года. |
SYS_TMPNAM |
0x0D |
Возвращает временное имя для файла, иденти- |
|
|
фицированного системным идентификатором |
|
|
файла. |
SYS_WRITE |
0x05 |
Записывает содержимое буфера в указанный |
|
|
файл в текущей позиции файла. Текущая реа- |
|
|
лизация OpenOCD ожидает, что буфер заверша- |
|
|
ется символом конца строки (\n). |
SYS_WRITEC |
0x03 |
Записывает символьный байт, на который ука- |
|
|
зывает R1, в канал отладки. При выполнении в |
|
|
отладчике ARM символ появляется на консоли |
|
|
отладчика хоста. |
SYS_WRITE0 |
0x04 |
Записывает строку с завершающим нулем в ка- |
|
|
нал отладки. При выполнении в отладчике ARM |
символы появляются на консоли отладчика хоста.