
- •Оглавление
- •Предисловие
- •Почему я написал книгу?
- •Для кого эта книга?
- •Как использовать эту книгу?
- •Как организована книга?
- •Об авторе
- •Ошибки и предложения
- •Поддержка книги
- •Как помочь автору
- •Отказ от авторского права
- •Благодарность за участие
- •Перевод
- •Благодарности
- •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
Управление DMA |
240 |
Мы остановились на еще одной вещи на рисунке 2: стрелка запросы к DMA, которая идет от модуля периферийных устройств (белый прямоугольник) к контроллеру DMA1. Что они делают? В Главе 7 мы увидели, что контроллер NVIC уведомляет ядро Cortex-M об асинхронных запросах прерываний (interrupt requests, IRQs), поступающих от периферийных устройств. Когда периферийное устройство готово что-то сделать (например, UART готов к приему данных или переполнен таймер), оно уведомляет соответствующую ему линию запроса прерывания IRQ. Ядро выполняет за заданное количество тактовых циклов соответствующую ISR, которая содержит код, необходимый для обработки IRQ. Не забывайте, что периферийные устройства являются ведомыми устройствами: они не могут получить доступ к шине независимо. Чтобы начать транзакцию, всегда необходимо ведущее устройство. Однако поскольку периферийные устройства являются ведомыми устройствами, если мы используем контроллер DMA для передачи данных из периферийных устройств в память, у нас должен быть способ уведомить его о том, что периферийные устройства готовы к обмену данными. По этой причине доступно выделенное количество линий запросов от периферийных устройств к контроллеру DMA. В следующем параграфе мы увидим, как они организованы и как мы можем их запрограммировать.
9.1.2. Контроллер DMA
В каждом микроконтроллере STM32 контроллер DMA представляет собой аппаратный модуль, который:
•имеет два ведущих порта, называемых, соответственно, периферийным портом и портом памяти, которые подключены к продвинутой высокопроизводительной шине (AHB), один может подключаться к ведомому периферийному устройству, а другой – к контроллеру памяти (SRAM, Flash-память, FSMC и т. д.); в некоторых контроллерах DMA периферийный порт также может взаимодействовать с контроллером памяти, что позволяет передавать данные из памяти в память
(memory-to-memory);
•имеет один ведомый порт, подключенный к шине AHB и используемый для программирования контроллера DMA от другого ведущего устройства, то есть ЦПУ;
•имеет несколько независимых и программируемых каналов (источников запросов), каждый из которых подключается к используемой периферийной линии запроса (UART_TX, TIM_UP и т. д. – количество и тип запросов для канала устанавливаются во время проектирования микроконтроллера);
•позволяет назначать разные приоритеты каналам для того, чтобы разрешать конфликты доступа к памяти, отдавая более высокий приоритет более быстрым и важным периферийным устройствам;
•позволяет передавать данные в обоих направлениях, то есть из памяти в периферию
(memory-to-peripheral) и из периферии в память (peripheral-to-memory).
Каждый микроконтроллер STM32 предоставляет различное количество контроллеров DMA и каналов в соответствии со своим семейством и видом поставки (sale type). В таблице 1 приведено их точное количество для микроконтроллеров STM32, оснащающих все платы Nucleo.

Управление DMA |
241 |
Таблица 1: Количество контроллеров DMA/каналов, доступных в каждой плате Nucleo
Данные характеристики являются общими для всех микроконтроллеров STM32. Однако семейства STM32F2/F4/F7 предоставляют более совершенный контроллер DMA в сочетании с многоуровневой шинной матрицей, которая позволяет ускорять и распараллеливать передачи через DMA. По этой причине мы собираемся рассматривать их отдельно6.
9.1.2.1.Реализация DMA в микроконтроллерах F0/F1/F3/L1
На рисунке 3 показано представление DMA в микроконтроллерах серий F0/F1/F3/L1. Здесь для простоты показана только одна линия запроса, но каждый DMA реализует линию запроса для каждого канала. Каждая линия запроса имеет переменное количество источников запросов периферии, подключенной к ней. Во время разработки чипа канал привязывается к неизменному набору периферийных устройств. Однако на одном канале одновременно может быть активно только одно периферийное устройство. Например, в таблице 27 показано, как каналы связаны с периферийными устройствами в микроконтроллере STM32F030. Каждая линия запроса также может быть сработана «программно». Эта способность используется для передач типа память-в-память.
Каждый канал имеет конфигурируемый приоритет, позволяющий управлять доступом к шине AHB. Внутренний арбитр управляет запросами, поступающими от каналов, в соответствии с конфигурируемым пользователем приоритетом. Если две линии запроса активируют запрос и их каналы имеют одинаковый приоритет, то канал с меньшим номером выигрывает конфликт.
6Однако имейте в виду, что данная книга не является исчерпывающим источником сведений об аппаратном обеспечении каждого семейства STM32. Всегда держите под рукой справочное руководство по микроконтроллеру, который вы рассматриваете, и внимательно изучите главу, посвященную DMA.
7Таблица взята из справочного руководства RM0360 от ST
(http://www.st.com/web/en/resource/technical/document/reference_manual/DM00091010.pdf)

Управление DMA |
242 |
Рисунок 3: Представление структуры DMA (другие линии запроса опущены)
В зависимости от используемого вида поставки доступен один или два контроллера DMA, всего 12 независимых каналов (5 для DMA1 и 7 для DMA2). Например, как показано в таблице 2, STM32F030 предоставляет только DMA1 с 5 каналами.
Таблица 2: Как каналы связаны с периферийными устройствами в микроконтроллере STM32F030

Управление DMA |
243 |
На рисунке 2 мы уже видели архитектуру шин STM32F030. Для полноты картины на рисунке 48 показана архитектура шин более производительного микроконтроллера с той же реализацией DMA (например, STM32F1). Как видите, два семейства имеют совершенно разную организацию внутренних шин.
Вы можете увидеть две дополнительные шины с именами ICode и DCode. В чем их разница?
Большинство микроконтроллеров STM32 имеют одинаковую компьютерную архитектуру, за исключением STM32F0 и STM32L0, спроектированных на базе ядер CortexM0/0+. По сути, они являются единственными ядрами Cortex-M, основанными на фонНеймановской архитектуре, по сравнению с другими ядрами Cortex-M, основанными на Гарвардской архитектуре9. Принципиальное различие между этими двумя архитектурами заключается в том, что ядра Cortex-M0/0+ получают доступ к Flash-памяти, SRAM и периферийным устройствам по одной общей шине, в то время как другие ядра Cortex- M имеют две отдельные линии шин для доступа к Flash-памяти (одна для выборки команд, называемая шиной команд (instruction bus), или просто I-Bus или даже I-Code, и одна для доступа к константам, называемая шиной данных (data bus), или просто D-Bus или даже D-Code) и одну выделенную линию запроса для доступа к SRAM и периферийным устройствам (также называемую системной шиной (system bus) или просто S-Bus). Какие преимущества это дает нашим приложениям?
Рисунок 4: Архитектура шин в микроконтроллере STM32F1 от линейки Connectivity Line
8 Рисунок взят из справочного руководства RM0008 от ST (http://www.st.com/web/en/resource/technical/document/reference_manual/CD00171190.pdf)
9 Для полноты картины мы должны сказать, что они основаны на модифицированной Гарвардской архитек-
туре (https://en.wikipedia.org/wiki/Modified_Harvard_architecture), но давайте оставим различие историкам информатики (computer science).

Управление DMA |
244 |
В ядрах Cortex-M0/0+ контроллер DMA и ядро Cortex соперничают за доступ к памяти и периферийным устройствам через шинную матрицу. Предположим, что ЦПУ выполняет математические операции над данными, содержащимися в его внутренних регистрах (R0-R14). Если контроллер DMA передает данные в SRAM, шинная матрица разрешает доступ от ядра Cortex-M0/0+ к Flash-памяти для загрузки следующей инструкции для выполнения. Поэтому данное ядро «стопорится» в ожидании своей очереди (подробнее об этом чуть позже). В других ядрах Cortex-M процессор может получать доступ к Flash-памяти независимо, что повышает общую производительность. Это принципиальное отличие, оправдывающее цену микроконтроллеров STM32F0: они не только могут иметь меньше SRAM и Flash-памяти и работать на более низких частотах, но и имеют более простую и менее производительную архитектуру.
Однако важно отметить, что шинная матрица реализует алгоритмы планирования (scheduling policies), избегающие слишком долгого «застопоривания» определенного ведущего устройства (ЦПУ и DMA в микроконтроллерах линеек Value Line, или ЦПУ, DMA, Ethernet и USB в микроконтроллерах линеек Connectivity Line). Каждая передача через DMA состоит из четырех фаз: выборка и фаза арбитража, фаза вычисления адреса, фаза доступа к шине и фаза окончательного подтверждения (которая используется, чтобы сигнализировать о том, что передача была завершена). Каждая фаза занимает один тактовый цикл, за исключением фазы доступа к шине, которая может длиться большее количество тактовых циклов. Однако ее максимальная продолжительность фиксирована, и шинная матрица гарантирует, что в конце фазы подтверждения будет назначено другое ведущее устройство для доступа к шине. Как мы увидим в следующем параграфе, семейства STM32F2/F4/F7 допускают более продвинутый параллелизм при доступе к ведомым устройствам. Однако подробности этих аспектов выходят за рамки данной книги. Настоятельно рекомендуется взглянуть на AN403110 от ST, чтобы лучше понять их.
Наконец, DMA также может выполнять передачи данных типа периферия-в-периферию (peripheral-to-peripheral) при определенных условиях, как мы увидим далее.
9.1.2.2.Реализация DMA в микроконтроллерах F2/F4/F7
В микроконтроллерах STM32F2/F4/F7 реализован более совершенный контроллер DMA, как показано на рисунке 5. Он предлагает более высокую степень гибкости по сравнению с контроллером DMA, рассмотренным в других микроконтроллерах STM32. Каждый контроллер DMA реализует 8 разных потоков. Каждый поток предназначен для управления запросами на доступ к памяти с одного или нескольких периферийных устройств. Каждый поток может иметь до 8 каналов (запросов) в общей сложности (но имейте в виду, что только один канал/запрос может быть активным одновременно в потоке), и они имеют арбитра для обработки приоритета между запросами к DMA. Кроме того, каждый поток может по выбору предоставлять (является вариантом конфигурации) 32-разрядный буфер памяти логики «первым пришёл/первым ушёл» (first- in/first-out, FIFO) глубиной в четыре слова. FIFO используется для временного хранения данных, поступающих из источника, до его передачи в пункт назначения. Каждый поток также может быть запущен «программно». Данная возможность используется для выполнения передач типа память-в-память, но она ограничена только контроллером DMA2, как обозначено в таблице 1.
10 http://www.st.com/web/en/resource/technical/document/application_note/DM00046011.pdf

Управление DMA |
245 |
Рисунок 5: Архитектура DMA в микроконтроллере STM32F2/F4/F7
Каждый микроконтроллер STM32F2/F4/F7 имеет два контроллера DMA, что в сумме дает 16 независимых потоков. Как и в других микроконтроллерах STM32, канал связан с фиксированным набором периферийных устройств на этапе проектирования микросхемы. Таблица 3 показывает отображение запросов потоков/каналов DMA1 в микроконтроллере STM32F401RE. Микроконтроллеры STM32F2/F4/F7 включают в себя архитектуру с несколькими ведущими и несколькими ведомыми шинами, состоящую из:
•8 ведущих шин:
–Шина ядра Cortex I-bus
–Шина ядра Cortex D-bus
–Шина ядра Cortex S-bus
–Шина DMA1 к памяти
–Шина DMA2 к памяти
–Шина DMA2 к периферии
–Шина DMA к устройству Ethernet (если доступна)
–Шина DMA к устройству USB high-speed (если доступна)
•8 ведомых шин:
–Шина внутренней Flash-памяти I-Code
–Шина внутренней Flash-памяти D-Code
–Шина основного внутреннего SRAM1
–Шина вспомогательного внутреннего SRAM2 (если доступна)

Управление DMA |
246 |
–Шина вспомогательного внутреннего SRAM3 (если доступна)
–Шина AHB1 периферии, включая мосты AHB-APB и шину APB периферии
–Шина AHB2 периферии
–Шина AHB3 периферийного устройства FMC (если доступна)
Таблица 3: Отображение запросов потоков/каналов к DMA1 в микроконтроллере STM32F401RE
Ведущие и ведомые устройства соединены между собой через многоуровневую шинную матрицу, обеспечивающую одновременный доступ от отдельных ведущих устройств, а также эффективную работу, даже когда несколько высокоскоростных периферийных устройств работают одновременно. Эта архитектура показана на рисунке 611
в случае линеек STM32F405/415 и STM32F407/417.
Многоуровневая шинная матрица позволяет разным ведущим устройствам одновременно выполнять передачу данных, если они обращаются к разным ведомым модулям (но для данного DMA только один поток одновременно может иметь доступ к шине). Помимо Гарвардской архитектуры Cortex-M и двух AHB-портов DMA, эта структура повышает параллелизм передачи данных, тем самым способствуя сокращению времени выполнения и оптимизации эффективности DMA и энергопотребления.
11 Рисунок взят из руководства по применению AN4031 от ST (http://www.st.com/web/en/resource/technical/document/application_note/DM00046011.pdf)

Управление DMA |
247 |
Рисунок 6: Многоуровневая шинная матрица в микроконтроллере STM32F405
9.1.2.3.Реализация DMA в микроконтроллерах L0/L4
Реализация DMA в микроконтроллерах STM32L0/L4 имеет гибридный подход между реализацией DMA, заложенной в микроконтроллерах F0/F1/F3/L1 и F2/F4/F7. Фактически, она обеспечивает многопотоковый/многоканальный подход, но без поддержки внутренних буферов FIFO для каждого потока.
ST приняла другую номенклатуру (терминологию) для обозначения потоков и каналов в этих контроллерах DMA. Здесь потоки называются каналами, а каналы называются запросами (вероятно, эта номенклатурная схема более четкая, чем у потока/канала, используемого в микроконтроллерах F2/F4/F7). В таблице 412 показано отображение каналов/запросов в микроконтроллере STM32L053. Данная номенклатура влияет и на HAL, как мы увидим далее.
12 Таблица взята из справочного руководства RM0367 от ST (http://www.st.com/web/en/resource/technical/document/reference_manual/DM00095744.pdf)