为什么回调标志在没有明显原因的情况下被清除和/或损坏
Why is a callback flag being cleared and/or corrupted without apparent cause?
我正在为处理器编写一个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;
};
- 在没有太多条件句的情况下,我如何避免被零除
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 在未初始化映射的情况下,将值插入到映射的映射中
- 是默认情况下分配给char数组常量的值
- 为什么我不能在不创建字符串变量的情况下使用函数的字符串输出
- 如何在不产生任何垃圾的情况下获得C中的像素
- 在已经使用Git的情况下减少编译时间
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- 如何在没有信号的情况下从C++执行QML插槽
- 如何在不知道向量大小的情况下输入向量内部的向量?
- 为什么在某些情况下不写入此文件?
- 为什么Mat类的两个对象可以在不重载运算符+的情况下添加
- 在没有Xcode的情况下在Mac捆绑包中嵌入框架
- libQGLViewer 如何在没有清除缓冲区的情况下绘制
- SDL2:如何在不清除屏幕的情况下渲染
- 如何在没有递归的情况下清除四叉树(也许使用队列?).
- 为什么回调标志在没有明显原因的情况下被清除和/或损坏
- 在不删除部件的情况下清除布局
- 如何输出到控制台,并在不清除屏幕和重写所有内容的情况下覆盖文本
- vector在没有交互的情况下被清除