[英]Const pointer to volatile struct member
我正在使用微控制器进行一些 ADC 测量。 当我尝试使用 -O2 优化编译以下代码时遇到问题,当代码中存在 PrintVal() function 时,MCU 冻结。 我做了一些调试,结果发现当我添加-fno-inline
编译器标志时,即使使用 PrintVal() function,代码也能正常运行。
这里有一些背景:
AdcIsr.c 包含在 ADC 完成工作时执行的中断。 该文件还包含 ISRInit() function,它初始化将在转换后保存值的变量。 在主循环中将等待中断,然后才访问 AdcMeas.value。
AdcIsr.c
static volatile uin16_t* isrVarPtr = NULL;
ISR()
{
uint8_t tmp = readAdc();
*isrVarPtr = tmp;
}
void ISRInit(volatile uint16_t *var)
{
isrVarPtr = var;
}
AdcMeas.c
typedef struct{
uint8_t id;
volatile uint16_t value;
}AdcMeas_t;
static AdcMeas_t AdcMeas = {0};
const AdcMeas_t* AdcMeasGetStructPtr()
{
return &AdcMeas;
}
main.c
void PrintVal(const AdcMeas_t* data)
{
printf("AdcMeas %d value: %d\r\n", data->id, data->value);
}
void StartMeasurement()
{
...
AdcOn();
...
}
int main()
{
ISRInit(AdcMeasGetStructPtr()->value);
while(1)
{
StartMeasurement();
WaitForISR();
PrintVal(AdcMeasGetStructPtr());
DelayMs(1000);
}
}
问题:
使用 const AdcMeas_t* 数据作为 PrintVal() function 的参数是否有问题? 我知道 AdcMeas.value 可能会在中断内部发生变化,并且 PrintVal() 可能已过时。
AdcMeas 包含一个“通用吸气剂”。 这是使用这种 function 来允许对 static 结构进行只读访问的好习惯吗? 或者我应该实现 AdcMeasGetId() 和 AdcMeasGetValue 函数(请注意,这个结构只有 2 个成员,如果它有 8 个成员怎么办)?
我知道这段代码有点笨(在while循环中等待中断),这只是一个例子。
一些错误:
您没有 header 文件,既不包含库文件,也不包含您自己的文件。 这意味着在你修复它之前,一切都被无可救药地破坏了。 在没有 header 文件的情况下,您不能在 C 中执行多个文件项目。
*isrVarPtr = tmp;
在这里,您在没有竞争条件保护的情况下写入变量。 如果主程序分几个步骤读取此变量,则可能会获得不正确的数据。 您需要防止竞争条件或保证原子访问。
const AdcMeasGetStructPtr()
是胡言乱语,没有办法return &AdcMeas;
它内部将使用符合要求的 C 编译器进行编译。
如果您有一个旧但符合 C90 的编译器,则返回类型将被视为int
。 否则,如果你有一个现代的 C 编译器,甚至 function 定义都不会编译。 因此,您的编译器似乎出了点问题,这比这个错误更令人担忧。
在 C 文件中声明typedef struct
然后返回指向它的指针没有任何意义。 你需要重新设计这个模块。 如果只有一个实例(单例),您可以让 getter function 将实例返回到私有结构。 但是,如前所述,它需要处理竞争条件。
风格问题:
function 声明中的空括号()
在 C 中几乎总是错误的。 这是过时的样式,意思是“接受任何参数”。 C++ 在这里有所不同。
int main()
在微控制器系统中根本没有任何意义。 您应该使用一些适用于独立程序的实现定义的形式。 最普遍支持的形式是void main (void)
。
DelayMs(1000);
在任何嵌入式系统中都是高度可疑的代码。 永远不应该有理由让你的 MCU 在最大电流消耗的情况下挂掉一整秒。
总体而言,您似乎将从“连续转换”ADC 中受益。 支持连续转换的 ADC 只需将其最新读取数据转储到数据寄存器中,您可以在需要时通过轮询来获取它。 捕获所有 ADC 中断实际上仅适用于硬实时系统、信号处理等。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.