STM32 как и микроконтроллеры других производителей поддерживает прерывания.
Каждому прерыванию можно назначить приоритет, что позволяет реализовать вложенные прерывания когда при выполнении одного прерывания возникает другое, более приоритетное, которое приостанавливает выполнение кода текущего прерывания с переходом к выполнению более приоритетного. Спецификация ядра ARM Cortex-M в состав которого входит контроллер прерываний NVIC, допускает до 256 приоритетов, но в STM32 в зависимости от версии ядра их гораздо меньше. Например в Cortex-M3 доступны 16 приоритетов, а в Cortex-M0 только 4. Приоритеты нумеруются от 0 и выше. При этом чем больше число тем меньше приоритет, т. е. приоритет 0 самый высокий.
Рассмотрим возможные источники прерываний STM32 Cortex-M0, список которых можно найти в файле startup_stm32f0xx.s.
.long __StackTop /* Top of Stack */
.long Reset_Handler /* Reset Handler */
.long NMI_Handler /* NMI Handler */
.long HardFault_Handler /* Hard Fault Handler */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long SVC_Handler /* SVCall Handler */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long PendSV_Handler /* PendSV Handler */
.long SysTick_Handler /* SysTick Handler */
// External Interrupts
.long WWDG_IRQHandler // Window Watchdog
.long PVD_IRQHandler // PVD through EXTI Line detect
.long RTC_IRQHandler // RTC through EXTI Line
.long FLASH_IRQHandler // FLASH
.long RCC_IRQHandler // RCC
.long EXTI0_1_IRQHandler // EXTI Line 0 and 1
.long EXTI2_3_IRQHandler // EXTI Line 2 and 3
.long EXTI4_15_IRQHandler // EXTI Line 4 to 15
.long TS_IRQHandler // TS
.long DMA1_Channel1_IRQHandler // DMA1 Channel 1
.long DMA1_Channel2_3_IRQHandler // DMA1 Channel 2 and Channel 3
.long DMA1_Channel4_5_IRQHandler // DMA1 Channel 4 and Channel 5
.long ADC1_COMP_IRQHandler // ADC1, COMP1 and COMP2
.long TIM1_BRK_UP_TRG_COM_IRQHandler // TIM1 Break, Update, Trigger and Commutation
.long TIM1_CC_IRQHandler // TIM1 Capture Compare
.long TIM2_IRQHandler // TIM2
.long TIM3_IRQHandler // TIM3
.long TIM6_DAC_IRQHandler // TIM6 and DAC
.long TIM7_IRQHandler // Not all devices!!
.long TIM14_IRQHandler // TIM14
.long TIM15_IRQHandler // TIM15
.long TIM16_IRQHandler // TIM16
.long TIM17_IRQHandler // TIM17
.long I2C1_IRQHandler // I2C1
.long I2C2_IRQHandler // I2C2
.long SPI1_IRQHandler // SPI1
.long SPI2_IRQHandler // SPI2
.long USART1_IRQHandler // USART1
.long USART2_IRQHandler // USART2
.long USART3_4_IRQHandler // Not all devices!!
.long CEC_IRQHandler // CEC
.long USB_IRQHandler // Not all devices!!
.long BootRAM // @0x108. This is for boot in RAM mode for
// STM32F0xx devices.Этот список можно разделить на две части, те что до комментария "External Interrupts" и после него. Первые это прерывания ядра, а вторые периферии.
Рассмотрим работу с прерываниями на примере таймера TIM14, который будет генерировать прерывание по переполнению. А в прерывании будем мигать светодиодом.
Схема тестового устройства.

Код функции настройки таймера TIM14.
void TimConfg(void) // Настройка таймера.
{
TIM_TimeBaseInitTypeDef Tim;
NVIC_InitTypeDef NVIC_I;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE); // Включаем тактирование TIM14.
Tim.TIM_ClockDivision = TIM_CKD_DIV1; // Выключаем предварительный делитель частоты таймера.
Tim.TIM_CounterMode = TIM_CounterMode_Up; // Значение в счетном регистре увеличивается.
Tim.TIM_Prescaler = (SystemCoreClock / 1000) - 1; // Делим так чтобы на таймер шел 1 КГц.
Tim.TIM_Period = 499; // Таймер будет генерирвать событие 2 раза в секунду.
Tim.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM14, &Tim); // Инициализация таймера.
// Настройка прерывания от таймера.
NVIC_I.NVIC_IRQChannel = TIM14_IRQn;
NVIC_I.NVIC_IRQChannelPriority = 3; // Приоритет прерывания (0 - 3. 0 - наивысший, 3 - наименьший).
NVIC_I.NVIC_IRQChannelCmd = ENABLE; // Разрешаем прерывание.
NVIC_Init(&NVIC_I);
TIM_ITConfig(TIM14, TIM_IT_Update, ENABLE); // Разрешаем прерывание таймера по переполнению.
TIM_Cmd(TIM14, ENABLE); // Запуск таймера.
}Сперва подается тактирование на таймер. Без этого он работать не будет. Затем значение предделителя устанавливается таким чтобы после него на таймер шла частота 1 КГц. А после значение периода задается равным 499 чтобы таймер переполнялся 2 раза в секунду.
Затем настраивается прерывание. Его приоритет устанавливается самым низким (3), но в данном проекте это не имеет особого значения т. к. нет других прерываний от периферии. Функция NVIC_Init() применяет параметры прерывания заданные в структуре NVIC_I.
Далее разрешается в качестве источника прерываний переполнение таймера и запускается таймер. На этом настройка таймера и прерываний от него завершена и два раза в секунду будет происходить прерывание от таймера. Его обработчиком является функция TIM14_IRQHandler.
void TIM14_IRQHandler(void) // Обработчик прерывания от таймера.
{
GPIO_TogglePin(GPIOB, GPIO_Pin_1); // Мигаем светодиодом.
TIM_ClearITPendingBit(TIM14, TIM_IT_Update); // Сброс флага прерывания по переполнению таймера.
}Почему у нее именно такое имя? Если взглянуть на список прерываний выше, то можно найти TIM14_IRQHandler, которое и определяет имя обработчика. Если ошибиться в имени функции или вообще забыть написать ее в коде, то вместо нее будет использован обработчик прерывания по умолчанию (его код в файле startup_stm32f0xx.s) в котором зациклится работа программы.
В функции TIM14_IRQHandler() вызывается функция GPIO_TogglePin() инвертирующая состояние вывода PB1, к которому подключен светодиод. После чего вызывается функция TIM_ClearITPendingBit() сбрасывающая флаг прерывания по переполнению таймера. Если этого не сделать, то прерывание считается необработанным и оно будет происходить постоянно, т. е. по факту работа программы зациклится в этом прерывании.