gpt4 book ai didi

c - 来自 ISR 和非 ISR 上下文的原子禁用和恢复中断 : may it be different on some platform?

转载 作者:行者123 更新时间:2023-11-30 15:29:12 25 4
gpt4 key购买 nike

我现在使用的是嵌入式产品,即 PIC32 Microchip CPU。

我熟悉几个实时内核:AVIX , FreeRTOS , TNKernel ,并且在所有这些函数中,几乎所有函数都有 2 个版本:第一个用于从任务调用,第二个用于从 ISR 调用。

当然,这对于可以切换上下文和/或 sleep 的函数来说是有意义的:显然,ISR 不能 sleep ,并且上下文切换应该以不同的方式完成。但有几个函数不切换上下文也不 sleep :例如,它可能返回系统滴答计数,或设置软件定时器等。

现在,我正在实现我自己的内核:TNeoKernel ,它具有格式良好的代码并经过仔细测试,我有时会考虑发明“通用”函数:可以从任务或 ISR 上下文中调用的函数。但由于上述所有三个内核都使用单独的函数,我担心我会做错什么。

比如说,在任务和 ISR 上下文中,TNKernel 使用不同的例程来禁用/恢复中断,但据我所知,唯一可能的区别是,如果目标平台不这样做,ISR 函数可能会被“编译出来”作为优化不支持嵌套中断。但如果目标平台支持嵌套中断,那么对于任务和 ISR 上下文来说,禁用/恢复中断看起来完全相同。

所以,我的问题是:在哪些平台上,禁用/恢复 ISR 中断的方式应与非 ISR 上下文不同?

如果没有这样的平台,我宁愿选择“通用”功能。如果您对此方法有任何意见,我们将不胜感激。

UPD:我不喜欢有两组函数,因为它们会导致显着的代码重复和复杂化。比如说,我需要提供一个启动软件定时器的函数。它看起来像这样:

enum TN_RCode _tn_timer_start(struct TN_Timer *timer, TN_Timeout timeout)
{
/* ... real job is done here ... */
}

/*
* Function to be called from task
*/
enum TN_RCode tn_timer_start(struct TN_Timer *timer, TN_Timeout timeout)
{
TN_INTSAVE_DATA; //-- define the variable to store interrupt status,
// it is used by TN_INT_DIS_SAVE()
// and TN_INT_RESTORE()
enum TN_RCode rc = TN_RC_OK;

//-- check that function is called from right context
if (!tn_is_task_context()){
rc = TN_RC_WCONTEXT;
goto out;
}

//-- disable interrupts
TN_INT_DIS_SAVE();

//-- perform real job, after all
rc = _tn_timer_start(timer, timeout);

//-- restore interrupts state
TN_INT_RESTORE();

out:
return rc;
}

/*
* Function to be called from ISR
*/
enum TN_RCode tn_timer_istart(struct TN_Timer *timer, TN_Timeout timeout)
{
TN_INTSAVE_DATA_INT; //-- define the variable to store interrupt status,
// it is used by TN_INT_DIS_SAVE()
// and TN_INT_RESTORE()
enum TN_RCode rc = TN_RC_OK;

//-- check that function is called from right context
if (!tn_is_isr_context()){
rc = TN_RC_WCONTEXT;
goto out;
}

//-- disable interrupts
TN_INT_IDIS_SAVE();

//-- perform real job, after all
rc = _tn_timer_start(timer, timeout);

//-- restore interrupts state
TN_INT_IRESTORE();

out:
return rc;
}

因此,我们几乎所有系统功能都需要像上面这样的包装器。对于我作为内核开发人员以及内核用户来说,这都是一种不便。

唯一的区别是使用了不同的宏:对于任务,这些是 TN_INTSAVE_DATATN_INT_DIS_SAVE()TN_INT_RESTORE();对于中断,这些是 TN_INTSAVE_DATA_INTTN_INT_IDIS_SAVE()TN_INT_IRESTORE()

对于支持嵌套中断的平台(ARM、PIC32),这些宏是相同的。对于不支持嵌套中断的其他平台,TN_INTSAVE_DATA_INTTN_INT_IDIS_SAVE()TN_INT_IRESTORE() 将扩展为空。所以是有点性能优化,但是在我看来成本太高了:维护比较困难,使用起来不太方便,而且代码量增加。

最佳答案

这完全取决于设计和 CPU 功能。我对任何 PIC 都不熟悉,但例如,飞思卡尔(摩托罗拉)MCU(以及许多其他)能够将条件代码寄存器(CCR)移入累加器并移回累加器。这允许人们保存中断启用/禁用掩码的先前状态,并在最后恢复它,而不必担心直接启用应该保持禁用状态的中断(在 ISR 内)。

然而,要回答哪些平台必须在 ISR 内部和外部以不同的方式执行此操作,需要熟悉所有这些平台,或者至少熟悉一个未通过此测试的平台。如果有一个CPU不允许保存和恢复CCR(如上所述),则别无选择,只能针对每种情况采取不同的做法。

关于c - 来自 ISR 和非 ISR 上下文的原子禁用和恢复中断 : may it be different on some platform?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26326041/

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