Bug dalam kompiler ARM Keil dengan interrupt handler dan C ++?

8

Saya memiliki masalah dengan penulisan interrupt handler di kompiler ARM Keil untuk LPC1114. Ketika saya menulis program dalam C ++ dan menentukan opsi --cpp compiler, semua kode dari interrupt handler menghilang, diganti dengan infinite loop. Saya menulis program sederhana yang menggambarkan masalah saya.

#include "LPC11xx.h"           // LPC11xx definitions
#define SYSTICK_DELAY 120000   // for 10 ms systick @ 12MHz osc

void SysTick_Handler(void)
{
  __NOP();
}

int main (void) 
{
  SystemInit();                   // from system_LPC11xx.c
  SysTick_Config(SYSTICK_DELAY);  // from core_cm0.h
  // Loop forever
  while (1) __NOP();
}

Ketika mencoba mengkompilasi kode ini dengan opsi --cpp compiler, saya mendapatkan infinite loop dalam disasm:

SysTick_Handler PROC
            EXPORT  SysTick_Handler           [WEAK]
            B       .
            ENDP

Ini adalah tempat di mana __NOP () dari program di atas harus. Dan itu ada ketika saya mengkompilasi kode dengan opsi kompiler --c99 atau tanpa opsi tambahan. Versi Keil MDK adalah 4.12. Adakah yang bisa memberi tahu saya apakah ada solusi atau solusi?

x4mer
sumber
Karena ISR Anda tidak melakukan apa-apa, itu hanya dioptimalkan saja? Mungkin Anda dapat mencoba menonaktifkan pengoptimalan atau menyatakan sesuatu volatiledi dalamnya.
Nick T
Optimasi diatur ke -level0, Optimalkan untuk Waktu - tidak dipilih. __NOP () bukan apa-apa. Tetapi saya juga mencoba mengubah vars global dalam interrupt handler atau memanggil fungsi. Kode yang diberikan di atas disederhanakan menjadi sangat kecil untuk mereproduksi masalah.
x4mer
1
Mengajukan permintaan dukungan teknis kepada Keil, akan mengirim ulang semua jawaban di sini.
x4mer
Mengapa Anda membutuhkan __NOP (); panggilan? Tidak bisakah Anda menggunakan titik koma sederhana?
Kevin Vermeer

Jawaban:

14

Referensi "lemah" hanya berarti bahwa rutin akan diganti dengan rutin dalam kode Anda dengan nama yang sama. Ketika menggunakan C ini sederhana, nama-nama akan selalu identik tetapi nama C ++ merusak fungsi (untuk fungsi yang berlebihan dll) sehingga nama yang dikompilasi mungkin tidak akan cocok dengan nama ISR default. Anda perlu membungkus fungsi (atau setidaknya referensi maju, saya tidak yakin secara spesifik saya sebagian besar bekerja di C) dalam pembungkus "C" eksternal untuk memaksa kompiler untuk tidak memotong nama.

extern "C" {
  void SysTick_Handler(void)
  {
    // do whatever
  }
}
timrorr
sumber
2
Terima kasih. Ini berfungsi persis seperti yang Anda tulis pada contoh. Dan saya juga dapat mendeklarasikan fungsi dalam file header sebagai extern "C" void SysTick_Handler (void); dan kemudian menulis interrupt handler saya dalam bentuk klasik yaitu tanpa extern "C".
x4mer
Ya Tuhan! Terima kasih atas jawaban yang bagus ini! Begitu banyak waktu yang terbuang karena tidak mengetahui hal ini) Terima kasih sekali lagi!