gpt4 book ai didi

c - 我怎样才能延迟 Linux 中断处理程序(我知道 sleep 通常是不可能的)

转载 作者:IT王子 更新时间:2023-10-29 00:24:05 27 4
gpt4 key购买 nike

我正在开发一个嵌入式 Linux ARM 系统,该系统需要通过按特定顺序关闭某些电源(通过 GPIO 控制)来对电源故障信号作出 react 。这个过程需要尽快开始,所以我安装了一个中断处理程序来检测这个电源故障。

问题是我们需要在关闭每个电源之间引入一点延迟。我知道中断处理程序通常不允许延迟,但如果此处理程序永远不会返回(电源故障!),那完全没问题。

我正在尝试使用 this post 中描述的方法引入延迟,但我这辈子都无法真正造成可测量的延迟(在示波器上观察到)。

我哪里做错了,我怎样才能做对?

下面是相关代码。

/* This function sets en_gpio low, then waits until pg_gpio goes low. */
static inline void powerdown(int en_gpio, int pg_gpio)
{
/* Bring the enable line low. */
gpio_set_value(en_gpio, 0);
/* Loop until power good goes low. */
while (gpio_get_value(pg_gpio) != 0);
}

/* This is my attempt at a delay function. */
#define DELAY_COUNT 1000000000
static void delay(void)
{
volatile u_int32_t random;
volatile u_int32_t accum;
volatile u_int32_t i;

get_random_bytes((void*)&random, 4);
accum = 0;
for (i = 0; i < DELAY_COUNT; i++)
accum = accum * random;
}

/* This is the interrupt handler. */
static irqreturn_t power_fail_interrupt(int irq, void *dev_id)
{
powerdown(VCC0V75_EN, VCC0V75_PG);
delay();
powerdown(DVDD15_EN, DVDD15_PG);
delay();
powerdown(DVDD18_EN, DVDD18_PG);
delay();
powerdown(CVDD1_EN, CVDD1_PG);
delay();
powerdown(CVDD_EN, CVDD_PG);
/* It doesn't matter if we get past this point. Power is failing. */
/* I'm amazed this printk() sometimes gets the message out before power drops! */
printk(KERN_ALERT "egon_power_fail driver: Power failure detected!\n");
return IRQ_HANDLED;
}

最佳答案

在硬 IRQ 处理程序中使用 delay 函数通常不是一个好主意,因为在硬 IRQ 处理程序中中断被禁用并且系统将挂起,直到您的硬 IRQ 函数完成。另一方面,您不能在硬 IRQ 处理程序中使用 sleep 函数,因为硬 IRQ 是原子上下文

考虑到所有这些,您可能需要使用 threaded IRQ .这样硬 IRQ 处理程序只会唤醒 bottom half IRQ 处理程序(在内核线程中执行)。在此线程处理程序中,您可以使用常规的 sleep 函数。

要实现线程 IRQ 而不是常规 IRQ,只需将 request_irq() 函数替换为 request_threaded_irq() 函数即可。例如。如果你有这样的 IRQ 请求:

ret = request_irq(irq, your_irq_handler, IRQF_SHARED,
dev_name(&dev->dev), chip);

你可以用这样的东西来代替它:

ret = request_threaded_irq(irq, NULL, your_irq_handler,
IRQF_ONESHOT | IRQF_SHARED,
dev_name(&dev->dev), chip);

此处NULL 表示将使用标准的硬 IRQ 处理程序(仅唤醒线程 IRQ 处理程序),并且 your_irq_handler() 函数将在内核线程中执行(您可以在其中调用 sleep 函数)。此外,在请求线程 IRQ 时应使用 IRQF_ONESHOT 标志。

还应该提到的是 managed request_threaded_irq() 函数的版本,称为 devm_request_threaded_irq()。使用它(而不是常规的 request_threaded_irq())允许您在驱动程序退出函数(以及错误路径)中省略 free_irq() 函数。我建议您使用 devm_* 函数(如果您的内核版本已经有它)。但是,如果您决定使用 devm_*,请不要忘记删除驱动程序中的所有 free_irq() 调用。

长话短说

request_irq() 替换为 request_threaded_irq()(如上所示),您将能够在 IRQ 中使用 sleep处理程序。

关于c - 我怎样才能延迟 Linux 中断处理程序(我知道 sleep 通常是不可能的),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30261424/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com