在下面的Mapper类中,静态成员函数timer0CompA作为中断服务程序。它在中断向量中获得名称“__vector_14”。
struct Mapper {
static void timer0CompA() __asm__("__vector_14") __attribute__((__signal__, __used__, __externally_visible__));
};
void Mapper::timer0CompA(){}
如果我尝试对模板类使用相同的方法
template<typename T>
struct Mapper {...};
模板成员函数未插入到中断向量中。
我知道如果它能工作的话将会有问题:不同的实例化将在汇编代码中获得相同的名称,因此我们将得到一个双重定义的符号。但就我而言,这很有用......
有什么提示吗?
运行时解决方案,并不完全是最佳的:
但是,由于您需要一次编写整个 Flash 页面,因此您最好一次完成所有操作。
注意:您可能会发现自己意外覆盖了应用程序代码,因此请确保用于执行更改的函数不在闪存的该部分中,并且写回不使用的页面部分。
gcc 和 clang 在使用
__asm__()
或 __attribute__((signal))
与类模板成员函数时似乎都有点不一致。
第一
__asm__()
.
__asm()
。据我所知根本没有任何影响。适用于静态和非静态成员。有一种方法可以同时适用于两者:
__asm()
在模板方法的显式特化中,gcc 和 clang 都遵循这种方法。您可以通过在每个专业化中为其指定不同的 __asm() 名称来多次实例化模板。
示例:
template <typename T>
class foo {
static void f();
// We put the real code in _f, each specialization of f() will
// just call _f() to avoid re-writing the code.
static inline void _f() { /*code*/ };
};
// Can only add __asm to a declaration, not a definition
template <> void foo<int>::f() __asm("__vector_1");
template <> void foo<int>::f() { foo<int>::_f(); }
template <> void foo<char>::f() __asm("__vector_2");
template <> void foo<char>::f() { foo<char>::_f(); }
上面的内容为您提供了在 clang 和 gcc 上具有正确的损坏符号名称的方法。
_f()
中的实际方法代码将内联到f()
中,因此额外的函数不需要任何成本。
下一个
__attribute__((signal/interrupt))
:
属性
signal
仅在AVR上支持,而godbolt上没有Clang AVR,所以我使用了interrupt
,这也是一个ISR,但与AVR“信号”类型略有不同。
这与
__asm()
上的处理方式相同。 Gcc 会在模板类方法上默默地忽略它,而 clang 会尊重它。
所以我们可以调整上面的例子来使其工作:
template <> void foo<int>::f() __asm("__vector_1") __attribute__((interrupt));
template <> void foo<char>::f() __asm("__vector_2") __attribute__((interrupt));
__attribute__((used))
还有另一个怪癖:如果将其放入类模板中,则尝试专门化该方法会失败。似乎在专业化中命名类足以定义“已使用”的类方法,然后专业化会尝试再次定义相同的方法。解决方案是仅在专业化中添加属性:
// This fails
class bar {
static void f() __attribute__((used));
};
template <> void bar<int>::f();
// error: explicit specialization of 'f' after instantiation
// template <> void bar<int>::f();
// ^
// implicit instantiation first required here
// template <> void bar<int>::f();
// ^
// This works
class bar {
static void f();
};
template <> void bar<int>::f() __attribute__((used));