Урок 18. Система прерываний STM32. Организация и управление прерываниями.

Уроки STM32

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

Предыдущий урок     Список уроков     Следующий урок

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

 

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

 

Аппаратные прерывания и события.

Аппаратное прерывание это сигнал, сообщающий о каком-то событии. По его приходу выполнение программы приостанавливается, и управление переходит на функцию обработки прерывания (обработчик прерывания). После отработки функции управление возвращается в прерванный код программы.

С точки зрения программы прерывание это вызов функции по внешнему, не связанному напрямую с программным кодом, событию.

При определении понятия “прерывание” я употребил слово “событие” в общепринятом значении. Т.е. происшествие, нечто случившееся. Но в системе STM32 наряду с прерыванием (interrupt) существует еще одно строгое понятие – аппаратное событие (event).

Событие – это нечто происшедшее с аппаратным узлом микроконтроллера. Например, переполнился таймер, в порт UART пришло данное, на внешнем входе изменился уровень сигнала и т.п.

Аппаратное событие – это то, что вызывает прерывание. Вернее может вызвать прерывание.

  • Без события прерывание невозможно. Именно аппаратное событие инициирует прерывание.
  • События без прерываний могут происходить.

И дело не только в том, что прерывания можно запретить и игнорировать события. В системе STM32 возможно использование событий для управления периферийными устройствами микроконтроллера. Например, прием байта портом UART вызывает событие, которое в свою очередь запускает контроллер прямого доступа к памяти (DMA) для пересылки этого байта в память. Получается, что происходит обработка события без прерывания программы.

 

Контроллер прерываний STM32.

Обработка и управление прерываниями производятся аппаратным узлом микроконтроллера – контроллером приоритетных векторных прерываний (NVIC). При возникновении разрешенного события контроллер прерывает выполнение программы, сохраняет в стеке необходимые данные и передает управление по адресу функции обработки прерывания. После выхода из функции-обработчика управление возвращается на адрес, по которому была прервана основная программа.

С точки зрения программного управления контроллер прерывания не особо сложное устройство. Я бы выделил следующее.

  • Контроллер приоритетный. Т.е. обработка прерывания может быть прервана другим прерыванием с более высоким приоритетом. Прерывания с таким же или более низким приоритетом будут ожидать окончания обработки активного прерывания. Приоритеты можно разбивать на группы и подгруппы.
  • Как следствие предыдущего пункта для каждого прерывания может быть задан приоритет. Это число от 0 до 15. 0 - самый высокий приоритет. Для установки приоритетов существует специальный блок регистров. На каждое прерывание в нем отведен один байт.
  • Могут быть запрещены сразу все прерывания – глобальный запрет.
  • Могут быть запрещены или разрешены отдельные прерывания. Для этого существует регистр разрешения или маски прерываний. Его отдельные биты определяют разрешение для каждого прерывания.
  • Существует блок регистров ожидания обработки прерываний, каждый бит которых соответствует конкретному прерыванию и показывает, ожидает ли оно обработки. Биты регистров могут быть установлены, для принудительного перевода прерываний в состояние ожидания или сброшены для удаления.
  • Есть регистры действующих прерываний, которые показывают, находятся ли прерывания в стадии обработки.
  • Любое прерывание может быть вызвано программно. Для этого существует регистр программного вызова прерываний. Прерывание вызывается записью в него соответствующего номера.
  • Каждому из прерываний соответствует свой фиксированный адрес-вектор, по которому передается управление для обработки прерывания.

Формально обработкой и управлением прерываниями занимается контроллер прерываний. Но для возникновения прерывания необходимо выполнение нескольких условий связанных как с контроллером прерываний, так и с периферийными устройствами микроконтроллера. Поэтому будем рассматривать задачу в комплексе.

 

Программное управление прерываниями STM32.

Для работы с аппаратными прерываниями необходимо:

  • Разрешить нужное прерывание в контроллере прерываний. Если необходимо, то задать для него приоритет.
  • Разрешить глобальные прерывания микроконтроллера.
  • Настроить устройство, в нашем случае таймер, на формирование запроса прерывания – события.
  • Создать функцию обработки прерывания.

 

Разрешение и запрет прерываний.

Для этого существуют функции библиотеки CMSIS.

void NVIC_EnableIRQ(IRQn_Type IRQn) – разрешение прерывания с номером IRQn.

void NVIC_DisableIRQ(IRQn_Type IRQn) – запрет прерывания с номером IRQn.

В файле stm32f103xb.h есть символьные имена, соответствующие номерам прерываний. Они описаны в структуре IRQn_Type. Я ее значительно сократил.

typedef enum {
. . . . . . . . . . . . . . . . . . . . . . . .
TIM1_BRK_IRQn               = 24,     /*!< TIM1 Break Interrupt */
TIM1_UP_IRQn                = 25,     /*!< TIM1 Update Interrupt */
TIM1_TRG_COM_IRQn           = 26,     /*!< TIM1 Trigger and Commutation Interrupt */
TIM1_CC_IRQn                = 27,     /*!< TIM1 Capture Compare Interrupt */
TIM2_IRQn                   = 28,     /*!< TIM2 global Interrupt */
TIM3_IRQn                   = 29,     /*!< TIM3 global Interrupt */
TIM4_IRQn                   = 30,     /*!< TIM4 global Interrupt */
} IRQn_Type;

Команда разрешения прерывания перезагрузки таймера TIM1 будет выглядеть так.

NVIC_EnableIRQ(TIM1_UP_IRQn);

 

Установка приоритетов прерываний.

По состоянию сброса для всех прерываний устанавливается самый высокий приоритет (0). Для его изменения существует функция библиотеки CMSIS.

void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)

  • IRQn – номер прерывания , можно в символьном виде типа IRQn_Type;
  • priority – приоритет (0 … 15), 0 – наивысший.

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

NVIC_SetPriority(TIM1_UP_IRQn, 15);

 

Глобальные разрешение и запрет прерываний.

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

__disable_irq (); // запретить прерывания

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

__enable_irq ();  // разрешить прерывания

 

Настройка устройства на формирование события и прерывания.

Это действие касается настройки конкретного периферийного устройства и индивидуально для каждого из них. Будем рассматривать для каждого устройства отдельно. В следующем уроке настроим таймер.

 

Функции обработки прерываний STM32.

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

В микроконтроллерах STM32 поддерживается до 68 аппаратных прерываний. Каждому из них соответствует свой адрес – вектор. По этому адресу передается управление программы при возникновении прерывания.

Конкретные адреса для каждого источника можно посмотреть в документации на микроконтроллер. Выглядит это примерно так.

Вектора прерываний

Из таблицы видно, что наш таймер TIM1 при перезагрузке формирует прерывания по адресу 00A4.

В файле startup\startup_stm32f103xb.s таблица векторов преобразуется в символьные имена функций обработки прерываний.

.word TIM1_BRK_IRQHandler
.word TIM1_UP_IRQHandler
.word TIM1_TRG_COM_IRQHandler
.word TIM1_CC_IRQHandler
.word TIM2_IRQHandler
.word TIM3_IRQHandler
.word TIM4_IRQHandler

Для нашего таймера это TIM1_UP_IRQHandler.

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

void TIM1_UP_IRQHandler(void) {

    // код обработки прерывания

    // код или функция завершения прерывания

}

В начале файла c/cpp или h надо объявить функцию, разместить прототип.

void TIM1_UP_IRQHandler(void);

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

Иначе может произойти следующее. Устройство сформировало событие. Как следствие стал активным флаг прерывания. Произошло, и было обработано прерывание. Программа вернулась к месту, на котором была прервана. А флаг прерывания остался активным. Произойдет новое прерывание, вызванное ошибкой алгоритма. Перед возвратом надо сбросить флаг. Об этом подробно в следующем уроке.

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

 

В следующем уроке будем настраивать таймеры.

 

Предыдущий урок     Список уроков     Следующий урок

1

Автор публикации

не в сети 2 дня

Эдуард

280
Комментарии: 1936Публикации: 197Регистрация: 13-12-2015

12 комментариев на «Урок 18. Система прерываний STM32. Организация и управление прерываниями.»

  1. Здравствуйте!
    Глобальный запрет прерываний действует на следующие прерывания?
    Non maskable interrupt; Hard fault interrupt; Memory management;
    Prefetch fault, memory access fault; Undefined instruction or illegal state; System service call via SWI instruction; Debug monitor; Pendable request for system service; Time base: System tick timer

    0
  2. привет всем. Подскажите, пожалуйста, сделал проект в True Studio. Без startup. Сейчас он понадобился. Как подключить его в проект, если он уже создан? Раньше вроде находил эту настройку, а сейчас не пойму как. Подскажите. Вообще мне нужно написать обработчик внешнего прерывания. В startup вроде есть готовые имена функций. А можно ли как-нибудь без startup-а обойтись? Как имя функции привязать к прерыванию?

    0
  3. «В файле startup\startup_stm32f103xb.s» — что это за файл и как он где-то подключается?

    «В начале файла c/cpp или h надо объявить функцию, разместить прототип.

    void TIM1_UP_IRQHandler(void);»

    — а почему STM32CubeMX не вписал сам? Файл прерывания создал, там функцию нарисовал, а не объявил её в main.c?

    0
  4. Вы показали часть таблицы векторов прерываний и далее поясняете приоритеты прерываний (0…15). В тоже время в таблице векторов прерываний во второй колонке указаны приоритеты устройств. Как соотносятся приоритеты в таблице с приоритетами прерываний (0…15)?

    1
    • Здравствуйте!
      В первом столбце (Position) указаны позиции битов разрешения прерываний в регистрах NVIC_ICERx. Я использовал для разрешения прерываний функцию NVIC_EnableIRQ, а не прямое обращение к регистрам.
      Во втором столбце (Priority) задан приоритет прерывания после сброса. Он может быть изменен, о чем говорит третий столбец (settable).

      0
  5. Добрый день, Эдуард! Прочитал в мануале PM0214 следующее:
    «Each priority field holds a priority value, 0-255. The lower the
    value, the greater the priority of the corresponding interrupt. The
    processor implements only bits[7:4] of each field, bits[3:0] read
    as zero and ignore writes.»
    Не совсем понял как это работает. Зачем тогда вообще задаются уровни приоритета 16 — 255? Зачем существуют биты [3:0]?
    Правильно ли я понял, что приоритет прерывания «EXTI Line[9:5] Interrupt», обозначенный в таблице как «30» (0001 1110) процессор воспринимает как «1» (0001), отбрасывая биты [3:0] (1110)?

    0
    • Здравствуйте!
      Очевидно такой формат выбран для совместимости с другими микроконтроллерами семейства STM32.

      0
  6. Здравствуйте. А чем разница между записью в регитстр ожидания обработки прерываний и записью в регистр программного вызова прерываний?

    0
    • Здравствуйте!
      Скорее всего, эффект будет одинаковым. Разработчики STM32 во втором случае реализовали установку события по тому же пути, что и аппаратный сигнал, вызывающий реальное прерывание.

      0

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Нажимая кнопку "Отправить" Вы даёте свое согласие на обработку введенной персональной информации в соответствии с Федеральным Законом №152-ФЗ от 27.07.2006 "О персональных данных".