Bug no compilador Keil ARM com manipuladores de interrupção e C ++?


8

Estou com um problema ao escrever manipuladores de interrupção no compilador Keil ARM para LPC1114. Quando escrevo um programa em C ++ e especifico a opção do compilador --cpp, todo o código dos manipuladores de interrupção desaparece, sendo substituído por um loop infinito. Eu escrevi um programa simples que ilustra meu problema.

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

Ao tentar compilar esse código com a opção de compilador --cpp, recebo um loop infinito no desastre:

SysTick_Handler PROC
            EXPORT  SysTick_Handler           [WEAK]
            B       .
            ENDP

Este é o local onde o __NOP () do programa acima deve estar. E está lá quando estou compilando código com a opção de compilador --c99 ou sem opções adicionais. A versão Keil MDK é 4.12. Alguém pode me dizer que existe alguma solução ou solução alternativa?


Como o seu ISR não faz nada, está apenas sendo otimizado? Talvez você possa tentar desativar a otimização ou declarar algo volatilenela.
Nick T

A otimização está definida como -level0, Optimize for Time - desmarcada. __NOP () não é nada. Mas também tentei alterar vars globais no manipulador de interrupções ou chamar funções. O código fornecido acima foi simplificado para ser pequeno demais para reproduzir o problema.
x4mer

1
Arquivado um pedido de suporte técnico para Keil, repassaremos aqui qualquer resposta.
x4mer

Por que você precisa de um __NOP (); ligar? Você não pode simplesmente usar um ponto e vírgula simples?
Kevin Vermeer

Respostas:


14

A referência "fraca" significa apenas que a rotina será substituída por uma rotina no seu código de mesmo nome. Ao usar C, isso é simples, os nomes sempre serão idênticos, mas o nome C ++ gerencia as funções (para sobrecarga de função, etc.), portanto o nome compilado provavelmente não corresponderá ao nome ISR padrão. Você precisa agrupar a função (ou pelo menos uma referência direta, não tenho certeza dos detalhes que geralmente trabalho em C) em um wrapper externo "C" para forçar o compilador a não alterar o nome.

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

2
Obrigado. Isso funciona exatamente como você escreveu no exemplo. E também posso declarar a função no arquivo de cabeçalho como extern "C" void SysTick_Handler (void); e depois escrevo meu manipulador de interrupções na forma clássica, ou seja, sem "C" externo.
X4mer

Oh meu Deus! Obrigado por esta ótima resposta! Tanto tempo foi desperdiçado por não saber disso) Obrigado mais uma vez!
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.