- •Оглавление
- •Предисловие
- •Почему я написал книгу?
- •Для кого эта книга?
- •Как использовать эту книгу?
- •Как организована книга?
- •Об авторе
- •Ошибки и предложения
- •Поддержка книги
- •Как помочь автору
- •Отказ от авторского права
- •Благодарность за участие
- •Перевод
- •Благодарности
- •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
7. Обработка прерываний
Управление аппаратными средствами связано с асинхронными событиями. Большинство из них приходит от аппаратной периферии. Например, таймер достигает заданного значения периода или UART, который предупреждает о поступлении данных. Другие порождаются «внешним окружением» нашей платы. Его примером может быть нажатие пользователем этого проклятого переключателя, заставляющего плату «зависать», а вы тратите целый день, чтобы понять, что не так.
Все микроконтроллеры предоставляют функцию, называемую прерываниями. Прерывание – это асинхронное событие, которое вызывает остановку выполнения текущего кода в приоритетном порядке (чем важнее прерывание, тем выше его приоритет; и более приоритетное прерывание приведет к приостановке прерывания с более низким приоритетом). Код, который обслуживает прерывание, называется Процедурой обслуживания прерывания (Interrupt Service Routine, ISR).
Прерывания являются источником многозадачности: аппаратное обеспечение знает о них и отвечает за сохранение текущего контекста исполнения (т. е. стекового кадра, текущего счетчика команд (Program Counter, PC) и некоторых других вещей) перед вызовом ISR. Они используются операционными системами реального времени для введения понятия задач. Без помощи аппаратного обеспечения невозможно создать настоящую вытесняющую многозадачность, которая позволяет переключаться между несколькими контекстами исполнения без необратимой потери текущего исполняемого потока.
Прерывания могут возникать как от аппаратного, так и от программного обеспечения. Архитектура ARM различает два типа исключений: прерывания, вызываемые аппаратным обеспечением, и исключения, вызываемые программным обеспечением (например, доступ к неверной ячейке памяти). В терминологии ARM прерывание – это тип исключения.
Процессоры Cortex-M предоставляют модуль, предназначенный для управления исклю-
чениями. Он называется Контроллером вложенных векторных прерываний (Nested Vectored Interrupt Controller, NVIC), и данная глава посвящена программированию этого действительно фундаментального аппаратного компонента. Однако в ней мы имеем дело только с управлением прерываниями. Обработка исключений будет рассмотрена в Главе 24 о продвинутой отладке.
7.1. Контроллер NVIC
Контроллер NVIC – это специальный аппаратный модуль внутри микроконтроллеров на базе Cortex-M, отвечающий за обработку исключений. На рисунке 1 показана взаимосвязь между модулем NVIC, ядром процессора и периферийными устройствами. Здесь мы должны различать два типа периферийных устройств: внешние по отношению к ядру Cortex-M, но внутренние по отношению к микроконтроллеру STM32 (например, таймеры, интерфейсы UART и т. д.), и периферийные устройства, внешние по отношению к микроконтроллеру. Источником прерываний, поступающих от последнего вида периферийных устройств, является вывод микроконтроллера, который может быть
Обработка прерываний |
175 |
сконфигурирован как I/O общего назначения (например, тактильный переключатель, подключенный к выводу, сконфигурированному как вход) или для управления внешним продвинутым периферийным устройством (например, I/O, сконфигурированные для обмена данными с ethernet phyther через интерфейс RMII). Как мы увидим далее, специальный программируемый контроллер, называемый Контроллером внешних преры-
ваний/событий (External Interrupt/Event Controller, EXTI), отвечает за взаимосвязь между внешними сигналами I/O и контроллером NVIC.
Рисунок 1: Взаимосвязь между контроллером NVIC, ядром Cortex-M и периферийными устройствами STM32
Как указывалось ранее, ARM различает системные исключения, возникающие внутри ядра ЦПУ, и аппаратные исключения, поступающие от внешних периферийных устройств, также называемые запросами прерываний (Interrupt Requests, IRQ). Программисты управляют исключениями посредством использования специальных ISR, которые кодируются на более высоком уровне (чаще всего с использованием языка Си). Процессор знает, где найти эти процедуры благодаря косвенной таблице, содержащей адреса процедур обслуживания прерываний в памяти. Данная таблица обычно называется таблицей векторов, и каждый микроконтроллер STM32 определяет свою собственную таблицу. Давайте проанализируем ее подробнее.
7.1.1. Таблица векторов в STM32
Все процессоры Cortex-M определяют фиксированный набор исключений (15 для ядер Cortex-M3/4/7 и 13 для ядер Cortex-M0/0+), общий для всех семейств Cortex-M и, следовательно, общий для всех серий STM32. Мы уже сталкивались с ним в Главе 1. Для вашего удобства, здесь вы можете найти ту же таблицу (таблица 1). Рекомендуется лишь бегло взглянуть на эти исключения (мы лучше изучим исключения отказов в Главе 24, посвященной продвинутой отладке).
Обработка прерываний |
|
176 |
||
Номер |
Тип исключения |
Приоритетa |
Описание |
|
1 |
Reset |
-3 |
Сброс |
|
2 |
NMI |
-2 |
Немаскируемое прерывание |
|
|
|
|
Любой отказ, если отказ не может быть |
|
3 |
Hard Fault |
-1 |
активирован из-за приоритета или |
|
программируемый обработчик отказа не |
||||
|
|
|
разрешен.
4 |
Memory |
Программируемыйb |
|
Managementc |
|||
|
|
||
5 |
Bus Faultc |
Программируемый |
|
6 |
Usage Faultc |
Программируемый |
Несоответствие MPU, включая нарушение прав доступа и отсутствие совпадений. Используется, даже если модуль MPU отключен или отсутствует.
Отказ предвыборки, отказ доступа к памяти и другие, связанные с адресом/памятью.
Ошибка в программе, такая как выполнение неопределенной инструкции или недопустимая попытка перехода между состояниями.
7-10 |
— |
— |
ЗАРЕЗЕРВИРОВАНО |
11 |
SVCall |
Программируемый |
Вызов системной службы командой SVC. |
12 |
Debug monitorc |
Программируемый |
Монитор отладки – для программной отладки. |
13 |
— |
— |
ЗАРЕЗЕРВИРОВАНО |
14 |
PendSV |
Программируемый |
Отложенный запрос для системной службы |
15 |
SYSTICK |
Программируемый |
Срабатывание системного таймера |
16-[47/240]d |
IRQ |
Программируемый |
Вход внешнего прерывания |
aЧем ниже значение приоритета, тем выше приоритет.
bМожно изменить приоритет исключения, назначив другой номер. Для процессоров Cortex-M0/0+ это число колеблется от 0 до 192 с шагом 64 (т. е. доступно 4 уровня приоритета). Для Cortex-M3/4/7 колеблется от 0 до 255.
cДанные исключения не доступны в Cortex-M0/0+.
dCortex-M0/0+ допускает 32 внешних конфигурируемых прерывания. Cortex-M3/4/7 допускает 240 конфигурируемых внешних прерываний. Однако на практике количество входов прерываний, реализованных в реальном микроконтроллере, намного меньше.
Таблица 1: Типы исключений Cortex-M
•Reset: исключение сброса возникает сразу после сброса ЦПУ. Его обработчик является реальной точкой входа работающей микропрограммы. В приложении STM32 все начинается с этого исключения. Обработчик содержит некоторые ассемблерные функции, предназначенные для инициализации среды выполнения, такие как основной стек, сегмент .bss и т. д. Глава 22, посвященная процессу начальной загрузки, подробно объяснит это.
•NMI: немаскируемое прерывание – это особое исключение, имеющее самый высокий приоритет после сброса. Как и исключение сброса Reset, оно не может быть маскировано (запрещено) и может быть связано с критическими и неотложными действиями. В микроконтроллерах STM32 оно связано с Системой защиты тактирования (Clock Security System, CSS). CSS является периферийным устройством для самодиагностики, обнаруживающим отказ HSE. Если он происходит, HSE автоматически отключается (это означает, что внутренний HSI автоматически включается) и возникает прерывание NMI, чтобы сообщить программному обеспечению, что что-то случилось с HSE. Подробнее об этой функции в Главе 10.
Обработка прерываний |
177 |
•Hard Fault: тяжелый отказ является общим исключением отказа, и, следовательно, связан с программными прерываниями. Когда другие исключения отказов запрещены, он действует как накопитель для всех типов исключений (например, обращение к недопустимой ячейке памяти вызывает исключения тяжелого отказа, если отказ шины (Bus Fault) не разрешен).
•Memory Management Fault1: отказ системы управления памятью происходит при попытке обращения выполняющимся кодом к некорректному адресу или нарушения им правил доступа Модуля защиты памяти (Memory Protection Unit, MPU). Подробнее об этом в Главе 20.
•Bus Fault1: отказ шины происходит, когда интерфейс шины AHB получает ответ об ошибке от ведомой шины (также называемой отказом предввыборки при выборке команд или отказом данных при чтении данных). Также может быть вызван другими некорректными доступами (например, чтение несуществующей ячейки памяти SRAM).
•Usage Fault1: отказ программы происходит, когда есть программная ошибка, такая как выполнение неопределенной инструкции, проблема выравнивания или попытка получить доступ к отсутствующему сопроцессору.
•SVCCall: данное исключение не является условием отказа, оно возникает при вызове инструкции «Вызов системной службы» (Supervisor Call, SVC). Она исполь-
зуется операционными системами реального времени для выполнения инструкций в привилегированном состоянии (задача, требующая выполнения привилегированных операций, выполняет инструкцию SVC, а ОС выполняет запрошенные операции – то же самое поведение у системного вызова в иной ОС).
•Debug Monitor1: исключение монитора отладки возникает, когда происходит событие отладки программного обеспечения при нахождении ядра процессора в режиме мониторной отладки (Monitor Debug-Mode). Оно также используется в качестве исключения для событий отладки, таких как точки останова и наблюдения, когда используется программное решение отладки (software based debug solution).
•PendSV: запрос системной службы – еще одно исключение, связанное с ОСРВ. В отличие от исключения SVCall, которое выполняется сразу после выполнения инструкции SVC, PendSV может быть отложено. Это позволяет ОСРВ выполнять задачи с более высокими приоритетами.
•SysTick: исключение системного таймера также обычно связано с действиями ОСРВ. Каждой ОСРВ необходим таймер, чтобы периодически прерывать выполнение текущего кода и переключаться на другую задачу. Все микроконтроллеры STM32 оснащены таймером SysTick, встроенным в ядро Cortex-M. Несмотря на то что любой другой таймер может использоваться для планирования системных действий, наличие специализированного таймера обеспечивает переносимость среди всех семейств STM32 (из-за причин оптимизации, связанных с внутренней площадкой для монтажа кристалла микроконтроллера, не все таймеры могут быть доступны в качестве внешнего периферийного устройства). Более того, даже если мы не используем ОСРВ в нашей микропрограмме, важно помнить, что CubeHAL от ST использует таймер SysTick для выполнения внутренних действий,
связанных со временем (а это также предполагает, что таймер SysTick сконфигурирован генерировать прерывание каждые 1 мс).
1 Данные исключения не доступны в микроконтроллерах на базе Cortex-M0/0+.
Обработка прерываний |
178 |
Остальные исключения, которые могут быть определены для какого-либо микроконтроллера, связаны с обработкой IRQ. Ядра Cortex-M0/0+ допускают до 32 внешних прерываний, в то время как как ядра Cortex-M3/4/7 позволяют производителям интегральных схем определять до 240 прерываний.
Где можно найти список используемых прерываний для имеющегося микроконтроллера STM32? Техническое описание используемого микроконтроллера, безусловно, является основным источником доступных прерываний. Однако мы можем просто обратиться к таблице векторов, предоставленной ST в ее HAL. Эта таблица определена в startup-файле нашего микроконтроллера – ассемблерном файле, заканчивающимся на
.S, который мы научились импортировать в наш проект Eclipse в Главе 4 (например, для микроконтроллера STM32F030R8 имя файла – startup_stm32f030x8.S). Открыв данный файл, мы можем найти всю таблицу векторов для этого микроконтроллера, начиная примерно со строки 140.
Несмотря на то что таблица векторов содержит адреса процедур-обработчиков, ядру Cortex-M необходим способ найти таблицу векторов в памяти. Как правило, таблица векторов начинается с аппаратного адреса 0x0000 0000 во всех процессорах на базе Cor- tex-M. Если таблица векторов находится во внутренней Flash-памяти (как это обычно и бывает), и поскольку Flash-память во всех микроконтроллерах STM32 отображается с адреса 0x0800 0000, она размещена, начиная с адреса 0x0800 0000, который отражается (aliased) также на 0x0000 0000, когда процессор загружается2.
На рисунке 2 показано, как таблица векторов организована в памяти. Нулевым элементом данного массива является адрес Указателя основного стека (Main Stack Pointer, MSP) внутри SRAM. Обычно этот адрес соответствует конечному в SRAM, то есть базовый адрес SRAM + его размер (подробнее о структуре памяти приложения STM32 в Главе 20). Начиная со второй записи данной таблицы, мы можем найти все исключения и обработчики прерываний. Это означает, что таблица векторов имеет длину, равную 48 для микроконтроллеров на базе Cortex-M0/0+, и длину, равную 256 для Cortex-M3/4/7.
Важно уточнить некоторые моменты о таблице векторов.
1.Имена обработчиков исключений – это просто соглашение, и вы можете свободно переименовать их, если вам нравится другое. Это просто символьные имена, англ. symbols (как у переменных и функций в программе). Однако имейте в виду, что программное обеспечение CubeMX предназначено для генерирования ISR с теми именами, которые определены соглашением ST. Таким образом, вы должны переименовать и имя ISR тоже.
2.Как сказано выше, таблица векторов должна быть размещена в начале Flashпамяти, где процессор ожидает ее нахождение. Это работа компоновщика, который помещает векторную таблицу в начало данных Flash-памяти во время генерации абсолютного файла, являющегося бинарным файлом, который мы загружаем во Flash-память. В Главе 20 мы изучим содержимое файла ldscripts/sections.ld, который содержит директивы, инструктирующие компоновщик GNU LD.
2 Помимо Cortex-M0, остальные ядра Cortex-M позволяют переместить положение таблицы векторов в памяти. Кроме того, можно заставить микроконтроллер загружаться из памяти, отличной от внутренней Flash-памяти. Это сложные темы, которые будут рассмотрены в Главе 20, посвященной организации памяти, и еще одной теме, посвященной процессу начальной загрузки. Чтобы избежать путаницы у неопытных читателей, будет лучше считать положение таблицы векторов фиксированным и связанным с адре-
сом 0x0000 0000.