为什么回调标志在没有明显原因的情况下被清除和/或损坏

Why is a callback flag being cleared and/or corrupted without apparent cause?

本文关键字:情况下 清除 损坏 标志 回调 为什么      更新时间:2023-10-16

我正在为处理器编写一个SD卡SPI驱动程序。我知道SPI驱动程序很好,因为我也将其用于LCD,并且到目前为止,一直在愉快地向卡发送命令。我在一笔具体的交易中遇到了麻烦,在我看来,这笔交易与其他任何交易都没有什么不同。

在SPI总线上写入数据时,我等待中断回调说接收和发送完成。有两个回调函数,它们将struct中的下列布尔标志设置为true:

m_transaction_status.sdts_rx_complete

m_transaction_status.sdts_tx_complete

在正常的程序流中,我等待这些标志设置后再继续:

while ((m_transaction_status.sdts_rx_complete == false) //
        || (m_transaction_status.sdts_tx_complete == false))
{
    // Check whether we've had an error.
    if (m_transaction_status.sdts_error == true)
    {
        LOG_ERROR(SD::MODULE,
                "transfer_data: Transaction error.");
        transfer_status = false;
        break;
    }
}

对于问题事务,我在回调中设置了一个断点,可以看到两个标志都被设置了,但是当我返回到正常流时,变量突然不可用,似乎是false,因为我永远卡在循环中。此循环用于所有其他事务,没有问题。

是否有任何理由,我可以调查为什么这些变量被设置,但然后(显然)被清除或释放或其他不幸的东西?

编辑:

中断确实是微中断(准确地说是瑞萨RL78)。

结构声明为:

/**
 * The state of an SD SPI transaction.
 */
struct SDTransactionStatus
{
    /** Transaction error flag. */
    bool sdts_error;
    /** Transmission completion flag. */
    bool sdts_tx_complete;
    /** Reception completion flag. */
    bool sdts_rx_complete;
};

struct是作为SD类的私有成员实现的。这些标志是通过回调函数中的一个简单的setter函数来设置的。

我不知道你的特定微控制器,也不知道你必须使用的c++编译器,但这应该不会改变我要说的任何东西。

我相信问题是,在你的循环中,你永远不会改变你的标志的值,你只是读取它们,所以编译器可以自由地优化东西,并在循环外读取你的变量。缓存它们),因为它不知道它们可以改变。类似以下语句:

const bool complete = !m_transaction_status.sdts_rx_complete
                   || !m_transaction_status.sdts_tx_complete;
const bool error = m_transaction_status.sdts_error;
while (complete) {
  if (error) {
    //...
  }
}

你知道为什么这不能得到好的结果。解决方法是告诉编译器你的变量可以在"背后"改变,并且每次你在代码中访问它们时,它实际上都需要重新读取它们

由于您不是多线程或任何东西,您可以简单地通过在您的struct声明的变量中添加volatile限定符来实现:

struct SDTransactionStatus
{
    volatile bool sdts_error;
    volatile bool sdts_tx_complete;
    volatile bool sdts_rx_complete;
};

现在,为什么你没有在早些时候发现这个问题有点神秘,但是你必须记住,"编译器可以自由地优化"并不意味着它总是必须。作为一个大胆的猜测,我想说,您使用该循环的其他地方不适合进行这种优化,而您有问题的地方则适合。

当然,我可能对整个事情都是错的,但由于信息太少,很难判断,无论如何,这个优化/易失性问题仍然存在于你的代码中,即使它不是你当前问题的原因,所以你仍然需要修复它,因为即使你当前的问题是不相关的,我所描述的可能随时发生。

编辑:哦,你可能应该检查你的整个代码库,以确保这种情况不会发生在其他地方