Просмотр полной версии : _REAL:=_POINTER_TO_REAL^ НЕ РАБОТАЕТ?!
Здравствуйте.
Столкнулся с непонятным явлением. Исходный текст:
VAR_OUTPUT
Rate:REAL; (* рабочий расход *)
NormRate:REAL; (* нормализованный расход *)
Pressure:REAL; (* давление *)
Temperature:REAL; (* температура *)
TimeError:WORD; (* нерабочее время *)
Acc:BYTE; (* признак ошибки по питанию *)
END_VAR
VAR
Response:STRING[1024]; (* буфер для приёма данных, считанных с порта *)
pnt_Data_Byte:POINTER TO BYTE;
pnt_Data_Word:POINTER TO WORD;
pnt_Data_Real:POINTER TO REAL;
END_VAR
(************************************************* *********************************)
(************************************************* *********************************)
(* если добрались до сюда, то извлекаем данные из ответа *)
pnt_Data_Real:= ADR(Response)+15;
(*!!!*) Rate:= pnt_Data_Real^;
pnt_Data_Real:= pnt_Data_Real+4;
NormRate:= pnt_Data_Real^;
pnt_Data_Real:= pnt_Data_Real+4;
Pressure:= pnt_Data_Real^;
pnt_Data_Real:= pnt_Data_Real+4;
Temperature:= pnt_Data_Real^;
pnt_Data_Word:= ADR(Response)+31;
TimeError:= pnt_Data_Word^;
pnt_Data_Byte:= ADR(Response)+33;
Acc:=pnt_Data_Byte^;
Когда программа выполняет строку, помеченную восклицательными знаками, контроллер пикает и перезагружается, а CoDeSys выбрасывает окно обрыва коммуникации. Причем, все четыре байта, на которые в этот момент указывает pnt_Data_Real равны нулю, это я проверил.
В чём может быть дело?
Проект на текущий момент.
625
Игорь Петров
06.08.2008, 18:04
:eek: Возникают большие сомнения по поводу того, как вообще должен себя вести компилятор процессора типа ARM, при попытке размещения REAL на произвольные байтовые адреса (десериализация данных с игнорированием правил выравнивания)? Скорее всего, будет непредсказуемый результат или повисание. Если система исполнения ПЛК действительно ловит такую ситуацию и перезапускается, то большой респект и уважение разработчикам Овен!
Я бы объявил нормальную переменную типа REAL, взял бы на нее указатель и уже туда копировал бы данные из строки побайтно. Еще лучше оформить такой преобразователь в виде функции с проверкой допустимости формата данных.
По сути, я попал ногой в капкан, о котором в документации туманно сообщено, что он есть, но не больше. Ошибка нашлась часа через два после того, как разместил свой вопрос, но не стал сразу писать решение. Интересно было посмотреть, кто что скажет. Проблемка ведь не тривиальная. А на счёт такого варианта:
"Я бы объявил нормальную переменную типа REAL, взял бы на нее указатель и уже туда копировал бы данные из строки побайтно."
то я предпочёл другой способ
"SysMemCpy(ADR (Rate), ADR(Response)+15, 4);"
В четыре раза короче и, по-моему, нагляднее.
"Если система исполнения ПЛК действительно ловит такую ситуацию и перезапускается, то большой респект и уважение разработчикам Овен!"
Я не сомневаюсь, что если возникает фатальная ошибка, то лучше всего аварийно остановить работу контроллера. Но зачем его перезагружать? Я так и не нашёл способа получить информацию о причине остановки и рестарта от самого контроллера. Может, плохо ещё систему знаю, а может, и нет такой возможности вообще. Контроллер вылетает, перезагружается и стартует заново. Почему произошла остановка? В какой точке программы? Никакой информации. Как хочешь, так и ищи...
"Еще лучше оформить такой преобразователь в виде функции с проверкой допустимости формата данных."
А не могли бы Вы подбросить прототип такой функции? Может уже сталкивались и есть наработка?
P.S. Краткое резюме: Работа с указателями - как пересечение болота. Когда есть карта проверенных тропинок и известных опасных участков - пройдёшь без особых приключений. Хорошо бы в новых версиях документации посвятить отдельный параграф особенностям использования указателей на данной платформе.
Филоненко Владислав
07.08.2008, 09:13
1. Указатель - как атомная энергия, может дать тепло и свет, но может и жахнуть :)
2. Вы наступили на грабли выравнивания. Побайтовое копирование - единственный выход. Но по настоящему верным решением будет создать структуру данных, содержащихся в строке, передавать начало строки в указатель на эту структуру и работать с её полями. Компилятор сам учтёт выравнивания и проблем не возникнет.
Определение структуры на языке C также можно получить при необходимости, создав внешнюю (external) библиотеку с этой структурой. При записи создается .h файл со всеми прототипами функций и структурами данных.
3. По ошибке невыровненного доступа к памяти восстановление невозможно, поэтому единственным выходом является перезагрузка.
Вы наступили на грабли выравнивания.
Во-во, ещё бы эти грабли были подробнее описаны в мануале :) (опять я за старое, да ;) )
Побайтовое копирование - единственный выход.
А вариант с SysMemCpy хуже? Может тут тоже есть что-то, о чём ещё предстоит узнать? :cool:
На счёт структуры - надо подумать.
По ошибке невыровненного доступа к памяти восстановление невозможно, поэтому единственным выходом является перезагрузка.
А разве я говорил о восстановлении? По моему скромному мнению, в случае фатальной ошибки контроллер должен:
1. Остановить выполнение программы.
2. Перевести выходы в безопасные состояния.
3. Записать максимум информации об ошибке в энергонезависимую память.
4. Сохранить возможность коммуникаций со средой программирования.
5. Ни в коем случае не пытаться самостоятельно стартовать снова (и сделать это только по нажатию кнопки "Сброс").
6. Стоять и ждать программиста.
Было бы хорошо, если бы Вы добавили контроллеру операцию автоматической записи информации об ошибке (при её возникновении) в энергонезависимую память (минимально - тип ошибки и программый блок, где она произошла (в идеале - номер строки)). И возможность считать эту инфу через PLC-Browser, добавив соответствующую команду (типа GetLastError). Естественно, эта информация не должна теряться при перезагрузке.
Филоненко Владислав
07.08.2008, 11:16
Всё это хорошо и правильно. НО!
Ошибка происходит на аппаратном уровне и остановить чего либо уже нельзя.
Игорь Петров
Если система исполнения ПЛК действительно ловит такую ситуацию и перезапускается, то большой респект и уважение разработчикам Овен!
Филоненко Владислав
Ошибка происходит на аппаратном уровне и остановить чего либо уже нельзя.
:)
Получается, что ошибку с указателем обнаруживает сам процессор и сам себе делает резет? И никаких прерываний, ничего, куда можно всунуть перед резетом процедурку записи инфы об ошибке? По идее, в этом случае он должен предоставить какой-то регистр, где сохраняет код причины рестарта?...
Филоненко Владислав
07.08.2008, 15:22
При перезагрузке индицируется коды последней причины перезагрузки (на гипертерминале) и зап. соотв. информация в лог-файлы
Филоненко Владислав
07.08.2008, 15:53
На внутреннем диске ПЛК. log.txt и debug.txt
Команда filedir рулит.
На внутреннем диске ПЛК. log.txt и debug.txt
Команда filedir рулит.
Премного благодарен :)
Скачал и посмотрел "log.txt" и "debug.txt". В "log.txt" ничего интересного, а в "debug.txt" удивительные строки:
2000. 3. 6 0:20:33 # 17 E PLC was reset by watchdog!
2000. 3. 6 0:20:34 # 3 M Last run module Id =100
2000. 3. 6 0:20:34 # 3 M Last post module Id =100
2000. 3. 6 0:20:34 # 3 M Total control code =18
2000. 3. 6 0:20:34 # 3 M Max cache utilisation =6
2000. 3. 6 0:20:34 # 3 M local_status =3
2000. 3. 6 0:20:34 # 3 M run_level =2
2000. 3. 6 0:20:34 # 3 M ff 45 ff ff ff 0 0 0 0 0 0 0 0 0 0 0
Из чего вытекают несколько вопросов:
1. Почему "reset by watchdog", если ошибка с указателями?
2. Есть ли описание этих сообщений (и других, возможных для "debug.txt"), что бы разобраться в них?
Игорь Петров
08.08.2008, 14:17
По моему скромному мнению, в случае фатальной ошибки контроллер должен:
...
6. Стоять и ждать программиста.
Эдак он опять в 10 часов вечера 31 декабря будет стоять и меня ждать в поселке Г… до которого 3 часа ехать (это летом при хорошей погоде)? Любимый заказчик опять пришлет ко мне своих веселых ребят в бронежилетах, дабы любезно подвезти меня к контролеру. Хорошо иногда энергетики выручали и сбрасывали контроллер путем дистанционного отключения райцентра В… вместе с Г… Все это было весело по молодости.
Сейчас я больше люблю контроллеры, которые сами восстанавливаются при фатальных сбоях.
1. Почему "reset by watchdog", если ошибка с указателями?
:cool: Вы действительно хотите, чтобы повисший процессор сам выполнял некие осознанные действия? Это примерно как в ходе операции на сердце попросить больного подержать себе капельницу.
5. Ни в коем случае не пытаться самостоятельно стартовать снова (и сделать это только по нажатию кнопки "Сброс").
6. Стоять и ждать программиста.
Для отладки программы это может быть и удобно, но трудно учесть абсолютно все возможное ситуации. Поэтому если вдруг в установленном на объекте ПЛК возникнет критический сбой и он встанет, ожидая пользователя, это приведет к остановке управляемых процессов.
Powered by vBulletin® Version 4.2.3 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot