Комментарии изменяют поведение компиляции (переопределение слабой ссылки sysTickHook)
У меня есть очень простая процедура, которая загорается встроенным светодиодом (вывод 13), когда системный таймер срабатывает при прерывании.
Я переопределяю слабую ссылку на int sysTickHook(пустоту)
, найденную в hooks.c
. Я обнаружил, что в целом для этого мне нужно использовать внешнюю связь "C"
Часть, которая вызывает недоумение, заключается в том, что это прерывание срабатывает нормально без "C"
, если над ним есть комментарии, как показано ниже. Это минимальный воспроизводимый пример, который я могу найти. Кто-нибудь может это объяснить?
Я использую старую простую Arduino IDE 1.8.16.
void setup() {
pinMode(13,OUTPUT);
digitalWrite(13,LOW);
}
void loop() {}
// { -- если вы удалите эту строку, системный вызов не будет вызван
// extern "C" -- если вы удалите эту строку, sysTickHook не будет вызываться
int sysTickHook()
{
digitalWrite(13,HIGH);
return 0;
}
@Adam V. Steele, 👍2
Обсуждение1 ответ
Лучший ответ:
Проблема заключается в препроцессоре в среде IDE. Это недостаточно умно, чтобы разработать внешнюю букву "C"
при добавлении прототипов функций.
С вашими комментариями вы получите:
#include <Arduino.h>
#line 1 "/home/matt/t/t.ino"
#line 1 "/home/matt/t/t.ino"
void setup();
#line 6 "/home/matt/t/t.ino"
void loop();
#line 10 "/home/matt/t/t.ino"
extern "C" int sysTickHook(); // << The extern gets added here from the comment
#line 1 "/home/matt/t/t.ino"
void setup() {
pinMode(13,OUTPUT);
digitalWrite(13,LOW);
}
void loop() {}
// { -- если вы удалите эту строку, системный вызов не будет вызван
// extern "C" -- если вы удалите эту строку, sysTickHook не будет называться
int sysTickHook()
{
digitalWrite(13,HIGH);
return 0;
}
Он находит внешнее
в комментарии и думает, что это реальный код. Если вы удалите маркеры комментариев, это приведет к нарушению кода, так как у вас есть случайный {
там. Если вы полностью удалите комментарии, вы получите функцию в связи C++, которая внутренне изменяет имя функции и затем не переопределяет слабую функцию. То же самое произойдет, если вы удалите только первый комментарий.
По сути, наличие этих комментариев нарушает работу препроцессора таким образом, что он работает. Правильный способ сделать это таков:
void setup() {
pinMode(13,OUTPUT);
digitalWrite(13,LOW);
}
void loop() {}
extern "C" {
int sysTickHook()
{
digitalWrite(13,HIGH);
return 0;
}
}
Обработка комментариев как кода-это довольно большая ошибка! Может ли препроцессор Arduino IDE действительно быть сломан таким образом?, @Adam V. Steele
@AdamV.Стил Уверен, что это возможно. Он менее сломан, чем раньше, - он даже помещал прототипы в совершенно неправильное место и пресекал любые попытки использовать структуры в качестве параметров., @Majenko
@AdamV.Стил, лол, добро пожаловать в Arduino., @timemage
- Запуск передачи SPI с помощью прерывания в Arduino Due
- Контакт клавиатуры как прерывание (проводка или программирование)
- Почему функция обработчика NVIC_EnableIRQ запускается только один раз?
- Почему Arduino Due останавливается после одного вызова ADC_Handler?
- Генерация комплементарного ШИМ с внешним триггером с помощью Arduino Due
- Использование millis() и micros() внутри процедуры прерывания
- Подсчет импульсов с прерыванием
- Arduino Due vs Mega 2560
Вероятно, это прототипы функций, которые вставляет IDE, нарушают его., @Majenko
Как на них повлияет наличие комментария?, @Adam V. Steele
Я бы изучил это подробнее, но если бы я собирался приложить к этому усилия, я бы хотел знать, какой пакет поддержки платы вы использовали и какая плата была выбрана., @timemage
@timemage Я не устанавливал ничего стороннего и не изменял ни одну из установленных библиотек. Я добавил через менеджера платы "Платы Arduino SAM 1.6.12". Для компиляции и загрузки я просто использую раскрывающийся список "Arduino Due (порт программирования)". Подробное описание гласит " Использование платы "arduino_due_x_dbg" с платформы " Какую еще информацию я могу предоставить?, @Adam V. Steele