⚡ hal::int
Nested Vectored Interrupt Controller (NVIC)
366 satır
~8 fonksiyon
NVIC
📖 Genel Bakış
Interrupt controller, asenkron olayları işler. GPIO, Timer, USART gibi çevre birimlerinin interrupt'larını yönetir.
🔑 Temel Özellikler
- Priority levels (0-15)
- Preemption & sub-priority
- Enable/Disable interrupts
- Pending flag management
- Nested interrupt support
🚀 Hızlı Başlangıç
içe_aktar hal::int
// Enable interrupt
int.enable(int.IRQ_TIM2)
// Set priority
int.set_priority(int.IRQ_TIM2, yap
preempt: 2, // Preemption priority
sub: 0 // Sub priority
son)
// Disable interrupt
int.disable(int.IRQ_TIM2)
// Global interrupt enable/disable
int.global_enable()
int.global_disable()
⚙️ Priority Groups
// Configure priority grouping
int.set_priority_grouping(int.PRIORITY_GROUP_4)
// Groups:
// GROUP_0: 0 bits preemption, 4 bits sub (16 sub-priorities)
// GROUP_4: 4 bits preemption, 0 bits sub (16 preemption levels)
💡 Örnek: Nested Interrupts (Priority Preemption)
içe_aktar hal::int, hal::timer, hal::gpio
değişken high_priority_count = 0
değişken low_priority_count = 0
fonksiyon high_priority_isr() yap
// High priority interrupt (timer)
high_priority_count += 1
io.println("HIGH priority ISR (count: {})", high_priority_count)
// Simulate work
core.delay_ms(50)
son
fonksiyon low_priority_isr() yap
// Low priority interrupt (button)
low_priority_count += 1
io.println(" LOW priority ISR (count: {})", low_priority_count)
// Simulate work
core.delay_ms(100)
son
fonksiyon nested_interrupt_demo() yap
// Set priority grouping (4 bits preemption, 0 bits sub)
int.set_priority_grouping(int.PRIORITY_GROUP_4)
// Configure Timer2 interrupt (high priority)
timer.init(timer.TIM2, yap
frequency: 10, // 10Hz
callback: high_priority_isr
son)
int.set_priority(int.IRQ_TIM2, yap
preempt: 0, // Highest priority
sub: 0
son)
int.enable(int.IRQ_TIM2)
// Configure GPIO interrupt (low priority)
gpio.pin_init(gpio.PORT_A, 0, yap
mode: gpio.MODE_INPUT,
interrupt: gpio.INT_RISING,
callback: low_priority_isr
son)
int.set_priority(int.IRQ_EXTI0, yap
preempt: 5, // Lower priority
sub: 0
son)
int.enable(int.IRQ_EXTI0)
io.println("Nested interrupt demo")
io.println("Timer interrupt can preempt button interrupt")
timer.start(timer.TIM2)
döngü yap
core.delay_ms(1000)
son
son
fonksiyon ana() yap
nested_interrupt_demo()
son
💡 Örnek: External Interrupts (EXTI)
içe_aktar hal::int, hal::gpio
değişken button1_pressed = 0
değişken button2_pressed = 0
fonksiyon button1_callback() yap
button1_pressed += 1
io.println("Button 1 pressed (total: {})", button1_pressed)
son
fonksiyon button2_callback() yap
button2_pressed += 1
io.println("Button 2 pressed (total: {})", button2_pressed)
son
fonksiyon multi_button_exti() yap
// Button 1 on PA0 (EXTI0)
gpio.clock_enable(gpio.PORT_A)
gpio.pin_init(gpio.PORT_A, 0, yap
mode: gpio.MODE_INPUT,
pull: gpio.PULL_DOWN,
interrupt: gpio.INT_RISING
son)
gpio.set_callback(gpio.PORT_A, 0, button1_callback)
int.set_priority(int.IRQ_EXTI0, yap preempt: 5, sub: 0 son)
int.enable(int.IRQ_EXTI0)
// Button 2 on PB1 (EXTI1)
gpio.clock_enable(gpio.PORT_B)
gpio.pin_init(gpio.PORT_B, 1, yap
mode: gpio.MODE_INPUT,
pull: gpio.PULL_DOWN,
interrupt: gpio.INT_RISING
son)
gpio.set_callback(gpio.PORT_B, 1, button2_callback)
int.set_priority(int.IRQ_EXTI1, yap preempt: 5, sub: 0 son)
int.enable(int.IRQ_EXTI1)
io.println("EXTI demo: Press buttons")
döngü yap
core.delay_ms(100)
son
son
fonksiyon ana() yap
multi_button_exti()
son
💡 Örnek: Interrupt Latency Measurement
içe_aktar hal::int, hal::timer, hal::gpio
değişken interrupt_timestamp = 0
değişken latency_us = 0
fonksiyon fast_isr() yap
// Measure interrupt latency
değişken now = core.uptime_us()
latency_us = now - interrupt_timestamp
// Toggle LED as visual indicator
gpio.pin_toggle(gpio.PORT_C, 13)
son
fonksiyon latency_test() yap
// Configure GPIO interrupt on PA0
gpio.pin_init(gpio.PORT_A, 0, yap
mode: gpio.MODE_INPUT,
interrupt: gpio.INT_RISING,
callback: fast_isr
son)
// Set highest priority
int.set_priority_grouping(int.PRIORITY_GROUP_4)
int.set_priority(int.IRQ_EXTI0, yap preempt: 0, sub: 0 son)
int.enable(int.IRQ_EXTI0)
// LED output
gpio.pin_init(gpio.PORT_C, 13, yap mode: gpio.MODE_OUTPUT son)
io.println("Interrupt latency test")
io.println("Trigger PA0 rising edge")
döngü yap
// Wait for interrupt
eğer latency_us > 0 ise yap
io.println("Interrupt latency: {}μs", latency_us)
latency_us = 0
son
core.delay_ms(100)
son
son
fonksiyon ana() yap
latency_test()
son
💡 Örnek: Software Interrupt Trigger
içe_aktar hal::int
değişken software_int_count = 0
fonksiyon software_isr() yap
software_int_count += 1
io.println("Software interrupt triggered! ({})", software_int_count)
son
fonksiyon software_interrupt_demo() yap
// Configure software interrupt
int.set_callback(int.IRQ_PendSV, software_isr)
int.set_priority(int.IRQ_PendSV, yap preempt: 15, sub: 0 son)
int.enable(int.IRQ_PendSV)
io.println("Software interrupt demo")
döngü yap
io.println("Triggering software interrupt...")
// Trigger PendSV interrupt manually
int.set_pending(int.IRQ_PendSV)
core.delay_ms(2000)
son
son
fonksiyon ana() yap
software_interrupt_demo()
son
💡 Örnek: Critical Section (Interrupt Disable)
içe_aktar hal::int
değişken shared_counter = 0
fonksiyon critical_section_demo() yap
// Unsafe increment (race condition possible)
fonksiyon unsafe_increment() yap
değişken temp = shared_counter
core.delay_us(10) // Simulate work
shared_counter = temp + 1
son
// Safe increment (atomic with interrupts disabled)
fonksiyon safe_increment() yap
// Enter critical section
int.global_disable()
değişken temp = shared_counter
core.delay_us(10)
shared_counter = temp + 1
// Exit critical section
int.global_enable()
son
// Better: use RAII-style guard
fonksiyon best_increment() yap
değişken guard = int.critical_section() // Auto disable
değişken temp = shared_counter
core.delay_us(10)
shared_counter = temp + 1
// Auto enable on scope exit
son
// Test
her i içinde 0..1000 için yap
safe_increment()
son
io.println("Counter: {}", shared_counter) // Should be 1000
son
fonksiyon ana() yap
critical_section_demo()
son
⚙️ NVIC Yapılandırma
// Priority Configuration
yapı PriorityConfig yap
preempt: sayı, // Preemption priority (0-15)
sub: sayı // Sub-priority (0-15)
son
// Priority Grouping
enum PriorityGroup {
PRIORITY_GROUP_0, // 0:4 (0 preemption, 16 sub)
PRIORITY_GROUP_1, // 1:3 (2 preemption, 8 sub)
PRIORITY_GROUP_2, // 2:2 (4 preemption, 4 sub)
PRIORITY_GROUP_3, // 3:1 (8 preemption, 2 sub)
PRIORITY_GROUP_4 // 4:0 (16 preemption, 0 sub)
}
// Common IRQ Numbers (STM32F4)
enum IRQ {
IRQ_WWDG = 0, // Window watchdog
IRQ_EXTI0 = 6, // External line 0
IRQ_EXTI1 = 7, // External line 1
IRQ_DMA1_STREAM0 = 11, // DMA1 stream 0
IRQ_TIM2 = 28, // Timer 2
IRQ_USART1 = 37, // USART1
IRQ_EXTI15_10 = 40, // External lines 10-15
IRQ_SPI1 = 35, // SPI1
IRQ_PendSV = -2, // Pendable request
IRQ_SysTick = -1 // System tick
}
📚 NVIC Fonksiyonları
// Interrupt control
fonksiyon enable(irq: IRQ)
fonksiyon disable(irq: IRQ)
fonksiyon is_enabled(irq: IRQ) -> bool
// Priority management
fonksiyon set_priority(irq: IRQ, config: PriorityConfig)
fonksiyon get_priority(irq: IRQ) -> PriorityConfig
fonksiyon set_priority_grouping(group: PriorityGroup)
// Pending flags
fonksiyon set_pending(irq: IRQ) // Software trigger
fonksiyon clear_pending(irq: IRQ)
fonksiyon is_pending(irq: IRQ) -> bool
// Global control
fonksiyon global_enable() // Enable all interrupts
fonksiyon global_disable() // Disable all interrupts
fonksiyon critical_section() -> Guard // RAII-style
// Callback registration
fonksiyon set_callback(irq: IRQ, callback: fn())
📊 Priority Level Önerileri
| Priority | Use Case | Örnek |
|---|---|---|
| 0-2 (Highest) | Time-critical, real-time | Motor encoder, high-speed ADC |
| 3-7 (High) | Fast peripherals | USART, SPI, I2C, timers |
| 8-11 (Medium) | Normal peripherals | GPIO, ADC, RTC alarms |
| 12-15 (Low) | Background tasks | Software interrupts, low-priority IO |
⚡ İyi Pratikler
- ISR Short: Interrupt handler'ları kısa tutun (<10μs ideal)
- Defer Work: Ağır işlemi main loop'a erteyin (flag set)
- Volatile: ISR'den okunan değişkenler volatile olmalı
- Priority Planning: Time-critical işler yüksek priority
- Nesting: GROUP_4 kullanın (16 preemption level)
- Critical Sections: Shared data erişiminde disable interrupts
⚠️ Önemli Notlar
- Priority Number: Lower number = Higher priority (0 en yüksek)
- Preemption: Farklı preemption priority → nesting mümkün
- Sub-priority: Aynı preemption'da hangisinin önce işleneceğini belirler
- ISR Latency: Tipik 10-20 cycle (~12 cycle push/pop registers)
- Tail-Chaining: Back-to-back interrupt'larda push/pop skip (6 cycle saved)
- BASEPRI: Belirli priority altındaki interrupt'ları maske etme
- Fault Handlers: HardFault, MemManage, BusFault (priority -1, -2, -3)
- Systick: Tipik priority 15 (en düşük, timing-critical değil)
🔗 İlgili Modüller
hal::gpio- EXTI external interruptshal::timer- Timer interrupts (overflow, capture)hal::usart- USART TX/RX interruptshal::dma- DMA transfer complete interruptshal::rtc- RTC alarm interruptshal::core- Sleep mode wakeup
📖 Referanslar
- AN4044: Using STM32 Interrupts
- ARM CMSIS Documentation: NVIC
- Cortex-M Programming Manual: Nested Vectored Interrupt Controller