Можно ли написать обработчик прерываний на C++ для чипов ARM Cortex, таких как ST и NXP.
В настоящее время я разрабатываю много кода на C++ для чипов ARM cortex. Мне немного надоело вызывать объект static/global/singleton C++ из функции обратного вызова C. Есть ли способ не использовать функцию C.
Есть ли способ напрямую вызывать объектные функции С++ при возникновении прерывания?
Обработчик прерывания можно написать на любом языке, который компилируется в собственный код.
Он по-прежнему должен использовать связь языка C с соглашением о вызовах обработчиков прерываний. Это означает отсутствие функций-членов. (Формально статические функции-члены также недопустимы, хотя на практике они обычно работают. Нестатические функции-члены использовать нельзя.)
В C++ сначала включите связь языка C с помощью extern "C"
. Также используйте любое ключевое слово компилятора для обработчиков прерываний, которое вы использовали бы в C, например __interrupt
.
Внутри функции вы можете использовать всю мощь C++ — объекты, циклы for-in, интеллектуальные указатели, экземпляры шаблонов и т. д. Хотя вы все равно хотите быть осторожным с тем, сколько работы вы делаете в контексте прерывания, а C++ имеет тенденцию скрывать сложность, поэтому вы больше не чувствуете, сколько машинных инструкций генерируется.
На чипах ARM Cortex M есть таблица указателей функций по предустановленному адресу памяти. Таблица может быть построена на C или ассемблере, и если ваши обработчики прерываний не экспортированы с правильным именем, компоновщик не сможет найти адреса, принадлежащие таблице. Связывание языка C гарантирует, что любое изменение имени выполняется способом, совместимым со ссылками на символы в коде запуска.
Другие семейства процессоров используют фиксированный адрес только для вектора сброса и устанавливают другие обработчики прерываний, записывая адрес каждого обработчика в регистр специальной функции, соответствующий его прерыванию. Для них имеет значение только соглашение о вызовах, а не имя/связь функции. ARM Cortex-M позволяет вам написать регистр специальной функции для поиска всей таблицы векторов по альтернативному адресу, но не для перемещения отдельных обработчиков.
@Bart: Трудно подвести итог, потому что у вас было несколько вопросов. Ваш первый "Можно ли написать обработчик прерываний на C++ для чипов ARM Cortex?" ответ да. Для "Есть ли способ не пересылать через функцию C?" также Да. Для «Есть ли способ напрямую вызвать объектную функцию C++ при возникновении прерывания?» Нет. Есть несколько вещей, которые могут означать «объектная функция C++», и ни одна из них не может использоваться в качестве обработчиков прерываний.
@Bart: А что касается того, почему вы связаны этим соглашением, это потому, что оно встроено в аппаратное обеспечение. Процессор ничего не знает о this
указателях или чем-то подобном. Фактически, обработчики прерываний могут даже не использовать соглашение о вызовах C, используемое для других функций, вы можете получить специальное соглашение о вызовах, используя ключевое слово (например, __interrupt
, поэтому в C++ вы получите extern "C" __interrupt void whatever(void)
). (Написание ключевого слова зависит от вашего компилятора) Компилятор позаботится об этой детали. Чего он не может сделать, так это создать указатель this
из воздуха.
Благодарим Вас за разъяснения. Я понимаю, что ты имеешь в виду. Используя одноэлементный или глобальный объект, я неявно прекратил использовать это, поэтому работаю над этой проблемой.
@old_timer: Можете ли вы проверить, достаточно ли точно мое редактирование, чтобы избежать путаницы?
Компиляторы C могут выбрать свое собственное соглашение, нет никаких правил, которые могли бы их остановить. они могут использовать обычный или рекомендуемый вариант или пойти своим путем. Чтобы cortex-m мог иметь адрес метки функции c в векторной таблице и заставить его работать, компилятор должен соответствовать соглашению, «запеченному» в логике. иначе C тоже не будет работать. Затем вы можете использовать традиционный подход к обертыванию вашей функции C либо специфическими функциями компилятора, либо самостоятельно в сборке.
@old_timer: Да, безусловно, вы можете написать обработчик прерываний (или переадресацию) на ассемблере, если хотите, дав ему ожидаемое имя. Вы можете выбрать свои собственные имена символов для функций-обработчиков, если вы пишете свой собственный (или модифицируете) код поддержки платформы. Но большинство людей будут использовать функцию запуска, предоставляемую компилятором, чтобы они правильно инициализировали глобальные переменные и т. д. до вызова main()
. И в этом общем случае обработчики прерываний должны использовать имена, назначенные библиотекой поддержки платформы, которые имеют связь с C.
и большинство людей используют gnu или kiel или что-то другое, использующее совместимое соглашение о вызовах.
вектор сброса является особым случаем даже для C, но определенно для C++ другие векторы - это те, для которых вы хотите использовать эту функцию cortex-m.
Я думаю, что здесь упоминается что-то важное: это зависит от компилятора. Тем временем я нашел эту ссылку на сайт ИАР. Это пример таблицы преобразователя прерываний в C++. Я посмотрел на это, но должен понять это еще.
Is away to directly call a C++ object function when a interrupt occurs?
Короче нет. Даже если вы объявите свой нестатический метод как void (void)
, у него все равно будет неявный аргумент — this
. С другой стороны, обработчик прерываний вообще не имеет аргументов.
Спасибо за ваш ответ, я понимаю, что вы имеете в виду. Только статическая функция этого класса будет допустимым кандидатом.
Могу ли я обобщить ваш ответ: нет, это невозможно из-за требования использовать соглашение о вызовах C? Если это так, возникает другой вопрос, почему мы связаны этой конвенцией?