2. Структура доклада
Главные проблемы
Уровень представления прерывания
(interrupt managers)
Уровень объектов, имеющих в себе методы,
являющиеся прерываниями.
Сам пример
Плюсы и минусы
3. Главные проблемы:
Вектор прерывания стандартно не
масштабируем
Вектор прерывания один, объектов много
В вектор прерывания нельзя передать
параметр, функция реализующая
прерывание узнает все из глобальных
переменных.
4. Стандартный подход
void __attribute__ ((weak, alias ("Default_Handler")))
TIM2_IRQHandler(void);
extern "C" void TIM2_IRQHandler(void) {
Led1Up();
FlagLed=1;
}
void Led1Up(void)
{
Bla bla bla
}
5. ● Плюсы
Быстро
● Минусы
Нельзя менять на ходу
Никакая инкапсуляция
нужная глобальная переменная
при нескольких источниках прерывания по
одному вектору, нужно проверять все
7. Он же в статическом классе
class InterruptManager {
private:
static pHandlerPointer_t volatile IsrVectors[81];
public:
static void DefaultHandler(void) {asm volatile("nop"::);};
static void AddHandler(pHandlerPointer_t handler, IRQn_Type irq)
{IsrVectors[irq] = handler;};
static void RemoveHanlder(IRQn_Type irq) {IsrVectors[irq] =
DefaultHandler;};
static void Raise(IRQn_Type irq) {IsrVectors[irq]();};
};
InterruptManager::AddHandler(MyFuncton,TIM2_IRQHandler);
8. ● Плюсы
Можем менять на ходу.
● Минусы
Нельзя указать вектором прерывания ничего
кроме void*.
Все еще требуются глобальные
переменные.
9. Смещение таблицы прерываний в
оперативную память
void remap_vector_table (void)
{
if (SCB->VTOR)return;
memcpy ((void*) IsrVectors, (void*) SCB->VTOR, sizeof IsrVectors);
__disable_irq();
SCB->VTOR = (uint32_t) (IsrVectors);
__DSB ();
__enable_irq();
__ISB();
}
10. ● Плюсы
То же самое, что и предыдущий метод, но
указатель на функцию это и есть вектор, что
убирает косвенный вызов.
● Минусы
Нельзя указать вектором прерывания ничего
кроме void*.
Применимо только в Cortex M3,M4,M7,M0+
Все еще требуются глобальные
переменные.
12. ● Плюсы
Можно вызывать все что угодно функции с
параметрами,лямбды ,методы у классов.
и.т.п.
std::function<void()> Display42OnLCD = []() { lcd.write(42,4); };
std::function<void()> Testfunctor = [&]() { this->testmethod(); };
InterruptManager::AddHandler(Display42OnLCD,TIM2_IRQn);
InterruptManager::AddHandler(Testfunctor,TIM3_IRQn);
Теперь не нужны глобальные переменные
14. Пойдем на уровень выше
Не хотим решать проблему наличия
глобальных переменных на столь низком
уровне проектирования.
Считаем, что interruptManager уже
реализован.
15. Статический метод класса и
статическая переменная
возвращающая thisclass Clock
{
public:
Clock():pThis(this){}
static void StaticIrq(void) {pThis->Irq();}
void SetActiveIrq(void) {pThis=this;}
private:
void Irq(void);
static Clock *pThis;
}
InterruptManager::AddHandler(Clock::StaticIrq,TIM3_IRQn);
16. ● Плюсы
Мы избавились от глобальных переменных,
без std::function
Можно указывать какой класс сейчас
активен и примет сейчас управление
прерывания.
Минусы
Добавляем косвенный вызов
18. class InterruptSubject{
public:
InterruptSubject(){}
void IrqHandle(){
for(size_t i = 0; i < MAX_INTERRUPTS; i++){
if(ArrayOfInterruptClasses[i]!=NULL)
ArrayOfInterruptClasses[i]->interruptHandle();
};}
void SetInterrupt(Interruptable * pInterrupt);
void RemoveInterrupt(Interruptable * pInterrupt);
private:
Interruptable* ArrayOfInterruptClasses[MAX_INTERRUPTS];
};
19. ● Плюсы
Масштабируемо
Гибко
● Минусы
При системе один экземпляра класса
InterruptSubject на один вектор прерывания,
невозможно сделать IrqHandle статическим,
что позволяет использовать его только с
массивом std::function
21. ● Плюсы
Все то же самое, что и стандартный
observer, но у каждого прерывания
находится свой статический массив
указателей на функции, что позволило
сделать методы вызова прерывания
статическим (можно менять на лету в
оперативной памяти)
● Минусы
НЕТ :)
22. Осталось за кадром
● Mbed interrupt manager
(синглтон с самодельным связным списком
который хранит и указатели void* и указатель
на обьект, если это метод объекта)
● Статья с Embedded.com
Interrupts in C++
Arduino TimerOne lib
TimerOne Timer1; глобальный таймер
ISR(TIMER1_OVF_vect) {Timer1.isrCallback();}) стандартный подход