如何使用 void(*FUNC)(void)

How to use void(*FUNC)(void)

提问人:Alex_Chun 提问时间:11/16/2023 最后编辑:Alex_Chun 更新时间:11/16/2023 访问量:71

问:

我有一个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 的函数作为回调函数进行排列?

谢谢

c 函数指针 中断

评论

0赞 Jabberwocky 11/16/2023
ISRinstall想要一个,这意味着 ISR 没有参数。但是您提供了一个 .这可能是错误的,你会看到的 àrg' ponter 可能无处可去。void (*FUNC)(void)void task(void* arg)task
0赞 KamilCuk 11/16/2023
API producer究竟是谁?
0赞 Alex_Chun 11/16/2023
一个名为 uAbassi 的免费 RTOS 制作人,用于裸机 BMP SOC support.@KamilCuk。他们很好,但他们的回答通常很简短,对我来说缺乏关键信息。
2赞 Lundin 11/16/2023
void trampoline(void* arg)无法作为参数传递给期望的函数 - 聊天机器人谎言生成器生成的代码在各个方面都完全没有意义,甚至无法编译。通过询问 Bing,您现在比问问题之前更加困惑,并且对解决问题的了解更少......void (*FUNC)(void)
0赞 Lundin 11/16/2023
特别是,这归结为ISA - CPU是否真的支持ISR(Cortex M等)的普通功能(市场上的大多数其他MCU)。即使不知道那么多,也无法编写此代码。

答:

1赞 KamilCuk 11/16/2023 #1

使用蹦床作为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 .

评论

0赞 Alex_Chun 11/16/2023
感谢您的回答,但是 API 只是 with,我的数据结构没有给出。你的意思是我应该执行诸如'void task(void){ get(G_dataA); set(G_dataA);...... } 这样的任务`?ISRnumvoid (*FUNC)(void)void*
0赞 KamilCuk 11/16/2023
我不明白,是的,只需要 和 ,就像在提供的代码中一样。 我不明白“任务”是如何发挥作用的,它们之间有什么关系。所呈现的代码表示一个名为 的函数,据我了解,该函数用作类型为 的“您的回调函数”的示例。实际上,使用中断处理程序听起来是一个非常糟糕的主意,中断处理程序应该是原子的。ISRInstallISRnumvoid (*FUNC)(void)I should do the tasks liketaskvoid (*)(void *)printf
0赞 Lundin 11/16/2023
这是一个复杂的设计,我建议不要这样做——我们不应该只是盲目地回答这里的请求,而应该指出不良做法。保持程序简单,ISR简短。与 ISR 的通信应完全封装在驱动程序中。然后,应用程序程序员通过 setter/getter API 与驱动程序通信,而不是通过传递指针。此外,传递某种包装的指针会打开各种竞争条件电位。
0赞 Alex_Chun 11/16/2023
嗨,如果我是对的,请纠正我,@KamilCuk。这里的蹦床只是您任务的跳跃功能。所以基本上我可以只做'ISRinstall(TASK1, function1);void 函数1(void) { clear_pending(); mytask(&arg); }`?
0赞 KamilCuk 11/16/2023
So basically I can just do是的。
1赞 Lundin 11/16/2023 #2

你的回调函数是没有意义的。ISR 始终是一个不带参数且没有返回值的函数。如果此处的目标是注册要由 ISR 调用的回调,这仍然毫无意义,因为您绝对不应该在 ISR 内部调用。printf

您需要重写,以便它成为可以成为 ISR/从 ISR 调用的东西,具体取决于应该做什么。没有办法绕过它。第 1 步是研究中断的工作原理以及与中断一起使用的最佳实践。taskISRinstall

评论

0赞 Alex_Chun 11/16/2023
感谢您的帮助,请忽略printf,因为这是NEW BING的答案。我设置此代码的原因是,它是一种显示 NEW BING 使用蹦床来表示“void (*)(void)”之类的指针的方式
1赞 Lundin 11/16/2023
@Alex_Chun 忘记询问困惑的聊天机器人 - 它实际上对任何事情都一无所知,尤其是关于嵌入式系统。它本质上只是一个谎言制造者。请阅读一些可靠的学习材料,而不是嵌入式系统设计和中断。
0赞 Alex_Chun 11/16/2023
感谢您@Lundin的建议,我保证我会的。现在,您能否粗略地了解如何将数据传输到 IRQ 回调,或者我应该只使用全局值进行计算?
1赞 Lundin 11/16/2023
@Alex_Chun 基础知识摘要:electronics.stackexchange.com/a/329961/6102