我在读取和写入跨多个文件的结构时遇到问题。基本上我需要写一个结构中的变量,这些变量稍后会在定时器中断期间被检查。发生这种情况时,新的计时器值将被视为该结构中的成员。目前我在while(1)循环中硬设置这些定时器值,但稍后这些值将取自某些算法。我不太确定我是否正确读取结构成员。项目编译时,在运行时,它将计时器设置为随机值。 GDB脱欧证实它们是正确的。
如果我直接设置定时器值,一切都可以正常工作。
这是ARM cortex M4上的嵌入式项目。
我有一个在types.h中定义的结构
#ifndef __TYPES_H
#define __TYPES_H
typedef struct { uint32_t a; uint32_t b; uint32_t c;} myStruct;
#endif
然后在main.c
#include <types.h>
myStruct hello
int main(void){
while(1){
hello.a = 10;
hello.b = 43;
hello.c = 98;
}
}
然后在interrupt.c
#include <types.h>
myStruct hello
int count = 0;
void timer_IRQHandler(void){
if(interrupt != RESET){
switch(count){
case 0:
timerSet(hello.a); // if i just put a number here, it works fine
count++;
break;
case 1:
timerSet(hello.b);
count++;
break;
case 2:
timerSet(hello.c);
count++;
break;
}
resetInterrupt();
}
}
---解决方案---
好的我已经弄清楚了,可以做些移动的东西,但是它的工作原理如下:
types.h中
#ifndef __TYPES_H
#define __TYPES_H
typedef struct { uint32_t a; uint32_t b; uint32_t c;} myStruct;
#endif
然后在main.c
#include <types.h>
myStruct volatile hello = {10,10,10};
int main(void){
while(1){
hello.a = 10;
hello.b = 43;
hello.c = 98;
}
}
然后在interrupt.c
#include <types.h>
extern myStruct hello
int count = 0;
void timer_IRQHandler(void){
if(interrupt != RESET){
switch(count){
case 0:
timerSet(hello.a); // if i just put a number here, it works fine
count++;
break;
case 1:
timerSet(hello.b);
count++;
break;
case 2:
timerSet(hello.c);
count++;
break;
}
resetInterrupt();
}
}
extern似乎解决了跨越不同文件获取结构的问题,以及{10,10,10}的初始值声明,我认为解决了一些内存分配问题。代码编译,但没有它就没有正确的值。我不知道什么是挥发性的,如果我删除它没有区别。我会读到的东西。
答案 0 :(得分:3)
在标题
中声明它extern myStruct hello;
并仅在一个cpp
中定义它myStruct hello;
答案 1 :(得分:1)
编译器在while循环中优化访问时遇到问题吗?由于编译器不知道另一个执行线程正在查看hello的值,也许它只是不写它们?尝试将volatile添加到“extern myStruct hello”或查看混合程序集输出,看看它是否写入hello结构。
请参阅here
答案 2 :(得分:1)
您实际上声明了两次结构(使用相同的名称),这就是您的代码无效的原因。定义一次(比如在main中),然后使用extern在其他文件中引用它。
extern myStruct hello;
答案 3 :(得分:0)
在我看来,您的timer_IRQHandler
在内核中被调用为中断例程。如果为true,则可能永远不会调用main。
我会尝试静态初始化您的结构,而不是依靠main
来初始化它。例如:
myStruct hello = { 10, 43, 98 };
是的,如果有多个文件引用它,你应该在标题中将它声明为extern,并在源文件中定义/初始化它一次。
至于volatile,那是设备寄存器或内存映射地址,如果读取两次,可能不会给出相同的答案。它告诉编译器不要尝试优化该内存位置的多次读取。