Cortex-M bir MCU'da HardFault aldınız. Sorunun nedenini nasıl bulursunuz?
Cevap
Strateji şudur: Fault anında donanımın stack'e kaydettiği register'ları (özellikle PC ve LR) ve fault status register'larını okuyup hatayı oluşturan talimata ulaşmak. Aşağıdaki bilgiler Cortex-M3/M4/M7 içindir; M0/M0+'da fault status register'ları yoktur.
1. Stack frame'i yakalamak
Exception girişinde donanım R0-R3, R12, LR, PC, xPSR değerlerini aktif stack'e yazar. LR içindeki EXC_RETURN değerinin 2. biti, MSP mi PSP mi kullanıldığını gösterir (RTOS task'larında PSP kullanılır).
__attribute__((naked)) void HardFault_Handler(void)
{
__asm volatile(
"tst lr, #4 \n"
"ite eq \n"
"mrseq r0, msp \n"
"mrsne r0, psp \n"
"b hardfault_c \n");
}
void hardfault_c(uint32_t *sf)
{
volatile uint32_t r0 = sf[0];
volatile uint32_t lr = sf[5];
volatile uint32_t pc = sf[6]; /* hatayı yapan talimat (precise fault ise) */
volatile uint32_t cfsr = SCB->CFSR;
volatile uint32_t hfsr = SCB->HFSR;
volatile uint32_t mmfar = SCB->MMFAR;
volatile uint32_t bfar = SCB->BFAR;
(void)r0; (void)lr; (void)pc; (void)cfsr; (void)hfsr; (void)mmfar; (void)bfar;
__BKPT(0);
for (;;) { }
}arm-none-eabi-addr2line -e firmware.elf -f -C 0x08001A3C2. Register'ları yorumlamak
- HFSR.FORCED: Asıl hata Bus, Mem veya Usage fault'tur ve bu handler'lar kapalı olduğu için HardFault'a yükseltilmiştir. Ayrıntıya CFSR'de bakılır.
- CFSR (0xE000ED28) = MMFSR + BFSR + UFSR:
PRECISERR+BFARVALID: Geçersiz adrese erişim; adres BFAR'da (NULL pointer, kapalı saatli çevre birimi).IMPRECISERR: Yazma tamponu nedeniyle PC tam doğru değildir. Debug için yazma tamponu kapatılabilir (M3/M4'teACTLR.DISDEFWBUF).UNDEFINSTR/INVSTATE: Bozuk fonksiyon pointer'ı veya Thumb biti sıfır olan bir adrese atlama.UNALIGNED,DIVBYZERO: İlgili trap bitleri (CCR) açıksa oluşur.STKERR/MSTKERR: Stacking sırasında hata; büyük olasılıkla stack overflow.
3. Sık kök nedenler
- Stack overflow (RTOS task'ında küçük stack, büyük yerel dizi)
- NULL veya serbest bırakılmış pointer, dizi taşması
- Saatini açmadığınız çevre birimine erişim
- Hatalı kesme önceliği yüzünden bozulan RTOS veri yapıları
- Yanlış cast ile hizalanmamış
LDRD/LDMerişimi
4. Sahada (debugger yokken)
Fault bilgilerini noinit RAM bölümüne veya Flash'a yazıp reset atın, bir sonraki açılışta raporlayın. Memfault gibi araçlar bu coredump yaklaşımını hazır sunar.
İlgili Mikrodenetleyiciler soruları
- Kesme (interrupt) nedir? ISR yazarken nelere dikkat edilir?
- Watchdog timer nedir, ne işe yarar?
- Bir bootloader nasıl çalışır? Uygulamaya atlama ve güvenli firmware güncellemesi nasıl tasarlanır?
- Mekanik bir butonun debounce işlemi neden gereklidir ve yazılımda nasıl yapılır?
- DMA nedir, ne zaman kullanılır? DMA kullanırken cache coherency ve double buffering gibi konularda nelere dikkat edilmelidir?
- ADC çözünürlüğü, referans voltajı ve örnekleme hızı nedir? ADC okumasında doğruluğu etkileyen faktörler nelerdir?
Bu konuda başka bir soru biliyor musun?
Mülakatta karşılaştığın soruları ekle, onaylandıktan sonra yayına alınsın.