我有一个RTOS API,它看起来像这样:ISRInstall(int ISRnum,void(*FUNC)(void)).
然而我想要的回调函数是void task(void*),因为我需要数据输入来计算。
该平台是一个SOC与Cortex-A9双核HPS与裸金属BMP支持的RTOS。
API制作人建议我用蹦床作为入口,以下是NEW BING给我的解决方案
#include <stdio.h>
typedef struct {
void (*func)(void*);
int data;
} Callback;
static void trampoline(void* arg) {
Callback* cb = (Callback*)arg;
cb->func(&(cb->data));
}
void task(void* arg)
{
int* data = (int*)arg;
// using arg to do some calculations
}
// A given API
void ISRinstall(int ISRnum, void (*FUNC)(void));
int main() {
int task_data = 42;
Callback cb;
cb.func = task;
cb.data = task_data;
ISRinstall(1, trampoline);
trampoline(&cb);
return 0;
}
字符串
那么,用蹦床作为void(* F)(void)的入口来传递函数是否正确呢?
如果不是,那么如何使用蹦床函数来安排带有arg的函数作为回调函数?
谢谢你
2条答案
按热度按时间azpvetkf1#
用蹦床作为void(* F)(void)的入口来传递函数与元素是否正确?
传递上下文的正确方法是使用全局变量。回调不接受任何上下文。由于ISR本身就是“全局”的,因此处理信号是必须使用全局变量的情况之一。
通常你写一个 Package 器有一个好的接口,沿着这一点,这可以简化,如果有一个接口,以获得触发ISR内的处理程序。
字符串
真实的生活例子:https://github.com/ARMmbed/mbed-os/blob/master/targets/TARGET_STM/gpio_irq_api.c#L220。
62lalag42#
你的回调函数是没有意义的。ISR总是一个没有参数和没有返回值的函数。如果这里的目标是注册一个由ISR调用的回调,它仍然是没有意义的,因为你绝对不应该在ISR内部调用
printf
。您需要重写
task
,使其成为可以作为ISR/从ISR调用的对象,这取决于ISRinstall
应该做什么。没有办法绕过它。第1步是研究中断如何工作以及中断使用的最佳实践。