提问人:Alex_Chun 提问时间:11/16/2023 最后编辑:Alex_Chun 更新时间:11/16/2023 访问量:71
如何使用 void(*FUNC)(void)
How to use void(*FUNC)(void)
问:
我有一个RTOS API,看起来像这样: 然而我想要的回调函数是void task(void*),因为我需要数据输入来计算。ISRInstall(int ISRnum,void(*FUNC)(void)).
该平台是一个具有 Cortex-A9 双核 HPS 的 SOC,具有裸机 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(*FUNC)(void)的入口来转移函数与参数是否正确?
如果不是,那么如何使用蹦床函数将带有 arg 的函数作为回调函数进行排列?
谢谢
答:
使用蹦床作为void(*FUNC)(void)的入口来传递带参数的函数的正确方法?
传输上下文的正确方法是使用全局变量。回调不采用任何上下文。由于 ISR 本身是“全局”的,因此处理信号是必须使用全局变量的情况之一。
你可以编写一个包装器来拥有一个很好的接口,类似于此,如果有一个接口可以在处理程序中触发 ISR,则可以简化。
// ----- C HAL
void ISRinstall(int ISRnum, void (*FUNC)(void));
enum { MAX_NUMBER_OF_ISRS = 5 };
// ------ your library
void *cookies[MAX_NUMBER_OF_ISRS] = {0};
void (*callbacks[MAX_NUMBER_OF_ISRS])(void *cookie) = {0};
static void trampoline_1(void) { callbacks[1](cookies[1]); }
static void trampoline_2(void) { callbacks[2](cookies[2]); }
static void trampoline_3(void) { callbacks[3](cookies[3]); }
/* etc */
void yourISRinstall(int isr, void (*cb)(void *cookie), void *cookie) {
callbacks[isr] = cb;
cookies[isr] = cookie;
switch (isr) {
case 1: ISRinstall(isr, trampoline_1); break;
case 2: ISRinstall(isr, trampoline_2); break;
case 3: ISRinstall(isr, trampoline_3); break;
/* etc. */
}
}
// -------------------------
#include <stdio.h>
int data;
void task(void* arg) {
int* data = (int*)arg;
printf("The data is %d\n", *data);
}
int main() {
yourISRinstall(1, task, &data);
}
现实生活中的例子:https://github.com/ARMmbed/mbed-os/blob/master/targets/TARGET_STM/gpio_irq_api.c#L220 .
评论
ISRnum
void (*FUNC)(void)
void*
ISRInstall
ISRnum
void (*FUNC)(void)
I should do the tasks like
task
void (*)(void *)
printf
So basically I can just do
是的。
你的回调函数是没有意义的。ISR 始终是一个不带参数且没有返回值的函数。如果此处的目标是注册要由 ISR 调用的回调,这仍然毫无意义,因为您绝对不应该在 ISR 内部调用。printf
您需要重写,以便它成为可以成为 ISR/从 ISR 调用的东西,具体取决于应该做什么。没有办法绕过它。第 1 步是研究中断的工作原理以及与中断一起使用的最佳实践。task
ISRinstall
评论
ISRinstall
想要一个,这意味着 ISR 没有参数。但是您提供了一个 .这可能是错误的,你会看到的 àrg' ponter 可能无处可去。void (*FUNC)(void)
void task(void* arg)
task
API producer
究竟是谁?void trampoline(void* arg)
无法作为参数传递给期望的函数 - 聊天机器人谎言生成器生成的代码在各个方面都完全没有意义,甚至无法编译。通过询问 Bing,您现在比问问题之前更加困惑,并且对解决问题的了解更少......void (*FUNC)(void)