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.