1. В сообществе нашего форума Вконтакте создан раздел по продаже электронных компонентов.
    Каждый может продать в нем свои залежавшиеся детали. Подробности здесь.

Решено Не изменяется extern переменная в классе

Тема в разделе "STM8/STM32", создана пользователем radioengineer, 24 фев 2016.

  1. radioengineer

    radioengineer Администратор Команда форума

    Сообщения:
    3.552
    Симпатии:
    352
    Адрес:
    Алматы
    Попробую описать проблему следующим образом. Есть файл file1.c, в котором определена функция обработчик прерывания. В обработчике устанавливается флаг timeoutFlag, объявленный в file1.h:
    PHP:
    volatile static bool timeoutFlag;
    Этот же флаг используется в классе file2.cpp и объявлен в file2.h как:
    PHP:
    #include "file1.h"
    extern volatile bool timeoutFlag;
    Флаг используется как проверка таймаута по приему для USART:
    PHP:
    while(!(ClassName::USARTx->SR USART_SR_RXNE)) {
            if(
    timeoutFlag) {
                return 
    ERR_TIMEOUT;
            }
    }
    Так вот в прерывании timeoutFlag корректно устанавливается в true, а в файле класса флаг всегда false и не изменяется. Подумал может проблема в том, что компилятор оптимизирует проверку условия, считая, что timeoutFlag никогда не изменяется и для него изменение в прерывании является волшебным и добавил volatile к объявлению флага, но ситуация не переменилась.
    Подскажите, пожалйста, как решить эту загадку?
     
    : c++, class, extern, stm32
  2. UL7AAjr

    UL7AAjr В доску свой

    Сообщения:
    1.848
    Симпатии:
    313
    Род занятий:
    инженер-программист
    Адрес:
    Алма-Ата
    Надо посмотреть в ассемблерном коде куски где идет успешное изменение флага и его неуспешная проверка. Я так подозреваю, что будет производиться проверка и установка разных переменных (разных адресов памяти).

    Еще я не очень понял, а для чего внешней переменной добавлять описание типа? Разве extern Имя_переменной не достаточно?
  3. radioengineer

    radioengineer Администратор Команда форума

    Сообщения:
    3.552
    Симпатии:
    352
    Адрес:
    Алматы
    Я совсем не разбираюсь в ассемблере, вот что в прерывании:
    PHP:
    0x0800048C 4907      LDR      r1,[pc,#28]  ; @0x080004AC
    0x0800048E 2001      MOVS     r0,#0x01
    0x08000490 7008      STRB     r0,[r1,#0x00]
    Вот в проверке условия:
    PHP:
    0x0800048C 4907      LDR      r1,[pc,#28]  ; @0x080004AC
    0x08000776 6AE0      LDR      r0,[r4,#0x2C]
    0x08000778 E004      B        0x08000784
    0x0800077A 7811      LDRB     r1
    ,[r2,#0x00]
    0x0800077C B111      CBZ      r1,0x08000784
    --- Сообщения объединены, 24 фев 2016 ---
    Тип переменной все-таки указывать обязательно после extern.
  4. Alex

    Alex В доску свой

    Сообщения:
    191
    Симпатии:
    13
    extern "C" {
    #include file1.h
    }
    Те же грабли.
  5. radioengineer

    radioengineer Администратор Команда форума

    Сообщения:
    3.552
    Симпатии:
    352
    Адрес:
    Алматы
    Нет, не те, что-то другое.
  6. Alex

    Alex В доску свой

    Сообщения:
    191
    Симпатии:
    13
    extern "C" volatile bool timeoutFlag;
  7. radioengineer

    radioengineer Администратор Команда форума

    Сообщения:
    3.552
    Симпатии:
    352
    Адрес:
    Алматы
    Не работает здесь extern "C"
  8. UL7AAjr

    UL7AAjr В доску свой

    Сообщения:
    1.848
    Симпатии:
    313
    Род занятий:
    инженер-программист
    Адрес:
    Алма-Ата
    да... так не понятно. Надо как-то в дебугере смотреть что там в регистры грузится с тех адресов.
    Но в итоге просто станет видно, что используются два разных адреса. Иначе быть не может. Вот понять почему одну и ту-же переменную линкер в два адреса распихивает - не понятно.
  9. UL7AAjr

    UL7AAjr В доску свой

    Сообщения:
    1.848
    Симпатии:
    313
    Род занятий:
    инженер-программист
    Адрес:
    Алма-Ата
    так... а volatile в C не намекает на аппаратный флаг какой-то? Он может быть set/reset by harware?

    хотя не... volatile тут не то.....

    а вот судя по ассемблеру - проверка выполняется
    --- Сообщения объединены, 24 фев 2016 ---
    еще вот странная штука
    0x0800048C 4907 LDR r1,[pc,#28] ; @0x080004AC
    ... тут еще куча кода должна ведь быть между 0x0800048C и 0x08000776
    0x08000776 6AE0 LDR r0,[r4,#0x2C]
  10. Alex

    Alex В доску свой

    Сообщения:
    191
    Симпатии:
    13
    Попробуй не объявлять ее как static
  11. radioengineer

    radioengineer Администратор Команда форума

    Сообщения:
    3.552
    Симпатии:
    352
    Адрес:
    Алматы
    Если не объявлять как static линкер ругается на нее как на multiply definition
  12. Alex

    Alex В доску свой

    Сообщения:
    191
    Симпатии:
    13
    Попробуй в "extern" убрать "volatile bool". Возможно компилятор считает это инициализацией, что в extern недопустимо.
    А компилятор какой?
    А почему не хочешь объявить ее глобальной?
  13. radioengineer

    radioengineer Администратор Команда форума

    Сообщения:
    3.552
    Симпатии:
    352
    Адрес:
    Алматы
    На данный момент понятно, что static говорит линкеру создать по одной копии переменной в каждом сишном файле при подключении хэдера с объявлением, отсюда и ошибка Error: L6200E: Symbol timeoutFlag multiply defined если не писать static, т.е. создаются 2 копии с одинаковыми именами в каждом сишном файле.
  14. radioengineer

    radioengineer Администратор Команда форума

    Сообщения:
    3.552
    Симпатии:
    352
    Адрес:
    Алматы
    Значится решено следующим образом. В file1.h объявляю переменную как:
    PHP:
    extern volatile bool timeoutFlag;
    В file1.c инициализирую ее:
    PHP:
    volatile bool timeoutFlag false
    В file2.h просто подключаю
    PHP:
    #include "file1.h"
    В file1.c у меня библиотека, где описаны прерывания и т.п., в ней устанавливается флаг. file2.cpp это класс, в котором происходит проверка флага, после прерывания.
    Buba_Chkhadze нравится это.
  15. Buba_Chkhadze

    Buba_Chkhadze Модератор Команда форума

    Сообщения:
    4.328
    Симпатии:
    352
    Адрес:
    Талгар
    вай ну маладэс ну :)
  16. Drunyaruma

    Drunyaruma Гость

    Сообщения:
    2
    Симпатии:
    1
    Адрес:
    Киев
    Вы пишите библиотеку для USART? А у вас там что прием байта осуществляется по чтению флага RXNE?

Поделиться этой страницей