#c #struct #stm32
#c #структура #stm32
Вопрос:
У меня проблема с чтением и записью структур в нескольких файлах. По сути, мне нужно записать переменные внутри структуры, которые позже проверяются во время прерывания по таймеру. Когда это происходит, новое значение таймера принимается в качестве элемента в этой структуре. На данный момент я жестко устанавливаю эти значения таймера в цикле 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();
}
}
— РЕШЕНИЕ —
Хорошо, я понял это, мог бы сделать с перемещением вещей, но в остальном это работает так:
типы.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();
}
}
Внешний интерфейс, похоже, решил проблему получения структуры в разных файлах, а объявление начального значения {10,10,10}, я думаю, решило некоторую проблему с распределением памяти. Код компилируется, но без него не содержит корректных значений. Я пока не знаю, что делает volatile, никакой разницы, если я его удалю. Кое-что, о чем я должен прочитать.
Комментарии:
1. Я бы не стал помещать внешнюю ссылку в types.h. Я бы написал это отдельно в других (неосновных) файлах. Или поместите его в другой включаемый файл (после types.h), который вы не включаете в main.
2. Volatile предназначен для регистров устройств, которые могут не выдавать один и тот же ответ при повторном чтении. Это говорит компилятору не пытаться оптимизировать несколько операций чтения для этой области памяти.
3. Вы должны использовать «static» для переменных области видимости файла, в настоящее время вы объявляете все с глобальной видимостью.
Ответ №1:
объявите ее в заголовке
extern myStruct hello;
и определите ее только в одном cpp
myStruct hello;
Комментарии:
1. При попытке этого компилятору, похоже, это не нравится. Я получаю сообщение об ошибке: ‘hello’ необъявленный (впервые используется в этой функции). Везде, где я не объявлял структуру
2. убедитесь, что вы включаете заголовок везде, где вы используете
hello
Ответ №2:
У вас возникли проблемы с компилятором, оптимизирующим обращения в цикле while? Поскольку компилятор не знает, что другой поток выполнения просматривает значения hello, может быть, он просто не записывает их? Попробуйте добавить volatile к вашему «extern MyStruct hello» или посмотрите на результат смешанной сборки и посмотрите, проходит ли его запись в структуру hello.
Смотрите здесь
Ответ №3:
Фактически вы объявляете структуру дважды (с одним и тем же именем), поэтому ваш код не работает. Определите его один раз (скажем, в main), а затем используйте extern для ссылки на него в других ваших файлах.
extern myStruct hello;
Ответ №4:
Мне кажется, что ваш timer_IRQHandler
вызывается в ядре как процедура прерывания. Если true, main, вероятно, никогда не вызывается.
Я бы попытался статически инициализировать вашу структуру, а не полагаться на main
для ее инициализации. Например:
myStruct hello = { 10, 43, 98 };
и да, если на нее ссылаются несколько файлов, вы должны объявить ее как extern в заголовке и определить / инициализировать ее только один раз в исходном файле.
Что касается volatile, то это для регистров устройств или адресов, отображенных в памяти, которые могут не давать один и тот же ответ при повторном чтении. Это говорит компилятору не пытаться оптимизировать несколько операций чтения для этой области памяти.
Комментарии:
1. main() выполняется. В функции происходят другие вещи, которые работают нормально. Используя отладчик GDB, я вижу, что структура была инициализирована и имеет правильные значения. Просто, когда дело доходит до функции прерывания, значения кажутся случайными.
2. Правильно. Не определяйте ее как в main, так и в interrupt. Просто определите ее в одном месте и извлеките в другом (или предпочтительно в заголовке).
3. Правильно, я определил ее в main.c с некоторыми начальными значениями {10,10,10}. Затем в interrupt.c я определил это как: extern MyStruct привет; По какой-то причине я не могу изменить эти значения по умолчанию в main.c. Если я перемещу эту строку в типы. в заголовочном файле компилятор жалуется, что ‘hello’ не определено в interrupt.c.
4. Разобрался с проблемой. Я опубликовал решение в вопросе выше ^ _ ^. Ваше первоначальное решение было фактически тем, что было необходимо. Я думаю, что это была какая-то проблема с выделением памяти.