Рабочее решение для прерываний внутри классов C ++

Бубулиндо
Чт, 01 сентября 2016 г. 8:18 утра
Привет,

Я уверен, что это прошло раньше, но я не могу найти элегантное решение для того, что я хочу сделать.
Я ищу библиотеку для использования таймеров в качестве квадратурных читателей энкодера, и одна из предполагаемых функций для меня - подсчитать количество прерываний (и на основе направления подсчета добавить или вычесть это число).

Моя проблема в том, что я не могу найти хороший способ сделать это. Если я создаю функцию, я не могу получить доступ к переменной внутри класса.

Если я определяю метод как статический, я не могу найти способ повторного использования кода для разных таймеров... или так мне кажется.

Любые идеи?

Rogerclark
Чт, 01 сентября 2016 г. 10:10
Я помню, как смотрел на ту же проблему лет назад

И я не думаю, что есть решение, так как невозможно получить указатель на функцию в C ++, которую вы можете использовать в качестве ISR

Об этом была нить.CC, но это, должно быть, было по крайней мере год назад, так что может быть трудно найти.

Вы могли бы попробовать PM''s Tho Tho The @rick Kimball, он знает, что знает много умных кодирующих вещей, но я сомневаюсь, что есть элегантное решение

Эдогальдо
Чт, 01 сентября 2016 г. 10:53 утра
Бубулиндо написал:Если я создаю функцию, я не могу получить доступ к переменной внутри класса.

Бубулиндо
Чт, 01 сентября 2016 г., 11:19
Если вы объявите переменную в общедоступном разделе, вам необходимо будет создавать объект, прежде чем вы сможете использовать эту переменную в функции.

Сжимать
Чт, 08 сентября 2016 г., 15:44
Другой вариант - использовать векторы прерывания в ОЗУ.
Я не знаю, поддерживается ли это STM32Duino, но это можно сделать.
Обычно векторы прерываний расположены в первых байтах вспышки, начиная с 0x0800000 (или 0x08002000, если используется загрузчик), и 59 векторов, которые занимают 236 байтов (это число различено в семействе STM32).
Хитрость состоит в том, чтобы скопировать эти векторы в ОЗУ, изменив немного сценария ссылки, можно сделать сегмент ОЗУ для запуска с 0x20000100 вместо 0x20000000 (измените линию, которая определяет происхождение и длину сегмента ОЗУ), это оставляет 256 байтов бесплатной памяти ОЗУ.
Теперь в начале вашей программы очень легко скопировать обычные векторы прерывания от вспышки на ОЗУ, а затем изменить указатель таблицы векторов прерываний по телефону 0x20000000.
Я не знаю, как Libmaple называет регистры управления системой (это должно быть что -то подобное, может быть, scb_base->VTOR) Но с официальным именованием ST это можно сделать с помощью следующего кода: #define NVIC_RAM_VECTOR_ADDRESS (0x20000000) #define NVIC_NUM_VECTORS 59 uint32_t *vectors = (uint32_t *)SCB->VTOR; uint32_t i; uint32_t *old_vectors = vectors; vectors = (uint32_t*)NVIC_RAM_VECTOR_ADDRESS; for (i=0; iVTOR = (uint32_t)NVIC_RAM_VECTOR_ADDRESS; . // Somewhere in your code assign vector[x] = (uint32_t)foo; where foo() is your function

Rogerclark
Чт, 08 сентября 2016 г., 21:24
@slammer

Я думаю, что проблема в том, что в C ++ невозможно получить указатель на функцию определенного экземпляра объекта.

Поэтому при написании библиотеки, например, программного обеспечения i2c, где каждый экземпляр имеет частные переменные (свойства) для SDA и SCL

Вы не могли сделать

прикрепить Intertrupt (sdapin, это.isrfunction);

Потому что компилятор не может решить это.ISRFUNCMNACT по отдельному адресу

Я подозреваю, что способ сделать это в C ++ может быть для использования шаблонов, чтобы каждый экземпляр был экземпляром другого класса, но класс основан на одном и том же шаблоне.

Класс также должен иметь статическую функцию для ISR, а также в идеале будет синглтоном

Сжимать
Чт, 08 сентября 2016 г., 22:04
Существуют ограничения, но с векторами в ОЗУ можно играть с компилятором для решения этих проблем (шаблоны, синглтонские классы и т. Д.).

Rogerclark
Чт, 08 сентября 2016 г., 22:29
В конечном итоге не прилагается Intruptrupt () Используйте обновление VTOR ?

Возможно, есть функция обертки, но я все еще думаю, что проблема, которую пытается решить Бубулиндо, является указатель на метод экземпляра

Эдогальдо
Пт, 09 сентября 2016 г., 7:29 утра
Что я сделаю, так это определяет карту, которая связывает каждое прерывание с соответствующим экземпляром, передайте карту ISR и заставьте ISR использовать ее для решения правильного экземпляра.

Rogerclark
Пт, 09 сентября 2016 г., 7:49 утра
Эдогальдо написал:Что я сделаю, так это определяет карту, которая связывает каждое прерывание с соответствующим экземпляром, передайте карту ISR и заставьте ISR использовать ее для решения правильного экземпляра.

Эдогальдо
Пт, 09 сентября 2016 г. 8:18 утра
Rogerclark написал:Как вы справляетесь с картированием? Вы используете множество классов ?

Racemaniac
Пт, 09 сентября 2016 г. 8:37 утра
Связанный вопрос об этом: есть ли у нас надлежащая документация о том, как работать с векторами прерывания?
Когда я разрабатывал свои рамки, узнавая, что часть была довольно больной болью (я знал принцип, но никогда не сталкивался с ним на практике), также Libmaple уже указал процедуры обработчика для многих прерываний. мне выяснить, что происходит, где :).
Я смог с этим поработать, но если бы вы спросили меня сейчас, как указать свою собственную рутину ISR, я бы, вероятно, уже давно искал в коде, чтобы снова разобраться в этом.
Если кто -то хорошо разбирается в этом, может быть, стоит написать на ней страницу на вики? А затем также связывают подобные потоки с ним для связанных вопросов/обсуждений.

Эдогальдо
Пт, 09 сентября 2016 г., 9:12 утра
уважение к смешиванию C и C ++ Я нашел эту ссылку, которая кажется мне полезной: https: // isocpp.org/wiki/faq/mixing-c-and-cpp

Бубулиндо
Пт, 09 сентября 2016 г., 17:26
Эта ссылка имеет некоторую полезную информацию, но вам все равно понадобится указатель объекта, который должен быть передан в подпрограмму IRQ, что звучит немного сложно для меня.
Но я не эксперт C ++. : \

Эдогальдо
Пт, 09 сентября 2016 г. 18:01
Вы читали также предыдущие сообщения?

Сжимать
Сб 10 сентября 2016 г. 12:38 утра
Использование метода класса в качестве функции прерывания это возможно, и API MBED уже поддерживает его.
Первое требование состоит в том, чтобы использовать векторы прерывания в ОЗУ (посмотрите на мой предыдущий пост)
Затем тщательно осмотрите обратный вызов.H из источников MBED: https: // github.com/armmbed/mbed-os/blob ... Перезвонить.час
Вы можете использовать его почти непосредственно, так как у класса обратного вызова нет зависимостей, и это класс только за заголовком (это делается шаблонами)
Callback Class - это вспомогательный класс, который извлекает адрес простой функции или функции члена во время выполнения.
Наконец, вы можете использовать его для переносительного векторного вектора.
Прочитайте здесь связанный вопрос о Entreptin (это функция, которая назначает функцию внешнему прерыванию), чтобы увидеть использование обратных вызовов: https: // Разработчик.Mbed.org/forum/mbed/topic/639/

Я сделал несколько небольших тестов, и кажется, что этот метод работает. Я пытаюсь найти способ переместить векторы, не касаясь ничего в источниках STM32Duino (обратный вызов.H можно использовать почти нетронутым), и я опубликую полный пример.
Следите за обновлениями.....

Бубулиндо
Сб 10 сентября 2016 г., 6:24
Как я уже сказал, C ++ немного из моей глубины, и почему я хотел создать библиотеку как средство для изучения немного больше.
Я буду следить за обновлениями, так как это может быть очень интересной разработкой. :)

Пол
Чт 10 ноября 2016 г. 13:57
Некоторые из кленовых библиотек имеют процедуры прерываний, которые позволяют легко попасть в процедуру C ++.
Например, GPIO имеет две версии AttachInterrupt ()
void attachInterrupt(uint8 pin, voidFuncPtr handler, ExtIntTriggerMode mode); void attachInterrupt(uint8 pin, voidArgumentFuncPtr handler, void *arg, ExtIntTriggerMode mode);