【问题标题】:Variable is not incremented in ISR变量在 ISR 中不递增
【发布时间】:2018-05-08 17:21:17
【问题描述】:

我有一个 ISR,它增加了一个数组的变量“头”。问题是几个小时后,这个变量即使在增加之后又回到了之前的值。比如:

array[head] = val; 
head++;
/*val is the byte that came from ISR and I am assigning it to my buffer 'array' at head position*/

现在,当我运行代码几个小时时,我观察到如果 head 是 119,则存储来自 ISR 的字节,变为 120,并且在下一个中断时,而不是在 120 上存储下一个字节并将 head 增加到 121,head再次变为 120 并覆盖我数组中的那个字节。可能是什么问题呢?欢迎提出任何建议!

注意:

  • head 是一个 volatile 变量。
  • 中断速度非常快。

代码sn-p:

    /*before storing on to the circular buffer check whether it is full*/

    if ((COM1RxBufHead == COM1RxBufTail - 1) ||((COM1RxBufHead == (COM1RXBUFSIZE - 1)) && (COM1RxBufTail == 0)))
    {

        logDEBUG("[FULL]");
        U1STAbits.OERR = 0;
        return;
    }
    else
    {
        /* Byte can be safely stored on to buffer*/
        COM1RxBuf[COM1RxBufHead] = U1RXREG;


        if (COM1RxBufHead == (COM1RXBUFSIZE - 1))
        {
            COM1RxBufHead = 0;
        }
        else
        {
            COM1RxBufHead++;
        }

【问题讨论】:

  • 你能显示实际的代码吗?它总是发生,还是不时发生?如果第一个是真的,为什么需要运行几个小时?
  • 两个不同的 ISR 调用可能同时运行,将变量声明为 volatile 并不能确保它是从内存中读取、修改和写回的。您可能需要使用某种锁定方式?
  • 据我所知,这个 ISR 是原子的。此外,在阅读时,我会锁定以避免任何其他中断。请详细说明你的意思。
  • 所以你确定 ISR 没有嵌套?
  • 您是否收到任何 [FULL] 日志条目? logDEBUG() 调用是否可以从中断处理程序安全地工作?

标签: c embedded


【解决方案1】:

您在错误的抽象级别上工作。虽然使用 C 来编写这些东西是完全可以的,但是发现基于 C 代码本身似乎不可能的问题意味着你需要降级。

这意味着进入汇编程序/机器架构领域。

以下只是一般性建议,因为我实际上并不了解您的机器架构。

  • 检查编译器生成的实际汇编语言。看到翻译后的代码可能可以清楚地看出是什么导致了这个问题,例如缓存值的使用(即使你声明你已经标记了变量volatile)。

  • 确保在运行 ISR 时禁用更多中断。我不知道任何架构不是这种情况,但它们可能存在,需要您手动禁用和重新启用。

  • 即使中断在 ISR 中自动禁用,也有具有中断优先级的体系结构,其中较高优先级可以中断正在进行的较低优先级 ISR。还有 NMI,不可屏蔽中断,可以中断任何事情(尽管它们往往用于更严重的事情)。

  • 请确保,如果您在 ISR 之外修改变量,则在执行此操作时禁用中断。这是为了防止 ISR 在更新过程中运行的可能性,如果更新本身不是中断方式的原子操作。这很可能是这种情况,因为增加具有潜在循环缓冲区环绕的指针几乎肯定会是一个多指令(因此是可中断的)过程。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多