Lỗi trong trình biên dịch Keil ARM với trình xử lý ngắt và C ++?


8

Tôi gặp vấn đề với việc viết trình xử lý ngắt trong trình biên dịch Keil ARM cho LPC1114. Khi tôi viết chương trình trong C ++ và chỉ định tùy chọn trình biên dịch --cpp, tất cả mã từ các trình xử lý ngắt sẽ biến mất, nó được thay thế bằng vòng lặp vô hạn. Tôi đã viết chương trình đơn giản minh họa rắc rối của tôi.

#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();
}

Khi cố gắng biên dịch mã này với tùy chọn trình biên dịch --cpp, tôi nhận được vòng lặp vô hạn trong disasm:

SysTick_Handler PROC
            EXPORT  SysTick_Handler           [WEAK]
            B       .
            ENDP

Đây là nơi phải có __NOP () từ chương trình trên. Và nó ở đó khi tôi biên dịch mã với tùy chọn trình biên dịch --c99 hoặc không có tùy chọn bổ sung. Phiên bản MDK của Keil là 4,12. Bất cứ ai có thể cho tôi biết là có bất kỳ giải pháp hoặc giải pháp?


Vì ISR của bạn không có gì chỉ là nó được tối ưu hóa? Có lẽ bạn có thể thử vô hiệu hóa tối ưu hóa hoặc khai báo một cái gì đó volatiletrong đó.
Nick T

Tối ưu hóa được đặt thành -level0, Tối ưu hóa theo thời gian - bỏ chọn. __NOP () không là gì cả. Nhưng tôi cũng đã thử thay đổi các vars toàn cầu trong trình xử lý ngắt hoặc gọi các hàm. Mã được cung cấp ở trên đã được đơn giản hóa để chỉ rất nhỏ để tái tạo vấn đề.
x4mer

1
Gửi yêu cầu hỗ trợ kỹ thuật cho Keil, sẽ đăng lại ở đây bất kỳ câu trả lời nào.
x4mer

Tại sao bạn cần một __NOP (); gọi? Bạn có thể chỉ sử dụng một dấu chấm phẩy đơn giản?
Kevin Vermeer

Câu trả lời:


14

Tham chiếu "yếu" chỉ có nghĩa là thường trình sẽ được thay thế bằng một thường trình trong mã cùng tên của bạn. Khi sử dụng C, điều này rất đơn giản, các tên sẽ luôn giống nhau nhưng tên C ++ sẽ xử lý các hàm (đối với chức năng nạp chồng, v.v.) nên tên được biên dịch có thể sẽ không khớp với tên ISR mặc định. Bạn cần phải bọc hàm (hoặc ít nhất là một tham chiếu chuyển tiếp, tôi không chắc về các chi tiết cụ thể mà tôi chủ yếu làm việc trong C) trong một trình bao bọc "C" bên ngoài để buộc trình biên dịch không xáo trộn tên.

extern "C" {
  void SysTick_Handler(void)
  {
    // do whatever
  }
}

2
Cảm ơn bạn. Điều này hoạt động chính xác như bạn đã viết trong ví dụ. Và tôi cũng có thể khai báo hàm trong tệp tiêu đề là extern "C" void SysTick_Handler (void); và sau đó viết trình xử lý ngắt của tôi ở dạng cổ điển tức là không có "C" bên ngoài.
x4mer

Ôi chúa ơi! Cảm ơn bạn cho câu trả lời tuyệt vời này! Quá nhiều thời gian đã bị lãng phí vì không biết điều này) Cảm ơn bạn một lần nữa!
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.