C — структура для нескольких файлов

#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. Разобрался с проблемой. Я опубликовал решение в вопросе выше ^ _ ^. Ваше первоначальное решение было фактически тем, что было необходимо. Я думаю, что это была какая-то проблема с выделением памяти.