Форум » ПРОГРАММИРОВАНИЕ SCADAPack32 » грабли, решения и идеи... » Ответить

грабли, решения и идеи...

Радик: публикуем "грабли", чтобы другие не наступали и не изобретали велосипед. После очередной отловленной нестандартной ситуации при разработке\отладке ПО пришла мысль писать сюда описание проблемы и её решение (если удалось найти). Надеюсь, что публикация сэкономит время другим разработчикам и позволит CMI улучшить качество документации.

Ответов - 10

Радик: ПРОБЛЕМА: при использовании flashSettingsSave() и установленном ранее ручном режиме сторожевого таймера wd_manual() может перезапускаться контроллер. РЕШЕНИЕ: сторожевой таймер на время сохранения перевести в автоматический режим wd_auto(); request_resource( FLASH_MEMORY ); flashSettingsSave( CS_RUN ); release_resource( FLASH_MEMORY ); wd_manual(); в документации на С++Tools случай не описан

Радик: ПРОБЛЕМА: при попытке разместить в глобальной области памяти приложения экземпляр класса линкер выдает следующее сообщение: L1120 (W) Section address is not assigned to "C$INIT" после запуска приложение входит в бесконечный цикл перезагрузок, срабатывает сторожевой таймер.Чтение всякого рода мануалов результата не принесло, но помогло её понять. C++ автоматически генерирует вызовы конструктора\деструктора для глобальных объектов. Линкер говорит, что надо бы поместить объект в сегмент, предназначенный именно для таких целей. Как сделать - неясно, сделал несколько попыток с объявлением секций - результат отрицательный, сгенерированный образ приложения не грузится в контроллер. РЕШЕНИЕ: Проблема решена обходным путем: 1. Под объект выделяем память как обычный массив байтов размером с объект; 2. Заводим для объекта переменную-указатель и инициализируем её ссылкой на выделенный массив; 3. С объектом работаем через указатель, вызываем конструктор\деструктор в коде программы; 4. Пишем макрос, чтобы автоматизировать выделение памяти и инициализацию указателя. #define GLOBAL_CLASSPTR_DECLARE( CLASS, PTR ) char PTR##_Buf_[sizeof(CLASS)]; \ CLASS * PTR = (CLASS *)&PTR##_Buf_ ... class TClass1{ ... public: TClass1(); ... }; GLOBAL_CLASSPTR_DECLARE( TClass1, Class1 ); void main() { ... Class1->TClass1(); ... } код примера не протестирован (за исключением макроса) и приведен для пояснения идеи. Если кто знает нормальный способ решения проблемы - буду благодарен за подсказку

Радик: ПРОБЛЕМА: нужно определить тип установленной нижней платы ввода вывода, чтобы автоматически настроить универсальное ПО после установки РЕШЕНИЕ: // detect SCADAPack32 bottom module type in run-time, only 5601 or 5604 int BottomModule( void ) { int result; UINT32 Ticks; request_resource( IO_SYSTEM ); clearRegAssignment(); clearStatusBit( S_MODULE_FAILURE ); addRegAssignment( SCADAPack_lowerIO, 0, 1, 10001, 30001, 0 ); release_resource(IO_SYSTEM); Ticks = readStopwatch() + 5000; // on 2000 ms - incorrect detect do { release_processor(); } while ( readStopwatch() < Ticks ); request_resource( IO_SYSTEM ); if ( getStatusBit( S_MODULE_FAILURE )!= 0 ) { clearRegAssignment(); clearStatusBit( S_MODULE_FAILURE ); addRegAssignment( SCADAPack_5604IO, 0, 1, 10001, 30001, 40009 ); result = 5604; } else result = 5601; // здесь можно добавить остальные элементы таблицы release_resource(IO_SYSTEM); // если хочется сохранить результат request_resource(FLASH_MEMORY); flashSettingsSave(CS_PERMANENT); release_resource(FLASH_MEMORY); return result; } пробуем добавить элемент, ждем индикатора ошибок обмена, если они есть - создаем другой элемент. Пауза менее 2 сек не позволяет определить наличие ошибок. К сожалению, приходится чистить весь раздел register assignments, т.к. поэлементно он не редактируется. Но терпимо, поскольку была необходимость избавится от загрузки LAD-файла и всю настройку делать из С++ приложения.


Astilya: ПРОБЛЕМА: при использовании flashSettingsSave() и установленном ранее ручном режиме сторожевого таймера wd_manual() может перезапускаться контроллер. Радик, будем считать это недокументированной особенностью. Каких-либо существенных комментариев тут дать не могу. Наша тех. поддержка подтвердила обнаруженный Вами эффект. Астафьев Илья ПЛКСистемы Начальник отдела продаж и тех. поддержки

Astilya: Радик пишет: ПРОБЛЕМА: при попытке разместить в глобальной области памяти приложения экземпляр класса линкер выдает следующее сообщение: L1120 (W) Section address is not assigned to "C$INIT" Радик, мои ребята проверили - у нас все работает без проблем. Проблему не подтверждаю.

Astilya: Радик пишет: ПРОБЛЕМА: нужно определить тип установленной нижней платы ввода вывода, чтобы автоматически настроить универсальное ПО после установки Хорошее решение нестандартной задачи. Иных комментариев не имею. Спасибо за Вашу и Ваших коллег высокую квалификацию.

Радик: Astilya пишет: Радик, мои ребята проверили - у нас все работает без проблем. Проблему не подтверждаю. ну что сказать.... может и работает - у меня могло быть сочетание многих факторов, не только размещение и вызовы конструкторов\деструкторов. Наверно следует переформулировать - "как разместить экземпляр класса в глобальной памяти и при этом избежать генерации кода раннего автоматического вызова конструктора". Либо дополнить документацию на CTools примером работы с глобальным экземпляром класса, пояснив при этом, как реагировать на предупреждения линкера и когда фактически происходит вызов конструктора по умолчанию. Astilya пишет: Хорошее решение нестандартной задачи.тут немного помог Dmytro из службы техподдержки CMI, главным образом психологически - он не сомневался, что это возможно, что в конце концов и подтвердилось. А также как-то услышанная от Ваших специалистов идея, что можно стирать register assignments из С++ и заполнять заново при запуске, чтобы избавиться от LAD зависимости в этом отношении.

Радик: ПРОБЛЕМА: любителям использовать битовые поля в структурах небольшой облом - компилятор кода HEW при описании битовых полей в структурах размещает поля начиная с старших битов, а не с младших, как ожидалось. Почему - загадка... РЕШЕНИЕ: не использовать битовые поля :) они мало переносимы и зависят от реализации компилятора

Astilya: Радик пишет: ПРОБЛЕМА: любителям использовать битовые поля в структурах небольшой облом - компилятор кода HEW при описании битовых полей в структурах размещает поля начиная с старших битов, а не с младших, как ожидалось. Почему - загадка... Не назвал бы это загадкой. Разве что соглашусь, что это можно было бы и задокументировать. Это давно известная проблема, которая возникает при переносе программ на разные платформы, - учет требований процессоров по выравниванию данных и интерпретации числовых значений. Например, процессор Intel допускает обращение к числовым переменным, расположенным по адресу, не кратному длине операнда - порядок байт в слове: от младшего разряда к старшему. Компиляторы С/С++ для платформы Intel интерпретируют битовые структуры в порядке от младшего битового поля к старшему и такой же порядок байт в структуре. Процессоры MIPS и Sparc требуют выравнивания адреса переменной кратно ее длине (short - кратно 2, long - 4, double - 8), а порядок байт в слове: от старшего байта к младшему. Битовые поля в структуре располагаются от старшего поля к младшему в пределах байта, а байты от младшего к старшему (то есть обратно порядку битовых полей). Предлагаю принять за данность. Попробую уговорить CMI каким-либо образом внести это в документацию.

Astilya: Радик пишет: Astilya пишет: цитата: Радик, мои ребята проверили - у нас все работает без проблем. Проблему не подтверждаю. ну что сказать.... может и работает - у меня могло быть сочетание многих факторов, не только размещение и вызовы конструкторов\деструкторов. Наверно следует переформулировать - "как разместить экземпляр класса в глобальной памяти и при этом избежать генерации кода раннего автоматического вызова конструктора". Либо дополнить документацию на CTools примером работы с глобальным экземпляром класса, пояснив при этом, как реагировать на предупреждения линкера и когда фактически происходит вызов конструктора по умолчанию. Радик, пожалуйста, пришлите этот проект мне. Подозреваю, что Вы действительно "попали" на какое-то сочетание многих факторов. Хотелось бы с ним разобраться более пристрастно. Поскольку некий пробел в документации Вами подмечен совершенно правильно, я сейчас, слету, не могу сказать - что именно привело к такой работе с глобальным классом. Нам бы "руками пощупать"...



полная версия страницы