问题描述
我正在使用STM33F103,并且正在尝试实现一种回调机制,该机制将调用给定对象上的方法来处理中断,到目前为止,我使用以下解决方案:
class Nvic
{
public:
using function_pointer =void (*)(void);
template<typename T>
static void get_interrupt(int interrupt_number,T* object,void (T::*methode)())
{
class_vector[interrupt_number]=reinterpret_cast<Default_class*>(object);
method_vector[interrupt_number]=reinterpret_cast<default_method_type>(methode);
}
static void execute_interrupt(int interrupt_number)
{
(class_vector[interrupt_number]->*method_vector[interrupt_number])();
}
private:
struct Default_class{void default_method();};
using default_method_type =void(Default_class::*)(void);
static inline Default_class* class_vector[NUMBER_OF_INTERRUPTS];
static inline default_method_type method_vector[NUMBER_OF_INTERRUPTS];
}
extern "C"
{
void Some_ISR(void) __attribute__ ((interrupt));
void Some_ISR(void){Nvic::execute_interrupt(2);}
}
如果某个对象想要将中断绑定到自身:
class Some_class
{
public:
Some_class(int peripherial_iterrupt)
{
Nvic::get_interrupt(peripherial_iterrupt,this,&Some_class::my_interrupt);
}
private:
my_interrupt();
};
但是我想基于std::function
来实现这一点,不幸的是事实证明std::function
can dynamically allocate memory并不是可重入的。
那么,有什么方法可以确保std::function
是中断安全的吗?
也许使用分配器可以解决问题,如果我提供std::function
,我的自定义分配器将在某些静态内存缓冲区中分配内存,就不会出现中断堆损坏的问题。
或者如果我提供newlib-nano __malloc_lock
和__mallock_free
函数,那么堆内存分配将是中断安全的。
它也可能允许我在中断安全的环境中使用其他STL容器和算法,例如:
class Some_interface :private Some_peripherial
{
public:
Some_interface(int peripherial_number) :Some_peripherial(peripherial_number)
{
int interrupt_number =peripherial_number;
Nvic::get_interrupt(interrupt_number,&Some_interface::interrupt_routine);
}
void send_data(void* buff,size_t size)
{
for(size_t i=0;i<size;i++)
{
data_to_send.push_back((uint8_t)buff[i]);
}
}
void set_all_data_send_callback(std::function<void(void)> f){all_data_send_callback=f;}
private:
std::vector<uint8_t> data_to_send;
std::function<void(void)> all_data_send_callback;
void interrupt_routine()
{
if(data_to_send.empty()){if(all_data_send_callback)all_data_send_callback();};
else
{
Some_peripherial::send(data_to_send.back());
data_to_send.pop_back();
}
}
};
class Timer_task :private Timer_peripherial
{
public:
Timer_task(int peripherial_number) :Timer_peripherial(peripherial_number)
{
int interrupt_number =peripherial_number;
Nvic::get_interrupt(interrupt_number,&Timer_task ::on_interrupt);
Timer_peripherial::set_interrupt_on_evry_10ms();
}
template<typename T>
static void set_task(T* object,void (T::*methode)())
{
task =std::bind(std::mem_fn(methode),object);
}
private:
std::function<void(void)> task;
void on_interrupt()
{
if(task) task();
}
};
Some_interface interface_0{0};
Some_interface interface_1{1};
const char global_message[] ="global_message";
Timer_task timer_task{interface_1.send_data((void*)global_message,strlen(global_message))};
int main()
{
const char message_0[] ="123456";
const char message_1[] ="1256";
while(1)
{
interface_0.send_data((void*)message,strlen(message));
interface_1.send_data((void*)message,strlen(message));
delay();
}
}
在data_to_send中从main填充,并且还形成从另一个中断调用的其他方法。
如果需要,我们还可以设置all_data_send_callback。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)