Сообщение: 70
Зарегистрирован: 22.02.08
Откуда: РФ, Октябрьский РБ
Репутация:
0
Отправлено: 12.06.08 11:54. Заголовок: грабли, решения и идеи...
публикуем "грабли", чтобы другие не наступали и не изобретали велосипед. После очередной отловленной нестандартной ситуации при разработке\отладке ПО пришла мысль писать сюда описание проблемы и её решение (если удалось найти). Надеюсь, что публикация сэкономит время другим разработчикам и позволит CMI улучшить качество документации.
Сообщение: 72
Зарегистрирован: 22.02.08
Откуда: РФ, Октябрьский РБ
Репутация:
0
Отправлено: 12.06.08 12:53. Заголовок: размещение экземпляра класса в глобальной памяти приложения
ПРОБЛЕМА:
при попытке разместить в глобальной области памяти приложения экземпляр класса линкер выдает следующее сообщение:
L1120 (W) Section address is not assigned to "C$INIT"
после запуска приложение входит в бесконечный цикл перезагрузок, срабатывает сторожевой таймер.Чтение всякого рода мануалов результата не принесло, но помогло её понять. C++ автоматически генерирует вызовы конструктора\деструктора для глобальных объектов. Линкер говорит, что надо бы поместить объект в сегмент, предназначенный именно для таких целей. Как сделать - неясно, сделал несколько попыток с объявлением секций - результат отрицательный, сгенерированный образ приложения не грузится в контроллер. РЕШЕНИЕ:
Проблема решена обходным путем:
1. Под объект выделяем память как обычный массив байтов размером с объект; 2. Заводим для объекта переменную-указатель и инициализируем её ссылкой на выделенный массив; 3. С объектом работаем через указатель, вызываем конструктор\деструктор в коде программы; 4. Пишем макрос, чтобы автоматизировать выделение памяти и инициализацию указателя.
void main() { ... Class1->TClass1(); ... } код примера не протестирован (за исключением макроса) и приведен для пояснения идеи. Если кто знает нормальный способ решения проблемы - буду благодарен за подсказку
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-файла и всю настройку делать из С++ приложения.
Сообщение: 1
Зарегистрирован: 25.04.08
Откуда: РФ, Москва
Репутация:
0
Отправлено: 19.06.08 15:02. Заголовок: Проблема сторожевого таймера
цитата:
ПРОБЛЕМА:
при использовании flashSettingsSave() и установленном ранее ручном режиме сторожевого таймера wd_manual() может перезапускаться контроллер.
Радик, будем считать это недокументированной особенностью. Каких-либо существенных комментариев тут дать не могу. Наша тех. поддержка подтвердила обнаруженный Вами эффект.
Астафьев Илья ПЛКСистемы Начальник отдела продаж и тех. поддержки
Радик, мои ребята проверили - у нас все работает без проблем. Проблему не подтверждаю.
ну что сказать.... может и работает - у меня могло быть сочетание многих факторов, не только размещение и вызовы конструкторов\деструкторов. Наверно следует переформулировать - "как разместить экземпляр класса в глобальной памяти и при этом избежать генерации кода раннего автоматического вызова конструктора". Либо дополнить документацию на CTools примером работы с глобальным экземпляром класса, пояснив при этом, как реагировать на предупреждения линкера и когда фактически происходит вызов конструктора по умолчанию.
Astilya пишет:
цитата:
Хорошее решение нестандартной задачи.
тут немного помог Dmytro из службы техподдержки CMI, главным образом психологически - он не сомневался, что это возможно, что в конце концов и подтвердилось. А также как-то услышанная от Ваших специалистов идея, что можно стирать register assignments из С++ и заполнять заново при запуске, чтобы избавиться от LAD зависимости в этом отношении.
любителям использовать битовые поля в структурах небольшой облом - компилятор кода HEW при описании битовых полей в структурах размещает поля начиная с старших битов, а не с младших, как ожидалось. Почему - загадка...
РЕШЕНИЕ:
не использовать битовые поля :) они мало переносимы и зависят от реализации компилятора
любителям использовать битовые поля в структурах небольшой облом - компилятор кода HEW при описании битовых полей в структурах размещает поля начиная с старших битов, а не с младших, как ожидалось. Почему - загадка...
Не назвал бы это загадкой. Разве что соглашусь, что это можно было бы и задокументировать. Это давно известная проблема, которая возникает при переносе программ на разные платформы, - учет требований процессоров по выравниванию данных и интерпретации числовых значений. Например, процессор Intel допускает обращение к числовым переменным, расположенным по адресу, не кратному длине операнда - порядок байт в слове: от младшего разряда к старшему. Компиляторы С/С++ для платформы Intel интерпретируют битовые структуры в порядке от младшего битового поля к старшему и такой же порядок байт в структуре. Процессоры MIPS и Sparc требуют выравнивания адреса переменной кратно ее длине (short - кратно 2, long - 4, double - 8), а порядок байт в слове: от старшего байта к младшему. Битовые поля в структуре располагаются от старшего поля к младшему в пределах байта, а байты от младшего к старшему (то есть обратно порядку битовых полей). Предлагаю принять за данность. Попробую уговорить CMI каким-либо образом внести это в документацию.
цитата: Радик, мои ребята проверили - у нас все работает без проблем. Проблему не подтверждаю.
ну что сказать.... может и работает - у меня могло быть сочетание многих факторов, не только размещение и вызовы конструкторов\деструкторов. Наверно следует переформулировать - "как разместить экземпляр класса в глобальной памяти и при этом избежать генерации кода раннего автоматического вызова конструктора". Либо дополнить документацию на CTools примером работы с глобальным экземпляром класса, пояснив при этом, как реагировать на предупреждения линкера и когда фактически происходит вызов конструктора по умолчанию.
Радик, пожалуйста, пришлите этот проект мне. Подозреваю, что Вы действительно "попали" на какое-то сочетание многих факторов. Хотелось бы с ним разобраться более пристрастно. Поскольку некий пробел в документации Вами подмечен совершенно правильно, я сейчас, слету, не могу сказать - что именно привело к такой работе с глобальным классом. Нам бы "руками пощупать"...
Все даты в формате GMT
5 час. Хитов сегодня: 1
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет