- •Оглавление
- •Предисловие
- •Почему я написал книгу?
- •Для кого эта книга?
- •Как использовать эту книгу?
- •Как организована книга?
- •Об авторе
- •Ошибки и предложения
- •Поддержка книги
- •Как помочь автору
- •Отказ от авторского права
- •Благодарность за участие
- •Перевод
- •Благодарности
- •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
Продвинутые методы отладки |
|
|
676 |
||
|
|
Таблица 1: Возможные значения EXC_RETURN и их интерпретация |
|||
|
Режим после |
Стек после |
|
|
|
EXC_RETURN |
возврата |
возврата |
FPU включен |
Описание |
|
|
|
|
|
|
|
0xFFFF FFF1 |
0 |
(Обработчик) |
MSP |
Нет |
Возврат в режиме обработ- |
|
|
|
|
|
чика (с использованием MSP) |
0xFFFF FFF9 |
1 |
(Поток) |
MSP |
Нет |
Возврат в режиме потока (с |
|
|
|
|
|
использованием MSP) |
0xFFFF FFFD |
1 |
(Поток) |
PSP |
Нет |
Возврат в режиме потока (с |
|
|
|
|
|
использованием PSP) |
0xFFFF FFE1 |
0 |
(Обработчик) |
MSP |
Да |
Возврат в режиме обработ- |
|
|
|
|
|
чика (с использованием MSP) |
0xFFFF FFE9
0xFFFF FFED
1 (Поток) |
MSP |
Да |
Возврат в режиме потока (с |
|
|
|
использованием MSP) |
1 (Поток) |
PSP |
Да |
Возврат в режиме потока (с |
|
|
|
использованием PSP) |
Например, если ЦПУ выполняло «обычный код» (т. е. ЦПУ находилось в режиме потока) до перехода в исключение, если использовался стек MSP и если модуль FPU был отключен, то регистр LR будет содержать значение 0xFFFF FFF9. Если вместо этого ЦПУ обслуживало другое исключение (возможно, прерывание) при переходе в текущее исключение (то есть ЦПУ находилось в режиме обработчика), то содержимое регистра LR будет
равно 0xFFFF FFF1.
Именно благодаря механизму EXC_RETURN обычные функции Си могут использоваться в качестве обработчиков исключений без написания каких-либо строк ассемблерного кода. Это отличается от других архитектур микроконтроллеров, где требуется дополнительная работа от компилятора (или от разработчика) для выполнения операции загрузки в стек/извлечения из стека обработчиков исключений.
Рисунок 5: Как интерпретируется значение EXC_RETURN
На рисунке 5 показана полная структура значения EXC_RETURN. Как видите, четвертый бит указывает, какой стек использовался в момент срабатывания условия отказа. Это четко объясняет использование инструкции tst в предыдущем ассемблерном коде для определения используемого стека.
24.1.2. Исключения отказов и их анализ
Механизм исключений отказов, предоставляемый процессором Cortex-M, достаточно полезен для обнаружения источников отказов. В течение жизненного цикла разработки очень часто возникают условия отказов, особенно если вы новичок в платформе STM32 или во встроенном программировании.
Данный параграф демонстрирует краткий обзор анализа состояний отказов. Он не ставит своей целью заменить официальную документацию ARM или отличные работы
Продвинутые методы отладки |
677 |
Джозефа Ю8. Главная его цель – предоставить необходимые инструменты и концепции для понимания того, что происходит не так, когда возникает одно из четырех исключений отказов.
Ядра Cortex-M3/4/7 предоставляют ряд регистров, которые используются для анализа отказов. Они могут использоваться кодом обработчика отказа, но в большинстве случаев они используются во время сеанса отладки. В таблице 2 перечислены доступные регистры, полезные для анализа отказов.
Таблица 2: Регистры для состояний отказов и информации об адресах
Символ CMSIS |
Имя регистра |
Описание |
|
|
|
SCB->CFSR |
Регистр состояния конфигу- |
Предоставляет информацию о состоянии |
|
рируемых отказов |
конфигурируемых исключений (MemFault, |
|
|
BusFault, UsageFault) |
SCB->HFSR
SCB->DFSR
SCB->MMFAR
SCB->BFAR
Состояние отказа HardFault |
Предоставляет информацию о состоянии для |
|
исключения HardFault |
Регистр состояния отказа |
Предоставляет информацию о состоянии для |
отладки |
исключения Debug Monitor |
Регистр адреса отказа |
Если доступен, показывает адрес, который |
MemManage Fault |
вызвал отказ MemManage |
Регистр адреса отказа |
Если доступен, показывает адрес, который |
BusFault |
вызвал отказ BusFault |
SCB->CFSR – это регистр состояния конфигурируемых отказов (Configurable Fault Status Register), и он предоставляет информацию для тех исключений, которые могут быть разрешены по выбору (MemFault, BusFault, UsageFault). Он, в свою очередь, разделен на три подрегистра, как показано на рисунке 6. Мы собираемся предоставить их полное описание в соответствующих подпунктах.
Рисунок 6: Как SCB->CFSR делится на три подрегистра
24.1.2.1.Исключение Memory Management
Это исключение может быть вызвано из-за нарушения правил доступа, определенных конфигурацией MPU. Например, оно срабатывает при попытке доступа в режиме записи к области, определенной как доступная только для чтения. Это исключение доступно только в ядрах Cortex-M3/4/7, и оно должно быть разрешено. После разрешения отдельные биты регистра SCB->MFSR (который соответствует первому байту регистра SCB->CFSR) могут принимать значения, указанные в таблице 3. Регистр SCB->MFSR при сбросе устанавливается в 0x0, и его значения остаются высокими, пока значение 1 не будет записано в регистр. Проверяя отдельные значения битов, мы можем получить больше информации о причине отказа. Например, если установлен бит DACCVIOL, то исключение вызвало обращение к защищенной области памяти. В этом случае устанавливается бит MMARVALID, а регистр SCB->MMFAR содержит ячейку памяти назначения, которая вызвала отказ. Чтобы увидеть это исключение в работе, попробуйте выполнить пример, приведенный в параграфе об устройстве MPU.
8 http://amzn.to/1P5sZwq
Продвинутые методы отладки |
678 |
|
|
Таблица 3: Регистр состояния отказа MemManage Fault (SCB->MFSR) |
|
Бит |
Имя |
Описание |
|
|
|
7 |
MMARVALID |
Указывает на корректность содержимого регистра SCB->MMFAR |
6 |
ЗАРЕЗЕРВИРОВАНО |
ЗАРЕЗЕРВИРОВАНО |
5 |
MLSPERR |
Ошибка отложенной загрузки в стек регистров модуля FPU, |
|
|
англ. lazy stacking (доступно только для ядер Cortex-M4F) |
4 |
MSTKERR |
Ошибка загрузки данных в стек |
3 |
MUNSTKERR |
Ошибка извлечения данных из стека |
2 |
ЗАРЕЗЕРВИРОВАНО |
ЗАРЕЗЕРВИРОВАНО |
1 |
DACCVIOL |
Нарушение доступа к данным |
0 |
IACCVIOL |
Нарушение доступа к инструкции |
24.1.2.2.Исключение Bus Fault
Это исключение чаще всего возникает из-за обращения по недопустимому адресу памяти SRAM или памяти программ. Два более частых источника исключения отказа шины Bus Fault – неправильный указатель на недопустимую область памяти SRAM и неверный указатель на функцию. Кроме того, отказ шины Bus Fault также может возникать во время загрузки в/извлечения из стека последовательности обработки исключения:
•Если отказ шины Bus Fault произошел во время помещения данных в стек при последовательности перехода в исключение, это называется ошибкой загрузки дан-
ных в стек (stacking error).
•Если отказ шины Bus Fault произошел во время извлечения данных из стека при последовательности выхода из исключения, это называется ошибкой извлечения данных из стека (unstacking error).
Обычно ошибка загрузки данных в стек указывает на переполнение стека: стеку не хватает места, и это вызывает отказ шины Bus Fault из-за доступа к неверной ячейке SRAM. Система исключений вызывает исключение отказа, но ЦПУ не может поместить сохраненный регистр ядра в полный стек. Это вызывает ошибку загрузки данных в стек, которая, в свою очередь, вызывает тяжелый отказ Hard Fault. Считав SCB->BFSR, мы увидим, что установлены оба бита 15 и 12. Содержимое SCB->BFAR будет настолько некорректным, что мы увидим нечто похожее на 0x1fff bff8. Это недопустимое расположение SRAM в микроконтроллерах STM32, и поэтому мы можем легко определить, что произошло переполнение стека.
Таблица 4 показывает значение отдельных битов регистра SCB->BFSR.
Таблица 4: Регистр состояния отказа шины Bus Fault (SCB->BFSR)
Бит |
Имя |
Описание |
|
|
|
15 |
BFARVALID |
Указывает на корректность содержимого регистра SCB->BFAR |
14 |
ЗАРЕЗЕРВИРОВАНО |
ЗАРЕЗЕРВИРОВАНО |
13 |
LSPERR |
Ошибка отложенной загрузки в стек регистров модуля FPU, |
|
|
англ. lazy stacking (доступно только для ядер Cortex-M4F) |
12 |
STKERR |
Ошибка загрузки данных в стек |
11 |
UNSTKERR |
Ошибка извлечения данных из стека |
10 |
IMPRECISERR |
«Неточное» нарушение доступа к данным |
9 |
PRECISERR |
«Точное» нарушение доступа к данным |
8 |
IBUSERR |
Нарушение доступа к инструкции |
Продвинутые методы отладки |
679 |
Отказы шины можно классифицировать как:
•«Точные» отказы шины (Precise bus faults): исключения отказов произошли сразу при выполнении инструкции доступа к памяти.
•«Неточные» отказы шины (Imprecise bus faults): исключения отказов произошли через некоторое время после выполнения инструкции доступа к памяти.
Причина, по которой отказ шины становится «неточным», связана с наличием буферов записи в интерфейсе шин процессора. Когда процессор записывает данные по буферизируемому адресу, процессор может приступить к выполнению следующей инструкции, несмотря на то что передача занимает несколько тактовых циклов до завершения. При возникновении «неточного» отказа доступа к данным регистр SCB->BFAR некорректен. Чтобы определить источник отказа, нам нужно дизассемблировать исходный код на языке Си и определить ассемблерную инструкцию, которая логически предшествует той, на которую указывает загруженный в стек PC.
24.1.2.3.Исключение Usage Fault
Это исключение может быть вызвано очень обширным списком факторов. При разработке приложений на STM32 наиболее распространенными из них являются:
•Выполнение неопределенной инструкции (в том числе попытка выполнить инструкции вычислений с плавающей точкой, когда математический сопроцессор отключен). Оно часто происходит, когда у нас указатель на некорректную функцию, который указывает на корректную ячейку памяти (часто это происходит, когда у нас есть некоторые функции в SRAM), но содержимое указанной ячейки не соответствует инструкции ассемблера ARM.
•Некорректный код EXC_RETURN во время последовательности возврата из исключения. Например, попытка вернуться в режим потока с исключениями, которые все еще активны (кроме текущего обслуживаемого исключения).
•Невыровненный доступ к памяти инструкциями с множественными загрузкой или записью (включая инструкции загрузки и записи чисел формата double, англ. load double and store double instructions).
•Выполнение инструкции SVC, когда уровень приоритета SVC такой же или ниже текущего уровня. Оно возникает, когда произошло что-то неприятное с конфигурацией системных исключений FreeRTOS (обычно когда IRQ таймера SysTick не присвоен самый низкий приоритет).
Как только соответствующая конфигурация установлена, также возможно генерировать отказы программы при следующих условиях:
•Деление на ноль.
•Все невыровненные доступы к памяти.
Таблица 5 показывает значение отдельных битов регистра SCB->UFSR.
Продвинутые методы отладки |
680 |
Таблица 5: Регистр состояния отказа программы Usage Fault (SCB->UFSR)
Бит |
Имя |
Описание |
|
|
|
31-26 |
ЗАРЕЗЕРВИРОВАНО |
ЗАРЕЗЕРВИРОВАНО |
25 |
DIVBYZERO |
Указывает на отказ при делении на ноль (может быть установ- |
|
|
лен, только если он разрешен) |
24 |
UNALIGNED |
Указывает, что произошел отказ при невыровненном доступе |
23-20 |
ЗАРЕЗЕРВИРОВАНО |
ЗАРЕЗЕРВИРОВАНО |
19 |
NOCP |
Попытка выполнения инструкции вычислений с плавающей |
|
|
точкой, когда модуль FPU ядра Cortex-M4F не доступен или не |
|
|
был включен. |
18 |
INVPC |
Попытка выполнения исключения с неверным значением |
|
|
EXC_RETURN |
17 |
INVSTATE |
Попытки переключиться в недопустимое состояние (напри- |
|
|
мер, из ARM в Thumb) |
16 |
UNDEFINSTR |
Попытка выполнить неопределенную инструкцию |
По умолчанию микроконтроллеры на базе Cortex-M возвращают значение 0 при делении числа на ноль. Если вместо этого вам нужно перехватить ошибку деления на ноль, то вы можете разрешить данное условие отказа, установив бит DIV_0_TRP в регистре
SCB->CCR:
SCB->CCR |= SCB_CCR_DIV_0_TRP_Msk;
То же самое относится к невыровненному доступу к памяти:
SCB->CCR |= SCB_CCR_UNALIGN_TRP_Msk;
24.1.2.4.Исключение Hard Fault
Это исключение обычно вызывается эскалацией предыдущих конфигурируемых исключений, если они не разрешены. Кроме того, отказ HardFault может быть вызван:
•Отказом шины, полученным во время выборки таблицы векторов. Он происходит потому, что таблица векторов некорректна (в большинстве случаев, когда мы забыли включить в проект ассемблерный файл, предоставленный ST, или забыли изменить его расширение со строчной .s на прописную .S).
•Выполнением инструкции точки останова (asm("BKPT #0");) при не подключенном отладчике.
Таблица 6 показывает значение отдельных битов регистра SCB->HFSR.
Таблица 6: Регистр состояния тяжелого отказа Hard Fault (SCB->HFSR)
Бит |
Имя |
Описание |
|
|
|
31 |
DEBUGEVT |
Указывает, что отказ Hard Fault вызван событием отладки |
30 |
FORCED |
Указывает, что Hard Fault сгенерирован эскалацией конфигу- |
|
|
рируемых исключений отказов, когда они запрещены. В этом |
|
|
случае нам нужно проверить содержимое регистров SCB->MFSR, |
|
|
SCB->BFSR и SCB->UFSR для определения причины отказа. |
29-2 |
ЗАРЕЗЕРВИРОВАНО |
ЗАРЕЗЕРВИРОВАНО |
1 |
VECTBL |
Указывает, что отказ Hard Fault вызван неудачной выборкой |
|
|
таблицы векторов |
0 |
ЗАРЕЗЕРВИРОВАНО |
ЗАРЕЗЕРВИРОВАНО |