Цитата(_pv @ Jun 20 2017, 12:35)

вот с этим и вопрос, как объявить обработчик прерывания, если тип этого конкретного уарта становится известным только при объявлении из-за шаблона.
Опишу схему, которую реализовал для ARM процов (любые cortex).
Перед стартом производится копирование таблицы векторов из флэш в озу.
Копируются только главные вектора, относящиеся к ядру. startup свой, в нем нет обработчиков периферии (не ядра).
В зависимости от семейства таблицы имеют разный размер (2 таблицы, есть еще третья - отладочная, для своих целей).
Для создания класса нужно лишь знать номер вектора обработчика, т.е. индекс, который идет с файлом ARMCMxx.h.
В качестве обработчиков использовать голую С-функцию неинтересно и проблематично (разумеется с допиской extern "C"),
мне важно было при вызове функции обработчика вызывался соотв. класс обработчика (точнее его наследника), т.е. в стек должен класться соотв. this.
Это дает простую возможность наделять класс Interrupt<> таким функционалом, который раньше было сделать крайне геморрно.
Сам класс Interrupt может быть базовым для более высокооуровеных классов (например class SerialPort), либо быть полем в другом классе.
Код
template <class Owner, InterruptIndex INDEX, InterruptPriority PRIORITY = IRQ_DEFAULT_PRIORITY>
class Interrupt : public AbstractInterrupt
{
...
private: static void userVector() { AbstractInterrupt::callVector(INDEX + IRQ_OFFSET); }
...
}
Вот так используется:
Код
class SerialPort : public Interrupt<CommunicationThread, USART3_IRQn>
{
public:
SerialPort() : Interrupt<CommunicationThread, USART3_IRQn>("USART3") { port = USART3; }
virtual void initialize();
....
private:
virtual void body();
void doRecieveDataRegisterNotEmptyEvent();
void doTransmitDataRegisterEmptyEvent();
void doTransmissionCompleteEvent();
...
} serialPort;
вот так выглядит обработчик:
Код
void SerialPort::body()
{
doRecieveDataRegisterNotEmptyEvent();
doTransmitDataRegisterEmptyEvent();
doTransmissionCompleteEvent();
}
Цена этому - расход озу для хранения таблицы векторов, таблицы указателей на абстрактные классы С++ обработчиков и по мелочи.
И небольшой оверхед, т.к. при вызове обработчика еще вызывается соотв. С++ класс-обертка, т.е. нужно совсем чуть-чуть больше стека.
Делал сравнительные замеры по производительности - никакого криминала не узрел, теперь использую такую схему на всех своих проектах.
В итоге в проекте нет НИ ОДНОГО ГЛОБАЛЬНО ОБЪЕКТА, даже с квалификатором static.
Строгая и полностью контролируемая иерархия классов, никакой самодеятельности

Забыл добавить, что использую полностью вытесняющую модель обработчиков, т. к. это тоже накладывает расходы на main стек.
Еще раз - речь про ARM процы, у которых есть полный доступ к регистру VTOR.